TAITs are suggestable
This commit is contained in:
parent
ae42f22ba0
commit
f9e7489f87
6 changed files with 33 additions and 20 deletions
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue