diff --git a/compiler/rustc_session/src/lint/builtin.rs b/compiler/rustc_session/src/lint/builtin.rs index 2db4d2a7f51..66497df66ca 100644 --- a/compiler/rustc_session/src/lint/builtin.rs +++ b/compiler/rustc_session/src/lint/builtin.rs @@ -539,6 +539,16 @@ }; } +declare_lint! { + pub CONST_EVALUATABLE_UNCHECKED, + Warn, + "detects a generic constant is used in a type without a emitting a warning", + @future_incompatible = FutureIncompatibleInfo { + reference: "TODO", + edition: None, + }; +} + declare_lint_pass! { /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. @@ -612,6 +622,7 @@ UNSAFE_OP_IN_UNSAFE_FN, INCOMPLETE_INCLUDE, CENUM_IMPL_DROP_CAST, + CONST_EVALUATABLE_UNCHECKED, ] } diff --git a/src/librustc_trait_selection/traits/const_evaluatable.rs b/src/librustc_trait_selection/traits/const_evaluatable.rs index eb0e7f16fa3..87762cc43a1 100644 --- a/src/librustc_trait_selection/traits/const_evaluatable.rs +++ b/src/librustc_trait_selection/traits/const_evaluatable.rs @@ -1,10 +1,11 @@ -use rustc_middle::ty::{self, TypeFoldable}; -use rustc_infer::infer::InferCtxt; -use rustc_middle::ty::subst::SubstsRef; -use rustc_span::Span; -use rustc_span::def_id::DefId; -use rustc_middle::mir::interpret::ErrorHandled; use rustc_hir::def::DefKind; +use rustc_infer::infer::InferCtxt; +use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::ty::subst::SubstsRef; +use rustc_middle::ty::{self, TypeFoldable}; +use rustc_session::lint; +use rustc_span::def_id::DefId; +use rustc_span::Span; pub fn is_const_evaluatable<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, @@ -12,8 +13,31 @@ pub fn is_const_evaluatable<'cx, 'tcx>( substs: SubstsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, span: Span, -) -> Result<(), ErrorHandled> -{ +) -> Result<(), ErrorHandled> { + let future_compat_lint = || { + if let Some(local_def_id) = def.did.as_local() { + infcx.tcx.struct_span_lint_hir( + lint::builtin::CONST_EVALUATABLE_UNCHECKED, + infcx.tcx.hir().as_local_hir_id(local_def_id), + span, + |err| { + err.build("cannot use constants which depend on generic parameters in types") + .emit(); + }, + ); + } + }; + + // FIXME: We should only try to evaluate a given constant here if it is fully concrete + // as we don't want to allow things like `[u8; std::mem::size_of::<*mut T>()]`. + // + // We previously did not check this, so we only emit a future compat warning if + // const evaluation succeeds and the given constant is still polymorphic for now + // and hopefully soon change this to an error. + // + // See #74595 for more details about this. + let concrete = infcx.const_eval_resolve(param_env, def, substs, None, Some(span)); + let def_kind = infcx.tcx.def_kind(def.did); match def_kind { DefKind::AnonConst => { @@ -22,33 +46,16 @@ pub fn is_const_evaluatable<'cx, 'tcx>( } else { infcx.tcx.optimized_mir(def.did) }; - if mir_body.is_polymorphic { - return Err(ErrorHandled::TooGeneric); + if mir_body.is_polymorphic && concrete.is_ok() { + future_compat_lint(); } } _ => { - if substs.has_param_types_or_consts() { - return Err(ErrorHandled::TooGeneric); + if substs.has_param_types_or_consts() && concrete.is_ok() { + future_compat_lint(); } } } - match infcx.const_eval_resolve( - param_env, - def, - substs, - None, - Some(span), - ) { - Ok(_) => Ok(()), - Err(err) => { - if matches!(err, ErrorHandled::TooGeneric) { - infcx.tcx.sess.delay_span_bug( - span, - &format!("ConstEvaluatable too generic: {:?}, {:?}, {:?}", def, substs, param_env), - ); - } - Err(err) - } - } -} \ No newline at end of file + concrete.map(drop) +} diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs index 5fe526df5a7..cdc1db4c0b4 100644 --- a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs +++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs @@ -1,3 +1,4 @@ +// run-pass #![feature(arbitrary_enum_discriminant, core_intrinsics)] extern crate core; @@ -7,7 +8,8 @@ enum MyWeirdOption { None = 0, Some(T) = core::mem::size_of::<*mut T>(), - //~^ ERROR constant expression depends on a generic parameter + //~^ WARN cannot use constants which depend on generic parameters in types + //~| WARN this was previously accepted by the compiler but is being phased out } fn main() { diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr index 9aba2ea543f..2aeb1b32bcb 100644 --- a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr +++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr @@ -1,10 +1,12 @@ -error: constant expression depends on a generic parameter - --> $DIR/issue-70453-polymorphic-ctfe.rs:9:15 +warning: cannot use constants which depend on generic parameters in types + --> $DIR/issue-70453-polymorphic-ctfe.rs:10:15 | LL | Some(T) = core::mem::size_of::<*mut T>(), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this may fail depending on what value the parameter takes + = note: `#[warn(const_evaluatable_unchecked)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see TODO -error: aborting due to previous error +warning: 1 warning emitted diff --git a/src/test/ui/lazy_normalization_consts/issue-73980.rs b/src/test/ui/lazy_normalization_consts/issue-73980.rs index 2e4cb9ff7a8..e10040652c7 100644 --- a/src/test/ui/lazy_normalization_consts/issue-73980.rs +++ b/src/test/ui/lazy_normalization_consts/issue-73980.rs @@ -1,3 +1,4 @@ +// check-pass #![feature(lazy_normalization_consts)] #![allow(incomplete_features)] @@ -9,6 +10,7 @@ impl L { } impl X::S]> {} -//~^ ERROR constant expression depends on a generic parameter +//~^ WARN cannot use constants which depend on generic parameters +//~| WARN this was previously accepted by the compiler but is being phased out fn main() {} diff --git a/src/test/ui/lazy_normalization_consts/issue-73980.stderr b/src/test/ui/lazy_normalization_consts/issue-73980.stderr index 5ca11bf55fc..8636407a3a1 100644 --- a/src/test/ui/lazy_normalization_consts/issue-73980.stderr +++ b/src/test/ui/lazy_normalization_consts/issue-73980.stderr @@ -1,10 +1,12 @@ -error: constant expression depends on a generic parameter - --> $DIR/issue-73980.rs:11:9 +warning: cannot use constants which depend on generic parameters in types + --> $DIR/issue-73980.rs:12:9 | LL | impl X::S]> {} | ^^^^^^^^^^^^^^^^^^^^^ | - = note: this may fail depending on what value the parameter takes + = note: `#[warn(const_evaluatable_unchecked)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see TODO -error: aborting due to previous error +warning: 1 warning emitted