mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Rollup merge of #55745 - nnethercote:outlives_components-SmallVec, r=matthewjasper
Convert `outlives_components`' return value to a `SmallVec` outparam. This avoids some allocations, reducing instruction counts by 1% on a couple of benchmarks.
This commit is contained in:
commit
f0a6e3a583
@ -366,7 +366,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, '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) => {
|
||||
|
@ -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 @@ where
|
||||
|
||||
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 @@ where
|
||||
.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
|
||||
|
@ -155,7 +155,8 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, '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
|
||||
|
@ -200,8 +200,10 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, '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() {
|
||||
|
@ -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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '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)));
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ use ty::{List, TyS, ParamEnvAnd, ParamEnv};
|
||||
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 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
Param(_) |
|
||||
Bound(..) |
|
||||
Infer(_) |
|
||||
Error => {
|
||||
vec![]
|
||||
}
|
||||
Error => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@ use rustc::mir::{BasicBlock, FakeReadCause, Local, Location, Mir, Place};
|
||||
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 @@ impl<'tcx> Visitor<'tcx> for GatherBorrowedRegions {
|
||||
|
||||
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); }
|
||||
_ => {},
|
||||
|
@ -20,6 +20,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
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()
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user