diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index ede28522000af..2947799b791f2 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -3,7 +3,7 @@ use crate::mir::interpret::Scalar; use crate::mir::Promoted; use crate::ty::subst::{InternalSubsts, SubstsRef}; use crate::ty::ParamEnv; -use crate::ty::{self, TyCtxt, TypeFoldable}; +use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_errors::ErrorReported; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; @@ -107,12 +107,29 @@ impl<'tcx> ConstKind<'tcx> { .with_reveal_all_normalized(tcx) .and(tcx.erase_regions(&substs)); + struct Meh; + impl<'tcx> ty::fold::TypeVisitor<'tcx> for Meh { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + if matches!(ty.kind, ty::Bound(..)) { true } else { ty.super_visit_with(self) } + } + + fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> bool { + if matches!(ct.val, ConstKind::Bound(..)) { + true + } else { + ct.super_visit_with(self) + } + } + } + // HACK(eddyb) when the query key would contain inference variables, // attempt using identity substs and `ParamEnv` instead, that will succeed // when the expression doesn't depend on any parameters. // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that // we can call `infcx.const_eval_resolve` which handles inference variables. - let param_env_and_substs = if param_env_and_substs.needs_infer() { + let param_env_and_substs = if param_env_and_substs.needs_infer() + || param_env_and_substs.visit_with(&mut Meh) + { tcx.param_env(def.did).and(InternalSubsts::identity_for_item(tcx, def.did)) } else { param_env_and_substs diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index 93da6e3d38a93..53f846f5da8d5 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -527,6 +527,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { trace!("resolve: {:?}, {:#?}", def, substs); trace!("param_env: {:#?}", self.param_env); trace!("substs: {:#?}", substs); + struct Meh; + impl<'tcx> ty::fold::TypeVisitor<'tcx> for Meh { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + if matches!(ty.kind(), ty::Bound(..)) { true } else { ty.super_visit_with(self) } + } + + fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> bool { + if matches!(ct.val, ty::ConstKind::Bound(..)) { + true + } else { + ct.super_visit_with(self) + } + } + } + if self.param_env.and(substs).visit_with(&mut Meh) { + throw_inval!(TooGeneric) + } match ty::Instance::resolve_opt_const_arg(*self.tcx, self.param_env, def, substs) { Ok(Some(instance)) => Ok(instance), Ok(None) => throw_inval!(TooGeneric), diff --git a/src/test/ui/const-generics/const_evaluatable_checked/codegen-select-ice.rs b/src/test/ui/const-generics/const_evaluatable_checked/codegen-select-ice.rs new file mode 100644 index 0000000000000..8071e5308c5c7 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/codegen-select-ice.rs @@ -0,0 +1,32 @@ +// run-pass +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +trait FromBytesLittleEndian { + const N: usize; + fn from_bytes_le(other: &[u8; Self::N]) -> Self; +} + +impl FromBytesLittleEndian for u32 { + const N: usize = 4; + fn from_bytes_le(other: &[u8; 4]) -> Self { + Self::from_le_bytes(*other) + } +} + +#[derive(Debug, PartialEq, Eq)] +struct Header(u32); + +impl FromBytesLittleEndian for Header { + const N: usize = 4; + fn from_bytes_le(r: &[u8; 4]) -> Self { + Self(FromBytesLittleEndian::from_bytes_le(r)) + // This previously caused an ICE in the above line. + } +} + +fn main() { + let data = [1, 2, 3, 4]; + let h = Header::from_bytes_le(&data); + assert_eq!(h, Header(0x04030201)); +} diff --git a/src/test/ui/const-generics/issues/issue-64494.full.stderr b/src/test/ui/const-generics/issues/issue-64494.full.stderr index a97ec9308f814..375359fe55d97 100644 --- a/src/test/ui/const-generics/issues/issue-64494.full.stderr +++ b/src/test/ui/const-generics/issues/issue-64494.full.stderr @@ -1,18 +1,12 @@ -error: constant expression depends on a generic parameter - --> $DIR/issue-64494.rs:16:53 +error[E0119]: conflicting implementations of trait `MyTrait`: + --> $DIR/issue-64494.rs:18:1 | LL | impl MyTrait for T where Is<{T::VAL == 5}>: True {} - | ^^^^ - | - = note: this may fail depending on what value the parameter takes - -error: constant expression depends on a generic parameter - --> $DIR/issue-64494.rs:19:53 - | + | ------------------------------------ first implementation here +LL | LL | impl MyTrait for T where Is<{T::VAL == 6}>: True {} - | ^^^^ - | - = note: this may fail depending on what value the parameter takes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation -error: aborting due to 2 previous errors +error: aborting due to previous error +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/const-generics/issues/issue-64494.min.stderr b/src/test/ui/const-generics/issues/issue-64494.min.stderr index 07822f86f524b..1cfa6ca6693a0 100644 --- a/src/test/ui/const-generics/issues/issue-64494.min.stderr +++ b/src/test/ui/const-generics/issues/issue-64494.min.stderr @@ -7,7 +7,7 @@ LL | impl MyTrait for T where Is<{T::VAL == 5}>: True {} = note: type parameters are currently not permitted in anonymous constants error: generic parameters must not be used inside of non trivial constant values - --> $DIR/issue-64494.rs:19:38 + --> $DIR/issue-64494.rs:18:38 | LL | impl MyTrait for T where Is<{T::VAL == 6}>: True {} | ^^^^^^ non-trivial anonymous constants must not depend on the parameter `T` @@ -15,11 +15,11 @@ LL | impl MyTrait for T where Is<{T::VAL == 6}>: True {} = note: type parameters are currently not permitted in anonymous constants error[E0119]: conflicting implementations of trait `MyTrait`: - --> $DIR/issue-64494.rs:19:1 + --> $DIR/issue-64494.rs:18:1 | LL | impl MyTrait for T where Is<{T::VAL == 5}>: True {} | ------------------------------------ first implementation here -... +LL | LL | impl MyTrait for T where Is<{T::VAL == 6}>: True {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation diff --git a/src/test/ui/const-generics/issues/issue-64494.rs b/src/test/ui/const-generics/issues/issue-64494.rs index 3b598a415223a..9f25d4c9677a3 100644 --- a/src/test/ui/const-generics/issues/issue-64494.rs +++ b/src/test/ui/const-generics/issues/issue-64494.rs @@ -14,11 +14,9 @@ struct Is; impl True for Is<{true}> {} impl MyTrait for T where Is<{T::VAL == 5}>: True {} -//[full]~^ ERROR constant expression depends on a generic parameter -//[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values +//[min]~^ ERROR generic parameters must not be used inside of non trivial constant values impl MyTrait for T where Is<{T::VAL == 6}>: True {} -//[full]~^ ERROR constant expression depends on a generic parameter -//[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values -//[min]~| ERROR conflicting implementations of trait `MyTrait` +//[min]~^ ERROR generic parameters must not be used inside of non trivial constant values +//~^^ ERROR conflicting implementations of trait fn main() {}