Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b80c1ae

Browse files
committedJun 7, 2024·
Use the error variance for unused generic args
1 parent 9a97790 commit b80c1ae

18 files changed

+146
-71
lines changed
 

Diff for: ‎compiler/rustc_hir_analysis/src/check/wfcheck.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -1802,8 +1802,8 @@ fn receiver_is_implemented<'tcx>(
18021802
pub fn check_variances_for_type_defn<'tcx>(
18031803
tcx: TyCtxt<'tcx>,
18041804
item: LocalDefId,
1805-
variances: &[ty::Variance],
1806-
) -> Result<(), ErrorGuaranteed> {
1805+
variances: &'tcx [ty::Variance],
1806+
) -> Result<&'tcx [ty::Variance], ErrorGuaranteed> {
18071807
let identity_args = ty::GenericArgs::identity_for_item(tcx, item);
18081808

18091809
match tcx.def_kind(item) {
@@ -1819,7 +1819,7 @@ pub fn check_variances_for_type_defn<'tcx>(
18191819
);
18201820
tcx.type_of(item).skip_binder().error_reported()?;
18211821
}
1822-
_ => return Ok(()),
1822+
_ => return Ok(variances),
18231823
}
18241824

18251825
let ty_predicates = tcx.predicates_of(item);
@@ -1856,7 +1856,7 @@ pub fn check_variances_for_type_defn<'tcx>(
18561856

18571857
let ty_generics = tcx.generics_of(item);
18581858

1859-
let mut res = Ok(());
1859+
let mut variances = variances;
18601860

18611861
for (index, _) in variances.iter().enumerate() {
18621862
let parameter = Parameter(index as u32);
@@ -1868,30 +1868,30 @@ pub fn check_variances_for_type_defn<'tcx>(
18681868
let ty_param = &ty_generics.own_params[index];
18691869
let hir_param = &hir_generics.params[index];
18701870

1871-
if ty_param.def_id != hir_param.def_id.into() {
1871+
let guar = if ty_param.def_id != hir_param.def_id.into() {
18721872
// Valid programs always have lifetimes before types in the generic parameter list.
18731873
// ty_generics are normalized to be in this required order, and variances are built
18741874
// from ty generics, not from hir generics. but we need hir generics to get
18751875
// a span out.
18761876
//
18771877
// If they aren't in the same order, then the user has written invalid code, and already
18781878
// got an error about it (or I'm wrong about this).
1879-
tcx.dcx().span_delayed_bug(
1880-
hir_param.span,
1881-
"hir generics and ty generics in different order",
1882-
);
1883-
continue;
1884-
}
1885-
1886-
match hir_param.name {
1887-
hir::ParamName::Error(guar) => res = Err(guar),
1888-
_ => {
1889-
let has_explicit_bounds = explicitly_bounded_params.contains(&parameter);
1890-
res = Err(report_bivariance(tcx, hir_param, has_explicit_bounds, item));
1879+
tcx.dcx()
1880+
.span_delayed_bug(hir_param.span, "hir generics and ty generics in different order")
1881+
} else {
1882+
match hir_param.name {
1883+
hir::ParamName::Error(guar) => guar,
1884+
_ => {
1885+
let has_explicit_bounds = explicitly_bounded_params.contains(&parameter);
1886+
report_bivariance(tcx, hir_param, has_explicit_bounds, item)
1887+
}
18911888
}
1892-
}
1889+
};
1890+
let mut v = variances.to_vec();
1891+
v[index] = ty::Variance::Errvariant(guar);
1892+
variances = tcx.arena.alloc_slice(&v);
18931893
}
1894-
res
1894+
Ok(variances)
18951895
}
18961896

18971897
fn report_bivariance(

Diff for: ‎compiler/rustc_hir_analysis/src/variance/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
7272
}
7373
};
7474

75-
let _ = crate::check::wfcheck::check_variances_for_type_defn(tcx, item_def_id, variances);
76-
variances
75+
match crate::check::wfcheck::check_variances_for_type_defn(tcx, item_def_id, variances) {
76+
Ok(variances) => variances,
77+
Err(guar) => tcx.arena.alloc_from_iter(variances.iter().map(|_| ty::Errvariant(guar))),
78+
}
7779
}
7880

7981
#[instrument(level = "trace", skip(tcx), ret)]

Diff for: ‎compiler/rustc_infer/src/infer/relate/generalize.rs

+5
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,11 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
501501
// `Generalization`.
502502
ty::Bivariant => self.has_unconstrained_ty_var = true,
503503

504+
ty::Errvariant(guar) => {
505+
self.infcx.set_tainted_by_errors(guar);
506+
return Ok(Ty::new_error(self.tcx(), guar));
507+
}
508+
504509
// Co/contravariant: this will be
505510
// sufficiently constrained later on.
506511
ty::Covariant | ty::Contravariant => (),

Diff for: ‎compiler/rustc_infer/src/infer/relate/glb.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
4040
match variance {
4141
ty::Invariant => self.fields.equate(StructurallyRelateAliases::No).relate(a, b),
4242
ty::Covariant => self.relate(a, b),
43-
// TODO: report a new error kind
44-
ty::Errvariant(_) => Ok(a),
43+
ty::Errvariant(guar) => {
44+
self.fields.infcx.set_tainted_by_errors(guar);
45+
Ok(a)
46+
}
4547
// FIXME(#41044) -- not correct, need test
4648
ty::Bivariant => Ok(a),
4749
ty::Contravariant => self.fields.lub().relate(a, b),

Diff for: ‎compiler/rustc_infer/src/infer/relate/lub.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
4040
match variance {
4141
ty::Invariant => self.fields.equate(StructurallyRelateAliases::No).relate(a, b),
4242
ty::Covariant => self.relate(a, b),
43-
// TODO: report a new kind of type error that preserves the `ErrorGuaranteed`?
44-
ty::Errvariant(_) => Ok(a),
43+
ty::Errvariant(guar) => {
44+
self.fields.infcx.set_tainted_by_errors(guar);
45+
Ok(a)
46+
}
4547
// FIXME(#41044) -- not correct, need test
4648
ty::Bivariant => Ok(a),
4749
ty::Contravariant => self.fields.glb().relate(a, b),

Diff for: ‎compiler/rustc_infer/src/infer/relate/type_relating.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,11 @@ impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
117117
ty::Invariant => {
118118
infcx.inner.borrow_mut().type_variables().equate(a_id, b_id);
119119
}
120-
ty::Errvariant(_) | ty::Bivariant => {
120+
ty::Errvariant(guar) => {
121+
infcx.set_tainted_by_errors(guar);
122+
return Ok(Ty::new_error(self.tcx(), guar));
123+
}
124+
ty::Bivariant => {
121125
unreachable!("Expected bivariance to be handled in relate_with_variance")
122126
}
123127
}
@@ -204,7 +208,11 @@ impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
204208
.unwrap_region_constraints()
205209
.make_eqregion(origin, a, b);
206210
}
207-
ty::Errvariant(_) | ty::Bivariant => {
211+
ty::Errvariant(guar) => {
212+
self.fields.infcx.set_tainted_by_errors(guar);
213+
return Ok(ty::Region::new_error(self.tcx(), guar));
214+
}
215+
ty::Bivariant => {
208216
unreachable!("Expected bivariance to be handled in relate_with_variance")
209217
}
210218
}
@@ -289,15 +297,15 @@ impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
289297
self.relate(a, b)
290298
})?;
291299
}
292-
ty::Errvariant(_) | ty::Bivariant => {
293-
unreachable!("Expected bivariance to be handled in relate_with_variance")
294-
}
295-
}
296300
ty::Errvariant(guar) => {
297301
infcx.set_tainted_by_errors(guar);
298302
return self.relate(a, b);
299303
}
300304
ty::Bivariant => {
305+
unreachable!("Expected bivariance to be handled in relate_with_variance")
306+
}
307+
}
308+
}
301309

302310
Ok(a)
303311
}
@@ -345,13 +353,13 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
345353
b.into(),
346354
ty::AliasRelationDirection::Equate,
347355
),
348-
ty::Variance::Errvariant(_) | ty::Variance::Bivariant => {
349-
unreachable!("Expected bivariance to be handled in relate_with_variance")
350-
}
351-
})]);
352356
ty::Variance::Errvariant(guar) => {
353357
self.fields.infcx.set_tainted_by_errors(guar);
354358
ty::PredicateKind::Ambiguous
355359
}
356360
ty::Variance::Bivariant => {
361+
unreachable!("Expected bivariance to be handled in relate_with_variance")
362+
}
363+
})]);
364+
}
357365
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
struct Fail<T>;
2+
//~^ ERROR: type parameter `T` is never used
3+
4+
impl Fail<i32> {
5+
const C: () = ();
6+
}
7+
8+
fn main() {
9+
Fail::<()>::C
10+
//~^ ERROR: no associated item named `C` found for struct `Fail<()>`
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0392]: type parameter `T` is never used
2+
--> $DIR/wrong-projection-self-ty-on-invalid-type.rs:1:13
3+
|
4+
LL | struct Fail<T>;
5+
| ^ unused type parameter
6+
|
7+
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
8+
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
9+
10+
error[E0599]: no associated item named `C` found for struct `Fail<()>` in the current scope
11+
--> $DIR/wrong-projection-self-ty-on-invalid-type.rs:9:17
12+
|
13+
LL | struct Fail<T>;
14+
| -------------- associated item `C` not found for this struct
15+
...
16+
LL | Fail::<()>::C
17+
| ^ associated item not found in `Fail<()>`
18+
|
19+
= note: the associated item was found for
20+
- `Fail<i32>`
21+
22+
error: aborting due to 2 previous errors
23+
24+
Some errors have detailed explanations: E0392, E0599.
25+
For more information about an error, try `rustc --explain E0392`.

Diff for: ‎tests/ui/inference/dont-collect-stmts-from-parent-body.rs

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ fn main() {
88
impl<T> Type<T> {
99
fn new() -> Type<T> {
1010
Type
11-
//~^ ERROR type annotations needed
1211
}
1312
}
1413
};

Diff for: ‎tests/ui/inference/dont-collect-stmts-from-parent-body.stderr

+2-14
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,6 @@ LL | struct Type<T>;
77
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
88
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
99

10-
error[E0282]: type annotations needed
11-
--> $DIR/dont-collect-stmts-from-parent-body.rs:10:17
12-
|
13-
LL | Type
14-
| ^^^^ cannot infer type of the type parameter `T` declared on the struct `Type`
15-
|
16-
help: consider specifying the generic argument
17-
|
18-
LL | Type::<T>
19-
| +++++
20-
21-
error: aborting due to 2 previous errors
10+
error: aborting due to 1 previous error
2211

23-
Some errors have detailed explanations: E0282, E0392.
24-
For more information about an error, try `rustc --explain E0282`.
12+
For more information about this error, try `rustc --explain E0392`.

Diff for: ‎tests/ui/traits/trait-selection-ice-84727.rs

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ where
2020
{
2121
fn over(self) -> Cell<NewFg> {
2222
//~^ ERROR mismatched types
23+
//~| ERROR `over` has an incompatible type for trait
2324
self.over();
2425
}
2526
}

Diff for: ‎tests/ui/traits/trait-selection-ice-84727.stderr

+29-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ LL | Self: Over<Color<BottomBg>, Cell<NewFg>>,
1717
| ^^^^^ not found in this scope
1818

1919
error[E0412]: cannot find type `NewBg` in this scope
20-
--> $DIR/trait-selection-ice-84727.rs:32:27
20+
--> $DIR/trait-selection-ice-84727.rs:33:27
2121
|
2222
LL | fn over(self) -> Cell<NewBg> {
2323
| ^^^^^ not found in this scope
@@ -27,21 +27,45 @@ help: you might be missing a type parameter
2727
LL | impl<'b, TopFg, TopBg, BottomFg, BottomBg, NewBg> Over<&Cell<BottomFg, BottomBg>, ()>
2828
| +++++++
2929

30+
error[E0053]: method `over` has an incompatible type for trait
31+
--> $DIR/trait-selection-ice-84727.rs:21:22
32+
|
33+
LL | impl<TopFg, TopBg, BottomFg, BottomBg, NewFg, NewBg>
34+
| ----- ----- expected type parameter
35+
| |
36+
| found type parameter
37+
...
38+
LL | fn over(self) -> Cell<NewFg> {
39+
| ^^^^^^^^^^^
40+
| |
41+
| expected type parameter `NewBg`, found type parameter `NewFg`
42+
| help: change the output type to match the trait: `Cell<NewFg, NewBg>`
43+
|
44+
note: type in trait
45+
--> $DIR/trait-selection-ice-84727.rs:12:22
46+
|
47+
LL | fn over(self) -> Output;
48+
| ^^^^^^
49+
= note: expected signature `fn(Cell<_, _>) -> Cell<_, NewBg>`
50+
found signature `fn(Cell<_, _>) -> Cell<_, NewFg>`
51+
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
52+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
53+
3054
error[E0308]: mismatched types
3155
--> $DIR/trait-selection-ice-84727.rs:21:22
3256
|
3357
LL | fn over(self) -> Cell<NewFg> {
3458
| ---- ^^^^^^^^^^^ expected `Cell<NewFg>`, found `()`
3559
| |
3660
| implicitly returns `()` as its body has no tail or `return` expression
37-
LL |
61+
...
3862
LL | self.over();
3963
| - help: remove this semicolon to return this value
4064
|
4165
= note: expected struct `Cell<NewFg>`
4266
found unit type `()`
4367

44-
error: aborting due to 5 previous errors
68+
error: aborting due to 6 previous errors
4569

46-
Some errors have detailed explanations: E0308, E0412.
47-
For more information about an error, try `rustc --explain E0308`.
70+
Some errors have detailed explanations: E0053, E0308, E0412.
71+
For more information about an error, try `rustc --explain E0053`.

Diff for: ‎tests/ui/variance/variance-regions-direct.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ struct Test6<'a, 'b:'a> { //~ ERROR [+, o]
4949
// No uses at all is bivariant:
5050

5151
#[rustc_variance]
52-
struct Test7<'a> { //~ ERROR [*]
52+
struct Test7<'a> {
53+
//~ ERROR [{error}]
5354
//~^ ERROR: `'a` is never used
5455
x: isize
5556
}

Diff for: ‎tests/ui/variance/variance-regions-direct.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ error: [+, o]
3636
LL | struct Test6<'a, 'b:'a> {
3737
| ^^^^^^^^^^^^^^^^^^^^^^^
3838

39-
error: [*]
39+
error: [💥]
4040
--> $DIR/variance-regions-direct.rs:52:1
4141
|
4242
LL | struct Test7<'a> {

Diff for: ‎tests/ui/variance/variance-regions-indirect.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,31 @@
55
#![feature(rustc_attrs)]
66

77
#[rustc_variance]
8-
enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *]
8+
enum Base<'a, 'b, 'c: 'b, 'd> {
9+
//~ ERROR [-, +, o, {error}]
910
//~^ ERROR: `'d` is never used
1011
Test8A(extern "Rust" fn(&'a isize)),
1112
Test8B(&'b [isize]),
1213
Test8C(&'b mut &'c str),
1314
}
1415

1516
#[rustc_variance]
16-
struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR [*, o, +, -]
17+
struct Derived1<'w, 'x: 'y, 'y, 'z> {
18+
//~ ERROR [{error}, o, +, -]
1719
//~^ ERROR: `'w` is never used
1820
f: Base<'z, 'y, 'x, 'w>
1921
}
2022

2123
#[rustc_variance] // Combine - and + to yield o
22-
struct Derived2<'a, 'b:'a, 'c> { //~ ERROR [o, o, *]
24+
struct Derived2<'a, 'b: 'a, 'c> {
25+
//~ ERROR [o, o, {error}]
2326
//~^ ERROR: `'c` is never used
2427
f: Base<'a, 'a, 'b, 'c>
2528
}
2629

2730
#[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here)
28-
struct Derived3<'a:'b, 'b, 'c> { //~ ERROR [o, +, *]
31+
struct Derived3<'a: 'b, 'b, 'c> {
32+
//~ ERROR [o, +, {error}]
2933
//~^ ERROR: `'c` is never used
3034
f: Base<'a, 'b, 'a, 'c>
3135
}

Diff for: ‎tests/ui/variance/variance-regions-indirect.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,25 @@ LL | struct Derived3<'a:'b, 'b, 'c> {
3030
|
3131
= help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData`
3232

33-
error: [-, +, o, *]
33+
error: [-, +, o, 💥]
3434
--> $DIR/variance-regions-indirect.rs:8:1
3535
|
3636
LL | enum Base<'a, 'b, 'c:'b, 'd> {
3737
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3838

39-
error: [*, o, +, -]
39+
error: [💥, o, +, -]
4040
--> $DIR/variance-regions-indirect.rs:16:1
4141
|
4242
LL | struct Derived1<'w, 'x:'y, 'y, 'z> {
4343
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4444

45-
error: [o, o, *]
45+
error: [o, o, 💥]
4646
--> $DIR/variance-regions-indirect.rs:22:1
4747
|
4848
LL | struct Derived2<'a, 'b:'a, 'c> {
4949
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5050

51-
error: [o, +, *]
51+
error: [o, +, 💥]
5252
--> $DIR/variance-regions-indirect.rs:28:1
5353
|
5454
LL | struct Derived3<'a:'b, 'b, 'c> {

Diff for: ‎tests/ui/variance/variance-trait-bounds.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,22 @@ struct TestStruct<U,T:Setter<U>> { //~ ERROR [+, +]
1818
}
1919

2020
#[rustc_variance]
21-
enum TestEnum<U,T:Setter<U>> { //~ ERROR [*, +]
21+
enum TestEnum<U, T: Setter<U>> {
22+
//~ ERROR [{error}, +]
2223
//~^ ERROR: `U` is never used
2324
Foo(T)
2425
}
2526

2627
#[rustc_variance]
27-
struct TestContraStruct<U,T:Setter<U>> { //~ ERROR [*, +]
28+
struct TestContraStruct<U, T: Setter<U>> {
29+
//~ ERROR [{error}, +]
2830
//~^ ERROR: `U` is never used
2931
t: T
3032
}
3133

3234
#[rustc_variance]
33-
struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR [*, +]
35+
struct TestBox<U, T: Getter<U> + Setter<U>> {
36+
//~ ERROR [{error}, +]
3437
//~^ ERROR: `U` is never used
3538
t: T
3639
}

Diff for: ‎tests/ui/variance/variance-trait-bounds.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,19 @@ error: [+, +]
3131
LL | struct TestStruct<U,T:Setter<U>> {
3232
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3333

34-
error: [*, +]
34+
error: [💥, +]
3535
--> $DIR/variance-trait-bounds.rs:21:1
3636
|
3737
LL | enum TestEnum<U,T:Setter<U>> {
3838
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3939

40-
error: [*, +]
40+
error: [💥, +]
4141
--> $DIR/variance-trait-bounds.rs:27:1
4242
|
4343
LL | struct TestContraStruct<U,T:Setter<U>> {
4444
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4545

46-
error: [*, +]
46+
error: [💥, +]
4747
--> $DIR/variance-trait-bounds.rs:33:1
4848
|
4949
LL | struct TestBox<U,T:Getter<U>+Setter<U>> {

0 commit comments

Comments
 (0)
Please sign in to comment.