From a4f7ba376eef754ea76467d5d48f81dddb83b089 Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Mon, 24 Oct 2016 18:22:59 -0600 Subject: [PATCH 1/3] Add AccumulateVec, a potentially stack-allocated vector. AccumulateVec is generic over the Array trait, which is currently only implemented for [T; 8]. --- .../accumulate_vec.rs | 52 +++++++++ src/librustc_data_structures/array_vec.rs | 106 ++++++++++++++++++ src/librustc_data_structures/lib.rs | 5 + 3 files changed, 163 insertions(+) create mode 100644 src/librustc_data_structures/accumulate_vec.rs create mode 100644 src/librustc_data_structures/array_vec.rs diff --git a/src/librustc_data_structures/accumulate_vec.rs b/src/librustc_data_structures/accumulate_vec.rs new file mode 100644 index 0000000000000..3894db40277a1 --- /dev/null +++ b/src/librustc_data_structures/accumulate_vec.rs @@ -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 or the MIT license +// , 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 { + Array(ArrayVec), + Heap(Vec) +} + +impl Deref for AccumulateVec { + type Target = [A::Element]; + fn deref(&self) -> &Self::Target { + match *self { + AccumulateVec::Array(ref v) => &v[..], + AccumulateVec::Heap(ref v) => &v[..], + } + } +} + +impl FromIterator for AccumulateVec { + fn from_iter(iter: I) -> AccumulateVec where I: IntoIterator { + 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()) + } + } +} + diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs new file mode 100644 index 0000000000000..f87426cee59ea --- /dev/null +++ b/src/librustc_data_structures/array_vec.rs @@ -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 or the MIT license +// , 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]>; + const LEN: usize; +} + +unsafe impl Array for [T; 8] { + type Element = T; + type PartialStorage = [ManuallyDrop; 8]; + const LEN: usize = 8; +} + +pub struct ArrayVec { + count: usize, + values: A::PartialStorage +} + +impl ArrayVec { + pub fn new() -> Self { + ArrayVec { + count: 0, + values: Default::default(), + } + } +} + +impl fmt::Debug for ArrayVec + where A: Array, + A::Element: fmt::Debug { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self[..].fmt(f) + } +} + +impl Deref for ArrayVec { + 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 DerefMut for ArrayVec { + 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 Drop for ArrayVec { + fn drop(&mut self) { + unsafe { + drop_in_place(&mut self[..]) + } + } +} + +impl Extend for ArrayVec { + fn extend(&mut self, iter: I) where I: IntoIterator { + 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 { + value: T, + #[allow(dead_code)] + empty: (), +} + +impl Default for ManuallyDrop { + fn default() -> Self { + ManuallyDrop { empty: () } + } +} + diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 26b9f48ad04dd..143c180f823d0 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -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; From 982a48575b53e05cd53f679aac2fedf6346f78c7 Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Mon, 24 Oct 2016 18:23:29 -0600 Subject: [PATCH 2/3] Utilize AccumulateVec to avoid heap allocations in mk_{substs, type_list, tup} calls. --- src/libarena/lib.rs | 8 +- src/librustc/mir/tcx.rs | 4 +- src/librustc/traits/fulfill.rs | 4 +- src/librustc/traits/select.rs | 4 +- src/librustc/traits/util.rs | 8 +- src/librustc/ty/context.rs | 94 +++++++++++++++++-- src/librustc/ty/mod.rs | 17 +++- src/librustc/ty/relate.rs | 18 +--- src/librustc/ty/structural_impls.rs | 5 +- src/librustc/ty/subst.rs | 47 ++-------- src/librustc/util/ppaux.rs | 4 +- .../borrowck/mir/elaborate_drops.rs | 2 +- src/librustc_driver/test.rs | 19 ++-- src/librustc_lint/builtin.rs | 6 +- src/librustc_metadata/decoder.rs | 4 +- src/librustc_mir/build/expr/as_rvalue.rs | 2 +- src/librustc_mir/build/scope.rs | 6 +- src/librustc_mir/hair/cx/mod.rs | 4 +- src/librustc_trans/base.rs | 8 +- src/librustc_trans/callee.rs | 2 +- src/librustc_trans/collector.rs | 8 +- src/librustc_trans/common.rs | 4 +- src/librustc_trans/glue.rs | 4 +- src/librustc_trans/mir/constant.rs | 2 +- src/librustc_trans/mir/rvalue.rs | 2 +- src/librustc_trans/trans_item.rs | 2 +- src/librustc_typeck/astconv.rs | 11 +-- src/librustc_typeck/check/_match.rs | 5 +- src/librustc_typeck/check/autoderef.rs | 3 +- src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/intrinsic.rs | 4 +- src/librustc_typeck/check/method/suggest.rs | 3 +- src/librustc_typeck/check/mod.rs | 15 ++- src/librustc_typeck/lib.rs | 4 +- src/librustdoc/clean/mod.rs | 2 +- 35 files changed, 193 insertions(+), 144 deletions(-) diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index cfbd29571f7b2..0a06c0b2dfb76 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -157,13 +157,15 @@ impl TypedArena { /// 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::() != 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::(); diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 6fe6498ff789c..8dd82b2d07924 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -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::>() + ops.iter().map(|op| op.ty(mir, tcx)) )) } AggregateKind::Adt(def, _, substs, _) => { diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 65860671c4c63..ded2fdc58b42b 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -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(), diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index dbaa8db3e8971..216df8b092a02 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2599,7 +2599,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); @@ -2619,7 +2619,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) diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index fa951b5efdb2b..a0792dcf4dd59 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -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)) } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d075b08f7385a..8c7a2da3be7fa 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -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> { type Lifted = &'tcx Slice>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Slice>> { + 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], 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> { + if ts.len() == 0 { + Slice::empty() + } else { + self._intern_type_list(ts) + } + } + + pub fn intern_substs(self, ts: &[Kind<'tcx>]) -> &'tcx Slice> { + if ts.len() == 0 { + Slice::empty() + } else { + self._intern_substs(ts) + } + } + + pub fn mk_type_list], + &'tcx Slice>>>(self, iter: I) -> I::Output { + iter.intern_with(|xs| self.intern_type_list(xs)) + } + + pub fn mk_substs], + &'tcx Slice>>>(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>> { 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 { + type Output; + fn intern_with(self, F) -> Self::Output + where F: FnOnce(&T) -> R; +} + +impl InternAs<[T], R> for I + where E: InternIteratorElement, + I: Iterator { + type Output = E::Output; + fn intern_with(self, f: F) -> Self::Output + where F: FnOnce(&[T]) -> R { + E::intern_with(self, f) + } +} + +pub trait InternIteratorElement: Sized { + type Output; + fn intern_with, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output; +} + +impl InternIteratorElement for T { + type Output = R; + fn intern_with, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { + f(&iter.collect::>()) + } +} + +impl InternIteratorElement for Result { + type Output = Result; + fn intern_with, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { + Ok(f(&iter.collect::, _>>()?)) + } +} + diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 018f01e5913c0..53909b8143526 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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}; @@ -560,6 +561,14 @@ impl<'a, T> IntoIterator for &'a Slice { impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice> {} +impl Slice { + pub fn empty<'a>() -> &'a Slice { + 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. @@ -1797,7 +1806,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()) { @@ -1873,7 +1882,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) { @@ -2124,7 +2133,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(), } @@ -2796,7 +2805,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, diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 48b0b4ec9e58f..cb90e6392cf03 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -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>(&mut self, a: &[T], b: &[T]) -> RelateResult<'tcx, Vec> { - 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>(&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::, _>>()?; - 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)))? }) } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 0f4cff3d4875b..3165edebf1a46 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -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> { 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::>(); - folder.tcx().mk_type_list(&tys) + let v = self.iter().map(|t| t.fold_with(folder)).collect::>(); + folder.tcx().intern_type_list(&v) } fn super_visit_with>(&self, visitor: &mut V) -> bool { diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index b0fdaa170996d..a4ceecd8c9d7b 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -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>; impl<'a, 'gcx, 'tcx> Substs<'tcx> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, params: I) - -> &'tcx Substs<'tcx> - where I: IntoIterator> { - tcx.mk_substs(¶ms.into_iter().collect::>()) - } - - pub fn maybe_new(tcx: TyCtxt<'a, 'gcx, 'tcx>, params: I) - -> Result<&'tcx Substs<'tcx>, E> - where I: IntoIterator, E>> { - Ok(Substs::new(tcx, params.into_iter().collect::, _>>()?)) - } - - 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(substs: &mut Vec>, @@ -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())) } }) } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 1df0cf2d5cdf6..af92569cc350c 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -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); diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 25986b85f7b3a..fce5553c2fee9 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -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 { diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 15be80f4ee5a5..c400610a688a0 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -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 diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 3428ec8d4c960..3d6dd5dedf5ba 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -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, }; diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index e18fd58144398..7aa0ed1d1ab85 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -374,7 +374,7 @@ impl<'a, 'tcx> SpecializedDecoder> 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)))?) } } @@ -386,7 +386,7 @@ impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Region> for DecodeContext<'a, 'tcx> impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice>> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice>, 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)))?) } } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index d30af8b82555c..dcb301cab00c8 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -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, diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 01cce3c7dd794..e5d4ea8af50a2 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -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, @@ -800,7 +798,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, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 8dd33ad2f9c7a..9fe3addea4127 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -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) => { diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 02aa7c069f9b3..d4d4f883e7b85 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -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 = diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 5c7ab77648e5e..cdd3e919e61c0 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -327,7 +327,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], diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 8112bb8e65c5b..8a7919d01f5fc 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -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); diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 6ae5fc1657aa7..9158c06d6a168 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -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 { diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 64d959d29080c..648dd9f3e3aea 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -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, diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index baa306069f168..3e7d8acf610c2 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -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()); diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 5ffaadf972a63..b6172fa2a907d 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -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 diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 6c317eb994849..8930387c046e2 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -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) }, }; diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 0c4e6324b8911..2a601475fcd76 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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, @@ -1661,10 +1661,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::>(); - 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); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index f7e590871fc5e..d3fef0711b246 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -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]); diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 8127bcf825643..900c22a8176ed 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -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); diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 7b05cd1d48328..d478f1092bd87 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -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, diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 7171b33a3af39..cbe3893fbf67a 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -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)), diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index e93f990b81071..32bf839a4ed4e 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -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 = diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index af5a1d7b71383..915c46891c657 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2380,7 +2380,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, @@ -3718,9 +3718,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]; @@ -3731,13 +3730,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::>(); - 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) => { @@ -4193,7 +4192,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; } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index cb9b162cabe11..7752690e534bc 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -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, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index eb6115e937315..265b66b01ea52 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -670,7 +670,7 @@ impl Clean 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(), From 989eba79a33187de03d8cdadb4994bb6b52200b0 Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Mon, 24 Oct 2016 18:24:24 -0600 Subject: [PATCH 3/3] Add size hint to Result's FromIterator implementation. --- src/libcore/result.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 96845259299be..78230b608044b 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -1008,6 +1008,11 @@ impl> FromIterator> for Result { None => None, } } + + fn size_hint(&self) -> (usize, Option) { + let (_min, max) = self.iter.size_hint(); + (0, max) + } } let mut adapter = Adapter { iter: iter.into_iter(), err: None };