diagnostics: avoid mismatch between variance index and hir generic
This happens because variances are constructed from ty generics, and ty generics are always constructed with lifetimes first. See compiler/rustc_hir_analysis/src/collect/generics_of.rs:248-269 Fixes #83556
This commit is contained in:
parent
b3aa8e7168
commit
3799af3337
@ -1755,6 +1755,8 @@ fn check_variances_for_type_defn<'tcx>(
|
||||
.collect::<FxHashSet<_>>()
|
||||
});
|
||||
|
||||
let ty_generics = tcx.generics_of(item.owner_id);
|
||||
|
||||
for (index, _) in variances.iter().enumerate() {
|
||||
let parameter = Parameter(index as u32);
|
||||
|
||||
@ -1762,13 +1764,32 @@ fn check_variances_for_type_defn<'tcx>(
|
||||
continue;
|
||||
}
|
||||
|
||||
let param = &hir_generics.params[index];
|
||||
let ty_param = &ty_generics.params[index];
|
||||
let mut hir_param = &hir_generics.params[index];
|
||||
|
||||
match param.name {
|
||||
if ty_param.name != hir_param.name.ident().name {
|
||||
// valid programs always have lifetimes before types in the generic parameter list
|
||||
// ty_generics are normalized to be in this required order, and variances are built
|
||||
// from ty generics, not from hir generics. but we need hir generics to get
|
||||
// a span out
|
||||
//
|
||||
// if they aren't in the same order, then the user has written invalid code, and already
|
||||
// got an error about it (or I'm wrong about this)
|
||||
tcx.sess
|
||||
.delay_span_bug(hir_param.span, "hir generics and ty generics in different order");
|
||||
for hp in hir_generics.params {
|
||||
if hp.name.ident().name == ty_param.name {
|
||||
hir_param = hp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match hir_param.name {
|
||||
hir::ParamName::Error => {}
|
||||
_ => {
|
||||
let has_explicit_bounds = explicitly_bounded_params.contains(¶meter);
|
||||
report_bivariance(tcx, param, has_explicit_bounds);
|
||||
report_bivariance(tcx, hir_param, has_explicit_bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
5
tests/ui/generics/issue-83556.rs
Normal file
5
tests/ui/generics/issue-83556.rs
Normal file
@ -0,0 +1,5 @@
|
||||
struct Foo<T, 'a>(&'a ());
|
||||
//~^ ERROR lifetime parameters must be declared prior to
|
||||
//~| ERROR parameter `T` is never used
|
||||
|
||||
fn main() {}
|
18
tests/ui/generics/issue-83556.stderr
Normal file
18
tests/ui/generics/issue-83556.stderr
Normal file
@ -0,0 +1,18 @@
|
||||
error: lifetime parameters must be declared prior to type and const parameters
|
||||
--> $DIR/issue-83556.rs:1:15
|
||||
|
|
||||
LL | struct Foo<T, 'a>(&'a ());
|
||||
| ----^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T>`
|
||||
|
||||
error[E0392]: parameter `T` is never used
|
||||
--> $DIR/issue-83556.rs:1:12
|
||||
|
|
||||
LL | struct Foo<T, 'a>(&'a ());
|
||||
| ^ unused parameter
|
||||
|
|
||||
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
|
||||
= help: if you intended `T` to be a const parameter, use `const T: usize` instead
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0392`.
|
Loading…
x
Reference in New Issue
Block a user