Skip to content

Commit eb7bbe8

Browse files
committed
Note that type param is chosen by caller when suggesting return impl Trait
1 parent b054da8 commit eb7bbe8

File tree

9 files changed

+116
-8
lines changed

9 files changed

+116
-8
lines changed

compiler/rustc_hir_typeck/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {
103103
*[other] {" "}in the current scope
104104
}
105105
106+
hir_typeck_note_caller_chooses_ty_for_ty_param = the caller chooses a type for `{$ty_param_name}` which can be different from `{$found_ty}`
107+
106108
hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
107109
108110
hir_typeck_option_result_asref = use `{$def_path}::as_ref` to convert `{$expected_ty}` to `{$expr_ty}`

compiler/rustc_hir_typeck/src/errors.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_middle::ty::Ty;
1111
use rustc_span::{
1212
edition::{Edition, LATEST_STABLE_EDITION},
1313
symbol::Ident,
14-
Span,
14+
Span, Symbol,
1515
};
1616

1717
#[derive(Diagnostic)]
@@ -614,3 +614,10 @@ pub struct SuggestConvertViaMethod<'tcx> {
614614
pub expected: Ty<'tcx>,
615615
pub found: Ty<'tcx>,
616616
}
617+
618+
#[derive(Subdiagnostic)]
619+
#[note(hir_typeck_note_caller_chooses_ty_for_ty_param)]
620+
pub struct NoteCallerChoosesTyForTyParam<'tcx> {
621+
pub ty_param_name: Symbol,
622+
pub found_ty: Ty<'tcx>,
623+
}

compiler/rustc_hir_typeck/src/expr.rs

+33-6
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@
55
use crate::cast;
66
use crate::coercion::CoerceMany;
77
use crate::coercion::DynamicCoerceMany;
8-
use crate::errors::ReturnLikeStatementKind;
9-
use crate::errors::TypeMismatchFruTypo;
10-
use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive};
118
use crate::errors::{
12-
FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition,
13-
YieldExprOutsideOfCoroutine,
9+
AddressOfTemporaryTaken, FieldMultiplySpecifiedInInitializer,
10+
FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition, NoteCallerChoosesTyForTyParam,
11+
ReturnLikeStatementKind, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive,
12+
TypeMismatchFruTypo, YieldExprOutsideOfCoroutine,
1413
};
1514
use crate::fatally_break_rust;
1615
use crate::method::SelfSource;
@@ -116,11 +115,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
116115
expected: Ty<'tcx>,
117116
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
118117
) -> Ty<'tcx> {
118+
debug!("check_expr_coercible_to_type");
119119
let ty = self.check_expr_with_hint(expr, expected);
120120
// checks don't need two phase
121-
self.demand_coerce(expr, ty, expected, expected_ty_expr, AllowTwoPhase::No)
121+
let (res_ty, diag) =
122+
self.demand_coerce_diag(expr, ty, expected, expected_ty_expr, AllowTwoPhase::No);
123+
124+
if let Some(diag) = diag {
125+
self.note_caller_chooses_ty_for_ty_param(diag, expected, ty);
126+
}
127+
128+
res_ty
129+
}
130+
131+
fn note_caller_chooses_ty_for_ty_param(
132+
&self,
133+
mut diag: Diag<'tcx>,
134+
expected: Ty<'tcx>,
135+
found: Ty<'tcx>,
136+
) {
137+
if let ty::Param(expected_ty_as_param) = expected.kind() {
138+
diag.subdiagnostic(
139+
self.dcx(),
140+
NoteCallerChoosesTyForTyParam {
141+
ty_param_name: expected_ty_as_param.name,
142+
found_ty: found,
143+
},
144+
);
145+
}
146+
147+
diag.emit();
122148
}
123149

150+
#[instrument(skip(self, expr))]
124151
pub(super) fn check_expr_with_hint(
125152
&self,
126153
expr: &'tcx hir::Expr<'tcx>,

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
889889
self.dcx(),
890890
errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected },
891891
);
892-
self.try_suggest_return_impl_trait(err, expected, ty, fn_id);
892+
self.try_suggest_return_impl_trait(err, expected, found, fn_id);
893893
return true;
894894
}
895895
}
@@ -1010,6 +1010,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10101010
format!("impl {all_bounds_str}"),
10111011
Applicability::MaybeIncorrect,
10121012
);
1013+
1014+
err.subdiagnostic(
1015+
self.dcx(),
1016+
errors::NoteCallerChoosesTyForTyParam {
1017+
ty_param_name: expected_ty_as_param.name,
1018+
found_ty: found,
1019+
},
1020+
);
10131021
}
10141022

10151023
pub(in super::super) fn suggest_missing_break_or_return_expr(

tests/ui/const-generics/issues/issue-67945-1.full.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ LL | let x: S = MaybeUninit::uninit();
1111
|
1212
= note: expected type parameter `S`
1313
found union `MaybeUninit<_>`
14+
= note: the caller chooses a type for `S` which can be different from `MaybeUninit<_>`
1415

1516
error: aborting due to 1 previous error
1617

tests/ui/return/return-impl-trait-bad.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ LL | "don't suggest this, because the generic param is used in the bound."
5353
|
5454
= note: expected type parameter `T`
5555
found reference `&'static str`
56+
= note: the caller chooses a type for `T` which can be different from `&'static str`
5657

5758
error: aborting due to 4 previous errors
5859

tests/ui/return/return-impl-trait.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ LL | ()
1212
|
1313
= note: expected type parameter `T`
1414
found unit type `()`
15+
= note: the caller chooses a type for `T` which can be different from `()`
1516

1617
error[E0308]: mismatched types
1718
--> $DIR/return-impl-trait.rs:23:5
@@ -28,6 +29,7 @@ LL | ()
2829
|
2930
= note: expected type parameter `T`
3031
found unit type `()`
32+
= note: the caller chooses a type for `T` which can be different from `()`
3133

3234
error: aborting due to 2 previous errors
3335

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Checks existence of a note for "a caller chooses ty for ty param" upon return ty mismatch.
2+
3+
fn f<T>() -> (T,) {
4+
(0,) //~ ERROR mismatched types
5+
}
6+
7+
fn g<U, V>() -> (U, V) {
8+
(0, "foo")
9+
//~^ ERROR mismatched types
10+
//~| ERROR mismatched types
11+
}
12+
13+
fn h() -> u8 {
14+
0u8
15+
}
16+
17+
fn main() {
18+
f::<()>();
19+
g::<(), ()>;
20+
let _ = h();
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/return-ty-mismatch-note.rs:4:6
3+
|
4+
LL | fn f<T>() -> (T,) {
5+
| - expected this type parameter
6+
LL | (0,)
7+
| ^ expected type parameter `T`, found integer
8+
|
9+
= note: expected type parameter `T`
10+
found type `{integer}`
11+
= note: the caller chooses a type for `T` which can be different from `{integer}`
12+
13+
error[E0308]: mismatched types
14+
--> $DIR/return-ty-mismatch-note.rs:8:6
15+
|
16+
LL | fn g<U, V>() -> (U, V) {
17+
| - expected this type parameter
18+
LL | (0, "foo")
19+
| ^ expected type parameter `U`, found integer
20+
|
21+
= note: expected type parameter `U`
22+
found type `{integer}`
23+
= note: the caller chooses a type for `U` which can be different from `{integer}`
24+
25+
error[E0308]: mismatched types
26+
--> $DIR/return-ty-mismatch-note.rs:8:9
27+
|
28+
LL | fn g<U, V>() -> (U, V) {
29+
| - expected this type parameter
30+
LL | (0, "foo")
31+
| ^^^^^ expected type parameter `V`, found `&str`
32+
|
33+
= note: expected type parameter `V`
34+
found reference `&'static str`
35+
= note: the caller chooses a type for `V` which can be different from `&'static str`
36+
37+
error: aborting due to 3 previous errors
38+
39+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)