Skip to content

Commit dc5ccea

Browse files
authoredApr 27, 2022
Rollup merge of rust-lang#96377 - compiler-errors:infer-rustfix, r=petrochenkov
make `fn() -> _ { .. }` suggestion MachineApplicable This might not be valid, but it would be nice to promote this to `MachineApplicable` so people can use rustfix here. Also de65fcf009d07019689cfad7f327667e390a325d is to [restore the suggestion for `issue-77179.rs`](rust-lang@de65fcf#diff-12e43fb5d6d12ec7cb5c6b48204a18d113cf5de0e12eb71a358b639bd9aadaf0R8). (though in this case, the code in that issue still doesn't compile, so it's not marked with rustfix).
2 parents 8cc298d + f9e7489 commit dc5ccea

File tree

5 files changed

+46
-35
lines changed

5 files changed

+46
-35
lines changed
 

‎compiler/rustc_middle/src/ty/diagnostics.rs

+24-14
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
use crate::ty::subst::{GenericArg, GenericArgKind};
44
use crate::ty::TyKind::*;
55
use crate::ty::{
6-
ConstKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, InferTy,
7-
ProjectionTy, Term, Ty, TyCtxt, TypeAndMut,
6+
ConstKind, DefIdTree, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef,
7+
InferTy, ProjectionTy, Term, Ty, TyCtxt, TypeAndMut,
88
};
99

1010
use rustc_data_structures::fx::FxHashMap;
@@ -74,10 +74,10 @@ impl<'tcx> Ty<'tcx> {
7474
}
7575

7676
/// Whether the type can be safely suggested during error recovery.
77-
pub fn is_suggestable(self) -> bool {
78-
fn generic_arg_is_suggestible(arg: GenericArg<'_>) -> bool {
77+
pub fn is_suggestable(self, tcx: TyCtxt<'tcx>) -> bool {
78+
fn generic_arg_is_suggestible<'tcx>(arg: GenericArg<'tcx>, tcx: TyCtxt<'tcx>) -> bool {
7979
match arg.unpack() {
80-
GenericArgKind::Type(ty) => ty.is_suggestable(),
80+
GenericArgKind::Type(ty) => ty.is_suggestable(tcx),
8181
GenericArgKind::Const(c) => const_is_suggestable(c.val()),
8282
_ => true,
8383
}
@@ -99,36 +99,46 @@ impl<'tcx> Ty<'tcx> {
9999
// temporary, so I'll leave this as a fixme.
100100

101101
match self.kind() {
102-
Opaque(..)
103-
| FnDef(..)
102+
FnDef(..)
104103
| Closure(..)
105104
| Infer(..)
106105
| Generator(..)
107106
| GeneratorWitness(..)
108107
| Bound(_, _)
109108
| Placeholder(_)
110109
| Error(_) => false,
110+
Opaque(did, substs) => {
111+
let parent = tcx.parent(*did).expect("opaque types always have a parent");
112+
if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = tcx.def_kind(parent)
113+
&& let Opaque(parent_did, _) = tcx.type_of(parent).kind()
114+
&& parent_did == did
115+
{
116+
substs.iter().all(|a| generic_arg_is_suggestible(a, tcx))
117+
} else {
118+
false
119+
}
120+
}
111121
Dynamic(dty, _) => dty.iter().all(|pred| match pred.skip_binder() {
112122
ExistentialPredicate::Trait(ExistentialTraitRef { substs, .. }) => {
113-
substs.iter().all(generic_arg_is_suggestible)
123+
substs.iter().all(|a| generic_arg_is_suggestible(a, tcx))
114124
}
115125
ExistentialPredicate::Projection(ExistentialProjection {
116126
substs, term, ..
117127
}) => {
118128
let term_is_suggestable = match term {
119-
Term::Ty(ty) => ty.is_suggestable(),
129+
Term::Ty(ty) => ty.is_suggestable(tcx),
120130
Term::Const(c) => const_is_suggestable(c.val()),
121131
};
122-
term_is_suggestable && substs.iter().all(generic_arg_is_suggestible)
132+
term_is_suggestable && substs.iter().all(|a| generic_arg_is_suggestible(a, tcx))
123133
}
124134
_ => true,
125135
}),
126136
Projection(ProjectionTy { substs: args, .. }) | Adt(_, args) => {
127-
args.iter().all(generic_arg_is_suggestible)
137+
args.iter().all(|a| generic_arg_is_suggestible(a, tcx))
128138
}
129-
Tuple(args) => args.iter().all(|ty| ty.is_suggestable()),
130-
Slice(ty) | RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => ty.is_suggestable(),
131-
Array(ty, c) => ty.is_suggestable() && const_is_suggestable(c.val()),
139+
Tuple(args) => args.iter().all(|ty| ty.is_suggestable(tcx)),
140+
Slice(ty) | RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => ty.is_suggestable(tcx),
141+
Array(ty, c) => ty.is_suggestable(tcx) && const_is_suggestable(c.val()),
132142
_ => true,
133143
}
134144
}

‎compiler/rustc_typeck/src/astconv/generics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
8686
let param_type = tcx.infer_ctxt().enter(|infcx| {
8787
infcx.resolve_numeric_literals_with_default(tcx.type_of(param.def_id))
8888
});
89-
if param_type.is_suggestable() {
89+
if param_type.is_suggestable(tcx) {
9090
err.span_suggestion(
9191
tcx.def_span(src_def_id),
9292
"consider changing this type parameter to be a `const` generic",

‎compiler/rustc_typeck/src/astconv/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2466,7 +2466,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
24662466
span,
24672467
ty,
24682468
opt_sugg: Some((span, Applicability::MachineApplicable))
2469-
.filter(|_| ty.is_suggestable()),
2469+
.filter(|_| ty.is_suggestable(tcx)),
24702470
});
24712471

24722472
ty

‎compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs

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

‎compiler/rustc_typeck/src/collect.rs

+19-18
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use rustc_middle::ty::subst::InternalSubsts;
4141
use rustc_middle::ty::util::Discr;
4242
use rustc_middle::ty::util::IntTypeExt;
4343
use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, Ty, TyCtxt};
44-
use rustc_middle::ty::{ReprOptions, ToPredicate, TypeFoldable};
44+
use rustc_middle::ty::{ReprOptions, ToPredicate};
4545
use rustc_session::lint;
4646
use rustc_session::parse::feature_err;
4747
use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -2004,28 +2004,29 @@ fn infer_return_ty_for_fn_sig<'tcx>(
20042004
visitor.visit_ty(ty);
20052005
let mut diag = bad_placeholder(tcx, visitor.0, "return type");
20062006
let ret_ty = fn_sig.skip_binder().output();
2007-
if !ret_ty.references_error() {
2008-
if !ret_ty.is_closure() {
2009-
let ret_ty_str = match ret_ty.kind() {
2010-
// Suggest a function pointer return type instead of a unique function definition
2011-
// (e.g. `fn() -> i32` instead of `fn() -> i32 { f }`, the latter of which is invalid
2012-
// syntax)
2013-
ty::FnDef(..) => ret_ty.fn_sig(tcx).to_string(),
2014-
_ => ret_ty.to_string(),
2015-
};
2007+
if ret_ty.is_suggestable(tcx) {
2008+
diag.span_suggestion(
2009+
ty.span,
2010+
"replace with the correct return type",
2011+
ret_ty.to_string(),
2012+
Applicability::MachineApplicable,
2013+
);
2014+
} else if matches!(ret_ty.kind(), ty::FnDef(..)) {
2015+
let fn_sig = ret_ty.fn_sig(tcx);
2016+
if fn_sig.skip_binder().inputs_and_output.iter().all(|t| t.is_suggestable(tcx)) {
20162017
diag.span_suggestion(
20172018
ty.span,
20182019
"replace with the correct return type",
2019-
ret_ty_str,
2020-
Applicability::MaybeIncorrect,
2020+
fn_sig.to_string(),
2021+
Applicability::MachineApplicable,
20212022
);
2022-
} else {
2023-
// We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
2024-
// to prevent the user from getting a papercut while trying to use the unique closure
2025-
// syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
2026-
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
2027-
diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html");
20282023
}
2024+
} else if ret_ty.is_closure() {
2025+
// We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
2026+
// to prevent the user from getting a papercut while trying to use the unique closure
2027+
// syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
2028+
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
2029+
diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html");
20292030
}
20302031
diag.emit();
20312032

0 commit comments

Comments
 (0)