- }
-
- // If we're evaluating a foreign constant, under a nightly compiler without generic
- // const exprs, AND it would've passed if that expression had been evaluated with
- // generic const exprs, then suggest using generic const exprs.
- if concrete.is_err()
- && tcx.sess.is_nightly_build()
- && !uv.def.did.is_local()
- && !tcx.features().generic_const_exprs
- && let Ok(Some(ct)) = AbstractConst::new(tcx, uv)
- && satisfied_from_param_env(tcx, ct, param_env) == Ok(true)
- {
- tcx.sess
- .struct_span_fatal(
- // Slightly better span than just using `span` alone
- if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def.did) } else { span },
- "failed to evaluate generic const expression",
- )
- .note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
- .span_suggestion_verbose(
- rustc_span::DUMMY_SP,
- "consider enabling this feature",
- "#![feature(generic_const_exprs)]\n".to_string(),
- rustc_errors::Applicability::MaybeIncorrect,
- )
- .emit()
- }
-
- debug!(?concrete, "is_const_evaluatable");
- match concrete {
- Err(ErrorHandled::TooGeneric) => Err(match uv.has_infer_types_or_consts() {
- true => NotConstEvaluatable::MentionsInfer,
- false => NotConstEvaluatable::MentionsParam,
- }),
- Err(ErrorHandled::Linted) => {
- let reported =
- infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
- Err(NotConstEvaluatable::Error(reported))
+ let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
+ match concrete {
+ Err(ErrorHandled::TooGeneric) => Err(if !uv.has_infer_types_or_consts() {
+ infcx
+ .tcx
+ .sess
+ .delay_span_bug(span, &format!("unexpected `TooGeneric` for {:?}", uv));
+ NotConstEvaluatable::MentionsParam
+ } else {
+ NotConstEvaluatable::MentionsInfer
+ }),
+ Err(ErrorHandled::Linted) => {
+ let reported = infcx
+ .tcx
+ .sess
+ .delay_span_bug(span, "constant in type had error reported as lint");
+ Err(NotConstEvaluatable::Error(reported))
+ }
+ Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
+ Ok(_) => Ok(()),
+ }
+ } else {
+ // 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, uv.expand(), Some(span));
+
+ match concrete {
+ // If we're evaluating a foreign constant, under a nightly compiler without generic
+ // const exprs, AND it would've passed if that expression had been evaluated with
+ // generic const exprs, then suggest using generic const exprs.
+ Err(_) if tcx.sess.is_nightly_build()
+ && let Ok(Some(ct)) = AbstractConst::new(tcx, uv)
+ && satisfied_from_param_env(tcx, ct, param_env) == Ok(true) => {
+ tcx.sess
+ .struct_span_fatal(
+ // Slightly better span than just using `span` alone
+ if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def.did) } else { span },
+ "failed to evaluate generic const expression",
+ )
+ .note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
+ .span_suggestion_verbose(
+ rustc_span::DUMMY_SP,
+ "consider enabling this feature",
+ "#![feature(generic_const_exprs)]\n".to_string(),
+ rustc_errors::Applicability::MaybeIncorrect,
+ )
+ .emit()
+ }
+
+ Err(ErrorHandled::TooGeneric) => Err(if uv.has_infer_types_or_consts() {
+ NotConstEvaluatable::MentionsInfer
+ } else {
+ NotConstEvaluatable::MentionsParam
+ }),
+ Err(ErrorHandled::Linted) => {
+ let reported =
+ infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
+ Err(NotConstEvaluatable::Error(reported))
+ }
+ Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
+ Ok(_) => {
+ if uv.substs.has_param_types_or_consts() {
+ assert!(matches!(infcx.tcx.def_kind(uv.def.did), DefKind::AnonConst));
+ let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
+
+ if mir_body.is_polymorphic {
+ let Some(local_def_id) = uv.def.did.as_local() else { return Ok(()) };
+ tcx.struct_span_lint_hir(
+ lint::builtin::CONST_EVALUATABLE_UNCHECKED,
+ tcx.hir().local_def_id_to_hir_id(local_def_id),
+ span,
+ |err| {
+ err.build("cannot use constants which depend on generic parameters in types").emit();
+ })
+ }
+ }
+
+ Ok(())
+ },