Auto merge of #37270 - Mark-Simulacrum:smallvec-optimized-arenas, r=eddyb
Add ArrayVec and AccumulateVec to reduce heap allocations during interning of slices Updates `mk_tup`, `mk_type_list`, and `mk_substs` to allow interning directly from iterators. The previous PR, #37220, changed some of the calls to pass a borrowed slice from `Vec` instead of directly passing the iterator, and these changes further optimize that to avoid the allocation entirely. This change yields 50% less malloc calls in [some cases](https://pastebin.mozilla.org/8921686). It also yields decent, though not amazing, performance improvements: ``` futures-rs-test 4.091s vs 4.021s --> 1.017x faster (variance: 1.004x, 1.004x) helloworld 0.219s vs 0.220s --> 0.993x faster (variance: 1.010x, 1.018x) html5ever-2016- 3.805s vs 3.736s --> 1.018x faster (variance: 1.003x, 1.009x) hyper.0.5.0 4.609s vs 4.571s --> 1.008x faster (variance: 1.015x, 1.017x) inflate-0.1.0 3.864s vs 3.883s --> 0.995x faster (variance: 1.232x, 1.005x) issue-32062-equ 0.309s vs 0.299s --> 1.033x faster (variance: 1.014x, 1.003x) issue-32278-big 1.614s vs 1.594s --> 1.013x faster (variance: 1.007x, 1.004x) jld-day15-parse 1.390s vs 1.326s --> 1.049x faster (variance: 1.006x, 1.009x) piston-image-0. 10.930s vs 10.675s --> 1.024x faster (variance: 1.006x, 1.010x) reddit-stress 2.302s vs 2.261s --> 1.019x faster (variance: 1.010x, 1.026x) regex.0.1.30 2.250s vs 2.240s --> 1.005x faster (variance: 1.087x, 1.011x) rust-encoding-0 1.895s vs 1.887s --> 1.005x faster (variance: 1.005x, 1.018x) syntex-0.42.2 29.045s vs 28.663s --> 1.013x faster (variance: 1.004x, 1.006x) syntex-0.42.2-i 13.925s vs 13.868s --> 1.004x faster (variance: 1.022x, 1.007x) ``` We implement a small-size optimized vector, intended to be used primarily for collection of presumed to be short iterators. This vector cannot be "upsized/reallocated" into a heap-allocated vector, since that would require (slow) branching logic, but during the initial collection from an iterator heap-allocation is possible. We make the new `AccumulateVec` and `ArrayVec` generic over implementors of the `Array` trait, of which there is currently one, `[T; 8]`. In the future, this is likely to expand to other values of N. Huge thanks to @nnethercote for collecting the performance and other statistics mentioned above.
This commit is contained in:
commit
a6b3b01b5f
@ -157,13 +157,15 @@ impl<T> TypedArena<T> {
|
||||
|
||||
/// Allocates a slice of objects that are copy into the `TypedArena`, returning a mutable
|
||||
/// reference to it. Will panic if passed a zero-sized types.
|
||||
///
|
||||
/// Panics:
|
||||
/// - Zero-sized types
|
||||
/// - Zero-length slices
|
||||
#[inline]
|
||||
pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
|
||||
where T: Copy {
|
||||
assert!(mem::size_of::<T>() != 0);
|
||||
if slice.len() == 0 {
|
||||
return unsafe { slice::from_raw_parts_mut(heap::EMPTY as *mut T, 0) };
|
||||
}
|
||||
assert!(slice.len() != 0);
|
||||
|
||||
let available_capacity_bytes = self.end.get() as usize - self.ptr.get() as usize;
|
||||
let at_least_bytes = slice.len() * mem::size_of::<T>();
|
||||
|
@ -1008,6 +1008,11 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (_min, max) = self.iter.size_hint();
|
||||
(0, max)
|
||||
}
|
||||
}
|
||||
|
||||
let mut adapter = Adapter { iter: iter.into_iter(), err: None };
|
||||
|
@ -163,7 +163,7 @@ impl<'tcx> Rvalue<'tcx> {
|
||||
let lhs_ty = lhs.ty(mir, tcx);
|
||||
let rhs_ty = rhs.ty(mir, tcx);
|
||||
let ty = op.ty(tcx, lhs_ty, rhs_ty);
|
||||
let ty = tcx.mk_tup(&[ty, tcx.types.bool]);
|
||||
let ty = tcx.intern_tup(&[ty, tcx.types.bool]);
|
||||
Some(ty)
|
||||
}
|
||||
&Rvalue::UnaryOp(_, ref operand) => {
|
||||
@ -184,7 +184,7 @@ impl<'tcx> Rvalue<'tcx> {
|
||||
}
|
||||
AggregateKind::Tuple => {
|
||||
Some(tcx.mk_tup(
|
||||
&ops.iter().map(|op| op.ty(mir, tcx)).collect::<Vec<_>>()
|
||||
ops.iter().map(|op| op.ty(mir, tcx))
|
||||
))
|
||||
}
|
||||
AggregateKind::Adt(def, _, substs, _) => {
|
||||
|
@ -11,7 +11,7 @@
|
||||
use dep_graph::DepGraph;
|
||||
use infer::{InferCtxt, InferOk};
|
||||
use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, TyCtxt, ToPredicate};
|
||||
use ty::subst::{Substs, Subst};
|
||||
use ty::subst::Subst;
|
||||
use rustc_data_structures::obligation_forest::{ObligationForest, Error};
|
||||
use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProcessor};
|
||||
use std::marker::PhantomData;
|
||||
@ -159,7 +159,7 @@ impl<'a, 'gcx, 'tcx> DeferredObligation<'tcx> {
|
||||
let concrete_ty = ty_scheme.ty.subst(tcx, substs);
|
||||
let predicate = ty::TraitRef {
|
||||
def_id: self.predicate.def_id(),
|
||||
substs: Substs::new_trait(tcx, concrete_ty, &[])
|
||||
substs: tcx.mk_substs_trait(concrete_ty, &[])
|
||||
}.to_predicate();
|
||||
|
||||
let original_obligation = Obligation::new(self.cause.clone(),
|
||||
|
@ -2596,7 +2596,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
k
|
||||
}
|
||||
});
|
||||
let substs = Substs::new(tcx, params);
|
||||
let substs = tcx.mk_substs(params);
|
||||
for &ty in fields.split_last().unwrap().1 {
|
||||
if ty.subst(tcx, substs).references_error() {
|
||||
return Err(Unimplemented);
|
||||
@ -2616,7 +2616,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
k
|
||||
}
|
||||
});
|
||||
let new_struct = tcx.mk_adt(def, Substs::new(tcx, params));
|
||||
let new_struct = tcx.mk_adt(def, tcx.mk_substs(params));
|
||||
let origin = TypeOrigin::Misc(obligation.cause.span);
|
||||
let InferOk { obligations, .. } =
|
||||
self.infcx.sub_types(false, origin, new_struct, target)
|
||||
|
@ -380,7 +380,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
Ok(def_id) => {
|
||||
Ok(ty::TraitRef {
|
||||
def_id: def_id,
|
||||
substs: Substs::new_trait(self, param_ty, &[])
|
||||
substs: self.mk_substs_trait(param_ty, &[])
|
||||
})
|
||||
}
|
||||
Err(e) => {
|
||||
@ -400,7 +400,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
{
|
||||
let trait_ref = ty::TraitRef {
|
||||
def_id: trait_def_id,
|
||||
substs: Substs::new_trait(self, param_ty, ty_params)
|
||||
substs: self.mk_substs_trait(param_ty, ty_params)
|
||||
};
|
||||
predicate_for_trait_ref(cause, trait_ref, recursion_depth)
|
||||
}
|
||||
@ -486,11 +486,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
{
|
||||
let arguments_tuple = match tuple_arguments {
|
||||
TupleArgumentsFlag::No => sig.0.inputs[0],
|
||||
TupleArgumentsFlag::Yes => self.mk_tup(&sig.0.inputs),
|
||||
TupleArgumentsFlag::Yes => self.intern_tup(&sig.0.inputs[..]),
|
||||
};
|
||||
let trait_ref = ty::TraitRef {
|
||||
def_id: fn_trait_def_id,
|
||||
substs: Substs::new_trait(self, self_ty, &[arguments_tuple]),
|
||||
substs: self.mk_substs_trait(self_ty, &[arguments_tuple]),
|
||||
};
|
||||
ty::Binder((trait_ref, sig.0.output))
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ use ty::maps;
|
||||
use util::common::MemoizationMap;
|
||||
use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
|
||||
use util::nodemap::{FnvHashMap, FnvHashSet};
|
||||
use rustc_data_structures::accumulate_vec::AccumulateVec;
|
||||
|
||||
use arena::TypedArena;
|
||||
use std::borrow::Borrow;
|
||||
@ -44,6 +45,7 @@ use std::hash::{Hash, Hasher};
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use std::iter;
|
||||
use syntax::ast::{self, Name, NodeId};
|
||||
use syntax::attr;
|
||||
use syntax::parse::token::{self, keywords};
|
||||
@ -824,6 +826,9 @@ impl<'a, 'tcx> Lift<'tcx> for Ty<'a> {
|
||||
impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
|
||||
type Lifted = &'tcx Substs<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Substs<'tcx>> {
|
||||
if self.len() == 0 {
|
||||
return Some(Slice::empty());
|
||||
}
|
||||
if let Some(&Interned(substs)) = tcx.interners.substs.borrow().get(&self[..]) {
|
||||
if *self as *const _ == substs as *const _ {
|
||||
return Some(substs);
|
||||
@ -859,6 +864,9 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Ty<'a>> {
|
||||
type Lifted = &'tcx Slice<Ty<'tcx>>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
|
||||
-> Option<&'tcx Slice<Ty<'tcx>>> {
|
||||
if self.len() == 0 {
|
||||
return Some(Slice::empty());
|
||||
}
|
||||
if let Some(&Interned(list)) = tcx.interners.type_list.borrow().get(&self[..]) {
|
||||
if *self as *const _ == list as *const _ {
|
||||
return Some(list);
|
||||
@ -1212,8 +1220,8 @@ macro_rules! slice_interners {
|
||||
}
|
||||
|
||||
slice_interners!(
|
||||
type_list: mk_type_list(Ty),
|
||||
substs: mk_substs(Kind)
|
||||
type_list: _intern_type_list(Ty),
|
||||
substs: _intern_substs(Kind)
|
||||
);
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
@ -1318,12 +1326,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self.mk_ty(TySlice(ty))
|
||||
}
|
||||
|
||||
pub fn mk_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
|
||||
self.mk_ty(TyTuple(self.mk_type_list(ts)))
|
||||
pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
|
||||
self.mk_ty(TyTuple(self.intern_type_list(ts)))
|
||||
}
|
||||
|
||||
pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I) -> I::Output {
|
||||
iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts))))
|
||||
}
|
||||
|
||||
pub fn mk_nil(self) -> Ty<'tcx> {
|
||||
self.mk_tup(&[])
|
||||
self.intern_tup(&[])
|
||||
}
|
||||
|
||||
pub fn mk_diverging_default(self) -> Ty<'tcx> {
|
||||
@ -1369,7 +1381,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
-> Ty<'tcx> {
|
||||
self.mk_closure_from_closure_substs(closure_id, ClosureSubsts {
|
||||
func_substs: substs,
|
||||
upvar_tys: self.mk_type_list(tys)
|
||||
upvar_tys: self.intern_type_list(tys)
|
||||
})
|
||||
}
|
||||
|
||||
@ -1414,6 +1426,40 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self.mk_ty(TyAnon(def_id, substs))
|
||||
}
|
||||
|
||||
pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx Slice<Ty<'tcx>> {
|
||||
if ts.len() == 0 {
|
||||
Slice::empty()
|
||||
} else {
|
||||
self._intern_type_list(ts)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn intern_substs(self, ts: &[Kind<'tcx>]) -> &'tcx Slice<Kind<'tcx>> {
|
||||
if ts.len() == 0 {
|
||||
Slice::empty()
|
||||
} else {
|
||||
self._intern_substs(ts)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_type_list<I: InternAs<[Ty<'tcx>],
|
||||
&'tcx Slice<Ty<'tcx>>>>(self, iter: I) -> I::Output {
|
||||
iter.intern_with(|xs| self.intern_type_list(xs))
|
||||
}
|
||||
|
||||
pub fn mk_substs<I: InternAs<[Kind<'tcx>],
|
||||
&'tcx Slice<Kind<'tcx>>>>(self, iter: I) -> I::Output {
|
||||
iter.intern_with(|xs| self.intern_substs(xs))
|
||||
}
|
||||
|
||||
pub fn mk_substs_trait(self,
|
||||
s: Ty<'tcx>,
|
||||
t: &[Ty<'tcx>])
|
||||
-> &'tcx Substs<'tcx>
|
||||
{
|
||||
self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from))
|
||||
}
|
||||
|
||||
pub fn trait_items(self, trait_did: DefId) -> Rc<Vec<ty::ImplOrTraitItem<'gcx>>> {
|
||||
self.trait_items_cache.memoize(trait_did, || {
|
||||
let def_ids = self.impl_or_trait_items(trait_did);
|
||||
@ -1432,3 +1478,39 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub trait InternAs<T: ?Sized, R> {
|
||||
type Output;
|
||||
fn intern_with<F>(self, F) -> Self::Output
|
||||
where F: FnOnce(&T) -> R;
|
||||
}
|
||||
|
||||
impl<I, T, R, E> InternAs<[T], R> for I
|
||||
where E: InternIteratorElement<T, R>,
|
||||
I: Iterator<Item=E> {
|
||||
type Output = E::Output;
|
||||
fn intern_with<F>(self, f: F) -> Self::Output
|
||||
where F: FnOnce(&[T]) -> R {
|
||||
E::intern_with(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait InternIteratorElement<T, R>: Sized {
|
||||
type Output;
|
||||
fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<T, R> InternIteratorElement<T, R> for T {
|
||||
type Output = R;
|
||||
fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output {
|
||||
f(&iter.collect::<AccumulateVec<[_; 8]>>())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
|
||||
type Output = Result<R, E>;
|
||||
fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output {
|
||||
Ok(f(&iter.collect::<Result<AccumulateVec<[_; 8]>, _>>()?))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use std::slice;
|
||||
use std::vec::IntoIter;
|
||||
use std::mem;
|
||||
use syntax::ast::{self, Name, NodeId};
|
||||
use syntax::attr;
|
||||
use syntax::parse::token::{self, InternedString};
|
||||
@ -561,6 +562,14 @@ impl<'a, T> IntoIterator for &'a Slice<T> {
|
||||
|
||||
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice<Ty<'tcx>> {}
|
||||
|
||||
impl<T> Slice<T> {
|
||||
pub fn empty<'a>() -> &'a Slice<T> {
|
||||
unsafe {
|
||||
mem::transmute(slice::from_raw_parts(0x1 as *const T, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Upvars do not get their own node-id. Instead, we use the pair of
|
||||
/// the original var id (that is, the root variable that is referenced
|
||||
/// by the upvar) and the id of the closure expression.
|
||||
@ -1798,7 +1807,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
|
||||
_ if tys.references_error() => tcx.types.err,
|
||||
0 => tcx.types.bool,
|
||||
1 => tys[0],
|
||||
_ => tcx.mk_tup(&tys)
|
||||
_ => tcx.intern_tup(&tys[..])
|
||||
};
|
||||
|
||||
match self.sized_constraint.get(dep_node()) {
|
||||
@ -1874,7 +1883,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
|
||||
};
|
||||
let sized_predicate = Binder(TraitRef {
|
||||
def_id: sized_trait,
|
||||
substs: Substs::new_trait(tcx, ty, &[])
|
||||
substs: tcx.mk_substs_trait(ty, &[])
|
||||
}).to_predicate();
|
||||
let predicates = tcx.lookup_predicates(self.did).predicates;
|
||||
if predicates.into_iter().any(|p| p == sized_predicate) {
|
||||
@ -2125,7 +2134,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn node_id_item_substs(self, id: NodeId) -> ItemSubsts<'gcx> {
|
||||
match self.tables.borrow().item_substs.get(&id) {
|
||||
None => ItemSubsts {
|
||||
substs: Substs::empty(self.global_tcx())
|
||||
substs: self.global_tcx().intern_substs(&[])
|
||||
},
|
||||
Some(ts) => ts.clone(),
|
||||
}
|
||||
@ -2797,7 +2806,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
// regions, so it shouldn't matter what we use for the free id
|
||||
let free_id_outlive = self.region_maps.node_extent(ast::DUMMY_NODE_ID);
|
||||
ty::ParameterEnvironment {
|
||||
free_substs: Substs::empty(self),
|
||||
free_substs: self.intern_substs(&[]),
|
||||
caller_bounds: Vec::new(),
|
||||
implicit_region_bound: self.mk_region(ty::ReEmpty),
|
||||
free_id_outlive: free_id_outlive,
|
||||
|
@ -49,12 +49,6 @@ pub trait TypeRelation<'a, 'gcx: 'a+'tcx, 'tcx: 'a> : Sized {
|
||||
Relate::relate(self, a, b)
|
||||
}
|
||||
|
||||
/// Relete elements of two slices pairwise.
|
||||
fn relate_zip<T: Relate<'tcx>>(&mut self, a: &[T], b: &[T]) -> RelateResult<'tcx, Vec<T>> {
|
||||
assert_eq!(a.len(), b.len());
|
||||
a.iter().zip(b).map(|(a, b)| self.relate(a, b)).collect()
|
||||
}
|
||||
|
||||
/// Switch variance for the purpose of relating `a` and `b`.
|
||||
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
|
||||
variance: ty::Variance,
|
||||
@ -158,7 +152,7 @@ pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R,
|
||||
}
|
||||
});
|
||||
|
||||
Substs::maybe_new(tcx, params)
|
||||
Ok(tcx.mk_substs(params)?)
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for &'tcx ty::BareFnTy<'tcx> {
|
||||
@ -489,10 +483,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
|
||||
(&ty::TyTuple(as_), &ty::TyTuple(bs)) =>
|
||||
{
|
||||
if as_.len() == bs.len() {
|
||||
let ts = as_.iter().zip(bs)
|
||||
.map(|(a, b)| relation.relate(a, b))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
Ok(tcx.mk_tup(&ts))
|
||||
Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)))?)
|
||||
} else if !(as_.is_empty() || bs.is_empty()) {
|
||||
Err(TypeError::TupleSize(
|
||||
expected_found(relation, &as_.len(), &bs.len())))
|
||||
@ -544,10 +535,11 @@ impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> {
|
||||
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
|
||||
{
|
||||
let substs = relate_substs(relation, None, a.func_substs, b.func_substs)?;
|
||||
let upvar_tys = relation.relate_zip(&a.upvar_tys, &b.upvar_tys)?;
|
||||
assert_eq!(a.upvar_tys.len(), b.upvar_tys.len());
|
||||
Ok(ty::ClosureSubsts {
|
||||
func_substs: substs,
|
||||
upvar_tys: relation.tcx().mk_type_list(&upvar_tys)
|
||||
upvar_tys: relation.tcx().mk_type_list(
|
||||
a.upvar_tys.iter().zip(b.upvar_tys).map(|(a, b)| relation.relate(a, b)))?
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
use infer::type_variable;
|
||||
use ty::{self, Lift, Ty, TyCtxt};
|
||||
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
use rustc_data_structures::accumulate_vec::AccumulateVec;
|
||||
|
||||
use std::rc::Rc;
|
||||
use syntax::abi;
|
||||
@ -448,8 +449,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> {
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<Ty<'tcx>> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let tys = self.iter().map(|t| t.fold_with(folder)).collect::<Vec<_>>();
|
||||
folder.tcx().mk_type_list(&tys)
|
||||
let v = self.iter().map(|t| t.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
|
||||
folder.tcx().intern_type_list(&v)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
|
@ -16,6 +16,7 @@ use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
|
||||
use serialize::{self, Encodable, Encoder, Decodable, Decoder};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use rustc_data_structures::accumulate_vec::AccumulateVec;
|
||||
|
||||
use core::nonzero::NonZero;
|
||||
use std::fmt;
|
||||
@ -164,31 +165,6 @@ impl<'tcx> Decodable for Kind<'tcx> {
|
||||
pub type Substs<'tcx> = Slice<Kind<'tcx>>;
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||
pub fn new<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>, params: I)
|
||||
-> &'tcx Substs<'tcx>
|
||||
where I: IntoIterator<Item=Kind<'tcx>> {
|
||||
tcx.mk_substs(¶ms.into_iter().collect::<Vec<_>>())
|
||||
}
|
||||
|
||||
pub fn maybe_new<I, E>(tcx: TyCtxt<'a, 'gcx, 'tcx>, params: I)
|
||||
-> Result<&'tcx Substs<'tcx>, E>
|
||||
where I: IntoIterator<Item=Result<Kind<'tcx>, E>> {
|
||||
Ok(Substs::new(tcx, params.into_iter().collect::<Result<Vec<_>, _>>()?))
|
||||
}
|
||||
|
||||
pub fn new_trait(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
s: Ty<'tcx>,
|
||||
t: &[Ty<'tcx>])
|
||||
-> &'tcx Substs<'tcx>
|
||||
{
|
||||
let t = iter::once(s).chain(t.iter().cloned());
|
||||
Substs::new(tcx, t.map(Kind::from))
|
||||
}
|
||||
|
||||
pub fn empty(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> {
|
||||
Substs::new(tcx, iter::empty())
|
||||
}
|
||||
|
||||
/// Creates a Substs for generic parameter definitions,
|
||||
/// by calling closures to obtain each region and type.
|
||||
/// The closures get to observe the Substs as they're
|
||||
@ -203,10 +179,8 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||
FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx> {
|
||||
let defs = tcx.lookup_generics(def_id);
|
||||
let mut substs = Vec::with_capacity(defs.count());
|
||||
|
||||
Substs::fill_item(&mut substs, tcx, defs, &mut mk_region, &mut mk_type);
|
||||
|
||||
Substs::new(tcx, substs)
|
||||
tcx.intern_substs(&substs)
|
||||
}
|
||||
|
||||
fn fill_item<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
|
||||
@ -298,20 +272,20 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||
target_substs: &Substs<'tcx>)
|
||||
-> &'tcx Substs<'tcx> {
|
||||
let defs = tcx.lookup_generics(source_ancestor);
|
||||
Substs::new(tcx, target_substs.iter().chain(&self[defs.own_count()..]).cloned())
|
||||
tcx.mk_substs(target_substs.iter().chain(&self[defs.own_count()..]).cloned())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let params: Vec<_> = self.iter().map(|k| k.fold_with(folder)).collect();
|
||||
let params: AccumulateVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect();
|
||||
|
||||
// If folding doesn't change the substs, it's faster to avoid
|
||||
// calling `mk_substs` and instead reuse the existing substs.
|
||||
if params[..] == self[..] {
|
||||
self
|
||||
} else {
|
||||
folder.tcx().mk_substs(¶ms)
|
||||
folder.tcx().intern_substs(¶ms)
|
||||
}
|
||||
}
|
||||
|
||||
@ -547,10 +521,9 @@ impl<'a, 'gcx, 'tcx> ty::TraitRef<'tcx> {
|
||||
-> ty::TraitRef<'tcx> {
|
||||
let defs = tcx.lookup_generics(trait_id);
|
||||
|
||||
let params = substs[..defs.own_count()].iter().cloned();
|
||||
ty::TraitRef {
|
||||
def_id: trait_id,
|
||||
substs: Substs::new(tcx, params)
|
||||
substs: tcx.intern_substs(&substs[..defs.own_count()])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -562,10 +535,9 @@ impl<'a, 'gcx, 'tcx> ty::ExistentialTraitRef<'tcx> {
|
||||
// Assert there is a Self.
|
||||
trait_ref.substs.type_at(0);
|
||||
|
||||
let params = trait_ref.substs[1..].iter().cloned();
|
||||
ty::ExistentialTraitRef {
|
||||
def_id: trait_ref.def_id,
|
||||
substs: Substs::new(tcx, params)
|
||||
substs: tcx.intern_substs(&trait_ref.substs[1..])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -582,11 +554,10 @@ impl<'a, 'gcx, 'tcx> ty::PolyExistentialTraitRef<'tcx> {
|
||||
assert!(!self_ty.has_escaping_regions());
|
||||
|
||||
self.map_bound(|trait_ref| {
|
||||
let params = trait_ref.substs.iter().cloned();
|
||||
let params = iter::once(Kind::from(self_ty)).chain(params);
|
||||
ty::TraitRef {
|
||||
def_id: trait_ref.def_id,
|
||||
substs: Substs::new(tcx, params)
|
||||
substs: tcx.mk_substs(
|
||||
iter::once(Kind::from(self_ty)).chain(trait_ref.substs.iter().cloned()))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use ty::subst::{self, Subst, Substs};
|
||||
use ty::subst::{self, Subst};
|
||||
use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
|
||||
use ty::{TyBool, TyChar, TyAdt};
|
||||
use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
|
||||
@ -886,7 +886,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
|
||||
// by looking up the projections associated with the def_id.
|
||||
let item_predicates = tcx.lookup_predicates(def_id);
|
||||
let substs = tcx.lift(&substs).unwrap_or_else(|| {
|
||||
Substs::empty(tcx)
|
||||
tcx.intern_substs(&[])
|
||||
});
|
||||
let bounds = item_predicates.instantiate(tcx, substs);
|
||||
|
||||
|
@ -857,7 +857,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
let unit_temp = Lvalue::Local(self.patch.new_temp(tcx.mk_nil()));
|
||||
let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem)
|
||||
.unwrap_or_else(|e| tcx.sess.fatal(&e));
|
||||
let substs = Substs::new(tcx, iter::once(Kind::from(ty)));
|
||||
let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
|
||||
let fty = tcx.lookup_item_type(free_func).ty.subst(tcx, substs);
|
||||
|
||||
self.patch.new_block(BasicBlockData {
|
||||
|
52
src/librustc_data_structures/accumulate_vec.rs
Normal file
52
src/librustc_data_structures/accumulate_vec.rs
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! A vector type intended to be used for collecting from iterators onto the stack.
|
||||
//!
|
||||
//! Space for up to N elements is provided on the stack. If more elements are collected, Vec is
|
||||
//! used to store the values on the heap. This type does not support re-allocating onto the heap,
|
||||
//! and there is no way to push more elements onto the existing storage.
|
||||
//!
|
||||
//! The N above is determined by Array's implementor, by way of an associatated constant.
|
||||
|
||||
use std::ops::Deref;
|
||||
use std::iter::{IntoIterator, FromIterator};
|
||||
|
||||
use array_vec::{Array, ArrayVec};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AccumulateVec<A: Array> {
|
||||
Array(ArrayVec<A>),
|
||||
Heap(Vec<A::Element>)
|
||||
}
|
||||
|
||||
impl<A: Array> Deref for AccumulateVec<A> {
|
||||
type Target = [A::Element];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match *self {
|
||||
AccumulateVec::Array(ref v) => &v[..],
|
||||
AccumulateVec::Heap(ref v) => &v[..],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> FromIterator<A::Element> for AccumulateVec<A> {
|
||||
fn from_iter<I>(iter: I) -> AccumulateVec<A> where I: IntoIterator<Item=A::Element> {
|
||||
let iter = iter.into_iter();
|
||||
if iter.size_hint().1.map_or(false, |n| n <= A::LEN) {
|
||||
let mut v = ArrayVec::new();
|
||||
v.extend(iter);
|
||||
AccumulateVec::Array(v)
|
||||
} else {
|
||||
AccumulateVec::Heap(iter.collect())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
106
src/librustc_data_structures/array_vec.rs
Normal file
106
src/librustc_data_structures/array_vec.rs
Normal file
@ -0,0 +1,106 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! A stack-allocated vector, allowing storage of N elements on the stack.
|
||||
//!
|
||||
//! Currently, only the N = 8 case is supported (due to Array only being impl-ed for [T; 8]).
|
||||
|
||||
use std::marker::Unsize;
|
||||
use std::iter::Extend;
|
||||
use std::ptr::drop_in_place;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::slice;
|
||||
use std::fmt;
|
||||
|
||||
pub unsafe trait Array {
|
||||
type Element;
|
||||
type PartialStorage: Default + Unsize<[ManuallyDrop<Self::Element>]>;
|
||||
const LEN: usize;
|
||||
}
|
||||
|
||||
unsafe impl<T> Array for [T; 8] {
|
||||
type Element = T;
|
||||
type PartialStorage = [ManuallyDrop<T>; 8];
|
||||
const LEN: usize = 8;
|
||||
}
|
||||
|
||||
pub struct ArrayVec<A: Array> {
|
||||
count: usize,
|
||||
values: A::PartialStorage
|
||||
}
|
||||
|
||||
impl<A: Array> ArrayVec<A> {
|
||||
pub fn new() -> Self {
|
||||
ArrayVec {
|
||||
count: 0,
|
||||
values: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> fmt::Debug for ArrayVec<A>
|
||||
where A: Array,
|
||||
A::Element: fmt::Debug {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self[..].fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> Deref for ArrayVec<A> {
|
||||
type Target = [A::Element];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe {
|
||||
slice::from_raw_parts(&self.values as *const _ as *const A::Element, self.count)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> DerefMut for ArrayVec<A> {
|
||||
fn deref_mut(&mut self) -> &mut [A::Element] {
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(&mut self.values as *mut _ as *mut A::Element, self.count)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> Drop for ArrayVec<A> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
drop_in_place(&mut self[..])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> Extend<A::Element> for ArrayVec<A> {
|
||||
fn extend<I>(&mut self, iter: I) where I: IntoIterator<Item=A::Element> {
|
||||
for el in iter {
|
||||
unsafe {
|
||||
let arr = &mut self.values as &mut [ManuallyDrop<_>];
|
||||
arr[self.count].value = el;
|
||||
}
|
||||
self.count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: This should use repr(transparent) from rust-lang/rfcs#1758.
|
||||
#[allow(unions_with_drop_fields)]
|
||||
pub union ManuallyDrop<T> {
|
||||
value: T,
|
||||
#[allow(dead_code)]
|
||||
empty: (),
|
||||
}
|
||||
|
||||
impl<T> Default for ManuallyDrop<T> {
|
||||
fn default() -> Self {
|
||||
ManuallyDrop { empty: () }
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,9 @@
|
||||
#![feature(staged_api)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(fn_traits)]
|
||||
#![feature(untagged_unions)]
|
||||
#![feature(associated_consts)]
|
||||
#![feature(unsize)]
|
||||
|
||||
#![cfg_attr(unix, feature(libc))]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
@ -41,6 +44,8 @@ extern crate serialize as rustc_serialize; // used by deriving
|
||||
#[cfg(unix)]
|
||||
extern crate libc;
|
||||
|
||||
pub mod array_vec;
|
||||
pub mod accumulate_vec;
|
||||
pub mod bitslice;
|
||||
pub mod blake2b;
|
||||
pub mod bitvec;
|
||||
|
@ -20,14 +20,13 @@ use rustc::middle::region::{self, CodeExtent};
|
||||
use rustc::middle::region::CodeExtentData;
|
||||
use rustc::middle::resolve_lifetime;
|
||||
use rustc::middle::stability;
|
||||
use rustc::ty::subst::{Kind, Subst, Substs};
|
||||
use rustc::ty::subst::{Kind, Subst};
|
||||
use rustc::traits::Reveal;
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc::infer::{self, InferOk, InferResult, TypeOrigin};
|
||||
use rustc_metadata::cstore::CStore;
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::session::{self, config};
|
||||
use std::iter;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use syntax::abi::Abi;
|
||||
@ -275,7 +274,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> {
|
||||
self.infcx.tcx.mk_tup(&[ty1, ty2])
|
||||
self.infcx.tcx.intern_tup(&[ty1, ty2])
|
||||
}
|
||||
|
||||
pub fn t_param(&self, index: u32) -> Ty<'tcx> {
|
||||
@ -679,7 +678,7 @@ fn subst_ty_renumber_bound() {
|
||||
env.t_fn(&[t_param], env.t_nil())
|
||||
};
|
||||
|
||||
let substs = Substs::new(env.infcx.tcx, iter::once(Kind::from(t_rptr_bound1)));
|
||||
let substs = env.infcx.tcx.intern_substs(&[Kind::from(t_rptr_bound1)]);
|
||||
let t_substituted = t_source.subst(env.infcx.tcx, substs);
|
||||
|
||||
// t_expected = fn(&'a isize)
|
||||
@ -714,7 +713,7 @@ fn subst_ty_renumber_some_bounds() {
|
||||
env.t_pair(t_param, env.t_fn(&[t_param], env.t_nil()))
|
||||
};
|
||||
|
||||
let substs = Substs::new(env.infcx.tcx, iter::once(Kind::from(t_rptr_bound1)));
|
||||
let substs = env.infcx.tcx.intern_substs(&[Kind::from(t_rptr_bound1)]);
|
||||
let t_substituted = t_source.subst(env.infcx.tcx, substs);
|
||||
|
||||
// t_expected = (&'a isize, fn(&'a isize))
|
||||
@ -776,7 +775,7 @@ fn subst_region_renumber_region() {
|
||||
env.t_fn(&[env.t_rptr(re_early)], env.t_nil())
|
||||
};
|
||||
|
||||
let substs = Substs::new(env.infcx.tcx, iter::once(Kind::from(re_bound1)));
|
||||
let substs = env.infcx.tcx.intern_substs(&[Kind::from(re_bound1)]);
|
||||
let t_substituted = t_source.subst(env.infcx.tcx, substs);
|
||||
|
||||
// t_expected = fn(&'a isize)
|
||||
@ -803,8 +802,8 @@ fn walk_ty() {
|
||||
let tcx = env.infcx.tcx;
|
||||
let int_ty = tcx.types.isize;
|
||||
let uint_ty = tcx.types.usize;
|
||||
let tup1_ty = tcx.mk_tup(&[int_ty, uint_ty, int_ty, uint_ty]);
|
||||
let tup2_ty = tcx.mk_tup(&[tup1_ty, tup1_ty, uint_ty]);
|
||||
let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty]);
|
||||
let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty]);
|
||||
let uniq_ty = tcx.mk_box(tup2_ty);
|
||||
let walked: Vec<_> = uniq_ty.walk().collect();
|
||||
assert_eq!(walked,
|
||||
@ -819,8 +818,8 @@ fn walk_ty_skip_subtree() {
|
||||
let tcx = env.infcx.tcx;
|
||||
let int_ty = tcx.types.isize;
|
||||
let uint_ty = tcx.types.usize;
|
||||
let tup1_ty = tcx.mk_tup(&[int_ty, uint_ty, int_ty, uint_ty]);
|
||||
let tup2_ty = tcx.mk_tup(&[tup1_ty, tup1_ty, uint_ty]);
|
||||
let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty]);
|
||||
let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty]);
|
||||
let uniq_ty = tcx.mk_box(tup2_ty);
|
||||
|
||||
// types we expect to see (in order), plus a boolean saying
|
||||
|
@ -503,21 +503,21 @@ impl LateLintPass for MissingCopyImplementations {
|
||||
return;
|
||||
}
|
||||
let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id));
|
||||
(def, cx.tcx.mk_adt(def, Substs::empty(cx.tcx)))
|
||||
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
|
||||
}
|
||||
hir::ItemUnion(_, ref ast_generics) => {
|
||||
if ast_generics.is_parameterized() {
|
||||
return;
|
||||
}
|
||||
let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id));
|
||||
(def, cx.tcx.mk_adt(def, Substs::empty(cx.tcx)))
|
||||
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
|
||||
}
|
||||
hir::ItemEnum(_, ref ast_generics) => {
|
||||
if ast_generics.is_parameterized() {
|
||||
return;
|
||||
}
|
||||
let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id));
|
||||
(def, cx.tcx.mk_adt(def, Substs::empty(cx.tcx)))
|
||||
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
|
@ -387,7 +387,7 @@ impl<'a, 'tcx> SpecializedDecoder<ty::GenericPredicates<'tcx>> for DecodeContext
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<&'tcx Substs<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> {
|
||||
Ok(self.tcx().mk_substs(&Vec::decode(self)?))
|
||||
Ok(self.tcx().mk_substs((0..self.read_usize()?).map(|_| Decodable::decode(self)))?)
|
||||
}
|
||||
}
|
||||
|
||||
@ -399,7 +399,7 @@ impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Region> for DecodeContext<'a, 'tcx>
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<Ty<'tcx>>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice<Ty<'tcx>>, Self::Error> {
|
||||
Ok(self.tcx().mk_type_list(&Vec::decode(self)?))
|
||||
Ok(self.tcx().mk_type_list((0..self.read_usize()?).map(|_| Decodable::decode(self)))?)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,7 +257,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
let source_info = self.source_info(span);
|
||||
let bool_ty = self.hir.bool_ty();
|
||||
if self.hir.check_overflow() && op.is_checkable() && ty.is_integral() {
|
||||
let result_tup = self.hir.tcx().mk_tup(&[ty, bool_ty]);
|
||||
let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty]);
|
||||
let result_value = self.temp(result_tup);
|
||||
|
||||
self.cfg.push_assign(block, source_info,
|
||||
|
@ -89,15 +89,13 @@ should go to.
|
||||
use build::{BlockAnd, BlockAndExtension, Builder, CFG, ScopeAuxiliary, ScopeId};
|
||||
use rustc::middle::region::{CodeExtent, CodeExtentData};
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::ty::subst::{Kind, Substs, Subst};
|
||||
use rustc::ty::subst::{Kind, Subst};
|
||||
use rustc::ty::{Ty, TyCtxt};
|
||||
use rustc::mir::repr::*;
|
||||
use syntax_pos::Span;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_data_structures::fnv::FnvHashMap;
|
||||
|
||||
use std::iter;
|
||||
|
||||
pub struct Scope<'tcx> {
|
||||
/// the scope-id within the scope_auxiliary
|
||||
id: ScopeId,
|
||||
@ -804,7 +802,7 @@ fn build_free<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
-> TerminatorKind<'tcx> {
|
||||
let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem)
|
||||
.unwrap_or_else(|e| tcx.sess.fatal(&e));
|
||||
let substs = Substs::new(tcx, iter::once(Kind::from(data.item_ty)));
|
||||
let substs = tcx.intern_substs(&[Kind::from(data.item_ty)]);
|
||||
TerminatorKind::Call {
|
||||
func: Operand::Constant(Constant {
|
||||
span: data.span,
|
||||
|
@ -27,7 +27,7 @@ use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::intravisit::FnKind;
|
||||
use rustc::hir::map::blocks::FnLikeNode;
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::ty::subst::{Subst, Substs};
|
||||
use rustc::ty::subst::Subst;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use syntax::parse::token;
|
||||
use rustc::hir;
|
||||
@ -146,7 +146,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
params: &[Ty<'tcx>])
|
||||
-> (Ty<'tcx>, Literal<'tcx>) {
|
||||
let method_name = token::intern(method_name);
|
||||
let substs = Substs::new_trait(self.tcx, self_ty, params);
|
||||
let substs = self.tcx.mk_substs_trait(self_ty, params);
|
||||
for trait_item in self.tcx.trait_items(trait_def_id).iter() {
|
||||
match *trait_item {
|
||||
ty::ImplOrTraitItem::MethodTraitItem(ref method) => {
|
||||
|
@ -214,7 +214,7 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
|
||||
// Allocate space:
|
||||
let def_id = require_alloc_fn(bcx, info_ty, ExchangeMallocFnLangItem);
|
||||
let r = Callee::def(bcx.ccx(), def_id, Substs::empty(bcx.tcx()))
|
||||
let r = Callee::def(bcx.ccx(), def_id, bcx.tcx().intern_substs(&[]))
|
||||
.call(bcx, debug_loc, &[size, align], None);
|
||||
|
||||
Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr))
|
||||
@ -405,7 +405,7 @@ pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx
|
||||
-> CustomCoerceUnsized {
|
||||
let trait_ref = ty::Binder(ty::TraitRef {
|
||||
def_id: scx.tcx().lang_items.coerce_unsized_trait().unwrap(),
|
||||
substs: Substs::new_trait(scx.tcx(), source_ty, &[target_ty])
|
||||
substs: scx.tcx().mk_substs_trait(source_ty, &[target_ty])
|
||||
});
|
||||
|
||||
match fulfill_obligation(scx, DUMMY_SP, trait_ref) {
|
||||
@ -848,7 +848,7 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
|
||||
common::validate_substs(instance.substs);
|
||||
(instance.substs, Some(instance.def))
|
||||
}
|
||||
None => (Substs::empty(ccx.tcx()), None)
|
||||
None => (ccx.tcx().intern_substs(&[]), None)
|
||||
};
|
||||
|
||||
let local_id = def_id.and_then(|id| ccx.tcx().map.as_local_node_id(id));
|
||||
@ -1211,7 +1211,7 @@ pub fn maybe_create_entry_wrapper(ccx: &CrateContext) {
|
||||
Ok(id) => id,
|
||||
Err(s) => ccx.sess().fatal(&s)
|
||||
};
|
||||
let empty_substs = Substs::empty(ccx.tcx());
|
||||
let empty_substs = ccx.tcx().intern_substs(&[]);
|
||||
let start_fn = Callee::def(ccx, start_def_id, empty_substs).reify(ccx);
|
||||
let args = {
|
||||
let opaque_rust_main =
|
||||
|
@ -326,7 +326,7 @@ fn trans_fn_pointer_shim<'a, 'tcx>(
|
||||
}
|
||||
};
|
||||
let sig = tcx.erase_late_bound_regions_and_normalize(sig);
|
||||
let tuple_input_ty = tcx.mk_tup(&sig.inputs);
|
||||
let tuple_input_ty = tcx.intern_tup(&sig.inputs[..]);
|
||||
let sig = ty::FnSig {
|
||||
inputs: vec![bare_fn_ty_maybe_ref,
|
||||
tuple_input_ty],
|
||||
|
@ -732,7 +732,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
create_fn_trans_item(scx,
|
||||
exchange_free_fn_def_id,
|
||||
fn_substs,
|
||||
Substs::empty(scx.tcx()));
|
||||
scx.tcx().intern_substs(&[]));
|
||||
|
||||
output.push(exchange_free_fn_trans_item);
|
||||
}
|
||||
@ -752,7 +752,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
.drop_trait()
|
||||
.unwrap();
|
||||
|
||||
let self_type_substs = Substs::new_trait(scx.tcx(), ty, &[]);
|
||||
let self_type_substs = scx.tcx().mk_substs_trait(ty, &[]);
|
||||
|
||||
let trait_ref = ty::TraitRef {
|
||||
def_id: drop_trait_def_id,
|
||||
@ -768,7 +768,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
let trans_item = create_fn_trans_item(scx,
|
||||
destructor_did,
|
||||
substs,
|
||||
Substs::empty(scx.tcx()));
|
||||
scx.tcx().intern_substs(&[]));
|
||||
output.push(trans_item);
|
||||
}
|
||||
|
||||
@ -1035,7 +1035,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a,
|
||||
|
||||
if let ty::TyTrait(ref trait_ty) = trait_ty.sty {
|
||||
let poly_trait_ref = trait_ty.principal.with_self_ty(scx.tcx(), impl_ty);
|
||||
let param_substs = Substs::empty(scx.tcx());
|
||||
let param_substs = scx.tcx().intern_substs(&[]);
|
||||
|
||||
// Walk all methods of the trait, including those of its supertraits
|
||||
let methods = traits::get_vtable_methods(scx.tcx(), poly_trait_ref);
|
||||
|
@ -376,7 +376,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
|
||||
let tcx = ccx.tcx();
|
||||
match tcx.lang_items.eh_personality() {
|
||||
Some(def_id) if !base::wants_msvc_seh(ccx.sess()) => {
|
||||
Callee::def(ccx, def_id, Substs::empty(tcx)).reify(ccx)
|
||||
Callee::def(ccx, def_id, tcx.intern_substs(&[])).reify(ccx)
|
||||
}
|
||||
_ => {
|
||||
if let Some(llpersonality) = ccx.eh_personality().get() {
|
||||
@ -403,7 +403,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
|
||||
let tcx = ccx.tcx();
|
||||
assert!(ccx.sess().target.target.options.custom_unwind_resume);
|
||||
if let Some(def_id) = tcx.lang_items.eh_unwind_resume() {
|
||||
return Callee::def(ccx, def_id, Substs::empty(tcx));
|
||||
return Callee::def(ccx, def_id, tcx.intern_substs(&[]));
|
||||
}
|
||||
|
||||
let ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
|
||||
|
@ -48,7 +48,7 @@ pub fn trans_exchange_free_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
|
||||
let def_id = langcall(bcx.tcx(), None, "", ExchangeFreeFnLangItem);
|
||||
let args = [PointerCast(bcx, v, Type::i8p(bcx.ccx())), size, align];
|
||||
Callee::def(bcx.ccx(), def_id, Substs::empty(bcx.tcx()))
|
||||
Callee::def(bcx.ccx(), def_id, bcx.tcx().intern_substs(&[]))
|
||||
.call(bcx, debug_loc, &args, None).bcx
|
||||
}
|
||||
|
||||
@ -292,7 +292,7 @@ fn trans_custom_dtor<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
|
||||
let trait_ref = ty::Binder(ty::TraitRef {
|
||||
def_id: tcx.lang_items.drop_trait().unwrap(),
|
||||
substs: Substs::new_trait(tcx, t, &[])
|
||||
substs: tcx.mk_substs_trait(t, &[])
|
||||
});
|
||||
let vtbl = match fulfill_obligation(bcx.ccx().shared(), DUMMY_SP, trait_ref) {
|
||||
traits::VtableImpl(data) => data,
|
||||
|
@ -773,7 +773,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
let rhs = self.const_operand(rhs, span)?;
|
||||
let ty = lhs.ty;
|
||||
let val_ty = op.ty(tcx, lhs.ty, rhs.ty);
|
||||
let binop_ty = tcx.mk_tup(&[val_ty, tcx.types.bool]);
|
||||
let binop_ty = tcx.intern_tup(&[val_ty, tcx.types.bool]);
|
||||
let (lhs, rhs) = (lhs.llval, rhs.llval);
|
||||
assert!(!ty.is_fp());
|
||||
|
||||
|
@ -430,7 +430,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
lhs.immediate(), rhs.immediate(),
|
||||
lhs.ty);
|
||||
let val_ty = op.ty(bcx.tcx(), lhs.ty, rhs.ty);
|
||||
let operand_ty = bcx.tcx().mk_tup(&[val_ty, bcx.tcx().types.bool]);
|
||||
let operand_ty = bcx.tcx().intern_tup(&[val_ty, bcx.tcx().types.bool]);
|
||||
let operand = OperandRef {
|
||||
val: result,
|
||||
ty: operand_ty
|
||||
|
@ -310,7 +310,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||
},
|
||||
TransItem::Static(node_id) => {
|
||||
let def_id = hir_map.local_def_id(node_id);
|
||||
let instance = Instance::new(def_id, Substs::empty(tcx));
|
||||
let instance = Instance::new(def_id, tcx.intern_substs(&[]));
|
||||
to_string_internal(tcx, "static ", instance)
|
||||
},
|
||||
};
|
||||
|
@ -635,9 +635,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
{
|
||||
let anon_scope = rscope.anon_type_scope();
|
||||
let binding_rscope = MaybeWithAnonTypes::new(BindingRscope::new(), anon_scope);
|
||||
let inputs: Vec<_> = data.inputs.iter().map(|a_t| {
|
||||
let inputs = self.tcx().mk_type_list(data.inputs.iter().map(|a_t| {
|
||||
self.ast_ty_arg_to_ty(&binding_rscope, None, region_substs, a_t)
|
||||
}).collect();
|
||||
}));
|
||||
let inputs_len = inputs.len();
|
||||
let input_params = || vec![String::new(); inputs_len];
|
||||
let implied_output_region = self.find_implied_output_region(&inputs, input_params);
|
||||
@ -660,7 +660,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
span: output_span
|
||||
};
|
||||
|
||||
(self.tcx().mk_tup(&inputs), output_binding)
|
||||
(self.tcx().mk_ty(ty::TyTuple(inputs)), output_binding)
|
||||
}
|
||||
|
||||
pub fn instantiate_poly_trait_ref(&self,
|
||||
@ -1660,10 +1660,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
tcx.types.never
|
||||
},
|
||||
hir::TyTup(ref fields) => {
|
||||
let flds = fields.iter()
|
||||
.map(|t| self.ast_ty_to_ty(rscope, &t))
|
||||
.collect::<Vec<_>>();
|
||||
tcx.mk_tup(&flds)
|
||||
tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(rscope, &t)))
|
||||
}
|
||||
hir::TyBareFn(ref bf) => {
|
||||
require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
|
||||
|
@ -168,8 +168,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
let max_len = cmp::max(expected_len, elements.len());
|
||||
|
||||
let element_tys: Vec<_> = (0 .. max_len).map(|_| self.next_ty_var()).collect();
|
||||
let pat_ty = tcx.mk_tup(&element_tys);
|
||||
let element_tys_iter = (0..max_len).map(|_| self.next_ty_var());
|
||||
let element_tys = tcx.mk_type_list(element_tys_iter);
|
||||
let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys));
|
||||
self.demand_eqtype(pat.span, expected, pat_ty);
|
||||
for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
|
||||
self.check_pat(elem, &element_tys[i]);
|
||||
|
@ -16,7 +16,6 @@ use rustc::traits;
|
||||
use rustc::ty::{self, Ty, TraitRef};
|
||||
use rustc::ty::{ToPredicate, TypeFoldable};
|
||||
use rustc::ty::{MethodCall, MethodCallee};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
|
||||
use rustc::hir;
|
||||
|
||||
@ -106,7 +105,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
|
||||
Some(f) => f,
|
||||
None => return None,
|
||||
},
|
||||
substs: Substs::new_trait(tcx, self.cur_ty, &[]),
|
||||
substs: tcx.mk_substs_trait(self.cur_ty, &[]),
|
||||
};
|
||||
|
||||
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
|
||||
|
@ -88,7 +88,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
// Tuple up the arguments and insert the resulting function type into
|
||||
// the `closures` table.
|
||||
fn_ty.sig.0.inputs = vec![self.tcx.mk_tup(&fn_ty.sig.0.inputs)];
|
||||
fn_ty.sig.0.inputs = vec![self.tcx.intern_tup(&fn_ty.sig.0.inputs[..])];
|
||||
|
||||
debug!("closure for {:?} --> sig={:?} opt_kind={:?}",
|
||||
expr_def_id,
|
||||
|
@ -89,7 +89,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
|
||||
"cxchg" | "cxchgweak" => (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)),
|
||||
param(ccx, 0),
|
||||
param(ccx, 0)),
|
||||
tcx.mk_tup(&[param(ccx, 0), tcx.types.bool])),
|
||||
tcx.intern_tup(&[param(ccx, 0), tcx.types.bool])),
|
||||
"load" => (1, vec!(tcx.mk_imm_ptr(param(ccx, 0))),
|
||||
param(ccx, 0)),
|
||||
"store" => (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)),
|
||||
@ -274,7 +274,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
|
||||
|
||||
"add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" =>
|
||||
(1, vec!(param(ccx, 0), param(ccx, 0)),
|
||||
tcx.mk_tup(&[param(ccx, 0), tcx.types.bool])),
|
||||
tcx.intern_tup(&[param(ccx, 0), tcx.types.bool])),
|
||||
|
||||
"unchecked_div" | "unchecked_rem" =>
|
||||
(1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
|
||||
|
@ -19,7 +19,6 @@ use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TypeFoldable};
|
||||
use hir::def::Def;
|
||||
use hir::def_id::{CRATE_DEF_INDEX, DefId};
|
||||
use middle::lang_items::FnOnceTraitLangItem;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::traits::{Obligation, SelectionContext};
|
||||
use util::nodemap::FnvHashSet;
|
||||
|
||||
@ -55,7 +54,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
self.autoderef(span, ty).any(|(ty, _)| {
|
||||
self.probe(|_| {
|
||||
let fn_once_substs = Substs::new_trait(tcx, ty, &[self.next_ty_var()]);
|
||||
let fn_once_substs = tcx.mk_substs_trait(ty, &[self.next_ty_var()]);
|
||||
let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
|
||||
let poly_trait_ref = trait_ref.to_poly_trait_ref();
|
||||
let obligation =
|
||||
|
@ -2388,7 +2388,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
let err_inputs = match tuple_arguments {
|
||||
DontTupleArguments => err_inputs,
|
||||
TupleArguments => vec![self.tcx.mk_tup(&err_inputs)],
|
||||
TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..])],
|
||||
};
|
||||
|
||||
self.check_argument_types(sp, &err_inputs[..], &[], args_no_rcvr,
|
||||
@ -3726,9 +3726,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
_ => None
|
||||
}
|
||||
});
|
||||
let mut err_field = false;
|
||||
|
||||
let elt_ts = elts.iter().enumerate().map(|(i, e)| {
|
||||
let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| {
|
||||
let t = match flds {
|
||||
Some(ref fs) if i < fs.len() => {
|
||||
let ety = fs[i];
|
||||
@ -3739,13 +3738,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
self.check_expr_with_expectation(&e, NoExpectation)
|
||||
}
|
||||
};
|
||||
err_field = err_field || t.references_error();
|
||||
t
|
||||
}).collect::<Vec<_>>();
|
||||
if err_field {
|
||||
});
|
||||
let tuple = tcx.mk_tup(elt_ts_iter);
|
||||
if tuple.references_error() {
|
||||
tcx.types.err
|
||||
} else {
|
||||
tcx.mk_tup(&elt_ts)
|
||||
tuple
|
||||
}
|
||||
}
|
||||
hir::ExprStruct(ref path, ref fields, ref base_expr) => {
|
||||
@ -4201,7 +4200,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
let ty = self.normalize_associated_types_in(span, &ty);
|
||||
self.write_ty(node_id, ty);
|
||||
self.write_substs(node_id, ty::ItemSubsts {
|
||||
substs: Substs::empty(self.tcx)
|
||||
substs: self.tcx.intern_substs(&[])
|
||||
});
|
||||
return ty;
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
|
||||
_ => ()
|
||||
}
|
||||
let main_def_id = tcx.map.local_def_id(main_id);
|
||||
let substs = Substs::empty(tcx);
|
||||
let substs = tcx.intern_substs(&[]);
|
||||
let se_ty = tcx.mk_fn_def(main_def_id, substs,
|
||||
tcx.mk_bare_fn(ty::BareFnTy {
|
||||
unsafety: hir::Unsafety::Normal,
|
||||
@ -285,7 +285,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
|
||||
}
|
||||
|
||||
let start_def_id = ccx.tcx.map.local_def_id(start_id);
|
||||
let substs = Substs::empty(tcx);
|
||||
let substs = tcx.intern_substs(&[]);
|
||||
let se_ty = tcx.mk_fn_def(start_def_id, substs,
|
||||
tcx.mk_bare_fn(ty::BareFnTy {
|
||||
unsafety: hir::Unsafety::Normal,
|
||||
|
@ -670,7 +670,7 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
|
||||
Some(tcx) => tcx,
|
||||
None => return RegionBound(Lifetime::statik())
|
||||
};
|
||||
let empty = Substs::empty(tcx);
|
||||
let empty = tcx.intern_substs(&[]);
|
||||
let (did, path) = match *self {
|
||||
ty::BoundSend =>
|
||||
(tcx.lang_items.send_trait().unwrap(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user