change ConstEvaluatable
to use ty::Const
This commit is contained in:
parent
98a5ac269c
commit
660ca48041
@ -198,7 +198,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
|||||||
(
|
(
|
||||||
ty::PredicateKind::ConstEvaluatable(a),
|
ty::PredicateKind::ConstEvaluatable(a),
|
||||||
ty::PredicateKind::ConstEvaluatable(b),
|
ty::PredicateKind::ConstEvaluatable(b),
|
||||||
) => tcx.try_unify_abstract_consts(self_param_env.and((a, b))),
|
) => relator.relate(predicate.rebind(a), predicate.rebind(b)).is_ok(),
|
||||||
(
|
(
|
||||||
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, lt_a)),
|
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, lt_a)),
|
||||||
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_b, lt_b)),
|
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_b, lt_b)),
|
||||||
|
@ -1101,8 +1101,6 @@ fn check_type_defn<'tcx, F>(
|
|||||||
|
|
||||||
// Explicit `enum` discriminant values must const-evaluate successfully.
|
// Explicit `enum` discriminant values must const-evaluate successfully.
|
||||||
if let Some(discr_def_id) = variant.explicit_discr {
|
if let Some(discr_def_id) = variant.explicit_discr {
|
||||||
let discr_substs = InternalSubsts::identity_for_item(tcx, discr_def_id.to_def_id());
|
|
||||||
|
|
||||||
let cause = traits::ObligationCause::new(
|
let cause = traits::ObligationCause::new(
|
||||||
tcx.def_span(discr_def_id),
|
tcx.def_span(discr_def_id),
|
||||||
wfcx.body_id,
|
wfcx.body_id,
|
||||||
@ -1112,10 +1110,7 @@ fn check_type_defn<'tcx, F>(
|
|||||||
cause,
|
cause,
|
||||||
wfcx.param_env,
|
wfcx.param_env,
|
||||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
|
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
|
||||||
ty::UnevaluatedConst::new(
|
ty::Const::from_anon_const(tcx, discr_def_id),
|
||||||
ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
|
|
||||||
discr_substs,
|
|
||||||
),
|
|
||||||
))
|
))
|
||||||
.to_predicate(tcx),
|
.to_predicate(tcx),
|
||||||
));
|
));
|
||||||
|
@ -318,10 +318,10 @@ impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> {
|
|||||||
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
|
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
|
||||||
let def_id = self.tcx.hir().local_def_id(c.hir_id);
|
let def_id = self.tcx.hir().local_def_id(c.hir_id);
|
||||||
let ct = ty::Const::from_anon_const(self.tcx, def_id);
|
let ct = ty::Const::from_anon_const(self.tcx, def_id);
|
||||||
if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
|
if let ty::ConstKind::Unevaluated(_) = ct.kind() {
|
||||||
let span = self.tcx.hir().span(c.hir_id);
|
let span = self.tcx.hir().span(c.hir_id);
|
||||||
self.preds.insert((
|
self.preds.insert((
|
||||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
|
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
|
||||||
.to_predicate(self.tcx),
|
.to_predicate(self.tcx),
|
||||||
span,
|
span,
|
||||||
));
|
));
|
||||||
|
@ -263,6 +263,10 @@ pub fn eval_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 {
|
|||||||
self.try_eval_usize(tcx, param_env)
|
self.try_eval_usize(tcx, param_env)
|
||||||
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
|
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_ct_infer(self) -> bool {
|
||||||
|
matches!(self.kind(), ty::ConstKind::Infer(_))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx> {
|
pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx> {
|
||||||
|
@ -256,7 +256,7 @@ fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) {
|
|||||||
self.add_substs(substs);
|
self.add_substs(substs);
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEvaluatable(uv) => {
|
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||||
self.add_unevaluated_const(uv);
|
self.add_const(uv);
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEquate(expected, found) => {
|
ty::PredicateKind::ConstEquate(expected, found) => {
|
||||||
self.add_const(expected);
|
self.add_const(expected);
|
||||||
|
@ -682,7 +682,7 @@ pub enum PredicateKind<'tcx> {
|
|||||||
Coerce(CoercePredicate<'tcx>),
|
Coerce(CoercePredicate<'tcx>),
|
||||||
|
|
||||||
/// Constant initializer must evaluate successfully.
|
/// Constant initializer must evaluate successfully.
|
||||||
ConstEvaluatable(ty::UnevaluatedConst<'tcx>),
|
ConstEvaluatable(ty::Const<'tcx>),
|
||||||
|
|
||||||
/// Constants must be equal. The first component is the const that is expected.
|
/// Constants must be equal. The first component is the const that is expected.
|
||||||
ConstEquate(Const<'tcx>, Const<'tcx>),
|
ConstEquate(Const<'tcx>, Const<'tcx>),
|
||||||
|
@ -2702,8 +2702,8 @@ pub struct PrintClosureAsImpl<'tcx> {
|
|||||||
print_value_path(closure_def_id, &[]),
|
print_value_path(closure_def_id, &[]),
|
||||||
write("` implements the trait `{}`", kind))
|
write("` implements the trait `{}`", kind))
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEvaluatable(uv) => {
|
ty::PredicateKind::ConstEvaluatable(ct) => {
|
||||||
p!("the constant `", print_value_path(uv.def.did, uv.substs), "` can be evaluated")
|
p!("the constant `", print(ct), "` can be evaluated")
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEquate(c1, c2) => {
|
ty::PredicateKind::ConstEquate(c1, c2) => {
|
||||||
p!("the constant `", print(c1), "` equals `", print(c2), "`")
|
p!("the constant `", print(c1), "` equals `", print(c2), "`")
|
||||||
|
@ -166,8 +166,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|||||||
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
|
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
|
||||||
write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
|
write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEvaluatable(uv) => {
|
ty::PredicateKind::ConstEvaluatable(ct) => {
|
||||||
write!(f, "ConstEvaluatable({:?}, {:?})", uv.def, uv.substs)
|
write!(f, "ConstEvaluatable({ct:?})")
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
|
ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
|
||||||
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
|
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
|
||||||
|
@ -188,6 +188,14 @@ pub fn expect_const(self) -> ty::Const<'tcx> {
|
|||||||
_ => bug!("expected a const, but found another kind"),
|
_ => bug!("expected a const, but found another kind"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_non_region_infer(self) -> bool {
|
||||||
|
match self.unpack() {
|
||||||
|
GenericArgKind::Lifetime(_) => false,
|
||||||
|
GenericArgKind::Type(ty) => ty.is_ty_infer(),
|
||||||
|
GenericArgKind::Const(ct) => ct.is_ct_infer(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> {
|
impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> {
|
||||||
|
@ -112,6 +112,22 @@ pub fn walk(self) -> TypeWalker<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> ty::Const<'tcx> {
|
||||||
|
/// Iterator that walks `self` and any types reachable from
|
||||||
|
/// `self`, in depth-first order. Note that just walks the types
|
||||||
|
/// that appear in `self`, it does not descend into the fields of
|
||||||
|
/// structs or variants. For example:
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// isize => { isize }
|
||||||
|
/// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
|
||||||
|
/// [isize] => { [isize], isize }
|
||||||
|
/// ```
|
||||||
|
pub fn walk(self) -> TypeWalker<'tcx> {
|
||||||
|
TypeWalker::new(self.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// We push `GenericArg`s on the stack in reverse order so as to
|
/// We push `GenericArg`s on the stack in reverse order so as to
|
||||||
/// maintain a pre-order traversal. As of the time of this
|
/// maintain a pre-order traversal. As of the time of this
|
||||||
/// writing, the fact that the traversal is pre-order is not
|
/// writing, the fact that the traversal is pre-order is not
|
||||||
|
@ -159,15 +159,7 @@ fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<V::
|
|||||||
ty.visit_with(self)
|
ty.visit_with(self)
|
||||||
}
|
}
|
||||||
ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE,
|
ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE,
|
||||||
ty::PredicateKind::ConstEvaluatable(uv)
|
ty::PredicateKind::ConstEvaluatable(ct) => ct.visit_with(self),
|
||||||
if self.def_id_visitor.tcx().features().generic_const_exprs =>
|
|
||||||
{
|
|
||||||
let tcx = self.def_id_visitor.tcx();
|
|
||||||
if let Ok(Some(ct)) = AbstractConst::new(tcx, uv) {
|
|
||||||
self.visit_abstract_const_expr(tcx, ct)?;
|
|
||||||
}
|
|
||||||
ControlFlow::CONTINUE
|
|
||||||
}
|
|
||||||
ty::PredicateKind::WellFormed(arg) => arg.visit_with(self),
|
ty::PredicateKind::WellFormed(arg) => arg.visit_with(self),
|
||||||
_ => bug!("unexpected predicate: {:?}", predicate),
|
_ => bug!("unexpected predicate: {:?}", predicate),
|
||||||
}
|
}
|
||||||
|
@ -161,11 +161,20 @@ pub fn try_unify_abstract_consts<'tcx>(
|
|||||||
#[instrument(skip(infcx), level = "debug")]
|
#[instrument(skip(infcx), level = "debug")]
|
||||||
pub fn is_const_evaluatable<'tcx>(
|
pub fn is_const_evaluatable<'tcx>(
|
||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
uv: ty::UnevaluatedConst<'tcx>,
|
ct: ty::Const<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<(), NotConstEvaluatable> {
|
) -> Result<(), NotConstEvaluatable> {
|
||||||
let tcx = infcx.tcx;
|
let tcx = infcx.tcx;
|
||||||
|
let uv = match ct.kind() {
|
||||||
|
ty::ConstKind::Unevaluated(uv) => uv,
|
||||||
|
ty::ConstKind::Param(_)
|
||||||
|
| ty::ConstKind::Bound(_, _)
|
||||||
|
| ty::ConstKind::Placeholder(_)
|
||||||
|
| ty::ConstKind::Value(_)
|
||||||
|
| ty::ConstKind::Error(_) => return Ok(()),
|
||||||
|
ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
|
||||||
|
};
|
||||||
|
|
||||||
if tcx.features().generic_const_exprs {
|
if tcx.features().generic_const_exprs {
|
||||||
if let Some(ct) = AbstractConst::new(tcx, uv)? {
|
if let Some(ct) = AbstractConst::new(tcx, uv)? {
|
||||||
@ -285,7 +294,7 @@ fn satisfied_from_param_env<'tcx>(
|
|||||||
for pred in param_env.caller_bounds() {
|
for pred in param_env.caller_bounds() {
|
||||||
match pred.kind().skip_binder() {
|
match pred.kind().skip_binder() {
|
||||||
ty::PredicateKind::ConstEvaluatable(uv) => {
|
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||||
if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
|
if let Some(b_ct) = AbstractConst::from_const(tcx, uv)? {
|
||||||
let const_unify_ctxt = ConstUnifyCtxt { tcx, param_env };
|
let const_unify_ctxt = ConstUnifyCtxt { tcx, param_env };
|
||||||
|
|
||||||
// Try to unify with each subtree in the AbstractConst to allow for
|
// Try to unify with each subtree in the AbstractConst to allow for
|
||||||
|
@ -1304,7 +1304,10 @@ fn report_selection_error(
|
|||||||
}
|
}
|
||||||
|
|
||||||
match obligation.predicate.kind().skip_binder() {
|
match obligation.predicate.kind().skip_binder() {
|
||||||
ty::PredicateKind::ConstEvaluatable(uv) => {
|
ty::PredicateKind::ConstEvaluatable(ct) => {
|
||||||
|
let ty::ConstKind::Unevaluated(uv) = ct.kind() else {
|
||||||
|
bug!("const evaluatable failed for non-unevaluated const `{ct:?}`");
|
||||||
|
};
|
||||||
let mut err =
|
let mut err =
|
||||||
self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
|
self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
|
||||||
let const_span = self.tcx.def_span(uv.def.did);
|
let const_span = self.tcx.def_span(uv.def.did);
|
||||||
@ -2368,7 +2371,7 @@ fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
|
|||||||
if predicate.references_error() || self.is_tainted_by_errors() {
|
if predicate.references_error() || self.is_tainted_by_errors() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let subst = data.substs.iter().find(|g| g.has_non_region_infer());
|
let subst = data.walk().find(|g| g.is_non_region_infer());
|
||||||
if let Some(subst) = subst {
|
if let Some(subst) = subst {
|
||||||
let err = self.emit_inference_failure_err(
|
let err = self.emit_inference_failure_err(
|
||||||
body_id,
|
body_id,
|
||||||
|
@ -476,9 +476,7 @@ fn process_obligation(
|
|||||||
Err(NotConstEvaluatable::MentionsInfer) => {
|
Err(NotConstEvaluatable::MentionsInfer) => {
|
||||||
pending_obligation.stalled_on.clear();
|
pending_obligation.stalled_on.clear();
|
||||||
pending_obligation.stalled_on.extend(
|
pending_obligation.stalled_on.extend(
|
||||||
uv.substs
|
uv.walk().filter_map(TyOrConstInferVar::maybe_from_generic_arg),
|
||||||
.iter()
|
|
||||||
.filter_map(TyOrConstInferVar::maybe_from_generic_arg),
|
|
||||||
);
|
);
|
||||||
ProcessResult::Unchanged
|
ProcessResult::Unchanged
|
||||||
}
|
}
|
||||||
|
@ -148,13 +148,8 @@ pub fn predicate_obligations<'tcx>(
|
|||||||
wf.compute(a.into());
|
wf.compute(a.into());
|
||||||
wf.compute(b.into());
|
wf.compute(b.into());
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEvaluatable(uv) => {
|
ty::PredicateKind::ConstEvaluatable(ct) => {
|
||||||
let obligations = wf.nominal_obligations(uv.def.did, uv.substs);
|
wf.compute(ct.into());
|
||||||
wf.out.extend(obligations);
|
|
||||||
|
|
||||||
for arg in uv.substs.iter() {
|
|
||||||
wf.compute(arg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEquate(c1, c2) => {
|
ty::PredicateKind::ConstEquate(c1, c2) => {
|
||||||
wf.compute(c1.into());
|
wf.compute(c1.into());
|
||||||
@ -476,14 +471,14 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
|
|||||||
// obligations are handled by the parent (e.g. `ty::Ref`).
|
// obligations are handled by the parent (e.g. `ty::Ref`).
|
||||||
GenericArgKind::Lifetime(_) => continue,
|
GenericArgKind::Lifetime(_) => continue,
|
||||||
|
|
||||||
GenericArgKind::Const(constant) => {
|
GenericArgKind::Const(ct) => {
|
||||||
match constant.kind() {
|
match ct.kind() {
|
||||||
ty::ConstKind::Unevaluated(uv) => {
|
ty::ConstKind::Unevaluated(uv) => {
|
||||||
let obligations = self.nominal_obligations(uv.def.did, uv.substs);
|
let obligations = self.nominal_obligations(uv.def.did, uv.substs);
|
||||||
self.out.extend(obligations);
|
self.out.extend(obligations);
|
||||||
|
|
||||||
let predicate =
|
let predicate =
|
||||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
|
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
|
||||||
.to_predicate(self.tcx());
|
.to_predicate(self.tcx());
|
||||||
let cause = self.cause(traits::WellFormed(None));
|
let cause = self.cause(traits::WellFormed(None));
|
||||||
self.out.push(traits::Obligation::with_depth(
|
self.out.push(traits::Obligation::with_depth(
|
||||||
@ -500,7 +495,7 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
|
|||||||
cause,
|
cause,
|
||||||
self.recursion_depth,
|
self.recursion_depth,
|
||||||
self.param_env,
|
self.param_env,
|
||||||
ty::Binder::dummy(ty::PredicateKind::WellFormed(constant.into()))
|
ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into()))
|
||||||
.to_predicate(self.tcx()),
|
.to_predicate(self.tcx()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user