mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-30 16:43:41 +00:00
Improve error messages for generics with default parameters
Fixes #120785
This commit is contained in:
parent
c475e2303b
commit
49961947c8
@ -1247,10 +1247,23 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
(&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
|
||||
let did1 = def1.did();
|
||||
let did2 = def2.did();
|
||||
let sub_no_defaults_1 =
|
||||
self.tcx.generics_of(did1).own_args_no_defaults(self.tcx, sub1);
|
||||
let sub_no_defaults_2 =
|
||||
self.tcx.generics_of(did2).own_args_no_defaults(self.tcx, sub2);
|
||||
|
||||
let generics1 = self.tcx.generics_of(did1);
|
||||
let generics2 = self.tcx.generics_of(did2);
|
||||
|
||||
let non_default_after_default = generics1
|
||||
.check_concrete_type_after_default(self.tcx, sub1)
|
||||
|| generics2.check_concrete_type_after_default(self.tcx, sub2);
|
||||
let sub_no_defaults_1 = if non_default_after_default {
|
||||
generics1.own_args(sub1)
|
||||
} else {
|
||||
generics1.own_args_no_defaults(self.tcx, sub1)
|
||||
};
|
||||
let sub_no_defaults_2 = if non_default_after_default {
|
||||
generics2.own_args(sub2)
|
||||
} else {
|
||||
generics2.own_args_no_defaults(self.tcx, sub2)
|
||||
};
|
||||
let mut values = (DiagStyledString::new(), DiagStyledString::new());
|
||||
let path1 = self.tcx.def_path_str(did1);
|
||||
let path2 = self.tcx.def_path_str(did2);
|
||||
|
@ -360,6 +360,33 @@ impl<'tcx> Generics {
|
||||
let own = &args[self.parent_count..][..self.params.len()];
|
||||
if self.has_self && self.parent.is_none() { &own[1..] } else { own }
|
||||
}
|
||||
|
||||
/// Returns true if a concrete type is specified after a default type.
|
||||
/// For example, consider `struct T<W = usize, X = Vec<W>>(W, X)`
|
||||
/// `T<usize, String>` will return true
|
||||
/// `T<usize>` will return false
|
||||
pub fn check_concrete_type_after_default(
|
||||
&'tcx self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
args: &'tcx [ty::GenericArg<'tcx>],
|
||||
) -> bool {
|
||||
let mut default_param_seen = false;
|
||||
for param in self.params.iter() {
|
||||
if param
|
||||
.default_value(tcx)
|
||||
.is_some_and(|default| default.instantiate(tcx, args) == args[param.index as usize])
|
||||
{
|
||||
default_param_seen = true;
|
||||
} else if default_param_seen
|
||||
&& param.default_value(tcx).is_some_and(|default| {
|
||||
default.instantiate(tcx, args) != args[param.index as usize]
|
||||
})
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Bounds on generics.
|
||||
|
@ -0,0 +1,11 @@
|
||||
struct What<W = usize, X = Vec<W>>(W, X);
|
||||
|
||||
fn main() {
|
||||
let mut b: What<usize> = What(5, vec![1, 2, 3]);
|
||||
let c: What<usize, String> = What(1, String::from("meow"));
|
||||
b = c; //~ ERROR mismatched types
|
||||
|
||||
let mut e: What<usize> = What(5, vec![1, 2, 3]);
|
||||
let f: What<usize, Vec<String>> = What(1, vec![String::from("meow")]);
|
||||
e = f; //~ ERROR mismatched types
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/clarify-error-for-generics-with-default-issue-120785.rs:6:9
|
||||
|
|
||||
LL | let mut b: What<usize> = What(5, vec![1, 2, 3]);
|
||||
| ----------- expected due to this type
|
||||
LL | let c: What<usize, String> = What(1, String::from("meow"));
|
||||
LL | b = c;
|
||||
| ^ expected `What`, found `What<usize, String>`
|
||||
|
|
||||
= note: expected struct `What<_, Vec<usize>>`
|
||||
found struct `What<_, String>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/clarify-error-for-generics-with-default-issue-120785.rs:10:9
|
||||
|
|
||||
LL | let mut e: What<usize> = What(5, vec![1, 2, 3]);
|
||||
| ----------- expected due to this type
|
||||
LL | let f: What<usize, Vec<String>> = What(1, vec![String::from("meow")]);
|
||||
LL | e = f;
|
||||
| ^ expected `What`, found `What<usize, Vec<String>>`
|
||||
|
|
||||
= note: expected struct `What<_, Vec<usize>>`
|
||||
found struct `What<_, Vec<String>>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user