Rollup merge of #88644 - eopb:abstractconst_leaf_subst, r=lcnr

`AbstractConst` private fields

Calls `subst` in `AbstractConst::root` when `Node` is `Leaf`.

r? ``@lcnr``
This commit is contained in:
Yuki Okushi 2021-10-21 14:11:03 +09:00 committed by GitHub
commit 6f0acbcbd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 29 deletions

View File

@ -23,7 +23,7 @@ use rustc_middle::span_bug;
use rustc_middle::thir::abstract_const::Node as ACNode;
use rustc_middle::ty::fold::TypeVisitor;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable};
use rustc_session::lint;
use rustc_span::hygiene::Transparency;
@ -153,11 +153,8 @@ where
tcx: TyCtxt<'tcx>,
ct: AbstractConst<'tcx>,
) -> ControlFlow<V::BreakTy> {
const_evaluatable::walk_abstract_const(tcx, ct, |node| match node.root() {
ACNode::Leaf(leaf) => {
let leaf = leaf.subst(tcx, ct.substs);
self.visit_const(leaf)
}
const_evaluatable::walk_abstract_const(tcx, ct, |node| match node.root(tcx) {
ACNode::Leaf(leaf) => self.visit_const(leaf),
ACNode::Cast(_, _, ty) => self.visit_ty(ty),
ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => {
ControlFlow::CONTINUE

View File

@ -80,9 +80,8 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
Concrete,
}
let mut failure_kind = FailureKind::Concrete;
walk_abstract_const::<!, _>(tcx, ct, |node| match node.root() {
walk_abstract_const::<!, _>(tcx, ct, |node| match node.root(tcx) {
Node::Leaf(leaf) => {
let leaf = leaf.subst(tcx, ct.substs);
if leaf.has_infer_types_or_consts() {
failure_kind = FailureKind::MentionsInfer;
} else if leaf.definitely_has_param_types_or_consts(tcx) {
@ -92,7 +91,6 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
ControlFlow::CONTINUE
}
Node::Cast(_, _, ty) => {
let ty = ty.subst(tcx, ct.substs);
if ty.has_infer_types_or_consts() {
failure_kind = FailureKind::MentionsInfer;
} else if ty.definitely_has_param_types_or_consts(tcx) {
@ -187,8 +185,8 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
pub struct AbstractConst<'tcx> {
// FIXME: Consider adding something like `IndexSlice`
// and use this here.
pub inner: &'tcx [Node<'tcx>],
pub substs: SubstsRef<'tcx>,
inner: &'tcx [Node<'tcx>],
substs: SubstsRef<'tcx>,
}
impl<'tcx> AbstractConst<'tcx> {
@ -218,8 +216,14 @@ impl<'tcx> AbstractConst<'tcx> {
}
#[inline]
pub fn root(self) -> Node<'tcx> {
self.inner.last().copied().unwrap()
pub fn root(self, tcx: TyCtxt<'tcx>) -> Node<'tcx> {
let node = self.inner.last().copied().unwrap();
match node {
Node::Leaf(leaf) => Node::Leaf(leaf.subst(tcx, self.substs)),
Node::Cast(kind, operand, ty) => Node::Cast(kind, operand, ty.subst(tcx, self.substs)),
// Don't perform substitution on the following as they can't directly contain generic params
Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => node,
}
}
}
@ -542,7 +546,7 @@ where
f: &mut dyn FnMut(AbstractConst<'tcx>) -> ControlFlow<R>,
) -> ControlFlow<R> {
f(ct)?;
let root = ct.root();
let root = ct.root(tcx);
match root {
Node::Leaf(_) => ControlFlow::CONTINUE,
Node::Binop(_, l, r) => {
@ -570,16 +574,14 @@ pub(super) fn try_unify<'tcx>(
// We substitute generics repeatedly to allow AbstractConsts to unify where a
// ConstKind::Unevalated could be turned into an AbstractConst that would unify e.g.
// Param(N) should unify with Param(T), substs: [Unevaluated("T2", [Unevaluated("T3", [Param(N)])])]
while let Node::Leaf(a_ct) = a.root() {
let a_ct = a_ct.subst(tcx, a.substs);
while let Node::Leaf(a_ct) = a.root(tcx) {
match AbstractConst::from_const(tcx, a_ct) {
Ok(Some(a_act)) => a = a_act,
Ok(None) => break,
Err(_) => return true,
}
}
while let Node::Leaf(b_ct) = b.root() {
let b_ct = b_ct.subst(tcx, b.substs);
while let Node::Leaf(b_ct) = b.root(tcx) {
match AbstractConst::from_const(tcx, b_ct) {
Ok(Some(b_act)) => b = b_act,
Ok(None) => break,
@ -587,10 +589,8 @@ pub(super) fn try_unify<'tcx>(
}
}
match (a.root(), b.root()) {
match (a.root(tcx), b.root(tcx)) {
(Node::Leaf(a_ct), Node::Leaf(b_ct)) => {
let a_ct = a_ct.subst(tcx, a.substs);
let b_ct = b_ct.subst(tcx, b.substs);
if a_ct.ty != b_ct.ty {
return false;
}

View File

@ -837,14 +837,13 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
// constants which are not considered const evaluatable.
use rustc_middle::thir::abstract_const::Node;
if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv.shrink()) {
const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node.root() {
Node::Leaf(leaf) => {
let leaf = leaf.subst(self.tcx, ct.substs);
self.visit_const(leaf)
}
Node::Cast(_, _, ty) => self.visit_ty(ty),
Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => {
ControlFlow::CONTINUE
const_evaluatable::walk_abstract_const(self.tcx, ct, |node| {
match node.root(self.tcx) {
Node::Leaf(leaf) => self.visit_const(leaf),
Node::Cast(_, _, ty) => self.visit_ty(ty),
Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => {
ControlFlow::CONTINUE
}
}
})
} else {