1
Fork 0

TAITs are suggestable

This commit is contained in:
Michael Goulet 2022-04-24 20:41:37 -07:00
parent ae42f22ba0
commit f9e7489f87
6 changed files with 33 additions and 20 deletions

View file

@ -3,8 +3,8 @@
use crate::ty::subst::{GenericArg, GenericArgKind}; use crate::ty::subst::{GenericArg, GenericArgKind};
use crate::ty::TyKind::*; use crate::ty::TyKind::*;
use crate::ty::{ use crate::ty::{
ConstKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, InferTy, ConstKind, DefIdTree, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef,
ProjectionTy, Term, Ty, TyCtxt, TypeAndMut, InferTy, ProjectionTy, Term, Ty, TyCtxt, TypeAndMut,
}; };
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
@ -74,10 +74,10 @@ impl<'tcx> Ty<'tcx> {
} }
/// Whether the type can be safely suggested during error recovery. /// Whether the type can be safely suggested during error recovery.
pub fn is_suggestable(self) -> bool { pub fn is_suggestable(self, tcx: TyCtxt<'tcx>) -> bool {
fn generic_arg_is_suggestible(arg: GenericArg<'_>) -> bool { fn generic_arg_is_suggestible<'tcx>(arg: GenericArg<'tcx>, tcx: TyCtxt<'tcx>) -> bool {
match arg.unpack() { match arg.unpack() {
GenericArgKind::Type(ty) => ty.is_suggestable(), GenericArgKind::Type(ty) => ty.is_suggestable(tcx),
GenericArgKind::Const(c) => const_is_suggestable(c.val()), GenericArgKind::Const(c) => const_is_suggestable(c.val()),
_ => true, _ => true,
} }
@ -99,8 +99,7 @@ impl<'tcx> Ty<'tcx> {
// temporary, so I'll leave this as a fixme. // temporary, so I'll leave this as a fixme.
match self.kind() { match self.kind() {
Opaque(..) FnDef(..)
| FnDef(..)
| Closure(..) | Closure(..)
| Infer(..) | Infer(..)
| Generator(..) | Generator(..)
@ -108,27 +107,38 @@ impl<'tcx> Ty<'tcx> {
| Bound(_, _) | Bound(_, _)
| Placeholder(_) | Placeholder(_)
| Error(_) => false, | Error(_) => false,
Opaque(did, substs) => {
let parent = tcx.parent(*did).expect("opaque types always have a parent");
if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = tcx.def_kind(parent)
&& let Opaque(parent_did, _) = tcx.type_of(parent).kind()
&& parent_did == did
{
substs.iter().all(|a| generic_arg_is_suggestible(a, tcx))
} else {
false
}
}
Dynamic(dty, _) => dty.iter().all(|pred| match pred.skip_binder() { Dynamic(dty, _) => dty.iter().all(|pred| match pred.skip_binder() {
ExistentialPredicate::Trait(ExistentialTraitRef { substs, .. }) => { ExistentialPredicate::Trait(ExistentialTraitRef { substs, .. }) => {
substs.iter().all(generic_arg_is_suggestible) substs.iter().all(|a| generic_arg_is_suggestible(a, tcx))
} }
ExistentialPredicate::Projection(ExistentialProjection { ExistentialPredicate::Projection(ExistentialProjection {
substs, term, .. substs, term, ..
}) => { }) => {
let term_is_suggestable = match term { let term_is_suggestable = match term {
Term::Ty(ty) => ty.is_suggestable(), Term::Ty(ty) => ty.is_suggestable(tcx),
Term::Const(c) => const_is_suggestable(c.val()), Term::Const(c) => const_is_suggestable(c.val()),
}; };
term_is_suggestable && substs.iter().all(generic_arg_is_suggestible) term_is_suggestable && substs.iter().all(|a| generic_arg_is_suggestible(a, tcx))
} }
_ => true, _ => true,
}), }),
Projection(ProjectionTy { substs: args, .. }) | Adt(_, args) => { Projection(ProjectionTy { substs: args, .. }) | Adt(_, args) => {
args.iter().all(generic_arg_is_suggestible) args.iter().all(|a| generic_arg_is_suggestible(a, tcx))
} }
Tuple(args) => args.iter().all(|ty| ty.is_suggestable()), Tuple(args) => args.iter().all(|ty| ty.is_suggestable(tcx)),
Slice(ty) | RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => ty.is_suggestable(), Slice(ty) | RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => ty.is_suggestable(tcx),
Array(ty, c) => ty.is_suggestable() && const_is_suggestable(c.val()), Array(ty, c) => ty.is_suggestable(tcx) && const_is_suggestable(c.val()),
_ => true, _ => true,
} }
} }

View file

@ -86,7 +86,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let param_type = tcx.infer_ctxt().enter(|infcx| { let param_type = tcx.infer_ctxt().enter(|infcx| {
infcx.resolve_numeric_literals_with_default(tcx.type_of(param.def_id)) infcx.resolve_numeric_literals_with_default(tcx.type_of(param.def_id))
}); });
if param_type.is_suggestable() { if param_type.is_suggestable(tcx) {
err.span_suggestion( err.span_suggestion(
tcx.def_span(src_def_id), tcx.def_span(src_def_id),
"consider changing this type parameter to be a `const` generic", "consider changing this type parameter to be a `const` generic",

View file

@ -2466,7 +2466,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
span, span,
ty, ty,
opt_sugg: Some((span, Applicability::MachineApplicable)) opt_sugg: Some((span, Applicability::MachineApplicable))
.filter(|_| ty.is_suggestable()), .filter(|_| ty.is_suggestable(tcx)),
}); });
ty ty

View file

@ -525,7 +525,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(found)); self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(found));
// Only suggest changing the return type for methods that // Only suggest changing the return type for methods that
// haven't set a return type at all (and aren't `fn main()` or an impl). // haven't set a return type at all (and aren't `fn main()` or an impl).
match (&fn_decl.output, found.is_suggestable(), can_suggest, expected.is_unit()) { match (&fn_decl.output, found.is_suggestable(self.tcx), can_suggest, expected.is_unit()) {
(&hir::FnRetTy::DefaultReturn(span), true, true, true) => { (&hir::FnRetTy::DefaultReturn(span), true, true, true) => {
err.span_suggestion( err.span_suggestion(
span, span,

View file

@ -2004,7 +2004,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
visitor.visit_ty(ty); visitor.visit_ty(ty);
let mut diag = bad_placeholder(tcx, visitor.0, "return type"); let mut diag = bad_placeholder(tcx, visitor.0, "return type");
let ret_ty = fn_sig.skip_binder().output(); let ret_ty = fn_sig.skip_binder().output();
if ret_ty.is_suggestable() { if ret_ty.is_suggestable(tcx) {
diag.span_suggestion( diag.span_suggestion(
ty.span, ty.span,
"replace with the correct return type", "replace with the correct return type",
@ -2013,7 +2013,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
); );
} else if matches!(ret_ty.kind(), ty::FnDef(..)) { } else if matches!(ret_ty.kind(), ty::FnDef(..)) {
let fn_sig = ret_ty.fn_sig(tcx); let fn_sig = ret_ty.fn_sig(tcx);
if fn_sig.skip_binder().inputs_and_output.iter().all(|t| t.is_suggestable()) { if fn_sig.skip_binder().inputs_and_output.iter().all(|t| t.is_suggestable(tcx)) {
diag.span_suggestion( diag.span_suggestion(
ty.span, ty.span,
"replace with the correct return type", "replace with the correct return type",

View file

@ -2,7 +2,10 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
--> $DIR/issue-77179.rs:7:22 --> $DIR/issue-77179.rs:7:22
| |
LL | fn test() -> Pointer<_> { LL | fn test() -> Pointer<_> {
| ^ not allowed in type signatures | --------^-
| | |
| | not allowed in type signatures
| help: replace with the correct return type: `Pointer<i32>`
error: aborting due to previous error error: aborting due to previous error