ty/walk: switch walk_shallow from Ty to GenericArg.

This commit is contained in:
Eduard-Mihai Burtescu 2020-03-20 07:42:14 +02:00
parent 0d4705b009
commit 26199f0cbc
5 changed files with 58 additions and 80 deletions

View File

@ -3,11 +3,9 @@ use crate::infer::{GenericKind, VerifyBound};
use crate::traits;
use rustc_data_structures::captures::Captures;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst};
use rustc_middle::ty::{self, Ty, TyCtxt};
use smallvec::smallvec;
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
/// obligation into a series of `'a: 'b` constraints and "verifys", as
/// described on the module comment. The final constraints are emitted
@ -44,7 +42,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
match ty.kind {
ty::Param(p) => self.param_bound(p),
ty::Projection(data) => self.projection_bound(data),
_ => self.recursive_type_bound(ty),
_ => self.recursive_bound(ty.into()),
}
}
@ -144,25 +142,33 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
// see the extensive comment in projection_must_outlive
let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
let recursive_bound = self.recursive_type_bound(ty);
let recursive_bound = self.recursive_bound(ty.into());
VerifyBound::AnyBound(env_bounds.chain(trait_bounds).collect()).or(recursive_bound)
}
fn recursive_type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
let mut bounds = ty.walk_shallow().map(|subty| self.type_bound(subty)).collect::<Vec<_>>();
fn recursive_bound(&self, parent: GenericArg<'tcx>) -> VerifyBound<'tcx> {
let mut bounds = parent
.walk_shallow()
.filter_map(|child| match child.unpack() {
GenericArgKind::Type(ty) => Some(self.type_bound(ty)),
GenericArgKind::Lifetime(lt) => {
// Ignore late-bound regions.
if !lt.is_late_bound() { Some(VerifyBound::OutlivedBy(lt)) } else { None }
}
GenericArgKind::Const(_) => Some(self.recursive_bound(child)),
})
.filter(|bound| {
// Remove bounds that must hold, since they are not interesting.
!bound.must_hold()
});
let mut regions = smallvec![];
ty.push_regions(&mut regions);
regions.retain(|r| !r.is_late_bound()); // ignore late-bound regions
bounds.push(VerifyBound::AllBounds(
regions.into_iter().map(|r| VerifyBound::OutlivedBy(r)).collect(),
));
// remove bounds that must hold, since they are not interesting
bounds.retain(|b| !b.must_hold());
if bounds.len() == 1 { bounds.pop().unwrap() } else { VerifyBound::AllBounds(bounds) }
match (bounds.next(), bounds.next()) {
(Some(first), None) => first,
(first, second) => {
VerifyBound::AllBounds(first.into_iter().chain(second).chain(bounds).collect())
}
}
}
/// Searches the environment for where-clauses like `G: 'a` where

View File

@ -2701,13 +2701,6 @@ impl<'tcx> TyS<'tcx> {
TypeWalker::new(self.into())
}
/// Iterator that walks the immediate children of `self`. Hence
/// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
/// (but not `i32`, like `walk`).
pub fn walk_shallow(&'tcx self) -> impl Iterator<Item = Ty<'tcx>> {
walk::walk_shallow(self.into())
}
/// Walks `ty` and any types appearing within `ty`, invoking the
/// callback `f` on each type. If the callback returns `false`, then the
/// children of the current type are ignored.

View File

@ -2,6 +2,7 @@
// refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that
// RFC for reference.
use crate::ty::subst::{GenericArg, GenericArgKind};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
use smallvec::SmallVec;
@ -107,8 +108,9 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
// fallback case: hard code
// OutlivesProjectionComponents. Continue walking
// through and constrain Pi.
let subcomponents = capture_components(tcx, ty);
out.push(Component::EscapingProjection(subcomponents));
let mut subcomponents = smallvec![];
compute_components_recursive(tcx, ty.into(), &mut subcomponents);
out.push(Component::EscapingProjection(subcomponents.into_iter().collect()));
}
}
@ -153,26 +155,30 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
// "bound regions list". In our representation, no such
// list is maintained explicitly, because bound regions
// themselves can be readily identified.
push_region_constraints(ty, out);
for subty in ty.walk_shallow() {
compute_components(tcx, subty, out);
}
compute_components_recursive(tcx, ty.into(), out);
}
}
}
fn capture_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Vec<Component<'tcx>> {
let mut temp = smallvec![];
push_region_constraints(ty, &mut temp);
for subty in ty.walk_shallow() {
compute_components(tcx, subty, &mut temp);
fn compute_components_recursive(
tcx: TyCtxt<'tcx>,
parent: GenericArg<'tcx>,
out: &mut SmallVec<[Component<'tcx>; 4]>,
) {
for child in parent.walk_shallow() {
match child.unpack() {
GenericArgKind::Type(ty) => {
compute_components(tcx, ty, out);
}
GenericArgKind::Lifetime(lt) => {
// Ignore late-bound regions.
if !lt.is_late_bound() {
out.push(Component::Region(lt));
}
}
GenericArgKind::Const(_) => {
compute_components_recursive(tcx, child, out);
}
}
}
temp.into_iter().collect()
}
fn push_region_constraints<'tcx>(ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
let mut regions = smallvec![];
ty.push_regions(&mut regions);
out.extend(regions.iter().filter(|&r| !r.is_late_bound()).map(|r| Component::Region(r)));
}

View File

@ -25,7 +25,6 @@ use rustc_macros::HashStable;
use rustc_span::symbol::{kw, Symbol};
use rustc_target::abi::{Size, VariantIdx};
use rustc_target::spec::abi;
use smallvec::SmallVec;
use std::borrow::Cow;
use std::cmp::Ordering;
use std::marker::PhantomData;
@ -2152,31 +2151,6 @@ impl<'tcx> TyS<'tcx> {
}
}
/// Pushes onto `out` the regions directly referenced from this type (but not
/// types reachable from this type via `walk_tys`). This ignores late-bound
/// regions binders.
pub fn push_regions(&self, out: &mut SmallVec<[ty::Region<'tcx>; 4]>) {
match self.kind {
Ref(region, _, _) => {
out.push(region);
}
Dynamic(ref obj, region) => {
out.push(region);
if let Some(principal) = obj.principal() {
out.extend(principal.skip_binder().substs.regions());
}
}
Adt(_, substs) | Opaque(_, substs) => out.extend(substs.regions()),
Closure(_, ref substs) | Generator(_, ref substs, _) => out.extend(substs.regions()),
Projection(ref data) | UnnormalizedProjection(ref data) => {
out.extend(data.substs.regions())
}
FnDef(..) | FnPtr(_) | GeneratorWitness(..) | Bool | Char | Int(_) | Uint(_)
| Float(_) | Str | Array(..) | Slice(_) | RawPtr(_) | Never | Tuple(..)
| Foreign(..) | Param(_) | Bound(..) | Placeholder(..) | Infer(_) | Error => {}
}
}
/// When we create a closure, we record its kind (i.e., what trait
/// it implements) into its `ClosureSubsts` using a type
/// parameter. This is kind of a phantom type, except that the

View File

@ -57,16 +57,15 @@ impl<'tcx> Iterator for TypeWalker<'tcx> {
}
}
pub fn walk_shallow(parent: GenericArg<'tcx>) -> impl Iterator<Item = Ty<'tcx>> {
let mut stack = SmallVec::new();
push_inner(&mut stack, parent);
stack.into_iter().filter_map(|child| {
// FIXME(eddyb) remove this filter and expose all `GenericArg`s.
match child.unpack() {
GenericArgKind::Type(ty) => Some(ty),
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => None,
}
})
impl GenericArg<'tcx> {
/// Iterator that walks the immediate children of `self`. Hence
/// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
/// (but not `i32`, like `walk`).
pub fn walk_shallow(self) -> impl Iterator<Item = GenericArg<'tcx>> {
let mut stack = SmallVec::new();
push_inner(&mut stack, self);
stack.into_iter()
}
}
// We push `GenericArg`s on the stack in reverse order so as to