Skip to content

Commit 5b2314b

Browse files
committed
Use SmallVec outparams in several functions.
This avoids some allocations, reducing instruction counts by 1% on a couple of benchmarks.
1 parent 0117b42 commit 5b2314b

File tree

9 files changed

+56
-42
lines changed

9 files changed

+56
-42
lines changed

src/librustc/infer/opaque_types/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
366366
let mut types = vec![concrete_ty];
367367
let bound_region = |r| self.sub_regions(infer::CallReturn(span), least_region, r);
368368
while let Some(ty) = types.pop() {
369-
let mut components = self.tcx.outlives_components(ty);
369+
let mut components = smallvec![];
370+
self.tcx.push_outlives_components(ty, &mut components);
370371
while let Some(component) = components.pop() {
371372
match component {
372373
Component::Region(r) => {

src/librustc/infer/outlives/obligations.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
//! Code that handles "type-outlives" constraints like `T: 'a`. This
12-
//! is based on the `outlives_components` function defined on the tcx,
12+
//! is based on the `push_outlives_components` function defined on the tcx,
1313
//! but it adds a bit of heuristics on top, in particular to deal with
1414
//! associated types and projections.
1515
//!
@@ -307,31 +307,32 @@ where
307307

308308
assert!(!ty.has_escaping_bound_vars());
309309

310-
let components = self.tcx.outlives_components(ty);
311-
self.components_must_outlive(origin, components, region);
310+
let mut components = smallvec![];
311+
self.tcx.push_outlives_components(ty, &mut components);
312+
self.components_must_outlive(origin, &components, region);
312313
}
313314

314315
fn components_must_outlive(
315316
&mut self,
316317
origin: infer::SubregionOrigin<'tcx>,
317-
components: Vec<Component<'tcx>>,
318+
components: &[Component<'tcx>],
318319
region: ty::Region<'tcx>,
319320
) {
320-
for component in components {
321+
for component in components.iter() {
321322
let origin = origin.clone();
322323
match component {
323324
Component::Region(region1) => {
324325
self.delegate
325326
.push_sub_region_constraint(origin, region, region1);
326327
}
327328
Component::Param(param_ty) => {
328-
self.param_ty_must_outlive(origin, region, param_ty);
329+
self.param_ty_must_outlive(origin, region, *param_ty);
329330
}
330331
Component::Projection(projection_ty) => {
331-
self.projection_must_outlive(origin, region, projection_ty);
332+
self.projection_must_outlive(origin, region, *projection_ty);
332333
}
333334
Component::EscapingProjection(subcomponents) => {
334-
self.components_must_outlive(origin, subcomponents, region);
335+
self.components_must_outlive(origin, &subcomponents, region);
335336
}
336337
Component::UnresolvedInferenceVariable(v) => {
337338
// ignore this, we presume it will yield an error

src/librustc/infer/outlives/verify.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
155155
.map(|subty| self.type_bound(subty))
156156
.collect::<Vec<_>>();
157157

158-
let mut regions = ty.regions();
158+
let mut regions = smallvec![];
159+
ty.push_regions(&mut regions);
159160
regions.retain(|r| !r.is_late_bound()); // ignore late-bound regions
160161
bounds.push(VerifyBound::AllBounds(
161162
regions

src/librustc/traits/util.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,10 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
200200
}
201201

202202
let visited = &mut self.visited;
203+
let mut components = smallvec![];
204+
tcx.push_outlives_components(ty_max, &mut components);
203205
self.stack.extend(
204-
tcx.outlives_components(ty_max)
206+
components
205207
.into_iter()
206208
.filter_map(|component| match component {
207209
Component::Region(r) => if r.is_late_bound() {

src/librustc/ty/outlives.rs

+14-13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that
1313
// RFC for reference.
1414

15+
use smallvec::SmallVec;
1516
use ty::{self, Ty, TyCtxt, TypeFoldable};
1617

1718
#[derive(Debug)]
@@ -55,17 +56,15 @@ pub enum Component<'tcx> {
5556
}
5657

5758
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
58-
/// Returns all the things that must outlive `'a` for the condition
59+
/// Push onto `out` all the things that must outlive `'a` for the condition
5960
/// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
60-
pub fn outlives_components(&self, ty0: Ty<'tcx>)
61-
-> Vec<Component<'tcx>> {
62-
let mut components = vec![];
63-
self.compute_components(ty0, &mut components);
64-
debug!("components({:?}) = {:?}", ty0, components);
65-
components
61+
pub fn push_outlives_components(&self, ty0: Ty<'tcx>,
62+
out: &mut SmallVec<[Component<'tcx>; 4]>) {
63+
self.compute_components(ty0, out);
64+
debug!("components({:?}) = {:?}", ty0, out);
6665
}
6766

68-
fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
67+
fn compute_components(&self, ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
6968
// Descend through the types, looking for the various "base"
7069
// components and collecting them into `out`. This is not written
7170
// with `collect()` because of the need to sometimes skip subtrees
@@ -164,7 +163,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
164163
// list is maintained explicitly, because bound regions
165164
// themselves can be readily identified.
166165

167-
push_region_constraints(out, ty.regions());
166+
push_region_constraints(ty, out);
168167
for subty in ty.walk_shallow() {
169168
self.compute_components(subty, out);
170169
}
@@ -173,15 +172,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
173172
}
174173

175174
fn capture_components(&self, ty: Ty<'tcx>) -> Vec<Component<'tcx>> {
176-
let mut temp = vec![];
177-
push_region_constraints(&mut temp, ty.regions());
175+
let mut temp = smallvec![];
176+
push_region_constraints(ty, &mut temp);
178177
for subty in ty.walk_shallow() {
179178
self.compute_components(subty, &mut temp);
180179
}
181-
temp
180+
temp.into_iter().collect()
182181
}
183182
}
184183

185-
fn push_region_constraints<'tcx>(out: &mut Vec<Component<'tcx>>, regions: Vec<ty::Region<'tcx>>) {
184+
fn push_region_constraints<'tcx>(ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
185+
let mut regions = smallvec![];
186+
ty.push_regions(&mut regions);
186187
out.extend(regions.iter().filter(|&r| !r.is_late_bound()).map(|r| Component::Region(r)));
187188
}

src/librustc/ty/sty.rs

+12-14
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use ty::{List, TyS, ParamEnvAnd, ParamEnv};
2222
use util::captures::Captures;
2323
use mir::interpret::{Scalar, Pointer};
2424

25+
use smallvec::SmallVec;
2526
use std::iter;
2627
use std::cmp::Ordering;
2728
use rustc_target::spec::abi;
@@ -1846,28 +1847,27 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
18461847
}
18471848
}
18481849

1849-
/// Returns the regions directly referenced from this type (but
1850-
/// not types reachable from this type via `walk_tys`). This
1851-
/// ignores late-bound regions binders.
1852-
pub fn regions(&self) -> Vec<ty::Region<'tcx>> {
1850+
/// Push onto `out` the regions directly referenced from this type (but not
1851+
/// types reachable from this type via `walk_tys`). This ignores late-bound
1852+
/// regions binders.
1853+
pub fn push_regions(&self, out: &mut SmallVec<[ty::Region<'tcx>; 4]>) {
18531854
match self.sty {
18541855
Ref(region, _, _) => {
1855-
vec![region]
1856+
out.push(region);
18561857
}
18571858
Dynamic(ref obj, region) => {
1858-
let mut v = vec![region];
1859-
v.extend(obj.principal().skip_binder().substs.regions());
1860-
v
1859+
out.push(region);
1860+
out.extend(obj.principal().skip_binder().substs.regions());
18611861
}
18621862
Adt(_, substs) | Opaque(_, substs) => {
1863-
substs.regions().collect()
1863+
out.extend(substs.regions())
18641864
}
18651865
Closure(_, ClosureSubsts { ref substs }) |
18661866
Generator(_, GeneratorSubsts { ref substs }, _) => {
1867-
substs.regions().collect()
1867+
out.extend(substs.regions())
18681868
}
18691869
Projection(ref data) | UnnormalizedProjection(ref data) => {
1870-
data.substs.regions().collect()
1870+
out.extend(data.substs.regions())
18711871
}
18721872
FnDef(..) |
18731873
FnPtr(_) |
@@ -1887,9 +1887,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
18871887
Param(_) |
18881888
Bound(..) |
18891889
Infer(_) |
1890-
Error => {
1891-
vec![]
1892-
}
1890+
Error => {}
18931891
}
18941892
}
18951893

src/librustc_mir/transform/cleanup_post_borrowck.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use rustc::mir::{BasicBlock, FakeReadCause, Local, Location, Mir, Place};
3737
use rustc::mir::{Rvalue, Statement, StatementKind};
3838
use rustc::mir::visit::{MutVisitor, Visitor, TyContext};
3939
use rustc::ty::{Ty, RegionKind, TyCtxt};
40+
use smallvec::smallvec;
4041
use transform::{MirPass, MirSource};
4142

4243
pub struct CleanEndRegions;
@@ -80,7 +81,11 @@ impl<'tcx> Visitor<'tcx> for GatherBorrowedRegions {
8081

8182
fn visit_ty(&mut self, ty: &Ty<'tcx>, _: TyContext) {
8283
// Gather regions that occur in types
83-
for re in ty.walk().flat_map(|t| t.regions()) {
84+
let mut regions = smallvec![];
85+
for t in ty.walk() {
86+
t.push_regions(&mut regions);
87+
}
88+
for re in regions {
8489
match *re {
8590
RegionKind::ReScope(ce) => { self.seen_regions.insert(ce); }
8691
_ => {},

src/librustc_traits/implied_outlives_bounds.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
2020
use rustc::ty::outlives::Component;
2121
use rustc::ty::query::Providers;
2222
use rustc::ty::wf;
23+
use smallvec::{SmallVec, smallvec};
2324
use syntax::ast::DUMMY_NODE_ID;
2425
use syntax::source_map::DUMMY_SP;
2526
use rustc::traits::FulfillmentContext;
@@ -133,7 +134,8 @@ fn compute_implied_outlives_bounds<'tcx>(
133134
None => vec![],
134135
Some(ty::OutlivesPredicate(ty_a, r_b)) => {
135136
let ty_a = infcx.resolve_type_vars_if_possible(&ty_a);
136-
let components = tcx.outlives_components(ty_a);
137+
let mut components = smallvec![];
138+
tcx.push_outlives_components(ty_a, &mut components);
137139
implied_bounds_from_components(r_b, components)
138140
}
139141
},
@@ -155,7 +157,7 @@ fn compute_implied_outlives_bounds<'tcx>(
155157
/// those relationships.
156158
fn implied_bounds_from_components(
157159
sub_region: ty::Region<'tcx>,
158-
sup_components: Vec<Component<'tcx>>,
160+
sup_components: SmallVec<[Component<'tcx>; 4]>,
159161
) -> Vec<OutlivesBound<'tcx>> {
160162
sup_components
161163
.into_iter()

src/librustc_typeck/outlives/utils.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use rustc::ty::outlives::Component;
1212
use rustc::ty::subst::{Kind, UnpackedKind};
1313
use rustc::ty::{self, Region, RegionKind, Ty, TyCtxt};
14+
use smallvec::smallvec;
1415
use std::collections::BTreeSet;
1516

1617
/// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
@@ -40,7 +41,9 @@ pub fn insert_outlives_predicate<'tcx>(
4041
//
4142
// Or if within `struct Foo<U>` you had `T = Vec<U>`, then
4243
// we would want to add `U: 'outlived_region`
43-
for component in tcx.outlives_components(ty) {
44+
let mut components = smallvec![];
45+
tcx.push_outlives_components(ty, &mut components);
46+
for component in components {
4447
match component {
4548
Component::Region(r) => {
4649
// This would arise from something like:

0 commit comments

Comments
 (0)