-use rustc_middle::ty::{self, TypeFoldable};
+use rustc_hir::def::DefKind;
use rustc_infer::infer::InferCtxt;
+use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::subst::SubstsRef;
-use rustc_span::Span;
+use rustc_middle::ty::{self, TypeFoldable};
+use rustc_session::lint;
use rustc_span::def_id::DefId;
-use rustc_middle::mir::interpret::ErrorHandled;
-use rustc_hir::def::DefKind;
+use rustc_span::Span;
pub fn is_const_evaluatable<'cx, 'tcx>(
infcx: &InferCtxt<'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 => {
} 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)
+}
-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
-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<T> X<T, [u8; L::<T>::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