From d1a9a9551741c3e888d350d8d4f4821a5addccb2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 22 May 2022 12:34:34 -0700 Subject: [PATCH] Make Lazy not care about lifetimes until decode --- compiler/rustc_metadata/src/creader.rs | 6 +- compiler/rustc_metadata/src/lib.rs | 1 + compiler/rustc_metadata/src/rmeta/decoder.rs | 34 +++-- .../src/rmeta/def_path_hash_map.rs | 5 + compiler/rustc_metadata/src/rmeta/encoder.rs | 27 ++-- compiler/rustc_metadata/src/rmeta/mod.rs | 67 ++++++---- compiler/rustc_metadata/src/rmeta/table.rs | 9 +- compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_middle/src/ty/mod.rs | 2 + compiler/rustc_middle/src/ty/parameterized.rs | 119 ++++++++++++++++++ 10 files changed, 217 insertions(+), 54 deletions(-) create mode 100644 compiler/rustc_middle/src/ty/parameterized.rs diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index dfc675a0494b1..947d563ae3cd1 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -323,7 +323,7 @@ impl<'a> CrateLoader<'a> { None } - fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> { + fn verify_no_symbol_conflicts(&self, root: &CrateRoot) -> Result<(), CrateError> { // Check for (potential) conflicts with the local crate if self.sess.local_stable_crate_id() == root.stable_crate_id() { return Err(CrateError::SymbolConflictsCurrent(root.name())); @@ -342,7 +342,7 @@ impl<'a> CrateLoader<'a> { fn verify_no_stable_crate_id_hash_conflicts( &mut self, - root: &CrateRoot<'_>, + root: &CrateRoot, cnum: CrateNum, ) -> Result<(), CrateError> { if let Some(existing) = self.cstore.stable_crate_ids.insert(root.stable_crate_id(), cnum) { @@ -623,7 +623,7 @@ impl<'a> CrateLoader<'a> { fn resolve_crate_deps( &mut self, root: &CratePaths, - crate_root: &CrateRoot<'_>, + crate_root: &CrateRoot, metadata: &MetadataBlob, krate: CrateNum, dep_kind: CrateDepKind, diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 5e4c1284e241e..4c5d13dfa6c8c 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -2,6 +2,7 @@ #![feature(decl_macro)] #![feature(drain_filter)] #![feature(generators)] +#![feature(generic_associated_types)] #![feature(let_chains)] #![feature(let_else)] #![feature(nll)] diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 72b7c08f04bc2..1420871b0256e 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -25,7 +25,7 @@ use rustc_middle::thir; use rustc_middle::ty::codec::TyDecoder; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::GeneratorDiagnosticData; -use rustc_middle::ty::{self, Ty, TyCtxt, Visibility}; +use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility}; use rustc_serialize::{opaque, Decodable, Decoder}; use rustc_session::cstore::{ CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib, @@ -86,7 +86,7 @@ pub(crate) struct CrateMetadata { /// lifetime is only used behind `Lazy`, and therefore acts like a /// universal (`for<'tcx>`), that is paired up with whichever `TyCtxt` /// is being used to decode those values. - root: CrateRoot<'static>, + root: CrateRoot, /// Trait impl data. /// FIXME: Used only from queries and can use query cache, /// so pre-decoding can probably be avoided. @@ -261,11 +261,14 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (CrateMetadataRef<'a>, TyCtxt<'tcx>) { } } -impl<'a, 'tcx, T: Decodable>> LazyValue { - fn decode>(self, metadata: M) -> T { +impl LazyValue { + fn decode<'a, 'tcx, M: Metadata<'a, 'tcx>>(self, metadata: M) -> T::Value<'tcx> + where + T::Value<'tcx>: Decodable>, + { let mut dcx = metadata.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); - T::decode(&mut dcx) + T::Value::decode(&mut dcx) } } @@ -292,6 +295,9 @@ impl<'a, 'tcx, T: Decodable>> Iterator for DecodeIterato impl<'a, 'tcx, T: Decodable>> ExactSizeIterator for DecodeIterator<'a, 'tcx, T> { + fn len(&self) -> usize { + self.elem_counter.len() + } } unsafe impl<'a, 'tcx, T: Decodable>> TrustedLen @@ -299,8 +305,14 @@ unsafe impl<'a, 'tcx, T: Decodable>> TrustedLen { } -impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable>> LazyArray { - fn decode>(self, metadata: M) -> DecodeIterator<'a, 'tcx, T> { +impl LazyArray { + fn decode<'a, 'tcx, M: Metadata<'a, 'tcx>>( + self, + metadata: M, + ) -> DecodeIterator<'a, 'tcx, T::Value<'tcx>> + where + T::Value<'tcx>: Decodable>, + { let mut dcx = metadata.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); DecodeIterator { elem_counter: (0..self.num_elems), dcx, _phantom: PhantomData } @@ -671,14 +683,14 @@ impl MetadataBlob { .decode(self) } - pub(crate) fn get_root<'tcx>(&self) -> CrateRoot<'tcx> { + pub(crate) fn get_root(&self) -> CrateRoot { let slice = &self.blob()[..]; let offset = METADATA_HEADER.len(); let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) | ((slice[offset + 2] as u32) << 8) | ((slice[offset + 3] as u32) << 0)) as usize; - LazyValue::>::from_position(NonZeroUsize::new(pos).unwrap()).decode(self) + LazyValue::::from_position(NonZeroUsize::new(pos).unwrap()).decode(self) } pub(crate) fn list_crate_metadata(&self, out: &mut dyn io::Write) -> io::Result<()> { @@ -705,7 +717,7 @@ impl MetadataBlob { } } -impl CrateRoot<'_> { +impl CrateRoot { pub(crate) fn is_proc_macro_crate(&self) -> bool { self.proc_macro_data.is_some() } @@ -1677,7 +1689,7 @@ impl CrateMetadata { sess: &Session, cstore: &CStore, blob: MetadataBlob, - root: CrateRoot<'static>, + root: CrateRoot, raw_proc_macros: Option<&'static [ProcMacro]>, cnum: CrateNum, cnum_map: CrateNumMap, diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs index 06045bb3e3d97..15fd190b0492a 100644 --- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -3,6 +3,7 @@ use crate::rmeta::EncodeContext; use crate::rmeta::MetadataBlob; use rustc_data_structures::owning_ref::OwningRef; use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap}; +use rustc_middle::parameterized_over_tcx; use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder}; use rustc_span::def_id::{DefIndex, DefPathHash}; @@ -11,6 +12,10 @@ pub(crate) enum DefPathHashMapRef<'tcx> { BorrowedFromTcx(&'tcx DefPathHashMap), } +parameterized_over_tcx! { + DefPathHashMapRef, +} + impl DefPathHashMapRef<'_> { #[inline] pub fn def_path_hash_to_def_index(&self, def_path_hash: &DefPathHash) -> DefIndex { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 28f289f06ecb2..1e83434b9d062 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -47,7 +47,7 @@ pub(super) struct EncodeContext<'a, 'tcx> { tcx: TyCtxt<'tcx>, feat: &'tcx rustc_feature::Features, - tables: TableBuilders<'tcx>, + tables: TableBuilders, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, @@ -388,10 +388,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.emit_usize(distance) } - fn lazy>, B: Borrow>( - &mut self, - value: B, - ) -> LazyValue { + fn lazy>>(&mut self, value: B) -> LazyValue + where + T::Value<'tcx>: Encodable>, + { let pos = NonZeroUsize::new(self.position()).unwrap(); assert_eq!(self.lazy_state, LazyState::NoNode); @@ -404,14 +404,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { LazyValue::from_position(pos) } - fn lazy_array< - T: Encodable>, - I: IntoIterator, - B: Borrow, - >( + fn lazy_array, B: Borrow>>( &mut self, values: I, - ) -> LazyArray { + ) -> LazyArray + where + T::Value<'tcx>: Encodable>, + { let pos = NonZeroUsize::new(self.position()).unwrap(); assert_eq!(self.lazy_state, LazyState::NoNode); @@ -456,7 +455,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } - fn encode_def_path_hash_map(&mut self) -> LazyValue> { + fn encode_def_path_hash_map(&mut self) -> LazyValue> { self.lazy(DefPathHashMapRef::BorrowedFromTcx( self.tcx.resolutions(()).definitions.def_path_hash_to_def_index_map(), )) @@ -535,7 +534,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy_array(adapted.iter().map(|rc| &**rc)) } - fn encode_crate_root(&mut self) -> LazyValue> { + fn encode_crate_root(&mut self) -> LazyValue { let tcx = self.tcx; let mut i = self.position(); @@ -1859,7 +1858,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_exported_symbols( &mut self, exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportInfo)], - ) -> LazyArray<(ExportedSymbol<'tcx>, SymbolExportInfo)> { + ) -> LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)> { empty_proc_macro!(self); // The metadata symbol name is special. It should not show up in // downstream crates. diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 00c4dc3955da0..fb2ffe1d73d96 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -21,7 +21,7 @@ use rustc_middle::thir; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, ReprOptions, Ty}; -use rustc_middle::ty::{GeneratorDiagnosticData, TyCtxt}; +use rustc_middle::ty::{GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt}; use rustc_serialize::opaque::Encoder; use rustc_session::config::SymbolManglingVersion; use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; @@ -83,6 +83,10 @@ struct LazyValue { _marker: PhantomData T>, } +impl ParameterizedOverTcx for LazyValue { + type Value<'tcx> = LazyValue>; +} + impl LazyValue { fn from_position(position: NonZeroUsize) -> LazyValue { LazyValue { position, _marker: PhantomData } @@ -105,6 +109,10 @@ struct LazyArray { _marker: PhantomData T>, } +impl ParameterizedOverTcx for LazyArray { + type Value<'tcx> = LazyArray>; +} + impl LazyArray { fn from_position_and_num_elems(position: NonZeroUsize, num_elems: usize) -> LazyArray { LazyArray { position, num_elems, _marker: PhantomData } @@ -126,6 +134,10 @@ struct LazyTable { _marker: PhantomData T>, } +impl ParameterizedOverTcx for LazyTable { + type Value<'tcx> = LazyTable>; +} + impl LazyTable { fn from_position_and_encoded_size( position: NonZeroUsize, @@ -199,7 +211,7 @@ pub(crate) struct ProcMacroData { /// a normal crate, much of what we serialized would be unusable in addition /// to being unused. #[derive(MetadataEncodable, MetadataDecodable)] -pub(crate) struct CrateRoot<'tcx> { +pub(crate) struct CrateRoot { name: Symbol, triple: TargetTriple, extra_filename: String, @@ -226,16 +238,16 @@ pub(crate) struct CrateRoot<'tcx> { interpret_alloc_index: LazyArray, proc_macro_data: Option, - tables: LazyTables<'tcx>, + tables: LazyTables, debugger_visualizers: LazyArray, - exported_symbols: LazyArray<(ExportedSymbol<'tcx>, SymbolExportInfo)>, + exported_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>, syntax_contexts: SyntaxContextTable, expn_data: ExpnDataTable, expn_hashes: ExpnHashTable, - def_path_hash_map: LazyValue>, + def_path_hash_map: LazyValue>, source_map: LazyArray, @@ -301,17 +313,17 @@ pub(crate) struct IncoherentImpls { macro_rules! define_tables { ($($name:ident: Table<$IDX:ty, $T:ty>),+ $(,)?) => { #[derive(MetadataEncodable, MetadataDecodable)] - pub(crate) struct LazyTables<'tcx> { + pub(crate) struct LazyTables { $($name: LazyTable<$IDX, $T>),+ } #[derive(Default)] - struct TableBuilders<'tcx> { + struct TableBuilders { $($name: TableBuilder<$IDX, $T>),+ } - impl<'tcx> TableBuilders<'tcx> { - fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> { + impl TableBuilders { + fn encode(&self, buf: &mut Encoder) -> LazyTables { LazyTables { $($name: self.$name.encode(buf)),+ } @@ -333,23 +345,23 @@ define_tables! { lookup_const_stability: Table>, lookup_deprecation_entry: Table>, // As an optimization, a missing entry indicates an empty `&[]`. - explicit_item_bounds: Table, Span)>>, - explicit_predicates_of: Table>>, + explicit_item_bounds: Table, Span)>>, + explicit_predicates_of: Table>>, generics_of: Table>, // As an optimization, a missing entry indicates an empty `&[]`. - inferred_outlives_of: Table, Span)>>, - super_predicates_of: Table>>, - type_of: Table>>, + inferred_outlives_of: Table, Span)>>, + super_predicates_of: Table>>, + type_of: Table>>, variances_of: Table>, - fn_sig: Table>>, + fn_sig: Table>>, codegen_fn_attrs: Table>, - impl_trait_ref: Table>>, - const_param_default: Table>>, - optimized_mir: Table>>, - mir_for_ctfe: Table>>, - promoted_mir: Table>>>, + impl_trait_ref: Table>>, + const_param_default: Table>>, + optimized_mir: Table>>, + mir_for_ctfe: Table>>, + promoted_mir: Table>>>, // FIXME(compiler-errors): Why isn't this a LazyArray? - thir_abstract_const: Table]>>, + thir_abstract_const: Table]>>, impl_parent: Table, impl_polarity: Table, impl_constness: Table, @@ -376,7 +388,7 @@ define_tables! { def_keys: Table>, def_path_hashes: Table, proc_macro_quoted_spans: Table>, - generator_diagnostic_data: Table>>, + generator_diagnostic_data: Table>>, may_have_doc_links: Table, } @@ -477,3 +489,14 @@ pub fn provide(providers: &mut Providers) { encoder::provide(providers); decoder::provide(providers); } + +trivially_parameterized_over_tcx! { + VariantData, + AssocFnData, + EntryKind, + RawDefId, + TraitImpls, + IncoherentImpls, + CrateRoot, + CrateDep, +} diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 60c5143a6c377..100bac15b80a4 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -3,6 +3,7 @@ use crate::rmeta::*; use rustc_data_structures::fingerprint::Fingerprint; use rustc_hir::def::{CtorKind, CtorOf}; use rustc_index::vec::Idx; +use rustc_middle::ty::ParameterizedOverTcx; use rustc_serialize::opaque::Encoder; use rustc_serialize::Encoder as _; use rustc_span::hygiene::MacroKind; @@ -296,7 +297,7 @@ where } } -impl LazyTable +impl LazyTable where Option: FixedSizeEncoding, { @@ -306,9 +307,9 @@ where &self, metadata: M, i: I, - ) -> Option + ) -> Option> where - Option: FixedSizeEncoding, + Option>: FixedSizeEncoding, { debug!("LazyTable::lookup: index={:?} len={:?}", i, self.encoded_size); @@ -322,7 +323,7 @@ where /// Size of the table in entries, including possible gaps. pub(super) fn size(&self) -> usize where - Option: FixedSizeEncoding, + for<'tcx> Option>: FixedSizeEncoding, { self.encoded_size / N } diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index b4dd253b83914..3a9fe31735fe2 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -33,6 +33,7 @@ #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] #![feature(get_mut_unchecked)] +#![feature(generic_associated_types)] #![feature(if_let_guard)] #![feature(map_first_last)] #![feature(negative_impls)] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 775b06c6c3832..b61a3827602fa 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -72,6 +72,7 @@ pub use self::context::{ }; pub use self::instance::{Instance, InstanceDef}; pub use self::list::List; +pub use self::parameterized::ParameterizedOverTcx; pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::BoundRegionKind::*; pub use self::sty::RegionKind::*; @@ -119,6 +120,7 @@ mod generics; mod impls_ty; mod instance; mod list; +mod parameterized; mod rvalue_scopes; mod structural_impls; mod sty; diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs new file mode 100644 index 0000000000000..54ba9e84fdb7b --- /dev/null +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -0,0 +1,119 @@ +use rustc_hir::def_id::DefId; +use rustc_index::vec::{Idx, IndexVec}; + +use crate::middle::exported_symbols::ExportedSymbol; +use crate::mir::Body; +use crate::thir::abstract_const::Node; +use crate::ty::{ + self, Const, FnSig, GeneratorDiagnosticData, GenericPredicates, Predicate, TraitRef, Ty, +}; + +pub trait ParameterizedOverTcx: 'static { + #[allow(unused_lifetimes)] + type Value<'tcx>; +} + +impl ParameterizedOverTcx for &'static [T] { + type Value<'tcx> = &'tcx [T::Value<'tcx>]; +} + +impl ParameterizedOverTcx for Option { + type Value<'tcx> = Option>; +} + +impl ParameterizedOverTcx for (A, B) { + type Value<'tcx> = (A::Value<'tcx>, B::Value<'tcx>); +} + +impl ParameterizedOverTcx for IndexVec { + type Value<'tcx> = IndexVec>; +} + +impl ParameterizedOverTcx for ty::Binder<'static, T> { + type Value<'tcx> = ty::Binder<'tcx, T::Value<'tcx>>; +} + +#[macro_export] +macro_rules! trivially_parameterized_over_tcx { + ($($ty:ty),+ $(,)?) => { + $( + impl $crate::ty::ParameterizedOverTcx for $ty { + #[allow(unused_lifetimes)] + type Value<'tcx> = $ty; + } + )* + } +} + +trivially_parameterized_over_tcx! { + usize, + (), + u32, + std::string::String, + crate::metadata::ModChild, + crate::middle::codegen_fn_attrs::CodegenFnAttrs, + crate::middle::exported_symbols::SymbolExportInfo, + crate::mir::ConstQualifs, + ty::Generics, + ty::ImplPolarity, + ty::ReprOptions, + ty::TraitDef, + ty::Visibility, + ty::adjustment::CoerceUnsizedInfo, + ty::fast_reject::SimplifiedTypeGen, + rustc_ast::Attribute, + rustc_ast::MacArgs, + rustc_attr::ConstStability, + rustc_attr::Deprecation, + rustc_attr::Stability, + rustc_hir::Constness, + rustc_hir::Defaultness, + rustc_hir::GeneratorKind, + rustc_hir::IsAsync, + rustc_hir::LangItem, + rustc_hir::def::DefKind, + rustc_hir::def_id::DefIndex, + rustc_hir::definitions::DefKey, + rustc_index::bit_set::FiniteBitSet, + rustc_session::cstore::ForeignModule, + rustc_session::cstore::LinkagePreference, + rustc_session::cstore::NativeLib, + rustc_span::DebuggerVisualizerFile, + rustc_span::ExpnData, + rustc_span::ExpnHash, + rustc_span::ExpnId, + rustc_span::SourceFile, + rustc_span::Span, + rustc_span::Symbol, + rustc_span::def_id::DefPathHash, + rustc_span::hygiene::SyntaxContextData, + rustc_span::symbol::Ident, + rustc_type_ir::Variance, +} + +// HACK(compiler-errors): This macro rule can only take an ident, +// not a path, due to parsing ambiguity reasons. That means we gotta +// import all of these types above. +#[macro_export] +macro_rules! parameterized_over_tcx { + ($($ident:ident),+ $(,)?) => { + $( + impl $crate::ty::ParameterizedOverTcx for $ident<'static> { + type Value<'tcx> = $ident<'tcx>; + } + )* + } +} + +parameterized_over_tcx! { + Ty, + FnSig, + GenericPredicates, + TraitRef, + Const, + Predicate, + GeneratorDiagnosticData, + Body, + Node, + ExportedSymbol, +}