Skip to content

Commit 2b874f0

Browse files
authored
Rollup merge of #89829 - voidc:assoc-const-variance, r=lcnr
Consider types appearing in const expressions to be invariant This is an approach to fix #80977. Currently, a type parameter which is only used in a constant expression is considered bivariant and will trigger error E0392 *"parameter T is never used"*. Here is a short example: ```rust pub trait Foo { const N: usize; } struct Bar<T: Foo>([u8; T::N]) where [(); T::N]:; ``` ([playgound](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2015&gist=b51a272853f75925e72efc1597478aa5)) While it is possible to silence this error by adding a `PhantomData<T>` field, I think the better solution would be to make `T` invariant. This would be analogous to the invariance constraints added for associated types. However, I'm quite new to the compiler and unsure whether this is the right approach. r? ``@varkor`` (since you authored #60058)
2 parents 17c602d + a400f10 commit 2b874f0

File tree

7 files changed

+57
-30
lines changed

7 files changed

+57
-30
lines changed

compiler/rustc_typeck/src/variance/constraints.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
223223
self.add_constraints_from_region(current, lt, variance_i)
224224
}
225225
GenericArgKind::Type(ty) => self.add_constraints_from_ty(current, ty, variance_i),
226-
GenericArgKind::Const(_) => {
227-
// Consts impose no constraints.
226+
GenericArgKind::Const(val) => {
227+
self.add_constraints_from_const(current, val, variance_i)
228228
}
229229
}
230230
}
@@ -263,7 +263,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
263263
self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance);
264264
}
265265

266-
ty::Array(typ, _) => {
266+
ty::Array(typ, len) => {
267+
self.add_constraints_from_const(current, len, variance);
267268
self.add_constraints_from_ty(current, typ, variance);
268269
}
269270

@@ -385,13 +386,32 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
385386
self.add_constraints_from_region(current, lt, variance_i)
386387
}
387388
GenericArgKind::Type(ty) => self.add_constraints_from_ty(current, ty, variance_i),
388-
GenericArgKind::Const(_) => {
389-
// Consts impose no constraints.
389+
GenericArgKind::Const(val) => {
390+
self.add_constraints_from_const(current, val, variance)
390391
}
391392
}
392393
}
393394
}
394395

396+
/// Adds constraints appropriate for a const expression `val`
397+
/// in a context with ambient variance `variance`
398+
fn add_constraints_from_const(
399+
&mut self,
400+
current: &CurrentItem,
401+
val: &ty::Const<'tcx>,
402+
variance: VarianceTermPtr<'a>,
403+
) {
404+
debug!("add_constraints_from_const(val={:?}, variance={:?})", val, variance);
405+
406+
match &val.val {
407+
ty::ConstKind::Unevaluated(uv) => {
408+
let substs = uv.substs(self.tcx());
409+
self.add_constraints_from_invariant_substs(current, substs, variance);
410+
}
411+
_ => {}
412+
}
413+
}
414+
395415
/// Adds constraints appropriate for a function with signature
396416
/// `sig` appearing in a context with ambient variance `variance`
397417
fn add_constraints_from_sig(

src/test/ui/const-generics/issues/issue-67375.full.stderr

+1-11
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,5 @@ LL | inner: [(); { [|_: &T| {}; 0].len() }],
88
|
99
= help: consider moving this anonymous constant into a `const` function
1010

11-
error[E0392]: parameter `T` is never used
12-
--> $DIR/issue-67375.rs:5:12
13-
|
14-
LL | struct Bug<T> {
15-
| ^ unused parameter
16-
|
17-
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
18-
= help: if you intended `T` to be a const parameter, use `const T: usize` instead
19-
20-
error: aborting due to 2 previous errors
11+
error: aborting due to previous error
2112

22-
For more information about this error, try `rustc --explain E0392`.

src/test/ui/const-generics/issues/issue-67375.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![cfg_attr(full, feature(generic_const_exprs))]
44

55
struct Bug<T> {
6-
//~^ ERROR parameter `T` is never used
6+
//[min]~^ ERROR parameter `T` is never used
77
inner: [(); { [|_: &T| {}; 0].len() }],
88
//[min]~^ ERROR generic parameters may not be used in const operations
99
//[full]~^^ ERROR overly complex generic constant

src/test/ui/const-generics/issues/issue-67945-1.full.stderr

+2-12
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,6 @@ LL | let x: S = MaybeUninit::uninit();
1212
= note: expected type parameter `S`
1313
found union `MaybeUninit<_>`
1414

15-
error[E0392]: parameter `S` is never used
16-
--> $DIR/issue-67945-1.rs:7:12
17-
|
18-
LL | struct Bug<S> {
19-
| ^ unused parameter
20-
|
21-
= help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
22-
= help: if you intended `S` to be a const parameter, use `const S: usize` instead
23-
24-
error: aborting due to 2 previous errors
15+
error: aborting due to previous error
2516

26-
Some errors have detailed explanations: E0308, E0392.
27-
For more information about an error, try `rustc --explain E0308`.
17+
For more information about this error, try `rustc --explain E0308`.

src/test/ui/const-generics/issues/issue-67945-1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use std::mem::MaybeUninit;
66

77
struct Bug<S> {
8-
//~^ ERROR parameter `S` is never used
8+
//[min]~^ ERROR parameter `S` is never used
99
A: [(); {
1010
let x: S = MaybeUninit::uninit();
1111
//[min]~^ ERROR generic parameters may not be used in const operations
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Test that the variance computation considers types that
2+
// appear in const expressions to be invariant.
3+
4+
#![feature(rustc_attrs)]
5+
#![allow(incomplete_features)]
6+
#![feature(generic_const_exprs)]
7+
8+
trait Trait {
9+
const Const: usize;
10+
}
11+
12+
#[rustc_variance]
13+
struct Foo<T: Trait> { //~ ERROR [o]
14+
field: [u8; <T as Trait>::Const]
15+
}
16+
17+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error[E0208]: [o]
2+
--> $DIR/variance-associated-consts.rs:13:1
3+
|
4+
LL | / struct Foo<T: Trait> {
5+
LL | | field: [u8; <T as Trait>::Const]
6+
LL | | }
7+
| |_^
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)