Skip to content

Commit 155dc35

Browse files
Rollup merge of rust-lang#121416 - veera-sivarajan:bugfix-120785, r=nnethercote
Improve error messages for generics with default parameters Fixes rust-lang#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.
2 parents a74886b + cc13f82 commit 155dc35

File tree

4 files changed

+79
-4
lines changed

4 files changed

+79
-4
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+17-4
Original file line numberDiff line numberDiff line change
@@ -1247,10 +1247,23 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
12471247
(&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
12481248
let did1 = def1.did();
12491249
let did2 = def2.did();
1250-
let sub_no_defaults_1 =
1251-
self.tcx.generics_of(did1).own_args_no_defaults(self.tcx, sub1);
1252-
let sub_no_defaults_2 =
1253-
self.tcx.generics_of(did2).own_args_no_defaults(self.tcx, sub2);
1250+
1251+
let generics1 = self.tcx.generics_of(did1);
1252+
let generics2 = self.tcx.generics_of(did2);
1253+
1254+
let non_default_after_default = generics1
1255+
.check_concrete_type_after_default(self.tcx, sub1)
1256+
|| generics2.check_concrete_type_after_default(self.tcx, sub2);
1257+
let sub_no_defaults_1 = if non_default_after_default {
1258+
generics1.own_args(sub1)
1259+
} else {
1260+
generics1.own_args_no_defaults(self.tcx, sub1)
1261+
};
1262+
let sub_no_defaults_2 = if non_default_after_default {
1263+
generics2.own_args(sub2)
1264+
} else {
1265+
generics2.own_args_no_defaults(self.tcx, sub2)
1266+
};
12541267
let mut values = (DiagStyledString::new(), DiagStyledString::new());
12551268
let path1 = self.tcx.def_path_str(did1);
12561269
let path2 = self.tcx.def_path_str(did2);

compiler/rustc_middle/src/ty/generics.rs

+24
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,30 @@ impl<'tcx> Generics {
360360
let own = &args[self.parent_count..][..self.params.len()];
361361
if self.has_self && self.parent.is_none() { &own[1..] } else { own }
362362
}
363+
364+
/// Returns true if a concrete type is specified after a default type.
365+
/// For example, consider `struct T<W = usize, X = Vec<W>>(W, X)`
366+
/// `T<usize, String>` will return true
367+
/// `T<usize>` will return false
368+
pub fn check_concrete_type_after_default(
369+
&'tcx self,
370+
tcx: TyCtxt<'tcx>,
371+
args: &'tcx [ty::GenericArg<'tcx>],
372+
) -> bool {
373+
let mut default_param_seen = false;
374+
for param in self.params.iter() {
375+
if let Some(inst) =
376+
param.default_value(tcx).map(|default| default.instantiate(tcx, args))
377+
{
378+
if inst == args[param.index as usize] {
379+
default_param_seen = true;
380+
} else if default_param_seen {
381+
return true;
382+
}
383+
}
384+
}
385+
false
386+
}
363387
}
364388

365389
/// Bounds on generics.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
struct What<W = usize, X = Vec<W>>(W, X);
2+
3+
fn main() {
4+
let mut b: What<usize> = What(5, vec![1, 2, 3]);
5+
let c: What<usize, String> = What(1, String::from("meow"));
6+
b = c; //~ ERROR mismatched types
7+
8+
let mut f: What<usize, Vec<String>> = What(1, vec![String::from("meow")]);
9+
let e: What<usize> = What(5, vec![1, 2, 3]);
10+
f = e; //~ ERROR mismatched types
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/clarify-error-for-generics-with-default-issue-120785.rs:6:9
3+
|
4+
LL | let mut b: What<usize> = What(5, vec![1, 2, 3]);
5+
| ----------- expected due to this type
6+
LL | let c: What<usize, String> = What(1, String::from("meow"));
7+
LL | b = c;
8+
| ^ expected `What`, found `What<usize, String>`
9+
|
10+
= note: expected struct `What<_, Vec<usize>>`
11+
found struct `What<_, String>`
12+
13+
error[E0308]: mismatched types
14+
--> $DIR/clarify-error-for-generics-with-default-issue-120785.rs:10:9
15+
|
16+
LL | let mut f: What<usize, Vec<String>> = What(1, vec![String::from("meow")]);
17+
| ------------------------ expected due to this type
18+
LL | let e: What<usize> = What(5, vec![1, 2, 3]);
19+
LL | f = e;
20+
| ^ expected `What<usize, Vec<String>>`, found `What`
21+
|
22+
= note: expected struct `What<_, Vec<String>>`
23+
found struct `What<_, Vec<usize>>`
24+
25+
error: aborting due to 2 previous errors
26+
27+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)