Skip to content

Commit

Permalink
Rollup merge of #89829 - voidc:assoc-const-variance, r=lcnr
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
matthiaskrgr committed Oct 23, 2021
2 parents 17c602d + a400f10 commit 2b874f0
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 30 deletions.
30 changes: 25 additions & 5 deletions compiler/rustc_typeck/src/variance/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
self.add_constraints_from_region(current, lt, variance_i)
}
GenericArgKind::Type(ty) => self.add_constraints_from_ty(current, ty, variance_i),
GenericArgKind::Const(_) => {
// Consts impose no constraints.
GenericArgKind::Const(val) => {
self.add_constraints_from_const(current, val, variance_i)
}
}
}
Expand Down Expand Up @@ -263,7 +263,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance);
}

ty::Array(typ, _) => {
ty::Array(typ, len) => {
self.add_constraints_from_const(current, len, variance);
self.add_constraints_from_ty(current, typ, variance);
}

Expand Down Expand Up @@ -385,13 +386,32 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
self.add_constraints_from_region(current, lt, variance_i)
}
GenericArgKind::Type(ty) => self.add_constraints_from_ty(current, ty, variance_i),
GenericArgKind::Const(_) => {
// Consts impose no constraints.
GenericArgKind::Const(val) => {
self.add_constraints_from_const(current, val, variance)
}
}
}
}

/// Adds constraints appropriate for a const expression `val`
/// in a context with ambient variance `variance`
fn add_constraints_from_const(
&mut self,
current: &CurrentItem,
val: &ty::Const<'tcx>,
variance: VarianceTermPtr<'a>,
) {
debug!("add_constraints_from_const(val={:?}, variance={:?})", val, variance);

match &val.val {
ty::ConstKind::Unevaluated(uv) => {
let substs = uv.substs(self.tcx());
self.add_constraints_from_invariant_substs(current, substs, variance);
}
_ => {}
}
}

/// Adds constraints appropriate for a function with signature
/// `sig` appearing in a context with ambient variance `variance`
fn add_constraints_from_sig(
Expand Down
12 changes: 1 addition & 11 deletions src/test/ui/const-generics/issues/issue-67375.full.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,5 @@ LL | inner: [(); { [|_: &T| {}; 0].len() }],
|
= help: consider moving this anonymous constant into a `const` function

error[E0392]: parameter `T` is never used
--> $DIR/issue-67375.rs:5:12
|
LL | struct Bug<T> {
| ^ 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
error: aborting due to previous error

For more information about this error, try `rustc --explain E0392`.
2 changes: 1 addition & 1 deletion src/test/ui/const-generics/issues/issue-67375.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#![cfg_attr(full, feature(generic_const_exprs))]

struct Bug<T> {
//~^ ERROR parameter `T` is never used
//[min]~^ ERROR parameter `T` is never used
inner: [(); { [|_: &T| {}; 0].len() }],
//[min]~^ ERROR generic parameters may not be used in const operations
//[full]~^^ ERROR overly complex generic constant
Expand Down
14 changes: 2 additions & 12 deletions src/test/ui/const-generics/issues/issue-67945-1.full.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,6 @@ LL | let x: S = MaybeUninit::uninit();
= note: expected type parameter `S`
found union `MaybeUninit<_>`

error[E0392]: parameter `S` is never used
--> $DIR/issue-67945-1.rs:7:12
|
LL | struct Bug<S> {
| ^ unused parameter
|
= help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
= help: if you intended `S` to be a const parameter, use `const S: usize` instead

error: aborting due to 2 previous errors
error: aborting due to previous error

Some errors have detailed explanations: E0308, E0392.
For more information about an error, try `rustc --explain E0308`.
For more information about this error, try `rustc --explain E0308`.
2 changes: 1 addition & 1 deletion src/test/ui/const-generics/issues/issue-67945-1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use std::mem::MaybeUninit;

struct Bug<S> {
//~^ ERROR parameter `S` is never used
//[min]~^ ERROR parameter `S` is never used
A: [(); {
let x: S = MaybeUninit::uninit();
//[min]~^ ERROR generic parameters may not be used in const operations
Expand Down
17 changes: 17 additions & 0 deletions src/test/ui/variance/variance-associated-consts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Test that the variance computation considers types that
// appear in const expressions to be invariant.

#![feature(rustc_attrs)]
#![allow(incomplete_features)]
#![feature(generic_const_exprs)]

trait Trait {
const Const: usize;
}

#[rustc_variance]
struct Foo<T: Trait> { //~ ERROR [o]
field: [u8; <T as Trait>::Const]
}

fn main() { }
10 changes: 10 additions & 0 deletions src/test/ui/variance/variance-associated-consts.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error[E0208]: [o]
--> $DIR/variance-associated-consts.rs:13:1
|
LL | / struct Foo<T: Trait> {
LL | | field: [u8; <T as Trait>::Const]
LL | | }
| |_^

error: aborting due to previous error

0 comments on commit 2b874f0

Please sign in to comment.