diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs index 1c8ac10818c03..33c27ce86ddb5 100644 --- a/compiler/rustc_typeck/src/variance/constraints.rs +++ b/compiler/rustc_typeck/src/variance/constraints.rs @@ -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) } } } @@ -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); } @@ -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( diff --git a/src/test/ui/const-generics/issues/issue-67375.full.stderr b/src/test/ui/const-generics/issues/issue-67375.full.stderr index 0f0e339655bca..0cf69879a5c20 100644 --- a/src/test/ui/const-generics/issues/issue-67375.full.stderr +++ b/src/test/ui/const-generics/issues/issue-67375.full.stderr @@ -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 { - | ^ 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`. diff --git a/src/test/ui/const-generics/issues/issue-67375.rs b/src/test/ui/const-generics/issues/issue-67375.rs index b5b842a15ae0c..8b4b276bae0ba 100644 --- a/src/test/ui/const-generics/issues/issue-67375.rs +++ b/src/test/ui/const-generics/issues/issue-67375.rs @@ -3,7 +3,7 @@ #![cfg_attr(full, feature(generic_const_exprs))] struct Bug { - //~^ 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 diff --git a/src/test/ui/const-generics/issues/issue-67945-1.full.stderr b/src/test/ui/const-generics/issues/issue-67945-1.full.stderr index 1edc7828caad2..8e18fcdffab70 100644 --- a/src/test/ui/const-generics/issues/issue-67945-1.full.stderr +++ b/src/test/ui/const-generics/issues/issue-67945-1.full.stderr @@ -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 { - | ^ 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`. diff --git a/src/test/ui/const-generics/issues/issue-67945-1.rs b/src/test/ui/const-generics/issues/issue-67945-1.rs index 7b7e8428639c7..99f88bc8e1055 100644 --- a/src/test/ui/const-generics/issues/issue-67945-1.rs +++ b/src/test/ui/const-generics/issues/issue-67945-1.rs @@ -5,7 +5,7 @@ use std::mem::MaybeUninit; struct Bug { - //~^ 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 diff --git a/src/test/ui/variance/variance-associated-consts.rs b/src/test/ui/variance/variance-associated-consts.rs new file mode 100644 index 0000000000000..da55bc96244f2 --- /dev/null +++ b/src/test/ui/variance/variance-associated-consts.rs @@ -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 { //~ ERROR [o] + field: [u8; ::Const] +} + +fn main() { } diff --git a/src/test/ui/variance/variance-associated-consts.stderr b/src/test/ui/variance/variance-associated-consts.stderr new file mode 100644 index 0000000000000..d1bf34781dfb2 --- /dev/null +++ b/src/test/ui/variance/variance-associated-consts.stderr @@ -0,0 +1,10 @@ +error[E0208]: [o] + --> $DIR/variance-associated-consts.rs:13:1 + | +LL | / struct Foo { +LL | | field: [u8; ::Const] +LL | | } + | |_^ + +error: aborting due to previous error +