diff --git a/Cargo.lock b/Cargo.lock index 3c278a6a491a9..fc31b8506cd87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4546,6 +4546,7 @@ dependencies = [ "rustc_index", "rustc_macros", "rustc_serialize", + "smallvec 1.6.1", ] [[package]] diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 721cfdd4459e5..cc894ecf8c737 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -733,10 +733,10 @@ macro_rules! declare_arena { self.dropless.alloc_slice(value) } - pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, U>, U>( - &'a self, - iter: impl ::std::iter::IntoIterator<Item = T>, - ) -> &'a mut [T] { + pub fn alloc_from_iter<T: ArenaAllocatable<'tcx, U>, U, V: IntoIterator<Item = T>>( + &self, + iter: V, + ) -> &mut [T] { T::allocate_from_iter(self, iter) } } diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 1e224dbf83390..fa1662fd1ce43 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -495,12 +495,10 @@ impl MetaItemKind { fn token_trees_and_spacings(&self, span: Span) -> Vec<TreeAndSpacing> { match *self { MetaItemKind::Word => vec![], - MetaItemKind::NameValue(ref lit) => { - vec![ - TokenTree::token(token::Eq, span).into(), - TokenTree::Token(lit.to_token()).into(), - ] - } + MetaItemKind::NameValue(ref lit) => vec![ + TokenTree::token(token::Eq, span).into(), + TokenTree::Token(lit.to_token()).into(), + ], MetaItemKind::List(ref list) => { let mut tokens = Vec::new(); for (i, item) in list.iter().enumerate() { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index e9b8388c1c915..d287ba9824675 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -27,8 +27,7 @@ use rustc_middle::middle::cstore::{ForeignModule, LinkagePreference, NativeLib}; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::mir::{self, Body, Promoted}; -use rustc_middle::ty::codec::TyDecoder; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, codec::TyDecoder, Interner, Ty, TyCtxt, TyInterner}; use rustc_serialize::{opaque, Decodable, Decoder}; use rustc_session::Session; use rustc_span::hygiene::ExpnDataDecodeMode; @@ -245,10 +244,6 @@ impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable<DecodeContext<'a, 'tcx>>> Lazy<[T]> { } impl<'a, 'tcx> DecodeContext<'a, 'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx.expect("missing TyCtxt in DecodeContext") - } - fn cdata(&self) -> CrateMetadataRef<'a> { self.cdata.expect("missing CrateMetadata in DecodeContext") } @@ -277,8 +272,8 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { const CLEAR_CROSS_CRATE: bool = true; #[inline] - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx.expect("missing TyCtxt in DecodeContext") + fn interner(&self) -> TyInterner<'tcx> { + self.tcx.expect("missing TyCtxt in DecodeContext").interner() } #[inline] @@ -299,16 +294,16 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { where F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>, { - let tcx = self.tcx(); + let mut interner = self.interner(); let key = ty::CReaderCacheKey { cnum: self.cdata().cnum, pos: shorthand }; - if let Some(&ty) = tcx.ty_rcache.borrow().get(&key) { + if let Some(ty) = interner.get_cached_ty(key) { return Ok(ty); } let ty = or_insert_with(self)?; - tcx.ty_rcache.borrow_mut().insert(key, ty); + interner.insert_cached_ty(key, ty); Ok(ty) } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 9a42bbe7bacdd..4b39912284b52 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -15,7 +15,7 @@ macro_rules! arena_types { // AdtDef are interned and compared by address [] adt_def: rustc_middle::ty::AdtDef, [] steal_mir: rustc_data_structures::steal::Steal<rustc_middle::mir::Body<$tcx>>, - [decode] mir: rustc_middle::mir::Body<$tcx>, + [] mir: rustc_middle::mir::Body<$tcx>, [] steal_promoted: rustc_data_structures::steal::Steal< rustc_index::vec::IndexVec< @@ -23,16 +23,16 @@ macro_rules! arena_types { rustc_middle::mir::Body<$tcx> > >, - [decode] promoted: + [] promoted: rustc_index::vec::IndexVec< rustc_middle::mir::Promoted, rustc_middle::mir::Body<$tcx> >, - [decode] typeck_results: rustc_middle::ty::TypeckResults<$tcx>, - [decode] borrowck_result: + [] typeck_results: rustc_middle::ty::TypeckResults<$tcx>, + [] borrowck_result: rustc_middle::mir::BorrowCheckResult<$tcx>, - [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult, - [decode] code_region: rustc_middle::mir::coverage::CodeRegion, + [] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult, + [] code_region: rustc_middle::mir::coverage::CodeRegion, [] const_allocs: rustc_middle::mir::interpret::Allocation, // Required for the incremental on-disk cache [few] mir_keys: rustc_hir::def_id::DefIdSet, @@ -99,11 +99,11 @@ macro_rules! arena_types { // Note that this deliberately duplicates items in the `rustc_hir::arena`, // since we need to allocate this type on both the `rustc_hir` arena // (during lowering) and the `librustc_middle` arena (for decoding MIR) - [decode] asm_template: rustc_ast::InlineAsmTemplatePiece, + [] asm_template: rustc_ast::InlineAsmTemplatePiece, // This is used to decode the &'tcx [Span] for InlineAsm's line_spans. - [decode] span: rustc_span::Span, - [decode] used_trait_imports: rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>, + [] span: rustc_span::Span, + [] used_trait_imports: rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>, ], $tcx); ) } diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 55fe5f971e718..5bcaece8881f6 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -111,6 +111,7 @@ use rustc_macros::HashStable; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_serialize::{Decodable, Encodable}; use rustc_target::abi::Endian; +use rustc_type_ir::Interner; use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; @@ -301,7 +302,7 @@ impl<'s> AllocDecodingSession<'s> { AllocDiscriminant::Alloc => { // If this is an allocation, we need to reserve an // `AllocId` so we can decode cyclic graphs. - let alloc_id = decoder.tcx().reserve_alloc_id(); + let alloc_id = decoder.interner().reserve_alloc_id(); *entry = State::InProgress(TinyList::new_single(self.session_id), alloc_id); Some(alloc_id) @@ -345,7 +346,7 @@ impl<'s> AllocDecodingSession<'s> { // We already have a reserved `AllocId`. let alloc_id = alloc_id.unwrap(); trace!("decoded alloc {:?}: {:#?}", alloc_id, alloc); - decoder.tcx().set_alloc_id_same_memory(alloc_id, alloc); + decoder.interner().set_alloc_id_same_memory(alloc_id, alloc); Ok(alloc_id) } AllocDiscriminant::Fn => { @@ -353,7 +354,7 @@ impl<'s> AllocDecodingSession<'s> { trace!("creating fn alloc ID"); let instance = ty::Instance::decode(decoder)?; trace!("decoded fn alloc instance: {:?}", instance); - let alloc_id = decoder.tcx().create_fn_alloc(instance); + let alloc_id = decoder.interner().create_fn_alloc(instance); Ok(alloc_id) } AllocDiscriminant::Static => { @@ -361,7 +362,7 @@ impl<'s> AllocDecodingSession<'s> { trace!("creating extern static alloc ID"); let did = <DefId as Decodable<D>>::decode(decoder)?; trace!("decoded static def-ID: {:?}", did); - let alloc_id = decoder.tcx().create_static_alloc(did); + let alloc_id = decoder.interner().create_static_alloc(did); Ok(alloc_id) } } @@ -545,7 +546,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called /// twice for the same `(AllocId, Allocation)` pair. - fn set_alloc_id_same_memory(self, id: AllocId, mem: &'tcx Allocation) { + pub fn set_alloc_id_same_memory(self, id: AllocId, mem: &'tcx Allocation) { self.alloc_map.lock().alloc_map.insert_same(id, GlobalAlloc::Memory(mem)); } } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 73ad87a9ef219..461e4462b2e4e 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -6,18 +6,18 @@ // The functionality in here is shared between persisting to crate metadata and // persisting to incr. comp. caches. -use crate::arena::ArenaAllocatable; use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; use crate::mir::{ self, interpret::{AllocId, Allocation}, }; use crate::ty::subst::SubstsRef; -use crate::ty::{self, List, Ty, TyCtxt}; +use crate::ty::{self, List, Ty, TyInterner}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::Span; +use rustc_type_ir::Interner; use std::hash::Hash; use std::intrinsics; use std::marker::DiscriminantKind; @@ -160,7 +160,7 @@ encodable_via_deref! { pub trait TyDecoder<'tcx>: Decoder { const CLEAR_CROSS_CRATE: bool; - fn tcx(&self) -> TyCtxt<'tcx>; + fn interner(&self) -> TyInterner<'tcx>; fn peek_byte(&self) -> u8; @@ -187,26 +187,6 @@ pub trait TyDecoder<'tcx>: Decoder { fn decode_alloc_id(&mut self) -> Result<AllocId, Self::Error>; } -#[inline] -pub fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable<D>>( - decoder: &mut D, -) -> Result<&'tcx T, D::Error> -where - D: TyDecoder<'tcx>, -{ - Ok(decoder.tcx().arena.alloc(Decodable::decode(decoder)?)) -} - -#[inline] -pub fn decode_arena_allocable_slice<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable<D>>( - decoder: &mut D, -) -> Result<&'tcx [T], D::Error> -where - D: TyDecoder<'tcx>, -{ - Ok(decoder.tcx().arena.alloc_from_iter(<Vec<T> as Decodable<D>>::decode(decoder)?)) -} - impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> { #[allow(rustc::usage_of_ty_tykind)] fn decode(decoder: &mut D) -> Result<Ty<'tcx>, D::Error> { @@ -220,8 +200,7 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> { decoder.with_position(shorthand, Ty::decode) }) } else { - let tcx = decoder.tcx(); - Ok(tcx.mk_ty(ty::TyKind::decode(decoder)?)) + Ok(decoder.interner().mk_ty(ty::TyKind::decode(decoder)?)) } } } @@ -244,7 +223,7 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Binder<ty::PredicateKind<'tc impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> { fn decode(decoder: &mut D) -> Result<ty::Predicate<'tcx>, D::Error> { let predicate_kind = Decodable::decode(decoder)?; - let predicate = decoder.tcx().mk_predicate(predicate_kind); + let predicate = decoder.interner().mk_predicate(predicate_kind); Ok(predicate) } } @@ -252,8 +231,7 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> { impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for SubstsRef<'tcx> { fn decode(decoder: &mut D) -> Result<Self, D::Error> { let len = decoder.read_usize()?; - let tcx = decoder.tcx(); - tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder))) + Ok(decoder.interner().mk_substs((0..len).map(|_| Decodable::decode(decoder)))?) } } @@ -262,14 +240,14 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for mir::Place<'tcx> { let local: mir::Local = Decodable::decode(decoder)?; let len = decoder.read_usize()?; let projection: &'tcx List<mir::PlaceElem<'tcx>> = - decoder.tcx().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?; + decoder.interner().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?; Ok(mir::Place { local, projection }) } } impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Region<'tcx> { fn decode(decoder: &mut D) -> Result<Self, D::Error> { - Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?)) + Ok(decoder.interner().mk_region(Decodable::decode(decoder)?)) } } @@ -278,7 +256,7 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarInfos<'tcx> { let len = decoder.read_usize()?; let interned: Result<Vec<CanonicalVarInfo<'tcx>>, _> = (0..len).map(|_| Decodable::decode(decoder)).collect(); - Ok(decoder.tcx().intern_canonical_var_infos(interned?.as_slice())) + Ok(decoder.interner().intern_canonical_var_infos(interned?.as_slice())) } } @@ -290,7 +268,7 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AllocId { impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::SymbolName<'tcx> { fn decode(decoder: &mut D) -> Result<Self, D::Error> { - Ok(ty::SymbolName::new(decoder.tcx(), &decoder.read_str()?)) + Ok(decoder.interner().mk_symbol_name(&decoder.read_str()?)) } } @@ -307,14 +285,14 @@ macro_rules! impl_decodable_via_ref { impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::AdtDef { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { let def_id = <DefId as Decodable<D>>::decode(decoder)?; - Ok(decoder.tcx().adt_def(def_id)) + Ok(decoder.interner().adt_def(def_id)) } } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<Ty<'tcx>> { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { let len = decoder.read_usize()?; - decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder))) + Ok(decoder.interner().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?) } } @@ -323,25 +301,27 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { let len = decoder.read_usize()?; - decoder.tcx().mk_poly_existential_predicates((0..len).map(|_| Decodable::decode(decoder))) + Ok(decoder + .interner() + .mk_poly_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?) } } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::Const<'tcx> { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?)) + Ok(decoder.interner().mk_const(Decodable::decode(decoder)?)) } } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for Allocation { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - Ok(decoder.tcx().intern_const_alloc(Decodable::decode(decoder)?)) + Ok(decoder.interner().intern_const_alloc(Decodable::decode(decoder)?)) } } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Predicate<'tcx>, Span)] { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - Ok(decoder.tcx().arena.alloc_from_iter( + Ok(decoder.interner().alloc_predicate_span_from_iter( (0..decoder.read_usize()?) .map(|_| Decodable::decode(decoder)) .collect::<Result<Vec<_>, _>>()?, @@ -351,7 +331,7 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Predicate<'tcx>, impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::Node<'tcx>] { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - Ok(decoder.tcx().arena.alloc_from_iter( + Ok(decoder.interner().alloc_node_from_iter( (0..decoder.read_usize()?) .map(|_| Decodable::decode(decoder)) .collect::<Result<Vec<_>, _>>()?, @@ -361,7 +341,7 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::N impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::NodeId] { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - Ok(decoder.tcx().arena.alloc_from_iter( + Ok(decoder.interner().alloc_node_id_from_iter( (0..decoder.read_usize()?) .map(|_| Decodable::decode(decoder)) .collect::<Result<Vec<_>, _>>()?, @@ -392,39 +372,59 @@ macro_rules! __impl_decoder_methods { } } -macro_rules! impl_arena_allocatable_decoder { - ([]$args:tt) => {}; - ([decode $(, $attrs:ident)*] - [[$name:ident: $ty:ty], $tcx:lifetime]) => { - impl<$tcx, D: TyDecoder<$tcx>> RefDecodable<$tcx, D> for $ty { +macro_rules! impl_ty_decoder_arena_type { + ($ty:ty, $alloc_method:ident, $alloc_slice_method:ident) => { + impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for $ty { #[inline] - fn decode(decoder: &mut D) -> Result<&$tcx Self, D::Error> { - decode_arena_allocable(decoder) + fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { + Ok(decoder.interner().$alloc_method(Decodable::decode(decoder)?)) } } - impl<$tcx, D: TyDecoder<$tcx>> RefDecodable<$tcx, D> for [$ty] { + impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [$ty] { #[inline] - fn decode(decoder: &mut D) -> Result<&$tcx Self, D::Error> { - decode_arena_allocable_slice(decoder) + fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { + Ok(decoder + .interner() + .$alloc_slice_method(<Vec<$ty> as Decodable<D>>::decode(decoder)?)) } } }; - ([$ignore:ident $(, $attrs:ident)*]$args:tt) => { - impl_arena_allocatable_decoder!([$($attrs),*]$args); - }; -} - -macro_rules! impl_arena_allocatable_decoders { - ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => { - $( - impl_arena_allocatable_decoder!($a [[$name: $ty], $tcx]); - )* - } } -rustc_hir::arena_types!(impl_arena_allocatable_decoders, [], 'tcx); -arena_types!(impl_arena_allocatable_decoders, [], 'tcx); +impl_ty_decoder_arena_type!(rustc_middle::mir::Body<'tcx>, alloc_mir, alloc_mir_from_iter); +impl_ty_decoder_arena_type!( + rustc_middle::ty::TypeckResults<'tcx>, + alloc_type_check_results, + alloc_type_check_results_from_iter +); +impl_ty_decoder_arena_type!( + rustc_middle::mir::BorrowCheckResult<'tcx>, + alloc_borrowck_result, + alloc_borrowck_result_from_iter +); +impl_ty_decoder_arena_type!( + rustc_middle::mir::UnsafetyCheckResult, + alloc_unsafety_check_result, + alloc_unsafety_check_result_from_iter +); +impl_ty_decoder_arena_type!( + rustc_middle::mir::coverage::CodeRegion, + alloc_code_region, + alloc_code_region_from_iter +); +impl_ty_decoder_arena_type!( + rustc_ast::InlineAsmTemplatePiece, + alloc_asm_template, + alloc_asm_template_from_iter +); +impl_ty_decoder_arena_type!(rustc_span::Span, alloc_span, alloc_span_from_iter); +impl_ty_decoder_arena_type!( + rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>, + alloc_used_trait_imports, + alloc_used_trait_imports_from_iter +); +impl_ty_decoder_arena_type!(rustc_index::vec::IndexVec<rustc_middle::mir::Promoted,rustc_middle::mir::Body<'tcx>>, alloc_promoted, alloc_promoted_from_iter); #[macro_export] macro_rules! implement_ty_decoder { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e1d79248171a8..08c2af639b5f1 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -11,8 +11,13 @@ use crate::middle; use crate::middle::cstore::{CrateStoreDyn, EncodedMetadata}; use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use crate::middle::stability; -use crate::mir::interpret::{self, Allocation, ConstValue, Scalar}; -use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted}; +use crate::mir::abstract_const::{Node as ConstNode, NodeId}; +use crate::mir::coverage::CodeRegion; +use crate::mir::interpret::{self, AllocId, Allocation, ConstValue, Scalar}; +use crate::mir::{ + Body, BorrowCheckResult, Field, Local, Place, PlaceElem, ProjectionKind, Promoted, + UnsafetyCheckResult, +}; use crate::traits; use crate::ty::query::{self, OnDiskCache, TyCtxtAt}; use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts}; @@ -20,8 +25,8 @@ use crate::ty::TyKind::*; use crate::ty::{ self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid, DefIdTree, ExistentialPredicate, FloatTy, FloatVar, FloatVid, GenericParamDefKind, InferConst, - InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, - PredicateInner, PredicateKind, ProjectionTy, Region, RegionKind, ReprOptions, + InferTy, Instance, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, + PredicateInner, PredicateKind, ProjectionTy, Region, RegionKind, ReprOptions, SymbolName, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy, Visibility, }; use rustc_ast as ast; @@ -34,11 +39,11 @@ use rustc_data_structures::stable_hasher::{ hash_stable_hashmap, HashStable, StableHasher, StableVec, }; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; +use rustc_data_structures::sync::{self, HashMapExt, Lock, Lrc, WorkerLocal}; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefPathHash, LocalDefId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; @@ -56,8 +61,8 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; +use rustc_type_ir::{InternAs, InternIteratorElement, Interner}; -use smallvec::SmallVec; use std::any::Any; use std::borrow::Borrow; use std::cmp::Ordering; @@ -69,6 +74,321 @@ use std::mem; use std::ops::{Bound, Deref}; use std::sync::Arc; +pub struct TyInterner<'tcx> { + tcx: TyCtxt<'tcx>, +} + +#[allow(rustc::usage_of_ty_tykind)] +impl<'tcx> Interner for TyInterner<'tcx> { + type GenericArg = GenericArg<'tcx>; + type ListGenericArg = &'tcx List<GenericArg<'tcx>>; + + type ExistentialPredicate = ty::Binder<ExistentialPredicate<'tcx>>; + type ListExistentialPredicate = &'tcx List<Binder<ExistentialPredicate<'tcx>>>; + + type Predicate = Predicate<'tcx>; + type BinderPredicateKind = Binder<PredicateKind<'tcx>>; + + type Ty = Ty<'tcx>; + type ListType = &'tcx List<Ty<'tcx>>; + type TyKind = TyKind<'tcx>; + type TypeKey = ty::CReaderCacheKey; + + type AllocationId = AllocId; + type Allocation = Allocation; + type InternedAllocation = &'tcx Allocation; + + type DefId = DefId; + type Instance = Instance<'tcx>; + + type CanonicalVarInfo = CanonicalVarInfo<'tcx>; + type ListCanonicalVarInfo = CanonicalVarInfos<'tcx>; + + type RegionKind = RegionKind; + type Region = Region<'tcx>; + + type Const = Const<'tcx>; + type InternedConst = &'tcx Const<'tcx>; + + type PlaceElem = PlaceElem<'tcx>; + type ListPlaceElem = &'tcx List<PlaceElem<'tcx>>; + + type DefPathHash = DefPathHash; + type AdtDef = &'tcx ty::AdtDef; + + type SymbolName = SymbolName<'tcx>; + + type Mir = Body<'tcx>; + type AllocatedMir = &'tcx mut Body<'tcx>; + type AllocatedMirSlice = &'tcx mut [Body<'tcx>]; + + type Promoted = IndexVec<Promoted, Body<'tcx>>; + type AllocatedPromoted = &'tcx mut IndexVec<Promoted, Body<'tcx>>; + type AllocatedPromotedSlice = &'tcx mut [IndexVec<Promoted, Body<'tcx>>]; + + type TypeCheckResults = TypeckResults<'tcx>; + type AllocatedTypeCheckResults = &'tcx mut TypeckResults<'tcx>; + type AllocatedTypeCheckResultsSlice = &'tcx mut [TypeckResults<'tcx>]; + + type BorrowCheckResult = BorrowCheckResult<'tcx>; + type AllocatedBorrowCheckResult = &'tcx mut BorrowCheckResult<'tcx>; + type AllocatedBorrowCheckResultSlice = &'tcx mut [BorrowCheckResult<'tcx>]; + + type CodeRegion = CodeRegion; + type AllocatedCodeRegion = &'tcx mut CodeRegion; + type AllocatedCodeRegionSlice = &'tcx mut [CodeRegion]; + + type UnsafetyCheckResult = UnsafetyCheckResult; + type AllocatedUnsafetyCheckResult = &'tcx mut UnsafetyCheckResult; + type AllocatedUnsafetyCheckResultSlice = &'tcx mut [UnsafetyCheckResult]; + + type Span = Span; + type AllocatedSpan = &'tcx mut Span; + type AllocatedSpanSlice = &'tcx mut [Span]; + + type UsedTraitsImports = FxHashSet<LocalDefId>; + type AllocatedUsedTraitsImports = &'tcx mut FxHashSet<LocalDefId>; + type AllocatedUsedTraitsImportsSlice = &'tcx mut [FxHashSet<LocalDefId>]; + + type AsmTemplate = ast::InlineAsmTemplatePiece; + type AllocatedAsmTemplate = &'tcx mut ast::InlineAsmTemplatePiece; + type AllocatedAsmTemplateSlice = &'tcx mut [ast::InlineAsmTemplatePiece]; + + type PredicateSpan = (ty::Predicate<'tcx>, Span); + type AllocatedPredicateSpanSlice = &'tcx mut [(ty::Predicate<'tcx>, Span)]; + + type Node = ConstNode<'tcx>; + type AllocatedNodeSlice = &'tcx mut [ConstNode<'tcx>]; + + type NodeId = NodeId; + type AllocatedNodeIdSlice = &'tcx mut [NodeId]; + + fn alloc_predicate_span_from_iter( + self, + iter: impl IntoIterator<Item = Self::PredicateSpan>, + ) -> Self::AllocatedPredicateSpanSlice { + self.tcx.arena.alloc_from_iter(iter) + } + + fn alloc_node_from_iter( + self, + iter: impl IntoIterator<Item = Self::Node>, + ) -> Self::AllocatedNodeSlice { + self.tcx.arena.alloc_from_iter(iter) + } + + fn alloc_node_id_from_iter( + self, + iter: impl IntoIterator<Item = Self::NodeId>, + ) -> Self::AllocatedNodeIdSlice { + self.tcx.arena.alloc_from_iter(iter) + } + + fn alloc_span(self, value: Self::Span) -> Self::AllocatedSpan { + self.tcx.arena.alloc::<_, Self::Span>(value) + } + + fn alloc_span_from_iter( + self, + iter: impl IntoIterator<Item = Self::Span>, + ) -> Self::AllocatedSpanSlice { + self.tcx.arena.alloc_from_iter::<Self::Span, Self::Span, _>(iter) + } + + fn alloc_promoted(self, value: Self::Promoted) -> Self::AllocatedPromoted { + self.tcx.arena.alloc(value) + } + + fn alloc_promoted_from_iter( + self, + iter: impl IntoIterator<Item = Self::Promoted>, + ) -> Self::AllocatedPromotedSlice { + self.tcx.arena.alloc_from_iter(iter) + } + + fn alloc_borrowck_result( + self, + value: Self::BorrowCheckResult, + ) -> Self::AllocatedBorrowCheckResult { + self.tcx.arena.alloc(value) + } + + fn alloc_borrowck_result_from_iter( + self, + iter: impl IntoIterator<Item = Self::BorrowCheckResult>, + ) -> Self::AllocatedBorrowCheckResultSlice { + self.tcx.arena.alloc_from_iter(iter) + } + + fn alloc_type_check_results( + self, + value: Self::TypeCheckResults, + ) -> Self::AllocatedTypeCheckResults { + self.tcx.arena.alloc(value) + } + + fn alloc_type_check_results_from_iter( + self, + iter: impl IntoIterator<Item = Self::TypeCheckResults>, + ) -> Self::AllocatedTypeCheckResultsSlice { + self.tcx.arena.alloc_from_iter(iter) + } + + fn alloc_mir(self, value: Self::Mir) -> Self::AllocatedMir { + self.tcx.arena.alloc(value) + } + + fn alloc_mir_from_iter( + self, + iter: impl IntoIterator<Item = Self::Mir>, + ) -> Self::AllocatedMirSlice { + self.tcx.arena.alloc_from_iter(iter) + } + + fn alloc_code_region(self, value: Self::CodeRegion) -> Self::AllocatedCodeRegion { + self.tcx.arena.alloc(value) + } + + fn alloc_code_region_from_iter( + self, + iter: impl IntoIterator<Item = Self::CodeRegion>, + ) -> Self::AllocatedCodeRegionSlice { + self.tcx.arena.alloc_from_iter(iter) + } + + fn alloc_unsafety_check_result( + self, + value: Self::UnsafetyCheckResult, + ) -> Self::AllocatedUnsafetyCheckResult { + self.tcx.arena.alloc(value) + } + + fn alloc_unsafety_check_result_from_iter( + self, + iter: impl IntoIterator<Item = Self::UnsafetyCheckResult>, + ) -> Self::AllocatedUnsafetyCheckResultSlice { + self.tcx.arena.alloc_from_iter(iter) + } + + fn alloc_used_trait_imports( + self, + value: Self::UsedTraitsImports, + ) -> Self::AllocatedUsedTraitsImports { + self.tcx.arena.alloc(value) + } + + fn alloc_used_trait_imports_from_iter( + self, + iter: impl IntoIterator<Item = Self::UsedTraitsImports>, + ) -> Self::AllocatedUsedTraitsImportsSlice { + self.tcx.arena.alloc_from_iter(iter) + } + + fn alloc_asm_template(self, value: Self::AsmTemplate) -> Self::AllocatedAsmTemplate { + self.tcx.arena.alloc(value) + } + + fn alloc_asm_template_from_iter( + self, + iter: impl IntoIterator<Item = Self::AsmTemplate>, + ) -> Self::AllocatedAsmTemplateSlice { + self.tcx.arena.alloc_from_iter(iter) + } + + fn mk_symbol_name(self, name: &str) -> Self::SymbolName { + SymbolName::new(self.tcx, name) + } + + fn get_cached_ty(&self, k: Self::TypeKey) -> Option<Self::Ty> { + self.tcx.ty_rcache.borrow().get(&k).map(|x| x.to_owned()) + } + fn insert_same_cached_ty(&mut self, key: Self::TypeKey, value: Self::Ty) { + self.tcx.ty_rcache.borrow_mut().insert_same(key, value); + } + + fn insert_cached_ty(&mut self, key: Self::TypeKey, value: Self::Ty) -> Option<Self::Ty> { + self.tcx.ty_rcache.borrow_mut().insert(key, value) + } + + fn adt_def(self, def_id: Self::DefId) -> Self::AdtDef { + self.tcx.adt_def(def_id) + } + + fn mk_predicate(self, binder: Self::BinderPredicateKind) -> Self::Predicate { + self.tcx.mk_predicate(binder) + } + + fn mk_ty(self, st: TyKind<'tcx>) -> Ty<'tcx> { + self.tcx.mk_ty(st) + } + + fn mk_substs<I: InternAs<[Self::GenericArg], Self::ListGenericArg>>( + self, + iter: I, + ) -> I::Output { + self.tcx.mk_substs(iter) + } + + fn mk_poly_existential_predicates< + I: InternAs<[Self::ExistentialPredicate], Self::ListExistentialPredicate>, + >( + self, + iter: I, + ) -> I::Output { + self.tcx.mk_poly_existential_predicates(iter) + } + + fn mk_type_list<I: InternAs<[Self::Ty], Self::ListType>>(self, iter: I) -> I::Output { + iter.intern_with(|xs| self.tcx.intern_type_list(xs)) + } + + fn mk_place_elems<I: InternAs<[Self::PlaceElem], Self::ListPlaceElem>>( + self, + iter: I, + ) -> I::Output { + iter.intern_with(|xs| self.tcx.intern_place_elems(xs)) + } + + fn mk_region(self, kind: Self::RegionKind) -> Self::Region { + self.tcx.mk_region(kind) + } + + fn mk_const(self, c: Self::Const) -> Self::InternedConst { + self.tcx.mk_const(c) + } + + fn intern_const_alloc(self, alloc: Self::Allocation) -> Self::InternedAllocation { + self.tcx.allocation_interner.intern(alloc, |alloc| self.tcx.arena.alloc(alloc)) + } + + fn intern_canonical_var_infos( + self, + ts: &[Self::CanonicalVarInfo], + ) -> Self::ListCanonicalVarInfo { + self.tcx.intern_canonical_var_infos(ts) + } + + fn reserve_alloc_id(self) -> Self::AllocationId { + self.tcx.reserve_alloc_id() + } + + fn set_alloc_id_same_memory(self, id: Self::AllocationId, mem: Self::InternedAllocation) { + self.tcx.set_alloc_id_same_memory(id, mem) + } + + fn create_fn_alloc(self, instance: Self::Instance) -> Self::AllocationId { + self.tcx.create_fn_alloc(instance) + } + + fn create_static_alloc(self, static_id: Self::DefId) -> Self::AllocationId { + self.tcx.create_static_alloc(static_id) + } + + fn def_path_hash_to_def_id(self, hash: Self::DefPathHash) -> Option<Self::DefId> { + self.tcx.on_disk_cache.as_ref().unwrap().def_path_hash_to_def_id(self.tcx, hash) + } +} + /// A type that is not publicly constructable. This prevents people from making [`TyKind::Error`]s /// except through the error-reporting functions on a [`tcx`][TyCtxt]. #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] @@ -1025,6 +1345,10 @@ pub struct GlobalCtxt<'tcx> { } impl<'tcx> TyCtxt<'tcx> { + pub fn interner(self) -> TyInterner<'tcx> { + TyInterner { tcx: self } + } + pub fn typeck_opt_const_arg( self, def: ty::WithOptConstParam<LocalDefId>, @@ -2647,81 +2971,6 @@ impl TyCtxtAt<'tcx> { } } -pub trait InternAs<T: ?Sized, R> { - type Output; - fn intern_with<F>(self, f: 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::<SmallVec<[_; 8]>>()) - } -} - -impl<'a, T, R> InternIteratorElement<T, R> for &'a T -where - T: Clone + 'a, -{ - type Output = R; - fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { - f(&iter.cloned().collect::<SmallVec<[_; 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>( - mut iter: I, - f: F, - ) -> Self::Output { - // This code is hot enough that it's worth specializing for the most - // common length lists, to avoid the overhead of `SmallVec` creation. - // The match arms are in order of frequency. The 1, 2, and 0 cases are - // typically hit in ~95% of cases. We assume that if the upper and - // lower bounds from `size_hint` agree they are correct. - Ok(match iter.size_hint() { - (1, Some(1)) => { - let t0 = iter.next().unwrap()?; - assert!(iter.next().is_none()); - f(&[t0]) - } - (2, Some(2)) => { - let t0 = iter.next().unwrap()?; - let t1 = iter.next().unwrap()?; - assert!(iter.next().is_none()); - f(&[t0, t1]) - } - (0, Some(0)) => { - assert!(iter.next().is_none()); - f(&[]) - } - _ => f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?), - }) - } -} - // We are comparing types with different invariant lifetimes, so `ptr::eq` // won't work for us. fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f5aef108927db..7bec890706436 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -59,7 +59,7 @@ pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt}; pub use self::context::{ tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt, - Lift, ResolvedOpaqueTy, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex, + Lift, ResolvedOpaqueTy, TyCtxt, TyInterner, TypeckResults, UserType, UserTypeAnnotationIndex, }; pub use self::instance::{Instance, InstanceDef}; pub use self::list::List; diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index d0cd8a48f99b3..38a1476f49115 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -3,10 +3,10 @@ use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use crate::mir::{self, interpret}; use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; use crate::ty::context::TyCtxt; -use crate::ty::{self, Ty}; +use crate::ty::{self, Ty, TyInterner}; use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder, FingerprintEncoder}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell}; +use rustc_data_structures::sync::{Lock, Lrc, OnceCell}; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::unhash::UnhashMap; use rustc_errors::Diagnostic; @@ -28,6 +28,7 @@ use rustc_span::hygiene::{ use rustc_span::source_map::{SourceMap, StableSourceFileId}; use rustc_span::CachingSourceMapView; use rustc_span::{BytePos, ExpnData, SourceFile, Span, DUMMY_SP}; +use rustc_type_ir::Interner; use std::collections::hash_map::Entry; use std::iter::FromIterator; use std::mem; @@ -741,8 +742,8 @@ impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { const CLEAR_CROSS_CRATE: bool = false; #[inline] - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx + fn interner(&self) -> TyInterner<'tcx> { + self.tcx.interner() } #[inline] @@ -763,18 +764,18 @@ impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { where F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>, { - let tcx = self.tcx(); + let mut interner = self.interner(); let cache_key = ty::CReaderCacheKey { cnum: CrateNum::ReservedForIncrCompCache, pos: shorthand }; - if let Some(&ty) = tcx.ty_rcache.borrow().get(&cache_key) { + if let Some(ty) = interner.get_cached_ty(cache_key) { return Ok(ty); } let ty = or_insert_with(self)?; // This may overwrite the entry, but it should overwrite with the same value. - tcx.ty_rcache.borrow_mut().insert_same(cache_key, ty); + interner.insert_same_cached_ty(cache_key, ty); Ok(ty) } @@ -904,12 +905,9 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefId { // If we get to this point, then all of the query inputs were green, // which means that the definition with this hash is guaranteed to // still exist in the current compilation session. - Ok(d.tcx() - .on_disk_cache - .as_ref() - .unwrap() - .def_path_hash_to_def_id(d.tcx(), def_path_hash) - .unwrap()) + + let def_if = d.interner().def_path_hash_to_def_id(def_path_hash); + Ok(def_if.unwrap()) } } diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index 3f64bd899979f..b35bac47fdd3e 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -13,3 +13,4 @@ rustc_index = { path = "../rustc_index" } rustc_serialize = { path = "../rustc_serialize" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_macros = { path = "../rustc_macros" } +smallvec = { version = "1.0", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index fccd8b795ef56..3de555cef2303 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -9,9 +9,285 @@ extern crate rustc_macros; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::unify::{EqUnifyValue, UnifyKey}; +use smallvec::SmallVec; use std::fmt; +use std::iter::IntoIterator; use std::mem::discriminant; +pub trait Interner { + type GenericArg; + type ListGenericArg; + + type ExistentialPredicate; + type ListExistentialPredicate; + + type Predicate; + type BinderPredicateKind; + + type Ty; + type ListType; + type TyKind; + type TypeKey; + + type AllocationId; + type Allocation; + type InternedAllocation; + + type DefId; + type Instance; + + type CanonicalVarInfo; + type ListCanonicalVarInfo; + + type RegionKind; + type Region; + + type Const; + type InternedConst; + + type PlaceElem; + type ListPlaceElem; + + type DefPathHash; + type AdtDef; + + type SymbolName; + + type Mir; + type AllocatedMir; + type AllocatedMirSlice; + + type Promoted; + type AllocatedPromoted; + type AllocatedPromotedSlice; + + type TypeCheckResults; + type AllocatedTypeCheckResults; + type AllocatedTypeCheckResultsSlice; + + type BorrowCheckResult; + type AllocatedBorrowCheckResult; + type AllocatedBorrowCheckResultSlice; + + type CodeRegion; + type AllocatedCodeRegion; + type AllocatedCodeRegionSlice; + + type UnsafetyCheckResult; + type AllocatedUnsafetyCheckResult; + type AllocatedUnsafetyCheckResultSlice; + + type Span; + type AllocatedSpan; + type AllocatedSpanSlice; + + type UsedTraitsImports; + type AllocatedUsedTraitsImports; + type AllocatedUsedTraitsImportsSlice; + + type AsmTemplate; + type AllocatedAsmTemplate; + type AllocatedAsmTemplateSlice; + + type PredicateSpan; + type AllocatedPredicateSpanSlice; + + type Node; + type AllocatedNodeSlice; + + type NodeId; + type AllocatedNodeIdSlice; + + fn alloc_mir(self, value: Self::Mir) -> Self::AllocatedMir; + fn alloc_mir_from_iter( + self, + iter: impl IntoIterator<Item = Self::Mir>, + ) -> Self::AllocatedMirSlice; + + fn alloc_promoted(self, value: Self::Promoted) -> Self::AllocatedPromoted; + fn alloc_promoted_from_iter( + self, + iter: impl IntoIterator<Item = Self::Promoted>, + ) -> Self::AllocatedPromotedSlice; + + fn alloc_type_check_results( + self, + value: Self::TypeCheckResults, + ) -> Self::AllocatedTypeCheckResults; + fn alloc_type_check_results_from_iter( + self, + iter: impl IntoIterator<Item = Self::TypeCheckResults>, + ) -> Self::AllocatedTypeCheckResultsSlice; + + fn alloc_borrowck_result( + self, + value: Self::BorrowCheckResult, + ) -> Self::AllocatedBorrowCheckResult; + fn alloc_borrowck_result_from_iter( + self, + iter: impl IntoIterator<Item = Self::BorrowCheckResult>, + ) -> Self::AllocatedBorrowCheckResultSlice; + + fn alloc_unsafety_check_result( + self, + value: Self::UnsafetyCheckResult, + ) -> Self::AllocatedUnsafetyCheckResult; + fn alloc_unsafety_check_result_from_iter( + self, + iter: impl IntoIterator<Item = Self::UnsafetyCheckResult>, + ) -> Self::AllocatedUnsafetyCheckResultSlice; + + fn alloc_code_region(self, value: Self::CodeRegion) -> Self::AllocatedCodeRegion; + fn alloc_code_region_from_iter( + self, + iter: impl IntoIterator<Item = Self::CodeRegion>, + ) -> Self::AllocatedCodeRegionSlice; + + fn alloc_span(self, value: Self::Span) -> Self::AllocatedSpan; + fn alloc_span_from_iter( + self, + iter: impl IntoIterator<Item = Self::Span>, + ) -> Self::AllocatedSpanSlice; + + fn alloc_used_trait_imports( + self, + value: Self::UsedTraitsImports, + ) -> Self::AllocatedUsedTraitsImports; + fn alloc_used_trait_imports_from_iter( + self, + iter: impl IntoIterator<Item = Self::UsedTraitsImports>, + ) -> Self::AllocatedUsedTraitsImportsSlice; + + fn alloc_asm_template(self, value: Self::AsmTemplate) -> Self::AllocatedAsmTemplate; + fn alloc_asm_template_from_iter( + self, + iter: impl IntoIterator<Item = Self::AsmTemplate>, + ) -> Self::AllocatedAsmTemplateSlice; + + fn alloc_predicate_span_from_iter( + self, + iter: impl IntoIterator<Item = Self::PredicateSpan>, + ) -> Self::AllocatedPredicateSpanSlice; + fn alloc_node_from_iter( + self, + iter: impl IntoIterator<Item = Self::Node>, + ) -> Self::AllocatedNodeSlice; + fn alloc_node_id_from_iter( + self, + iter: impl IntoIterator<Item = Self::NodeId>, + ) -> Self::AllocatedNodeIdSlice; + + fn get_cached_ty(&self, k: Self::TypeKey) -> Option<Self::Ty>; + fn insert_same_cached_ty(&mut self, key: Self::TypeKey, value: Self::Ty); + fn insert_cached_ty(&mut self, key: Self::TypeKey, value: Self::Ty) -> Option<Self::Ty>; + fn adt_def(self, def_id: Self::DefId) -> Self::AdtDef; + fn mk_symbol_name(self, name: &str) -> Self::SymbolName; + fn mk_predicate(self, binder: Self::BinderPredicateKind) -> Self::Predicate; + fn mk_ty(self, st: Self::TyKind) -> Self::Ty; + fn mk_substs<I: InternAs<[Self::GenericArg], Self::ListGenericArg>>(self, iter: I) + -> I::Output; + fn mk_poly_existential_predicates< + I: InternAs<[Self::ExistentialPredicate], Self::ListExistentialPredicate>, + >( + self, + iter: I, + ) -> I::Output; + fn mk_type_list<I: InternAs<[Self::Ty], Self::ListType>>(self, iter: I) -> I::Output; + fn mk_place_elems<I: InternAs<[Self::PlaceElem], Self::ListPlaceElem>>( + self, + iter: I, + ) -> I::Output; + fn mk_region(self, kind: Self::RegionKind) -> Self::Region; + fn mk_const(self, c: Self::Const) -> Self::InternedConst; + fn intern_const_alloc(self, alloc: Self::Allocation) -> Self::InternedAllocation; + fn intern_canonical_var_infos( + self, + ts: &[Self::CanonicalVarInfo], + ) -> Self::ListCanonicalVarInfo; + fn reserve_alloc_id(self) -> Self::AllocationId; + fn set_alloc_id_same_memory(self, id: Self::AllocationId, mem: Self::InternedAllocation); + fn create_fn_alloc(self, instance: Self::Instance) -> Self::AllocationId; + fn create_static_alloc(self, static_id: Self::DefId) -> Self::AllocationId; + fn def_path_hash_to_def_id(self, hash: Self::DefPathHash) -> Option<Self::DefId>; + + // arena methods +} + +pub trait InternAs<T: ?Sized, R> { + type Output; + fn intern_with<F>(self, f: 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::<SmallVec<[_; 8]>>()) + } +} + +impl<'a, T, R> InternIteratorElement<T, R> for &'a T +where + T: Clone + 'a, +{ + type Output = R; + fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { + f(&iter.cloned().collect::<SmallVec<[_; 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>( + mut iter: I, + f: F, + ) -> Self::Output { + // This code is hot enough that it's worth specializing for the most + // common length lists, to avoid the overhead of `SmallVec` creation. + // The match arms are in order of frequency. The 1, 2, and 0 cases are + // typically hit in ~95% of cases. We assume that if the upper and + // lower bounds from `size_hint` agree they are correct. + Ok(match iter.size_hint() { + (1, Some(1)) => { + let t0 = iter.next().unwrap()?; + assert!(iter.next().is_none()); + f(&[t0]) + } + (2, Some(2)) => { + let t0 = iter.next().unwrap()?; + let t1 = iter.next().unwrap()?; + assert!(iter.next().is_none()); + f(&[t0, t1]) + } + (0, Some(0)) => { + assert!(iter.next().is_none()); + f(&[]) + } + _ => f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?), + }) + } +} + bitflags! { /// Flags that we track on types. These flags are propagated upwards /// through the type during type construction, so that we can quickly check