Skip to content

Commit 2930dce

Browse files
authored
Rollup merge of #123761 - compiler-errors:suggest-more-impl-trait, r=estebank
Use `suggest_impl_trait` in return type suggestion on type error Discovered while doing other refactoring. Review with whitespace disabled. r? estebank
2 parents b24d2ad + 3764af6 commit 2930dce

File tree

7 files changed

+68
-60
lines changed

7 files changed

+68
-60
lines changed

compiler/rustc_hir_analysis/src/collect.rs

+56-42
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use rustc_middle::query::Providers;
3030
use rustc_middle::ty::util::{Discr, IntTypeExt};
3131
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
3232
use rustc_span::symbol::{kw, sym, Ident, Symbol};
33-
use rustc_span::Span;
33+
use rustc_span::{Span, DUMMY_SP};
3434
use rustc_target::abi::FieldIdx;
3535
use rustc_target::spec::abi;
3636
use rustc_trait_selection::infer::InferCtxtExt;
@@ -1383,7 +1383,9 @@ fn infer_return_ty_for_fn_sig<'tcx>(
13831383
Applicability::MachineApplicable,
13841384
);
13851385
should_recover = true;
1386-
} else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, def_id) {
1386+
} else if let Some(sugg) =
1387+
suggest_impl_trait(&tcx.infer_ctxt().build(), tcx.param_env(def_id), ret_ty)
1388+
{
13871389
diag.span_suggestion(
13881390
ty.span,
13891391
"replace with an appropriate return type",
@@ -1426,11 +1428,10 @@ fn infer_return_ty_for_fn_sig<'tcx>(
14261428
}
14271429
}
14281430

1429-
fn suggest_impl_trait<'tcx>(
1430-
tcx: TyCtxt<'tcx>,
1431+
pub fn suggest_impl_trait<'tcx>(
1432+
infcx: &InferCtxt<'tcx>,
1433+
param_env: ty::ParamEnv<'tcx>,
14311434
ret_ty: Ty<'tcx>,
1432-
span: Span,
1433-
def_id: LocalDefId,
14341435
) -> Option<String> {
14351436
let format_as_assoc: fn(_, _, _, _, _) -> _ =
14361437
|tcx: TyCtxt<'tcx>,
@@ -1464,24 +1465,28 @@ fn suggest_impl_trait<'tcx>(
14641465

14651466
for (trait_def_id, assoc_item_def_id, formatter) in [
14661467
(
1467-
tcx.get_diagnostic_item(sym::Iterator),
1468-
tcx.get_diagnostic_item(sym::IteratorItem),
1468+
infcx.tcx.get_diagnostic_item(sym::Iterator),
1469+
infcx.tcx.get_diagnostic_item(sym::IteratorItem),
14691470
format_as_assoc,
14701471
),
14711472
(
1472-
tcx.lang_items().future_trait(),
1473-
tcx.get_diagnostic_item(sym::FutureOutput),
1473+
infcx.tcx.lang_items().future_trait(),
1474+
infcx.tcx.get_diagnostic_item(sym::FutureOutput),
14741475
format_as_assoc,
14751476
),
1476-
(tcx.lang_items().fn_trait(), tcx.lang_items().fn_once_output(), format_as_parenthesized),
14771477
(
1478-
tcx.lang_items().fn_mut_trait(),
1479-
tcx.lang_items().fn_once_output(),
1478+
infcx.tcx.lang_items().fn_trait(),
1479+
infcx.tcx.lang_items().fn_once_output(),
1480+
format_as_parenthesized,
1481+
),
1482+
(
1483+
infcx.tcx.lang_items().fn_mut_trait(),
1484+
infcx.tcx.lang_items().fn_once_output(),
14801485
format_as_parenthesized,
14811486
),
14821487
(
1483-
tcx.lang_items().fn_once_trait(),
1484-
tcx.lang_items().fn_once_output(),
1488+
infcx.tcx.lang_items().fn_once_trait(),
1489+
infcx.tcx.lang_items().fn_once_output(),
14851490
format_as_parenthesized,
14861491
),
14871492
] {
@@ -1491,36 +1496,45 @@ fn suggest_impl_trait<'tcx>(
14911496
let Some(assoc_item_def_id) = assoc_item_def_id else {
14921497
continue;
14931498
};
1494-
if tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
1499+
if infcx.tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
14951500
continue;
14961501
}
1497-
let param_env = tcx.param_env(def_id);
1498-
let infcx = tcx.infer_ctxt().build();
1499-
let args = ty::GenericArgs::for_item(tcx, trait_def_id, |param, _| {
1500-
if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(span, param) }
1502+
let sugg = infcx.probe(|_| {
1503+
let args = ty::GenericArgs::for_item(infcx.tcx, trait_def_id, |param, _| {
1504+
if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(DUMMY_SP, param) }
1505+
});
1506+
if !infcx
1507+
.type_implements_trait(trait_def_id, args, param_env)
1508+
.must_apply_modulo_regions()
1509+
{
1510+
return None;
1511+
}
1512+
let ocx = ObligationCtxt::new(&infcx);
1513+
let item_ty = ocx.normalize(
1514+
&ObligationCause::dummy(),
1515+
param_env,
1516+
Ty::new_projection(infcx.tcx, assoc_item_def_id, args),
1517+
);
1518+
// FIXME(compiler-errors): We may benefit from resolving regions here.
1519+
if ocx.select_where_possible().is_empty()
1520+
&& let item_ty = infcx.resolve_vars_if_possible(item_ty)
1521+
&& let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None)
1522+
&& let Some(sugg) = formatter(
1523+
infcx.tcx,
1524+
infcx.resolve_vars_if_possible(args),
1525+
trait_def_id,
1526+
assoc_item_def_id,
1527+
item_ty,
1528+
)
1529+
{
1530+
return Some(sugg);
1531+
}
1532+
1533+
None
15011534
});
1502-
if !infcx.type_implements_trait(trait_def_id, args, param_env).must_apply_modulo_regions() {
1503-
continue;
1504-
}
1505-
let ocx = ObligationCtxt::new(&infcx);
1506-
let item_ty = ocx.normalize(
1507-
&ObligationCause::misc(span, def_id),
1508-
param_env,
1509-
Ty::new_projection(tcx, assoc_item_def_id, args),
1510-
);
1511-
// FIXME(compiler-errors): We may benefit from resolving regions here.
1512-
if ocx.select_where_possible().is_empty()
1513-
&& let item_ty = infcx.resolve_vars_if_possible(item_ty)
1514-
&& let Some(item_ty) = item_ty.make_suggestable(tcx, false, None)
1515-
&& let Some(sugg) = formatter(
1516-
tcx,
1517-
infcx.resolve_vars_if_possible(args),
1518-
trait_def_id,
1519-
assoc_item_def_id,
1520-
item_ty,
1521-
)
1522-
{
1523-
return Some(sugg);
1535+
1536+
if sugg.is_some() {
1537+
return sugg;
15241538
}
15251539
}
15261540
None

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use rustc_hir::{
2020
CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, Node,
2121
Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
2222
};
23+
use rustc_hir_analysis::collect::suggest_impl_trait;
2324
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
2425
use rustc_infer::traits::{self};
2526
use rustc_middle::lint::in_external_macro;
@@ -814,17 +815,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
814815
errors::AddReturnTypeSuggestion::Add { span, found: found.to_string() },
815816
);
816817
return true;
817-
} else if let ty::Closure(_, args) = found.kind()
818-
// FIXME(compiler-errors): Get better at printing binders...
819-
&& let closure = args.as_closure()
820-
&& closure.sig().is_suggestable(self.tcx, false)
821-
{
818+
} else if let Some(sugg) = suggest_impl_trait(self, self.param_env, found) {
822819
err.subdiagnostic(
823820
self.dcx(),
824-
errors::AddReturnTypeSuggestion::Add {
825-
span,
826-
found: closure.print_as_impl_trait().to_string(),
827-
},
821+
errors::AddReturnTypeSuggestion::Add { span, found: sugg },
828822
);
829823
return true;
830824
} else {

tests/ui/async-await/track-caller/async-closure-gate.afn.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ error[E0308]: mismatched types
6262
--> $DIR/async-closure-gate.rs:27:5
6363
|
6464
LL | fn foo3() {
65-
| - help: a return type might be missing here: `-> _`
65+
| - help: try adding a return type: `-> impl Future<Output = ()>`
6666
LL | / async {
6767
LL | |
6868
LL | | let _ = #[track_caller] || {
@@ -78,7 +78,7 @@ error[E0308]: mismatched types
7878
--> $DIR/async-closure-gate.rs:44:5
7979
|
8080
LL | fn foo5() {
81-
| - help: a return type might be missing here: `-> _`
81+
| - help: try adding a return type: `-> impl Future<Output = ()>`
8282
LL | / async {
8383
LL | |
8484
LL | | let _ = || {

tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ error[E0308]: mismatched types
6262
--> $DIR/async-closure-gate.rs:27:5
6363
|
6464
LL | fn foo3() {
65-
| - help: a return type might be missing here: `-> _`
65+
| - help: try adding a return type: `-> impl Future<Output = ()>`
6666
LL | / async {
6767
LL | |
6868
LL | | let _ = #[track_caller] || {
@@ -78,7 +78,7 @@ error[E0308]: mismatched types
7878
--> $DIR/async-closure-gate.rs:44:5
7979
|
8080
LL | fn foo5() {
81-
| - help: a return type might be missing here: `-> _`
81+
| - help: try adding a return type: `-> impl Future<Output = ()>`
8282
LL | / async {
8383
LL | |
8484
LL | | let _ = || {

tests/ui/suggestions/return-closures.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
22
--> $DIR/return-closures.rs:3:5
33
|
44
LL | fn foo() {
5-
| - help: try adding a return type: `-> impl for<'a> Fn(&'a i32) -> i32`
5+
| - help: try adding a return type: `-> impl FnOnce(&i32) -> i32`
66
LL |
77
LL | |x: &i32| 1i32
88
| ^^^^^^^^^^^^^^ expected `()`, found closure

tests/ui/typeck/return_type_containing_closure.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#[allow(unused)]
2-
fn foo() { //~ HELP a return type might be missing here
2+
fn foo() { //~ HELP try adding a return type
33
vec!['a'].iter().map(|c| c)
44
//~^ ERROR mismatched types [E0308]
55
//~| NOTE expected `()`, found `Map<Iter<'_, char>, ...>`

tests/ui/typeck/return_type_containing_closure.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ help: consider using a semicolon here
1010
|
1111
LL | vec!['a'].iter().map(|c| c);
1212
| +
13-
help: a return type might be missing here
13+
help: try adding a return type
1414
|
15-
LL | fn foo() -> _ {
16-
| ++++
15+
LL | fn foo() -> impl Iterator<Item = &char> {
16+
| ++++++++++++++++++++++++++++++
1717

1818
error: aborting due to 1 previous error
1919

0 commit comments

Comments
 (0)