Skip to content

Commit

Permalink
ty/walk: switch walk_shallow from Ty to GenericArg.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Apr 6, 2020
1 parent 0d4705b commit 26199f0
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 80 deletions.
42 changes: 24 additions & 18 deletions src/librustc_infer/infer/outlives/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()),
}
}

Expand Down Expand Up @@ -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<_>>();

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());
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()
});

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
Expand Down
7 changes: 0 additions & 7 deletions src/librustc_middle/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
44 changes: 25 additions & 19 deletions src/librustc_middle/ty/outlives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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()));
}
}

Expand Down Expand Up @@ -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)));
}
26 changes: 0 additions & 26 deletions src/librustc_middle/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
19 changes: 9 additions & 10 deletions src/librustc_middle/ty/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 26199f0

Please sign in to comment.