Note that type param is chosen by caller when suggesting return impl Trait

This commit is contained in:
许杰友 Jieyou Xu (Joe) 2024-03-09 20:32:36 +00:00
parent 22e241e32e
commit cacdf92d37
No known key found for this signature in database
GPG Key ID: 95DDEBD74A1DC2C0
13 changed files with 98 additions and 2 deletions

View File

@ -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}`

View File

@ -11,7 +11,7 @@ use rustc_middle::ty::Ty;
use rustc_span::{
edition::{Edition, LATEST_STABLE_EDITION},
symbol::Ident,
Span,
Span, Symbol,
};
#[derive(Diagnostic)]
@ -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>,
}

View File

@ -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;
}
}
@ -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`

View File

@ -19,6 +19,7 @@ LL | 42
|
= note: expected type parameter `u32`
found type `{integer}`
= note: the caller chooses a type for `u32` which can be different from `i32`
error: aborting due to 2 previous errors

View File

@ -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
@ -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
@ -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
@ -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

View File

@ -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
@ -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

View File

@ -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();
}

View File

@ -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`.

View File

@ -10,6 +10,7 @@ LL | t.clone()
|
= note: expected type parameter `_`
found reference `&_`
= note: the caller chooses a type for `T` which can be different from `&T`
note: `T` does not implement `Clone`, so `&T` was cloned instead
--> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
|

View File

@ -10,6 +10,7 @@ LL | return a.bar();
|
= note: expected type parameter `B`
found associated type `<A as MyTrait>::T`
= note: the caller chooses a type for `B` which can be different from `<A as MyTrait>::T`
help: consider further restricting this bound
|
LL | pub fn foo<A: MyTrait<T = B>, B>(a: A) -> B {

View File

@ -13,6 +13,7 @@ LL | x
found type parameter `Foo`
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
= note: the caller chooses a type for `Bar` which can be different from `Foo`
error: aborting due to 1 previous error

View File

@ -14,6 +14,7 @@ LL | u
found type parameter `X`
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
= note: the caller chooses a type for `Self` which can be different from `X`
error: aborting due to 1 previous error

View File

@ -9,6 +9,7 @@ LL | self.iter()
|
= note: expected type parameter `I`
found struct `std::slice::Iter<'_, N>`
= note: the caller chooses a type for `I` which can be different from `std::slice::Iter<'_, N>`
error[E0599]: no method named `iter` found for reference `&G` in the current scope
--> $DIR/issue-13853.rs:27:23