ignore const substs in implicit_infer

This commit is contained in:
lcnr 2021-07-19 14:05:13 +02:00
parent caa975c89e
commit 6755b2da44
2 changed files with 28 additions and 10 deletions

View File

@ -11,7 +11,7 @@ use smallvec::{self, SmallVec};
type TypeWalkerStack<'tcx> = SmallVec<[GenericArg<'tcx>; 8]>; type TypeWalkerStack<'tcx> = SmallVec<[GenericArg<'tcx>; 8]>;
pub struct TypeWalker<'tcx> { pub struct TypeWalker<'tcx> {
tcx: TyCtxt<'tcx>, expose_default_const_substs: Option<TyCtxt<'tcx>>,
stack: TypeWalkerStack<'tcx>, stack: TypeWalkerStack<'tcx>,
last_subtree: usize, last_subtree: usize,
pub visited: SsoHashSet<GenericArg<'tcx>>, pub visited: SsoHashSet<GenericArg<'tcx>>,
@ -26,8 +26,13 @@ pub struct TypeWalker<'tcx> {
/// It maintains a set of visited types and /// It maintains a set of visited types and
/// skips any types that are already there. /// skips any types that are already there.
impl<'tcx> TypeWalker<'tcx> { impl<'tcx> TypeWalker<'tcx> {
fn new(tcx: TyCtxt<'tcx>, root: GenericArg<'tcx>) -> Self { fn new(expose_default_const_substs: Option<TyCtxt<'tcx>>, root: GenericArg<'tcx>) -> Self {
Self { tcx, stack: smallvec![root], last_subtree: 1, visited: SsoHashSet::new() } Self {
expose_default_const_substs,
stack: smallvec![root],
last_subtree: 1,
visited: SsoHashSet::new(),
}
} }
/// Skips the subtree corresponding to the last type /// Skips the subtree corresponding to the last type
@ -56,7 +61,7 @@ impl<'tcx> Iterator for TypeWalker<'tcx> {
let next = self.stack.pop()?; let next = self.stack.pop()?;
self.last_subtree = self.stack.len(); self.last_subtree = self.stack.len();
if self.visited.insert(next) { if self.visited.insert(next) {
push_inner(self.tcx, &mut self.stack, next); push_inner(self.expose_default_const_substs, &mut self.stack, next);
debug!("next: stack={:?}", self.stack); debug!("next: stack={:?}", self.stack);
return Some(next); return Some(next);
} }
@ -76,7 +81,7 @@ impl GenericArg<'tcx> {
/// [isize] => { [isize], isize } /// [isize] => { [isize], isize }
/// ``` /// ```
pub fn walk(self, tcx: TyCtxt<'tcx>) -> TypeWalker<'tcx> { pub fn walk(self, tcx: TyCtxt<'tcx>) -> TypeWalker<'tcx> {
TypeWalker::new(tcx, self) TypeWalker::new(Some(tcx), self)
} }
/// Iterator that walks the immediate children of `self`. Hence /// Iterator that walks the immediate children of `self`. Hence
@ -92,13 +97,17 @@ impl GenericArg<'tcx> {
visited: &mut SsoHashSet<GenericArg<'tcx>>, visited: &mut SsoHashSet<GenericArg<'tcx>>,
) -> impl Iterator<Item = GenericArg<'tcx>> { ) -> impl Iterator<Item = GenericArg<'tcx>> {
let mut stack = SmallVec::new(); let mut stack = SmallVec::new();
push_inner(tcx, &mut stack, self); push_inner(Some(tcx), &mut stack, self);
stack.retain(|a| visited.insert(*a)); stack.retain(|a| visited.insert(*a));
stack.into_iter() stack.into_iter()
} }
} }
impl<'tcx> super::TyS<'tcx> { impl<'tcx> super::TyS<'tcx> {
pub fn walk_ignoring_default_const_substs(&'tcx self) -> TypeWalker<'tcx> {
TypeWalker::new(None, self.into())
}
/// Iterator that walks `self` and any types reachable from /// Iterator that walks `self` and any types reachable from
/// `self`, in depth-first order. Note that just walks the types /// `self`, in depth-first order. Note that just walks the types
/// that appear in `self`, it does not descend into the fields of /// that appear in `self`, it does not descend into the fields of
@ -110,7 +119,7 @@ impl<'tcx> super::TyS<'tcx> {
/// [isize] => { [isize], isize } /// [isize] => { [isize], isize }
/// ``` /// ```
pub fn walk(&'tcx self, tcx: TyCtxt<'tcx>) -> TypeWalker<'tcx> { pub fn walk(&'tcx self, tcx: TyCtxt<'tcx>) -> TypeWalker<'tcx> {
TypeWalker::new(tcx, self.into()) TypeWalker::new(Some(tcx), self.into())
} }
} }
@ -121,7 +130,7 @@ impl<'tcx> super::TyS<'tcx> {
/// natural order one would expect (basically, the order of the /// natural order one would expect (basically, the order of the
/// types as they are written). /// types as they are written).
fn push_inner<'tcx>( fn push_inner<'tcx>(
tcx: TyCtxt<'tcx>, expose_default_const_substs: Option<TyCtxt<'tcx>>,
stack: &mut TypeWalkerStack<'tcx>, stack: &mut TypeWalkerStack<'tcx>,
parent: GenericArg<'tcx>, parent: GenericArg<'tcx>,
) { ) {
@ -202,7 +211,11 @@ fn push_inner<'tcx>(
| ty::ConstKind::Error(_) => {} | ty::ConstKind::Error(_) => {}
ty::ConstKind::Unevaluated(ct) => { ty::ConstKind::Unevaluated(ct) => {
stack.extend(ct.substs(tcx).iter().rev()); if let Some(tcx) = expose_default_const_substs {
stack.extend(ct.substs(tcx).iter().rev());
} else if let Some(substs) = ct.substs_ {
stack.extend(substs.iter().rev());
}
} }
} }
} }

View File

@ -114,7 +114,12 @@ fn insert_required_predicates_to_be_wf<'tcx>(
required_predicates: &mut RequiredPredicates<'tcx>, required_predicates: &mut RequiredPredicates<'tcx>,
explicit_map: &mut ExplicitPredicatesMap<'tcx>, explicit_map: &mut ExplicitPredicatesMap<'tcx>,
) { ) {
for arg in field_ty.walk(tcx) { // We must not look into the default substs of consts
// as computing those depends on the results of `predicates_of`.
//
// Luckily the only types contained in default substs are type
// parameters which don't matter here.
for arg in field_ty.walk_ignoring_default_const_substs() {
let ty = match arg.unpack() { let ty = match arg.unpack() {
GenericArgKind::Type(ty) => ty, GenericArgKind::Type(ty) => ty,