Skip to content

Commit

Permalink
Note that type param is chosen by caller when suggesting return impl …
Browse files Browse the repository at this point in the history
…Trait
  • Loading branch information
jieyouxu committed Mar 16, 2024
1 parent 22e241e commit 09c1667
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 2 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_hir_typeck/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {
*[other] {" "}in the current scope
}
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}`
hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
hir_typeck_option_result_asref = use `{$def_path}::as_ref` to convert `{$expected_ty}` to `{$expr_ty}`
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_hir_typeck/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use rustc_middle::ty::Ty;
use rustc_span::{
edition::{Edition, LATEST_STABLE_EDITION},
symbol::Ident,
Span,
Span, Symbol,
};

#[derive(Diagnostic)]
Expand Down Expand Up @@ -614,3 +614,10 @@ pub struct SuggestConvertViaMethod<'tcx> {
pub expected: Ty<'tcx>,
pub found: Ty<'tcx>,
}

#[derive(Subdiagnostic)]
#[note(hir_typeck_note_caller_chooses_ty_for_ty_param)]
pub struct NoteCallerChoosesTyForTyParam<'tcx> {
pub ty_param_name: Symbol,
pub found_ty: Ty<'tcx>,
}
20 changes: 19 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -889,7 +889,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.dcx(),
errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected },
);
self.try_suggest_return_impl_trait(err, expected, ty, fn_id);
self.try_suggest_return_impl_trait(err, expected, found, fn_id);
self.note_caller_chooses_ty_for_ty_param(err, expected, found);
return true;
}
}
Expand All @@ -899,6 +900,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
false
}

fn note_caller_chooses_ty_for_ty_param(
&self,
diag: &mut Diag<'_>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
) {
if let ty::Param(expected_ty_as_param) = expected.kind() {
diag.subdiagnostic(
self.dcx(),
errors::NoteCallerChoosesTyForTyParam {
ty_param_name: expected_ty_as_param.name,
found_ty: found,
},
);
}
}

/// check whether the return type is a generic type with a trait bound
/// only suggest this if the generic param is not present in the arguments
/// if this is true, hint them towards changing the return type to `impl Trait`
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/return/return-impl-trait-bad.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ LL | "this should not suggest impl Trait"
|
= note: expected type parameter `T`
found reference `&'static str`
= note: the caller chooses a type for `T` which can be different from `&'static str`

error[E0308]: mismatched types
--> $DIR/return-impl-trait-bad.rs:9:5
Expand All @@ -23,6 +24,7 @@ LL | "this will not suggest it, because that would probably be wrong"
|
= note: expected type parameter `T`
found reference `&'static str`
= note: the caller chooses a type for `T` which can be different from `&'static str`

error[E0308]: mismatched types
--> $DIR/return-impl-trait-bad.rs:17:5
Expand All @@ -37,6 +39,7 @@ LL | "don't suggest this, because Option<T> places additional constraints"
|
= note: expected type parameter `T`
found reference `&'static str`
= note: the caller chooses a type for `T` which can be different from `&'static str`

error[E0308]: mismatched types
--> $DIR/return-impl-trait-bad.rs:28:5
Expand All @@ -53,6 +56,7 @@ LL | "don't suggest this, because the generic param is used in the bound."
|
= note: expected type parameter `T`
found reference `&'static str`
= note: the caller chooses a type for `T` which can be different from `&'static str`

error: aborting due to 4 previous errors

Expand Down
2 changes: 2 additions & 0 deletions tests/ui/return/return-impl-trait.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ LL | ()
|
= note: expected type parameter `T`
found unit type `()`
= note: the caller chooses a type for `T` which can be different from `()`

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

error: aborting due to 2 previous errors

Expand Down
21 changes: 21 additions & 0 deletions tests/ui/return/return-ty-mismatch-note.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Checks existence of a note for "a caller chooses ty for ty param" upon return ty mismatch.

fn f<T>() -> (T,) {
(0,) //~ ERROR mismatched types
}

fn g<U, V>() -> (U, V) {
(0, "foo")
//~^ ERROR mismatched types
//~| ERROR mismatched types
}

fn h() -> u8 {
0u8
}

fn main() {
f::<()>();
g::<(), ()>;
let _ = h();
}
36 changes: 36 additions & 0 deletions tests/ui/return/return-ty-mismatch-note.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
error[E0308]: mismatched types
--> $DIR/return-ty-mismatch-note.rs:4:6
|
LL | fn f<T>() -> (T,) {
| - expected this type parameter
LL | (0,)
| ^ expected type parameter `T`, found integer
|
= note: expected type parameter `T`
found type `{integer}`

error[E0308]: mismatched types
--> $DIR/return-ty-mismatch-note.rs:8:6
|
LL | fn g<U, V>() -> (U, V) {
| - expected this type parameter
LL | (0, "foo")
| ^ expected type parameter `U`, found integer
|
= note: expected type parameter `U`
found type `{integer}`

error[E0308]: mismatched types
--> $DIR/return-ty-mismatch-note.rs:8:9
|
LL | fn g<U, V>() -> (U, V) {
| - expected this type parameter
LL | (0, "foo")
| ^^^^^ expected type parameter `V`, found `&str`
|
= note: expected type parameter `V`
found reference `&'static str`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0308`.

0 comments on commit 09c1667

Please sign in to comment.