Convert `outlives_components`' return value to a `SmallVec` outparam.
This avoids some allocations, reducing instruction counts by 1% on a
couple of benchmarks.
let mut types = vec![concrete_ty];
let bound_region = |r| self.sub_regions(infer::CallReturn(span), least_region, r);
while let Some(ty) = types.pop() {
- let mut components = self.tcx.outlives_components(ty);
+ let mut components = smallvec![];
+ self.tcx.push_outlives_components(ty, &mut components);
while let Some(component) = components.pop() {
match component {
Component::Region(r) => {
// except according to those terms.
//! Code that handles "type-outlives" constraints like `T: 'a`. This
-//! is based on the `outlives_components` function defined on the tcx,
+//! is based on the `push_outlives_components` function defined on the tcx,
//! but it adds a bit of heuristics on top, in particular to deal with
//! associated types and projections.
//!
assert!(!ty.has_escaping_bound_vars());
- let components = self.tcx.outlives_components(ty);
- self.components_must_outlive(origin, components, region);
+ let mut components = smallvec![];
+ self.tcx.push_outlives_components(ty, &mut components);
+ self.components_must_outlive(origin, &components, region);
}
fn components_must_outlive(
&mut self,
origin: infer::SubregionOrigin<'tcx>,
- components: Vec<Component<'tcx>>,
+ components: &[Component<'tcx>],
region: ty::Region<'tcx>,
) {
- for component in components {
+ for component in components.iter() {
let origin = origin.clone();
match component {
Component::Region(region1) => {
.push_sub_region_constraint(origin, region, region1);
}
Component::Param(param_ty) => {
- self.param_ty_must_outlive(origin, region, param_ty);
+ self.param_ty_must_outlive(origin, region, *param_ty);
}
Component::Projection(projection_ty) => {
- self.projection_must_outlive(origin, region, projection_ty);
+ self.projection_must_outlive(origin, region, *projection_ty);
}
Component::EscapingProjection(subcomponents) => {
- self.components_must_outlive(origin, subcomponents, region);
+ self.components_must_outlive(origin, &subcomponents, region);
}
Component::UnresolvedInferenceVariable(v) => {
// ignore this, we presume it will yield an error
.map(|subty| self.type_bound(subty))
.collect::<Vec<_>>();
- let mut regions = ty.regions();
+ 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
}
let visited = &mut self.visited;
+ let mut components = smallvec![];
+ tcx.push_outlives_components(ty_max, &mut components);
self.stack.extend(
- tcx.outlives_components(ty_max)
+ components
.into_iter()
.filter_map(|component| match component {
Component::Region(r) => if r.is_late_bound() {
// refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that
// RFC for reference.
+use smallvec::SmallVec;
use ty::{self, Ty, TyCtxt, TypeFoldable};
#[derive(Debug)]
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
- /// Returns all the things that must outlive `'a` for the condition
+ /// Push onto `out` all the things that must outlive `'a` for the condition
/// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
- pub fn outlives_components(&self, ty0: Ty<'tcx>)
- -> Vec<Component<'tcx>> {
- let mut components = vec![];
- self.compute_components(ty0, &mut components);
- debug!("components({:?}) = {:?}", ty0, components);
- components
+ pub fn push_outlives_components(&self, ty0: Ty<'tcx>,
+ out: &mut SmallVec<[Component<'tcx>; 4]>) {
+ self.compute_components(ty0, out);
+ debug!("components({:?}) = {:?}", ty0, out);
}
- fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
+ fn compute_components(&self, ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
// Descend through the types, looking for the various "base"
// components and collecting them into `out`. This is not written
// with `collect()` because of the need to sometimes skip subtrees
// list is maintained explicitly, because bound regions
// themselves can be readily identified.
- push_region_constraints(out, ty.regions());
+ push_region_constraints(ty, out);
for subty in ty.walk_shallow() {
self.compute_components(subty, out);
}
}
fn capture_components(&self, ty: Ty<'tcx>) -> Vec<Component<'tcx>> {
- let mut temp = vec![];
- push_region_constraints(&mut temp, ty.regions());
+ let mut temp = smallvec![];
+ push_region_constraints(ty, &mut temp);
for subty in ty.walk_shallow() {
self.compute_components(subty, &mut temp);
}
- temp
+ temp.into_iter().collect()
}
}
-fn push_region_constraints<'tcx>(out: &mut Vec<Component<'tcx>>, regions: Vec<ty::Region<'tcx>>) {
+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)));
}
use util::captures::Captures;
use mir::interpret::{Scalar, Pointer};
+use smallvec::SmallVec;
use std::iter;
use std::cmp::Ordering;
use rustc_target::spec::abi;
}
}
- /// Returns 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 regions(&self) -> Vec<ty::Region<'tcx>> {
+ /// Push 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.sty {
Ref(region, _, _) => {
- vec![region]
+ out.push(region);
}
Dynamic(ref obj, region) => {
- let mut v = vec![region];
- v.extend(obj.principal().skip_binder().substs.regions());
- v
+ out.push(region);
+ out.extend(obj.principal().skip_binder().substs.regions());
}
Adt(_, substs) | Opaque(_, substs) => {
- substs.regions().collect()
+ out.extend(substs.regions())
}
Closure(_, ClosureSubsts { ref substs }) |
Generator(_, GeneratorSubsts { ref substs }, _) => {
- substs.regions().collect()
+ out.extend(substs.regions())
}
Projection(ref data) | UnnormalizedProjection(ref data) => {
- data.substs.regions().collect()
+ out.extend(data.substs.regions())
}
FnDef(..) |
FnPtr(_) |
Param(_) |
Bound(..) |
Infer(_) |
- Error => {
- vec![]
- }
+ Error => {}
}
}
use rustc::mir::{Rvalue, Statement, StatementKind};
use rustc::mir::visit::{MutVisitor, Visitor, TyContext};
use rustc::ty::{Ty, RegionKind, TyCtxt};
+use smallvec::smallvec;
use transform::{MirPass, MirSource};
pub struct CleanEndRegions;
fn visit_ty(&mut self, ty: &Ty<'tcx>, _: TyContext) {
// Gather regions that occur in types
- for re in ty.walk().flat_map(|t| t.regions()) {
+ let mut regions = smallvec![];
+ for t in ty.walk() {
+ t.push_regions(&mut regions);
+ }
+ for re in regions {
match *re {
RegionKind::ReScope(ce) => { self.seen_regions.insert(ce); }
_ => {},
use rustc::ty::outlives::Component;
use rustc::ty::query::Providers;
use rustc::ty::wf;
+use smallvec::{SmallVec, smallvec};
use syntax::ast::DUMMY_NODE_ID;
use syntax::source_map::DUMMY_SP;
use rustc::traits::FulfillmentContext;
None => vec![],
Some(ty::OutlivesPredicate(ty_a, r_b)) => {
let ty_a = infcx.resolve_type_vars_if_possible(&ty_a);
- let components = tcx.outlives_components(ty_a);
+ let mut components = smallvec![];
+ tcx.push_outlives_components(ty_a, &mut components);
implied_bounds_from_components(r_b, components)
}
},
/// those relationships.
fn implied_bounds_from_components(
sub_region: ty::Region<'tcx>,
- sup_components: Vec<Component<'tcx>>,
+ sup_components: SmallVec<[Component<'tcx>; 4]>,
) -> Vec<OutlivesBound<'tcx>> {
sup_components
.into_iter()
use rustc::ty::outlives::Component;
use rustc::ty::subst::{Kind, UnpackedKind};
use rustc::ty::{self, Region, RegionKind, Ty, TyCtxt};
+use smallvec::smallvec;
use std::collections::BTreeSet;
/// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
//
// Or if within `struct Foo<U>` you had `T = Vec<U>`, then
// we would want to add `U: 'outlived_region`
- for component in tcx.outlives_components(ty) {
+ let mut components = smallvec![];
+ tcx.push_outlives_components(ty, &mut components);
+ for component in components {
match component {
Component::Region(r) => {
// This would arise from something like: