attempt to re-add ty::Unevaluated visitor and friends
This commit is contained in:
@@ -19,7 +19,7 @@ use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable
|
||||
use rustc_middle::ty::subst::{Subst, SubstsRef};
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::def_id::{DefId, LocalDefId};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::cmp;
|
||||
@@ -29,26 +29,20 @@ use std::ops::ControlFlow;
|
||||
/// Check if a given constant can be evaluated.
|
||||
pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||
infcx: &InferCtxt<'cx, 'tcx>,
|
||||
def: ty::WithOptConstParam<DefId>,
|
||||
substs: SubstsRef<'tcx>,
|
||||
uv: ty::Unevaluated<'tcx, ()>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
span: Span,
|
||||
) -> Result<(), NotConstEvaluatable> {
|
||||
debug!("is_const_evaluatable({:?}, {:?})", def, substs);
|
||||
debug!("is_const_evaluatable({:?})", uv);
|
||||
if infcx.tcx.features().generic_const_exprs {
|
||||
let tcx = infcx.tcx;
|
||||
match AbstractConst::new(tcx, def, substs)? {
|
||||
match AbstractConst::new(tcx, uv)? {
|
||||
// We are looking at a generic abstract constant.
|
||||
Some(ct) => {
|
||||
for pred in param_env.caller_bounds() {
|
||||
match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::ConstEvaluatable(b_def, b_substs) => {
|
||||
if b_def == def && b_substs == substs {
|
||||
debug!("is_const_evaluatable: caller_bound ~~> ok");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(b_ct) = AbstractConst::new(tcx, b_def, b_substs)? {
|
||||
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||
if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
|
||||
// Try to unify with each subtree in the AbstractConst to allow for
|
||||
// `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
|
||||
// predicate for `(N + 1) * 2`
|
||||
@@ -132,7 +126,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||
}
|
||||
|
||||
let future_compat_lint = || {
|
||||
if let Some(local_def_id) = def.did.as_local() {
|
||||
if let Some(local_def_id) = uv.def.did.as_local() {
|
||||
infcx.tcx.struct_span_lint_hir(
|
||||
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
|
||||
infcx.tcx.hir().local_def_id_to_hir_id(local_def_id),
|
||||
@@ -153,16 +147,12 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||
// and hopefully soon change this to an error.
|
||||
//
|
||||
// See #74595 for more details about this.
|
||||
let concrete = infcx.const_eval_resolve(
|
||||
param_env,
|
||||
ty::Unevaluated { def, substs, promoted: None },
|
||||
Some(span),
|
||||
);
|
||||
let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
|
||||
|
||||
if concrete.is_ok() && substs.has_param_types_or_consts() {
|
||||
match infcx.tcx.def_kind(def.did) {
|
||||
if concrete.is_ok() && uv.substs.has_param_types_or_consts() {
|
||||
match infcx.tcx.def_kind(uv.def.did) {
|
||||
DefKind::AnonConst | DefKind::InlineConst => {
|
||||
let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(def);
|
||||
let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
|
||||
|
||||
if mir_body.is_polymorphic {
|
||||
future_compat_lint();
|
||||
@@ -174,7 +164,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||
|
||||
debug!(?concrete, "is_const_evaluatable");
|
||||
match concrete {
|
||||
Err(ErrorHandled::TooGeneric) => Err(match substs.has_infer_types_or_consts() {
|
||||
Err(ErrorHandled::TooGeneric) => Err(match uv.has_infer_types_or_consts() {
|
||||
true => NotConstEvaluatable::MentionsInfer,
|
||||
false => NotConstEvaluatable::MentionsParam,
|
||||
}),
|
||||
@@ -202,12 +192,11 @@ pub struct AbstractConst<'tcx> {
|
||||
impl<'tcx> AbstractConst<'tcx> {
|
||||
pub fn new(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def: ty::WithOptConstParam<DefId>,
|
||||
substs: SubstsRef<'tcx>,
|
||||
uv: ty::Unevaluated<'tcx, ()>,
|
||||
) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
|
||||
let inner = tcx.thir_abstract_const_opt_const_arg(def)?;
|
||||
debug!("AbstractConst::new({:?}, {:?}) = {:?}", def, substs, inner);
|
||||
Ok(inner.map(|inner| AbstractConst { inner, substs }))
|
||||
let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?;
|
||||
debug!("AbstractConst::new({:?}) = {:?}", uv, inner);
|
||||
Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs }))
|
||||
}
|
||||
|
||||
pub fn from_const(
|
||||
@@ -215,9 +204,7 @@ impl<'tcx> AbstractConst<'tcx> {
|
||||
ct: &ty::Const<'tcx>,
|
||||
) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
|
||||
match ct.val {
|
||||
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: _ }) => {
|
||||
AbstractConst::new(tcx, def, substs)
|
||||
}
|
||||
ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()),
|
||||
ty::ConstKind::Error(_) => Err(ErrorReported),
|
||||
_ => Ok(None),
|
||||
}
|
||||
@@ -539,14 +526,11 @@ pub(super) fn thir_abstract_const<'tcx>(
|
||||
|
||||
pub(super) fn try_unify_abstract_consts<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
((a, a_substs), (b, b_substs)): (
|
||||
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
|
||||
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
|
||||
),
|
||||
(a, b): (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>),
|
||||
) -> bool {
|
||||
(|| {
|
||||
if let Some(a) = AbstractConst::new(tcx, a, a_substs)? {
|
||||
if let Some(b) = AbstractConst::new(tcx, b, b_substs)? {
|
||||
if let Some(a) = AbstractConst::new(tcx, a)? {
|
||||
if let Some(b) = AbstractConst::new(tcx, b)? {
|
||||
return Ok(try_unify(tcx, a, b));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user