]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #55745 - nnethercote:outlives_components-SmallVec, r=matthewjasper
authorPietro Albini <pietro@pietroalbini.org>
Sat, 10 Nov 2018 23:21:12 +0000 (00:21 +0100)
committerGitHub <noreply@github.com>
Sat, 10 Nov 2018 23:21:12 +0000 (00:21 +0100)
Convert `outlives_components`' return value to a `SmallVec` outparam.

This avoids some allocations, reducing instruction counts by 1% on a
couple of benchmarks.

src/librustc/infer/opaque_types/mod.rs
src/librustc/infer/outlives/obligations.rs
src/librustc/infer/outlives/verify.rs
src/librustc/traits/util.rs
src/librustc/ty/outlives.rs
src/librustc/ty/sty.rs
src/librustc_mir/transform/cleanup_post_borrowck.rs
src/librustc_traits/implied_outlives_bounds.rs
src/librustc_typeck/outlives/utils.rs

index 49858972416d8f1c025b18e4fbd256d9a47bf87a..cc73dd63816aa466b4b75c1eaab89f59e65c120f 100644 (file)
@@ -366,7 +366,8 @@ pub fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
         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) => {
index 523f03c2cfc4773afc81f9c008a0fa7294bb5f92..f2825887f36e2d28dae70de54776647af151f6ee 100644 (file)
@@ -9,7 +9,7 @@
 // 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.
 //!
@@ -307,17 +307,18 @@ pub fn type_must_outlive(
 
         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) => {
@@ -325,13 +326,13 @@ fn components_must_outlive(
                         .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
index 88d45671b9afdfab86538d6a1b6d6345cfeed3ba..a7a79dd2e6560e6113407cfdb3c1fef2dc9f5971 100644 (file)
@@ -155,7 +155,8 @@ fn recursive_type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
             .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
index 24097fcca703b934e89c59ec813643ae3b571497..3a882506b41d6520e90921c0267f3752f75705b4 100644 (file)
@@ -200,8 +200,10 @@ fn push(&mut self, predicate: &ty::Predicate<'tcx>) {
                 }
 
                 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() {
index 449730c9d0601d6c991e7705131b3eb71ed122fe..7fac88a3d78f1855b97371e8dd793adf88572625 100644 (file)
@@ -12,6 +12,7 @@
 // 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)]
@@ -55,17 +56,15 @@ pub enum Component<'tcx> {
 }
 
 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
@@ -164,7 +163,7 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
                 // 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);
                 }
@@ -173,15 +172,17 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
     }
 
     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)));
 }
index 5c8549cba2333e3a37a5a7ee43a69709d16af263..a4130bf15cb8272f2bd726ae061b5f758a03a042 100644 (file)
@@ -22,6 +22,7 @@
 use util::captures::Captures;
 use mir::interpret::{Scalar, Pointer};
 
+use smallvec::SmallVec;
 use std::iter;
 use std::cmp::Ordering;
 use rustc_target::spec::abi;
@@ -1846,28 +1847,27 @@ pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> {
         }
     }
 
-    /// 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(_) |
@@ -1887,9 +1887,7 @@ pub fn regions(&self) -> Vec<ty::Region<'tcx>> {
             Param(_) |
             Bound(..) |
             Infer(_) |
-            Error => {
-                vec![]
-            }
+            Error => {}
         }
     }
 
index 4d3b422ab28171770a340aa99bfead908262e78e..98311444e28718d3b24aef07a04d92ba9a221e22 100644 (file)
@@ -37,6 +37,7 @@
 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;
@@ -80,7 +81,11 @@ fn visit_rvalue(&mut self,
 
     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); }
                 _ => {},
index 7cc064f9c3d3d81906ad96caaa92a9e4c5e79a23..7514c2c18e7ca8f77aec0fbe7fcd15be28e12c8a 100644 (file)
@@ -20,6 +20,7 @@
 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;
@@ -133,7 +134,8 @@ fn compute_implied_outlives_bounds<'tcx>(
                     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)
                     }
                 },
@@ -155,7 +157,7 @@ fn compute_implied_outlives_bounds<'tcx>(
 /// 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()
index d748d93d8988e63470b142ac6381cf7f01f9285b..6ed59837eb49a2c23a709491a25918c5e49d4c03 100644 (file)
@@ -11,6 +11,7 @@
 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
@@ -40,7 +41,9 @@ pub fn insert_outlives_predicate<'tcx>(
             //
             // 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: