mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 19:58:32 +00:00
Rollup merge of #121416 - veera-sivarajan:bugfix-120785, r=nnethercote
Improve error messages for generics with default parameters Fixes #120785 Issue: Previously, all type parameters with default types were deliberately ignored to simplify error messages. For example, an error message for Box type would display `Box<T>` instead of `Box<T, _>`. But, this resulted in unclear error message when a concrete type was used instead of the default type. Fix: This PR fixes it by checking if a concrete type is specified after a default type to display the entire type name or the simplified type name.
This commit is contained in:
commit
f23c6ddada
@ -1247,10 +1247,23 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
(&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
|
(&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
|
||||||
let did1 = def1.did();
|
let did1 = def1.did();
|
||||||
let did2 = def2.did();
|
let did2 = def2.did();
|
||||||
let sub_no_defaults_1 =
|
|
||||||
self.tcx.generics_of(did1).own_args_no_defaults(self.tcx, sub1);
|
let generics1 = self.tcx.generics_of(did1);
|
||||||
let sub_no_defaults_2 =
|
let generics2 = self.tcx.generics_of(did2);
|
||||||
self.tcx.generics_of(did2).own_args_no_defaults(self.tcx, sub2);
|
|
||||||
|
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 mut values = (DiagStyledString::new(), DiagStyledString::new());
|
||||||
let path1 = self.tcx.def_path_str(did1);
|
let path1 = self.tcx.def_path_str(did1);
|
||||||
let path2 = self.tcx.def_path_str(did2);
|
let path2 = self.tcx.def_path_str(did2);
|
||||||
|
@ -360,6 +360,30 @@ impl<'tcx> Generics {
|
|||||||
let own = &args[self.parent_count..][..self.params.len()];
|
let own = &args[self.parent_count..][..self.params.len()];
|
||||||
if self.has_self && self.parent.is_none() { &own[1..] } else { own }
|
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 let Some(inst) =
|
||||||
|
param.default_value(tcx).map(|default| default.instantiate(tcx, args))
|
||||||
|
{
|
||||||
|
if inst == args[param.index as usize] {
|
||||||
|
default_param_seen = true;
|
||||||
|
} else if default_param_seen {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bounds on generics.
|
/// 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 f: What<usize, Vec<String>> = What(1, vec![String::from("meow")]);
|
||||||
|
let e: What<usize> = What(5, vec![1, 2, 3]);
|
||||||
|
f = e; //~ 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 f: What<usize, Vec<String>> = What(1, vec![String::from("meow")]);
|
||||||
|
| ------------------------ expected due to this type
|
||||||
|
LL | let e: What<usize> = What(5, vec![1, 2, 3]);
|
||||||
|
LL | f = e;
|
||||||
|
| ^ expected `What<usize, Vec<String>>`, found `What`
|
||||||
|
|
|
||||||
|
= note: expected struct `What<_, Vec<String>>`
|
||||||
|
found struct `What<_, Vec<usize>>`
|
||||||
|
|
||||||
|
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