From ae331cb16a7a1f95eb1dd2b19e4d9736f98d519b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 30 Nov 2018 15:06:42 +0100 Subject: [PATCH 01/19] Update associated_item_def_ids --- src/librustc/query/mod.rs | 2 +- src/librustc/ty/mod.rs | 29 ++++++++++++++-------------- src/librustc_metadata/Cargo.toml | 1 + src/librustc_metadata/cstore_impl.rs | 5 +++-- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 2fff4c3f109b1..8b0c4ecea863c 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -264,7 +264,7 @@ rustc_queries! { Other { /// Maps from an impl/trait def-id to a list of the def-ids of its items - query associated_item_def_ids(_: DefId) -> Lrc> {} + query associated_item_def_ids(_: DefId) -> &'tcx [DefId] {} /// Maps from a trait item to the trait item "descriptor" query associated_item(_: DefId) -> ty::AssociatedItem {} diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2f71861d4dc0d..ee981a6b4452e 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3106,7 +3106,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub struct AssociatedItemsIterator<'a, 'gcx: 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, - def_ids: Lrc>, + def_ids: &'gcx [DefId], next_index: usize, } @@ -3183,26 +3183,27 @@ fn adt_sized_constraint<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Lrc> { + -> &'tcx [DefId] { let id = tcx.hir().as_local_hir_id(def_id).unwrap(); let item = tcx.hir().expect_item_by_hir_id(id); - let vec: Vec<_> = match item.node { + match item.node { hir::ItemKind::Trait(.., ref trait_item_refs) => { - trait_item_refs.iter() - .map(|trait_item_ref| trait_item_ref.id) - .map(|id| tcx.hir().local_def_id_from_hir_id(id.hir_id)) - .collect() + tcx.arena.alloc_from_iter( + trait_item_refs.iter() + .map(|trait_item_ref| trait_item_ref.id) + .map(|id| tcx.hir().local_def_id_from_hir_id(id.hir_id)) + ) } hir::ItemKind::Impl(.., ref impl_item_refs) => { - impl_item_refs.iter() - .map(|impl_item_ref| impl_item_ref.id) - .map(|id| tcx.hir().local_def_id_from_hir_id(id.hir_id)) - .collect() + tcx.arena.alloc_from_iter( + impl_item_refs.iter() + .map(|impl_item_ref| impl_item_ref.id) + .map(|id| tcx.hir().local_def_id_from_hir_id(id.hir_id)) + ) } - hir::ItemKind::TraitAlias(..) => vec![], + hir::ItemKind::TraitAlias(..) => &[], _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait") - }; - Lrc::new(vec) + } } fn def_span<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Span { diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index e234f4f880703..76aba33b6a404 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -13,6 +13,7 @@ crate-type = ["dylib"] flate2 = "1.0" log = "0.4" memmap = "0.6" +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } errors = { path = "../librustc_errors", package = "rustc_errors" } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 087256a971056..c54f106c01baa 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -21,6 +21,7 @@ use rustc::hir::map::definitions::DefPathTable; use rustc::util::nodemap::DefIdMap; use rustc_data_structures::svh::Svh; +use smallvec::SmallVec; use std::any::Any; use rustc_data_structures::sync::Lrc; use std::sync::Arc; @@ -108,10 +109,10 @@ provide! { <'tcx> tcx, def_id, other, cdata, } variances_of => { tcx.arena.alloc_from_iter(cdata.get_item_variances(def_id.index)) } associated_item_def_ids => { - let mut result = vec![]; + let mut result = SmallVec::<[_; 8]>::new(); cdata.each_child_of_item(def_id.index, |child| result.push(child.res.def_id()), tcx.sess); - Lrc::new(result) + tcx.arena.alloc_slice(&result) } associated_item => { cdata.get_associated_item(def_id.index) } impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) } From d2ef6c42dc28526a36bd8584add70aa1352b1a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 30 Nov 2018 15:19:12 +0100 Subject: [PATCH 02/19] Update inherent_impls --- src/librustc/arena.rs | 1 + src/librustc/query/mod.rs | 4 ++-- src/librustc/ty/mod.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_metadata/decoder.rs | 15 +++++++----- .../coherence/inherent_impls.rs | 24 ++++++------------- 6 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index b48d81f2ef8f4..a66a27d140772 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -58,6 +58,7 @@ macro_rules! arena_types { rustc::infer::canonical::Canonical<'tcx, rustc::infer::canonical::QueryResponse<'tcx, rustc::ty::Ty<'tcx>> >, + [few] crate_inherent_impls: rustc::ty::CrateInherentImpls, ], $tcx); ) } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 8b0c4ecea863c..8309154759914 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -279,7 +279,7 @@ rustc_queries! { /// Maps a DefId of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. - query inherent_impls(_: DefId) -> Lrc> { + query inherent_impls(_: DefId) -> &'tcx [DefId] { eval_always } } @@ -385,7 +385,7 @@ rustc_queries! { /// Not meant to be used directly outside of coherence. /// (Defined only for `LOCAL_CRATE`.) query crate_inherent_impls(k: CrateNum) - -> Lrc { + -> &'tcx CrateInherentImpls { eval_always desc { "all inherent impls defined in crate `{:?}`", k } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index ee981a6b4452e..0fba45dc3da14 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3389,7 +3389,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { /// (constructing this map requires touching the entire crate). #[derive(Clone, Debug, Default, HashStable)] pub struct CrateInherentImpls { - pub inherent_impls: DefIdMap>>, + pub inherent_impls: DefIdMap>, } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)] diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index c54f106c01baa..0a8cba0829273 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -135,7 +135,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, (cdata.mir_const_qualif(def_id.index), tcx.arena.alloc(BitSet::new_empty(0))) } fn_sig => { cdata.fn_sig(def_id.index, tcx) } - inherent_impls => { Lrc::new(cdata.get_inherent_implementations_for_type(def_id.index)) } + inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } is_const_fn_raw => { cdata.is_const_fn_raw(def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } static_mutability => { cdata.static_mutability(def_id.index) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index d882fe6f27ecc..c4d1f06b5c406 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1012,12 +1012,15 @@ impl<'a, 'tcx> CrateMetadata { None } - pub fn get_inherent_implementations_for_type(&self, id: DefIndex) -> Vec { - self.entry(id) - .inherent_impls - .decode(self) - .map(|index| self.local_def_id(index)) - .collect() + pub fn get_inherent_implementations_for_type( + &self, + tcx: TyCtxt<'_, 'tcx, '_>, + id: DefIndex + ) -> &'tcx [DefId] { + tcx.arena.alloc_from_iter(self.entry(id) + .inherent_impls + .decode(self) + .map(|index| self.local_def_id(index))) } pub fn get_implementations_for_trait(&self, diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index d167c7fcafbe4..644d95963e652 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -13,14 +13,13 @@ use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ty::{self, CrateInherentImpls, TyCtxt}; -use rustc_data_structures::sync::Lrc; use syntax::ast; use syntax_pos::Span; /// On-demand query: yields a map containing all types mapped to their inherent impls. pub fn crate_inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) - -> Lrc { + -> &'tcx CrateInherentImpls { assert_eq!(crate_num, LOCAL_CRATE); let krate = tcx.hir().krate(); @@ -29,13 +28,13 @@ pub fn crate_inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impls_map: Default::default(), }; krate.visit_all_item_likes(&mut collect); - Lrc::new(collect.impls_map) + tcx.arena.alloc(collect.impls_map) } /// On-demand query: yields a vector of the inherent impls for a specific type. pub fn inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty_def_id: DefId) - -> Lrc> { + -> &'tcx [DefId] { assert!(ty_def_id.is_local()); // NB. Until we adopt the red-green dep-tracking algorithm (see @@ -53,15 +52,11 @@ pub fn inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // // [the plan]: https://github.com/rust-lang/rust-roadmap/issues/4 - thread_local! { - static EMPTY_DEF_ID_VEC: Lrc> = Lrc::new(vec![]) - } - let result = tcx.dep_graph.with_ignore(|| { let crate_map = tcx.crate_inherent_impls(ty_def_id.krate); match crate_map.inherent_impls.get(&ty_def_id) { - Some(v) => v.clone(), - None => EMPTY_DEF_ID_VEC.with(|v| v.clone()) + Some(v) => &v[..], + None => &[], } }); @@ -289,13 +284,8 @@ impl<'a, 'tcx> InherentCollect<'a, 'tcx> { // type def ID, if there is a base type for this implementation and // the implementation does not have any associated traits. let impl_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id); - let mut rc_vec = self.impls_map.inherent_impls - .entry(def_id) - .or_default(); - - // At this point, there should not be any clones of the - // `Lrc`, so we can still safely push into it in place: - Lrc::get_mut(&mut rc_vec).unwrap().push(impl_def_id); + let vec = self.impls_map.inherent_impls.entry(def_id).or_default(); + vec.push(impl_def_id); } else { struct_span_err!(self.tcx.sess, item.span, From 63f15a5e6522d9fde947fc7093b6a0a9b7b3256a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 30 Nov 2018 20:15:09 +0100 Subject: [PATCH 03/19] Update borrowck --- src/librustc/arena.rs | 1 + src/librustc/query/mod.rs | 2 +- src/librustc_borrowck/borrowck/mod.rs | 7 +++---- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index a66a27d140772..de0e780b261f3 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -59,6 +59,7 @@ macro_rules! arena_types { rustc::infer::canonical::QueryResponse<'tcx, rustc::ty::Ty<'tcx>> >, [few] crate_inherent_impls: rustc::ty::CrateInherentImpls, + [decode] borrowck: rustc::middle::borrowck::BorrowCheckResult, ], $tcx); ) } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 8309154759914..346bff0efe23a 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -373,7 +373,7 @@ rustc_queries! { } BorrowChecking { - query borrowck(_: DefId) -> Lrc {} + query borrowck(_: DefId) -> &'tcx BorrowCheckResult {} /// Borrow checks the function body. If this is a closure, returns /// additional requirements that the closure's creator must verify. diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 65a550b1b8914..7dca47485bb92 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -32,7 +32,6 @@ use std::borrow::Cow; use std::cell::{Cell, RefCell}; use std::fmt; use std::rc::Rc; -use rustc_data_structures::sync::Lrc; use std::hash::{Hash, Hasher}; use syntax::source_map::CompilerDesugaringKind; use syntax_pos::{MultiSpan, Span}; @@ -75,7 +74,7 @@ pub struct AnalysisData<'a, 'tcx: 'a> { } fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) - -> Lrc + -> &'tcx BorrowCheckResult { assert!(tcx.use_ast_borrowck() || tcx.migrate_borrowck()); @@ -89,7 +88,7 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) // those things (notably the synthesized constructors from // tuple structs/variants) do not have an associated body // and do not need borrowchecking. - return Lrc::new(BorrowCheckResult { + return tcx.arena.alloc(BorrowCheckResult { used_mut_nodes: Default::default(), signalled_any_error: SignalledError::NoErrorsSeen, }) @@ -136,7 +135,7 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) check_loans::check_loans(&mut bccx, &loan_dfcx, &flowed_moves, &all_loans, body); } - Lrc::new(BorrowCheckResult { + tcx.arena.alloc(BorrowCheckResult { used_mut_nodes: bccx.used_mut_nodes.into_inner(), signalled_any_error: bccx.signalled_any_error.into_inner(), }) From cc60f169748fd6c358b78bde0cd5d2239194f120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 30 Nov 2018 21:05:48 +0100 Subject: [PATCH 04/19] Update upstream_monomorphizations and upstream_monomorphizations_for --- src/librustc/arena.rs | 7 +++++++ src/librustc/query/mod.rs | 4 ++-- src/librustc_codegen_ssa/back/symbol_export.rs | 12 ++++-------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index de0e780b261f3..e6808e0f3bfd8 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -60,6 +60,13 @@ macro_rules! arena_types { >, [few] crate_inherent_impls: rustc::ty::CrateInherentImpls, [decode] borrowck: rustc::middle::borrowck::BorrowCheckResult, + [few] upstream_monomorphizations: + rustc::util::nodemap::DefIdMap< + rustc_data_structures::fx::FxHashMap< + rustc::ty::subst::SubstsRef<'tcx>, + rustc::hir::def_id::CrateNum + > + >, ], $tcx); ) } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 346bff0efe23a..190d3bf321b6b 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -683,11 +683,11 @@ rustc_queries! { Codegen { query upstream_monomorphizations( k: CrateNum - ) -> Lrc, CrateNum>>>> { + ) -> &'tcx DefIdMap, CrateNum>> { desc { "collecting available upstream monomorphizations `{:?}`", k } } query upstream_monomorphizations_for(_: DefId) - -> Option, CrateNum>>> {} + -> Option<&'tcx FxHashMap, CrateNum>> {} } Other { diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index a55f783df43a3..616049ea112a4 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -282,7 +282,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn upstream_monomorphizations_provider<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum) - -> Lrc, CrateNum>>>> + -> &'tcx DefIdMap, CrateNum>> { debug_assert!(cnum == LOCAL_CRATE); @@ -326,20 +326,16 @@ fn upstream_monomorphizations_provider<'a, 'tcx>( } } - Lrc::new(instances.into_iter() - .map(|(key, value)| (key, Lrc::new(value))) - .collect()) + tcx.arena.alloc(instances) } fn upstream_monomorphizations_for_provider<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Option, CrateNum>>> + -> Option<&'tcx FxHashMap, CrateNum>> { debug_assert!(!def_id.is_local()); - tcx.upstream_monomorphizations(LOCAL_CRATE) - .get(&def_id) - .cloned() + tcx.upstream_monomorphizations(LOCAL_CRATE).get(&def_id) } fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> bool { From 64865444ed27176db6ee4c02573933bf79f70c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 30 Nov 2018 21:23:01 +0100 Subject: [PATCH 05/19] Update implementations_of_trait and all_trait_implementations --- src/librustc/query/mod.rs | 4 ++-- src/librustc_metadata/cstore_impl.rs | 10 ++-------- src/librustc_metadata/decoder.rs | 25 ++++++++++++++----------- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 190d3bf321b6b..00a3d58860bd1 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -726,12 +726,12 @@ rustc_queries! { TypeChecking { query implementations_of_trait(_: (CrateNum, DefId)) - -> Lrc> { + -> &'tcx [DefId] { no_force desc { "looking up implementations of a trait in a crate" } } query all_trait_implementations(_: CrateNum) - -> Lrc> { + -> &'tcx [DefId] { desc { "looking up all (?) trait implementations" } } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 0a8cba0829273..0358a92ece161 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -208,18 +208,12 @@ provide! { <'tcx> tcx, def_id, other, cdata, extra_filename => { cdata.root.extra_filename.clone() } - implementations_of_trait => { - let mut result = vec![]; - let filter = Some(other); - cdata.get_implementations_for_trait(filter, &mut result); - Lrc::new(result) + cdata.get_implementations_for_trait(tcx, Some(other)) } all_trait_implementations => { - let mut result = vec![]; - cdata.get_implementations_for_trait(None, &mut result); - Lrc::new(result) + cdata.get_implementations_for_trait(tcx, None) } visibility => { cdata.get_visibility(def_id.index) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index c4d1f06b5c406..31d0b56e48eda 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1023,31 +1023,34 @@ impl<'a, 'tcx> CrateMetadata { .map(|index| self.local_def_id(index))) } - pub fn get_implementations_for_trait(&self, - filter: Option, - result: &mut Vec) { + pub fn get_implementations_for_trait( + &self, + tcx: TyCtxt<'_, 'tcx, '_>, + filter: Option, + ) -> &'tcx [DefId] { if self.proc_macros.is_some() { // proc-macro crates export no trait impls. - return + return &[] } // Do a reverse lookup beforehand to avoid touching the crate_num // hash map in the loop below. let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) { Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)), - Some(None) => return, + Some(None) => return &[], None => None, }; if let Some(filter) = filter { - if let Some(impls) = self.trait_impls - .get(&filter) { - result.extend(impls.decode(self).map(|idx| self.local_def_id(idx))); + if let Some(impls) = self.trait_impls.get(&filter) { + tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx))) + } else { + &[] } } else { - for impls in self.trait_impls.values() { - result.extend(impls.decode(self).map(|idx| self.local_def_id(idx))); - } + tcx.arena.alloc_from_iter(self.trait_impls.values().flat_map(|impls| { + impls.decode(self).map(|idx| self.local_def_id(idx)) + })) } } From 097d27587207cf0586664a2d596c163d923012ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 30 Nov 2018 22:26:57 +0100 Subject: [PATCH 06/19] Update resolve_lifetimes, named_region_map, is_late_bound_map and object_lifetime_defaults_map --- src/librustc/arena.rs | 1 + src/librustc/middle/resolve_lifetime.rs | 23 +++++++++-------------- src/librustc/query/mod.rs | 8 ++++---- src/librustc/ty/context.rs | 4 ++-- 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index e6808e0f3bfd8..02ed30dd3865b 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -67,6 +67,7 @@ macro_rules! arena_types { rustc::hir::def_id::CrateNum > >, + [few] resolve_lifetimes: rustc::middle::resolve_lifetime::ResolveLifetimes, ], $tcx); ) } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 2402d0eefde48..7d645e3880caf 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -15,7 +15,6 @@ use crate::rustc::lint; use crate::session::Session; use crate::util::nodemap::{DefIdMap, FxHashMap, FxHashSet, HirIdMap, HirIdSet}; use errors::{Applicability, DiagnosticBuilder}; -use rustc_data_structures::sync::Lrc; use rustc_macros::HashStable; use std::borrow::Cow; use std::cell::Cell; @@ -211,10 +210,10 @@ struct NamedRegionMap { /// See [`NamedRegionMap`]. #[derive(Default)] pub struct ResolveLifetimes { - defs: FxHashMap>>, - late_bound: FxHashMap>>, + defs: FxHashMap>, + late_bound: FxHashMap>, object_lifetime_defaults: - FxHashMap>>>>, + FxHashMap>>, } impl_stable_hash_for!(struct crate::middle::resolve_lifetime::ResolveLifetimes { @@ -347,7 +346,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { named_region_map: |tcx, id| { let id = LocalDefId::from_def_id(DefId::local(id)); // (*) - tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id).cloned() + tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id) }, is_late_bound_map: |tcx, id| { @@ -355,7 +354,6 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { tcx.resolve_lifetimes(LOCAL_CRATE) .late_bound .get(&id) - .cloned() }, object_lifetime_defaults_map: |tcx, id| { @@ -363,7 +361,6 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { tcx.resolve_lifetimes(LOCAL_CRATE) .object_lifetime_defaults .get(&id) - .cloned() }, ..*providers @@ -379,7 +376,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { fn resolve_lifetimes<'tcx>( tcx: TyCtxt<'_, 'tcx, 'tcx>, for_krate: CrateNum, -) -> Lrc { +) -> &'tcx ResolveLifetimes { assert_eq!(for_krate, LOCAL_CRATE); let named_region_map = krate(tcx); @@ -388,24 +385,22 @@ fn resolve_lifetimes<'tcx>( for (hir_id, v) in named_region_map.defs { let map = rl.defs.entry(hir_id.owner_local_def_id()).or_default(); - Lrc::get_mut(map).unwrap().insert(hir_id.local_id, v); + map.insert(hir_id.local_id, v); } for hir_id in named_region_map.late_bound { let map = rl.late_bound .entry(hir_id.owner_local_def_id()) .or_default(); - Lrc::get_mut(map).unwrap().insert(hir_id.local_id); + map.insert(hir_id.local_id); } for (hir_id, v) in named_region_map.object_lifetime_defaults { let map = rl.object_lifetime_defaults .entry(hir_id.owner_local_def_id()) .or_default(); - Lrc::get_mut(map) - .unwrap() - .insert(hir_id.local_id, Lrc::new(v)); + map.insert(hir_id.local_id, v); } - Lrc::new(rl) + tcx.arena.alloc(rl) } fn krate<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> NamedRegionMap { diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 00a3d58860bd1..305e230f8a86f 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -756,19 +756,19 @@ rustc_queries! { BorrowChecking { // Lifetime resolution. See `middle::resolve_lifetimes`. - query resolve_lifetimes(_: CrateNum) -> Lrc { + query resolve_lifetimes(_: CrateNum) -> &'tcx ResolveLifetimes { desc { "resolving lifetimes" } } query named_region_map(_: DefIndex) -> - Option>> { + Option<&'tcx FxHashMap> { desc { "looking up a named region" } } query is_late_bound_map(_: DefIndex) -> - Option>> { + Option<&'tcx FxHashSet> { desc { "testing if a region is late bound" } } query object_lifetime_defaults_map(_: DefIndex) - -> Option>>>> { + -> Option<&'tcx FxHashMap>> { desc { "looking up lifetime defaults for a region" } } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index c9fee02f66bbd..aeb25d457ddf0 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2982,10 +2982,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn object_lifetime_defaults(self, id: HirId) - -> Option>> + -> Option<&'gcx [ObjectLifetimeDefault]> { self.object_lifetime_defaults_map(id.owner) - .and_then(|map| map.get(&id.local_id).cloned()) + .and_then(|map| map.get(&id.local_id).map(|v| &**v)) } } From b38af18bbbe2b19d76d0f4dc91310fa32729f58a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 30 Nov 2018 22:32:16 +0100 Subject: [PATCH 07/19] Update item_children --- src/librustc/query/mod.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 4 ++-- src/librustdoc/clean/mod.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 305e230f8a86f..a71936ae72290 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -786,7 +786,7 @@ rustc_queries! { eval_always desc { "fetching what a crate is named" } } - query item_children(_: DefId) -> Lrc>> {} + query item_children(_: DefId) -> &'tcx [Export] {} query extern_mod_stmt_cnum(_: DefId) -> Option {} query get_lib_features(_: CrateNum) -> Lrc { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 0358a92ece161..ae7e9d0bdabb7 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -223,9 +223,9 @@ provide! { <'tcx> tcx, def_id, other, cdata, } crate_name => { cdata.name } item_children => { - let mut result = vec![]; + let mut result = SmallVec::<[_; 8]>::new(); cdata.each_child_of_item(def_id.index, |child| result.push(child), tcx.sess); - Lrc::new(result) + tcx.arena.alloc_slice(&result) } defined_lib_features => { Lrc::new(cdata.get_lib_features()) } defined_lang_items => { Lrc::new(cdata.get_lang_items()) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f91cb469e4629..6ccfdd26e6578 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4430,7 +4430,7 @@ pub fn path_to_def(tcx: TyCtxt<'_, '_, '_>, path: &[Symbol]) -> Option { loop { let segment = path_it.next()?; - for item in mem::replace(&mut items, Lrc::new(vec![])).iter() { + for item in mem::replace(&mut items, &[]).iter() { if item.ident.name == *segment { if path_it.peek().is_none() { return match item.res { From ce797de027fc7c3ff1bedaac8d3c7a81bee238fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 30 Nov 2018 20:02:56 +0100 Subject: [PATCH 08/19] Update used_trait_imports --- src/librustc/arena.rs | 2 +- src/librustc/query/mod.rs | 2 +- src/librustc_typeck/check/mod.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 02ed30dd3865b..a9b7aa4c10d40 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -14,7 +14,7 @@ macro_rules! arena_types { rustc::hir::def_id::DefId, rustc::ty::subst::SubstsRef<$tcx> )>, - [few] mir_keys: rustc::util::nodemap::DefIdSet, + [few, decode] mir_keys: rustc::util::nodemap::DefIdSet, [decode] specialization_graph: rustc::traits::specialization_graph::Graph, [] region_scope_tree: rustc::middle::region::ScopeTree, [] item_local_set: rustc::util::nodemap::ItemLocalSet, diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index a71936ae72290..9e2310d968a55 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -361,7 +361,7 @@ rustc_queries! { } Other { - query used_trait_imports(_: DefId) -> Lrc {} + query used_trait_imports(_: DefId) -> &'tcx DefIdSet {} } TypeChecking { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 362b6f0504d99..e8e9246d05a31 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -808,8 +808,8 @@ fn has_typeck_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn used_trait_imports<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Lrc { - tcx.typeck_tables_of(def_id).used_trait_imports.clone() + -> &'tcx DefIdSet { + &*tcx.typeck_tables_of(def_id).used_trait_imports } fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, From 822b89ef243a9f79647063f751b7c83b56310016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 24 Apr 2019 01:45:50 +0200 Subject: [PATCH 09/19] Optimize alloc_from_iter --- src/libarena/lib.rs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index ce5e5f23a94b8..d6bec816e4ee6 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -486,9 +486,31 @@ impl DroplessArena { } } + #[inline] + unsafe fn write_from_iter>( + &self, + mut iter: I, + len: usize, + mem: *mut T, + ) -> &mut [T] { + let mut i = 0; + // Use a manual loop since LLVM manages to optimize it better for + // slice iterators + loop { + let value = iter.next(); + if i >= len || value.is_none() { + // We only return as many items as the iterator gave us, even + // though it was supposed to give us `len` + return slice::from_raw_parts_mut(mem, i); + } + ptr::write(mem.offset(i as isize), value.unwrap()); + i += 1; + } + } + #[inline] pub fn alloc_from_iter>(&self, iter: I) -> &mut [T] { - let mut iter = iter.into_iter(); + let iter = iter.into_iter(); assert!(mem::size_of::() != 0); assert!(!mem::needs_drop::()); @@ -505,10 +527,7 @@ impl DroplessArena { let size = len.checked_mul(mem::size_of::()).unwrap(); let mem = self.alloc_raw(size, mem::align_of::()) as *mut _ as *mut T; unsafe { - for i in 0..len { - ptr::write(mem.offset(i as isize), iter.next().unwrap()) - } - slice::from_raw_parts_mut(mem, len) + self.write_from_iter(iter, len, mem) } } (_, _) => { From 2d8bea365aa5ee203790275463aa340eb05d0299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 1 Dec 2018 18:13:27 +0100 Subject: [PATCH 10/19] Update GenericPredicates queries --- src/librustc/arena.rs | 1 + src/librustc/query/mod.rs | 10 ++--- src/librustc/ty/context.rs | 14 +++++++ src/librustc/ty/mod.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 8 ++-- src/librustc_privacy/lib.rs | 6 +-- src/librustc_typeck/astconv.rs | 3 +- src/librustc_typeck/check/mod.rs | 5 +-- src/librustc_typeck/collect.rs | 61 ++++++++++++---------------- src/librustdoc/clean/auto_trait.rs | 6 ++- src/librustdoc/clean/mod.rs | 3 +- 11 files changed, 64 insertions(+), 55 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index a9b7aa4c10d40..06e82f0ae9cb9 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -68,6 +68,7 @@ macro_rules! arena_types { > >, [few] resolve_lifetimes: rustc::middle::resolve_lifetime::ResolveLifetimes, + [decode] generic_predicates: rustc::ty::GenericPredicates<'tcx>, ], $tcx); ) } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 9e2310d968a55..64b20105da601 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -61,7 +61,7 @@ rustc_queries! { /// predicate gets in the way of some checks, which are intended /// to operate over only the actual where-clauses written by the /// user.) - query predicates_of(_: DefId) -> Lrc> {} + query predicates_of(_: DefId) -> &'tcx ty::GenericPredicates<'tcx> {} query native_libraries(_: CrateNum) -> Lrc> { desc { "looking up the native libraries of a linked crate" } @@ -166,11 +166,11 @@ rustc_queries! { /// equal to the `explicit_predicates_of` predicates plus the /// `inferred_outlives_of` predicates. query predicates_defined_on(_: DefId) - -> Lrc> {} + -> &'tcx ty::GenericPredicates<'tcx> {} /// Returns the predicates written explicit by the user. query explicit_predicates_of(_: DefId) - -> Lrc> {} + -> &'tcx ty::GenericPredicates<'tcx> {} /// Returns the inferred outlives predicates (e.g., for `struct /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`). @@ -182,14 +182,14 @@ rustc_queries! { /// evaluate them even during type conversion, often before the /// full predicates are available (note that supertraits have /// additional acyclicity requirements). - query super_predicates_of(key: DefId) -> Lrc> { + query super_predicates_of(key: DefId) -> &'tcx ty::GenericPredicates<'tcx> { desc { |tcx| "computing the supertraits of `{}`", tcx.def_path_str(key) } } /// To avoid cycles within the predicates of a single item we compute /// per-type-parameter predicates for resolving `T::AssocTy`. query type_param_predicates(key: (DefId, DefId)) - -> Lrc> { + -> &'tcx ty::GenericPredicates<'tcx> { no_force desc { |tcx| "computing the bounds for type parameter `{}`", { let id = tcx.hir().as_local_hir_id(key.1).unwrap(); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index aeb25d457ddf0..cccdfd13197c4 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -201,6 +201,10 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { } } +pub struct Common<'tcx> { + pub empty_predicates: ty::GenericPredicates<'tcx>, +} + pub struct CommonTypes<'tcx> { pub unit: Ty<'tcx>, pub bool: Ty<'tcx>, @@ -1045,6 +1049,9 @@ pub struct GlobalCtxt<'tcx> { pub dep_graph: DepGraph, + /// Common objects. + pub common: Common<'tcx>, + /// Common types, pre-interned for your convenience. pub types: CommonTypes<'tcx>, @@ -1252,6 +1259,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { s.fatal(&err); }); let interners = CtxtInterners::new(&arenas.interner); + let common = Common { + empty_predicates: ty::GenericPredicates { + parent: None, + predicates: vec![], + }, + }; let common_types = CommonTypes::new(&interners); let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); @@ -1308,6 +1321,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { global_arenas: &arenas.global, global_interners: interners, dep_graph, + common, types: common_types, lifetimes: common_lifetimes, consts: common_consts, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 0fba45dc3da14..0d22b8e0f4d5f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2298,7 +2298,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } #[inline] - pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Lrc> { + pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx GenericPredicates<'gcx> { tcx.predicates_of(self.did) } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index ae7e9d0bdabb7..19db99a1e185d 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -96,9 +96,11 @@ provide! { <'tcx> tcx, def_id, other, cdata, generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess)) } - predicates_of => { Lrc::new(cdata.get_predicates(def_id.index, tcx)) } - predicates_defined_on => { Lrc::new(cdata.get_predicates_defined_on(def_id.index, tcx)) } - super_predicates_of => { Lrc::new(cdata.get_super_predicates(def_id.index, tcx)) } + predicates_of => { tcx.arena.alloc(cdata.get_predicates(def_id.index, tcx)) } + predicates_defined_on => { + tcx.arena.alloc(cdata.get_predicates_defined_on(def_id.index, tcx)) + } + super_predicates_of => { tcx.arena.alloc(cdata.get_super_predicates(def_id.index, tcx)) } trait_def => { tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess)) } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index cd21713cddf97..cfeff4d193a09 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -67,7 +67,7 @@ trait DefIdVisitor<'a, 'tcx: 'a> { fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { self.skeleton().visit_trait(trait_ref) } - fn visit_predicates(&mut self, predicates: Lrc>) -> bool { + fn visit_predicates(&mut self, predicates: &ty::GenericPredicates<'tcx>) -> bool { self.skeleton().visit_predicates(predicates) } } @@ -89,8 +89,8 @@ impl<'a, 'tcx, V> DefIdVisitorSkeleton<'_, 'a, 'tcx, V> (!self.def_id_visitor.shallow() && substs.visit_with(self)) } - fn visit_predicates(&mut self, predicates: Lrc>) -> bool { - let ty::GenericPredicates { parent: _, predicates } = &*predicates; + fn visit_predicates(&mut self, predicates: &ty::GenericPredicates<'tcx>) -> bool { + let ty::GenericPredicates { parent: _, predicates } = predicates; for (predicate, _span) in predicates { match predicate { ty::Predicate::Trait(poly_predicate) => { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 4b052aec5fc2f..8032a95ea1ca1 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -17,7 +17,6 @@ use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef}; use rustc::ty::wf::object_region_bounds; use rustc::mir::interpret::ConstValue; -use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi; use crate::require_c_abi_if_c_variadic; use smallvec::SmallVec; @@ -46,7 +45,7 @@ pub trait AstConv<'gcx, 'tcx> { /// Returns the set of bounds in scope for the type parameter with /// the given id. fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) - -> Lrc>; + -> &'tcx ty::GenericPredicates<'tcx>; /// What lifetime should we use when a lifetime is omitted (and not elided)? fn re_infer(&self, span: Span, _def: Option<&ty::GenericParamDef>) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e8e9246d05a31..1abea8a78678d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -97,7 +97,6 @@ use crate::namespace::Namespace; use rustc::infer::{self, InferCtxt, InferOk, InferResult}; use rustc::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_data_structures::indexed_vec::Idx; -use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi::Abi; use rustc::infer::opaque_types::OpaqueTypeDecl; use rustc::infer::type_variable::{TypeVariableOrigin}; @@ -1907,7 +1906,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) - -> Lrc> + -> &'tcx ty::GenericPredicates<'tcx> { let tcx = self.tcx; let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); @@ -1915,7 +1914,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { let item_def_id = tcx.hir().local_def_id_from_hir_id(item_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; - Lrc::new(ty::GenericPredicates { + tcx.arena.alloc(ty::GenericPredicates { parent: None, predicates: self.param_env.caller_bounds.iter().filter_map(|&predicate| { match predicate { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 6527e8655b5ef..498d7e561274c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -31,7 +31,6 @@ use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; use rustc::ty::{ReprOptions, ToPredicate}; use rustc::util::captures::Captures; use rustc::util::nodemap::FxHashMap; -use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi; use syntax::ast; @@ -178,7 +177,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { } fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) - -> Lrc> { + -> &'tcx ty::GenericPredicates<'tcx> { self.tcx .at(span) .type_param_predicates((self.item_def_id, def_id)) @@ -243,7 +242,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { fn type_param_predicates<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, (item_def_id, def_id): (DefId, DefId), -) -> Lrc> { +) -> &'tcx ty::GenericPredicates<'tcx> { use rustc::hir::*; // In the AST, bounds can derive from two places. Either @@ -264,16 +263,11 @@ fn type_param_predicates<'a, 'tcx>( tcx.generics_of(item_def_id).parent }; - let mut result = parent.map_or_else( - || Lrc::new(ty::GenericPredicates { - parent: None, - predicates: vec![], - }), - |parent| { - let icx = ItemCtxt::new(tcx, parent); - icx.get_type_parameter_bounds(DUMMY_SP, def_id) - }, - ); + let result = parent.map_or(&tcx.common.empty_predicates, |parent| { + let icx = ItemCtxt::new(tcx, parent); + icx.get_type_parameter_bounds(DUMMY_SP, def_id) + }); + let mut extend = None; let item_hir_id = tcx.hir().as_local_hir_id(item_def_id).unwrap(); let ast_generics = match tcx.hir().get_by_hir_id(item_hir_id) { @@ -298,9 +292,7 @@ fn type_param_predicates<'a, 'tcx>( // Implied `Self: Trait` and supertrait bounds. if param_id == item_hir_id { let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id); - Lrc::make_mut(&mut result) - .predicates - .push((identity_trait_ref.to_predicate(), item.span)); + extend = Some((identity_trait_ref.to_predicate(), item.span)); } generics } @@ -317,11 +309,12 @@ fn type_param_predicates<'a, 'tcx>( }; let icx = ItemCtxt::new(tcx, item_def_id); - Lrc::make_mut(&mut result) - .predicates - .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, - OnlySelfBounds(true))); - result + let mut result = (*result).clone(); + result.predicates.extend(extend.into_iter()); + result.predicates + .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, + OnlySelfBounds(true))); + tcx.arena.alloc(result) } impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { @@ -690,7 +683,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad fn super_predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId, -) -> Lrc> { +) -> &'tcx ty::GenericPredicates<'tcx> { debug!("super_predicates(trait_def_id={:?})", trait_def_id); let trait_hir_id = tcx.hir().as_local_hir_id(trait_def_id).unwrap(); @@ -734,7 +727,7 @@ fn super_predicates_of<'a, 'tcx>( } } - Lrc::new(ty::GenericPredicates { + tcx.arena.alloc(ty::GenericPredicates { parent: None, predicates: superbounds, }) @@ -1842,7 +1835,7 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>( fn predicates_defined_on<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> Lrc> { +) -> &'tcx ty::GenericPredicates<'tcx> { debug!("predicates_defined_on({:?})", def_id); let mut result = tcx.explicit_predicates_of(def_id); debug!( @@ -1858,9 +1851,9 @@ fn predicates_defined_on<'a, 'tcx>( def_id, inferred_outlives, ); - Lrc::make_mut(&mut result) - .predicates - .extend(inferred_outlives.iter().map(|&p| (p, span))); + let mut predicates = (*result).clone(); + predicates.predicates.extend(inferred_outlives.iter().map(|&p| (p, span))); + result = tcx.arena.alloc(predicates); } debug!("predicates_defined_on({:?}) = {:?}", def_id, result); result @@ -1872,7 +1865,7 @@ fn predicates_defined_on<'a, 'tcx>( fn predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> Lrc> { +) -> &'tcx ty::GenericPredicates<'tcx> { let mut result = tcx.predicates_defined_on(def_id); if tcx.is_trait(def_id) { @@ -1889,9 +1882,9 @@ fn predicates_of<'a, 'tcx>( // used, and adding the predicate into this list ensures // that this is done. let span = tcx.def_span(def_id); - Lrc::make_mut(&mut result) - .predicates - .push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span)); + let mut predicates = (*result).clone(); + predicates.predicates.push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span)); + result = tcx.arena.alloc(predicates); } debug!("predicates_of(def_id={:?}) = {:?}", def_id, result); result @@ -1902,7 +1895,7 @@ fn predicates_of<'a, 'tcx>( fn explicit_predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> Lrc> { +) -> &'tcx ty::GenericPredicates<'tcx> { use rustc::hir::*; use rustc_data_structures::fx::FxHashSet; @@ -2017,7 +2010,7 @@ fn explicit_predicates_of<'a, 'tcx>( if impl_trait_fn.is_some() { // impl Trait - return Lrc::new(ty::GenericPredicates { + return tcx.arena.alloc(ty::GenericPredicates { parent: None, predicates: bounds.predicates(tcx, opaque_ty), }); @@ -2228,7 +2221,7 @@ fn explicit_predicates_of<'a, 'tcx>( ); } - let result = Lrc::new(ty::GenericPredicates { + let result = tcx.arena.alloc(ty::GenericPredicates { parent: generics.parent, predicates, }); diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 11e8192521d79..8e2460a14b87a 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -104,8 +104,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // Instead, we generate `impl !Send for Foo`, which better // expresses the fact that `Foo` never implements `Send`, // regardless of the choice of `T`. - let params = (self.cx.tcx.generics_of(param_env_def_id), &Default::default()) - .clean(self.cx).params; + let params = ( + self.cx.tcx.generics_of(param_env_def_id), + &&self.cx.tcx.common.empty_predicates, + ).clean(self.cx).params; Generics { params, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6ccfdd26e6578..296ce53ceb6db 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -10,7 +10,6 @@ mod auto_trait; mod blanket_impl; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; -use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi::Abi; use rustc_typeck::hir_ty_to_ty; use rustc::infer::region_constraints::{RegionConstraintData, Constraint}; @@ -1690,7 +1689,7 @@ impl Clean for hir::Generics { } impl<'a, 'tcx> Clean for (&'a ty::Generics, - &'a Lrc>) { + &'a &'tcx ty::GenericPredicates<'tcx>) { fn clean(&self, cx: &DocContext<'_>) -> Generics { use self::WherePredicate as WP; From ef3db91fc7713d2e069801d358c237c6b286489c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 5 Apr 2019 13:22:13 +0200 Subject: [PATCH 11/19] Remove subtle Default impl for Value --- src/librustc/ty/query/values.rs | 6 ----- .../incremental/cyclic-trait-hierarchy.rs | 1 - .../cycle-projection-based-on-where-clause.rs | 1 - ...le-projection-based-on-where-clause.stderr | 11 ++------- src/test/ui/issues/issue-20772.rs | 1 - src/test/ui/issues/issue-20772.stderr | 13 ++-------- src/test/ui/issues/issue-21177.rs | 1 - src/test/ui/issues/issue-21177.stderr | 11 ++------- src/test/ui/issues/issue-23302-3.rs | 1 - src/test/ui/issues/issue-23302-3.stderr | 24 +++---------------- 10 files changed, 9 insertions(+), 61 deletions(-) diff --git a/src/librustc/ty/query/values.rs b/src/librustc/ty/query/values.rs index a4b8d365a12ef..8834bc9f0f70b 100644 --- a/src/librustc/ty/query/values.rs +++ b/src/librustc/ty/query/values.rs @@ -14,12 +14,6 @@ impl<'tcx, T> Value<'tcx> for T { } } -impl<'tcx, T: Default> Value<'tcx> for T { - default fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> T { - T::default() - } -} - impl<'tcx> Value<'tcx> for Ty<'tcx> { fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> { tcx.types.err diff --git a/src/test/incremental/cyclic-trait-hierarchy.rs b/src/test/incremental/cyclic-trait-hierarchy.rs index 4102eb32580f0..27287d06d54b1 100644 --- a/src/test/incremental/cyclic-trait-hierarchy.rs +++ b/src/test/incremental/cyclic-trait-hierarchy.rs @@ -7,7 +7,6 @@ pub trait T2 { } #[cfg(cfail2)] pub trait T2: T1 { } //[cfail2]~^ ERROR cycle detected when computing the supertraits of `T2` -//[cfail2]~| ERROR cycle detected when computing the supertraits of `T2` pub trait T1: T2 { } diff --git a/src/test/ui/cycle-projection-based-on-where-clause.rs b/src/test/ui/cycle-projection-based-on-where-clause.rs index 336b67852cd01..d3609acfdff63 100644 --- a/src/test/ui/cycle-projection-based-on-where-clause.rs +++ b/src/test/ui/cycle-projection-based-on-where-clause.rs @@ -16,7 +16,6 @@ struct A where T : Trait, T : Add //~^ ERROR cycle detected - //~| ERROR associated type `Item` not found for `T` { data: T } diff --git a/src/test/ui/cycle-projection-based-on-where-clause.stderr b/src/test/ui/cycle-projection-based-on-where-clause.stderr index e5a5e2897cd0a..59815138e2e36 100644 --- a/src/test/ui/cycle-projection-based-on-where-clause.stderr +++ b/src/test/ui/cycle-projection-based-on-where-clause.stderr @@ -11,13 +11,6 @@ note: cycle used when processing `A` LL | T : Add | ^^^^^^^ -error[E0220]: associated type `Item` not found for `T` - --> $DIR/cycle-projection-based-on-where-clause.rs:17:19 - | -LL | T : Add - | ^^^^^^^ associated type `Item` not found - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0220, E0391. -For more information about an error, try `rustc --explain E0220`. +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/issues/issue-20772.rs b/src/test/ui/issues/issue-20772.rs index 36551e7014f10..1500bc831528a 100644 --- a/src/test/ui/issues/issue-20772.rs +++ b/src/test/ui/issues/issue-20772.rs @@ -1,6 +1,5 @@ trait T : Iterator //~^ ERROR cycle detected -//~| ERROR associated type `Item` not found for `Self` {} fn main() {} diff --git a/src/test/ui/issues/issue-20772.stderr b/src/test/ui/issues/issue-20772.stderr index 3b5dd975ce9e9..d64636310a368 100644 --- a/src/test/ui/issues/issue-20772.stderr +++ b/src/test/ui/issues/issue-20772.stderr @@ -3,7 +3,6 @@ error[E0391]: cycle detected when computing the supertraits of `T` | LL | / trait T : Iterator LL | | -LL | | LL | | {} | |__^ | @@ -13,17 +12,9 @@ note: cycle used when collecting item types in top-level module | LL | / trait T : Iterator LL | | -LL | | LL | | {} | |__^ -error[E0220]: associated type `Item` not found for `Self` - --> $DIR/issue-20772.rs:1:25 - | -LL | trait T : Iterator - | ^^^^^^^^^^ associated type `Item` not found - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0220, E0391. -For more information about an error, try `rustc --explain E0220`. +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/issues/issue-21177.rs b/src/test/ui/issues/issue-21177.rs index 9d153696b885e..258e362d1317c 100644 --- a/src/test/ui/issues/issue-21177.rs +++ b/src/test/ui/issues/issue-21177.rs @@ -5,6 +5,5 @@ trait Trait { fn foo>() { } //~^ ERROR cycle detected -//~| ERROR associated type `B` not found for `T` fn main() { } diff --git a/src/test/ui/issues/issue-21177.stderr b/src/test/ui/issues/issue-21177.stderr index 6841fe85dd792..00d9a3c46a723 100644 --- a/src/test/ui/issues/issue-21177.stderr +++ b/src/test/ui/issues/issue-21177.stderr @@ -11,13 +11,6 @@ note: cycle used when processing `foo` LL | fn foo>() { } | ^^^^ -error[E0220]: associated type `B` not found for `T` - --> $DIR/issue-21177.rs:6:21 - | -LL | fn foo>() { } - | ^^^^ associated type `B` not found - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0220, E0391. -For more information about an error, try `rustc --explain E0220`. +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/issues/issue-23302-3.rs b/src/test/ui/issues/issue-23302-3.rs index e17c5eea2a445..da75f33079886 100644 --- a/src/test/ui/issues/issue-23302-3.rs +++ b/src/test/ui/issues/issue-23302-3.rs @@ -1,5 +1,4 @@ const A: i32 = B; //~ ERROR cycle detected -//~^ ERROR cycle detected const B: i32 = A; diff --git a/src/test/ui/issues/issue-23302-3.stderr b/src/test/ui/issues/issue-23302-3.stderr index 94624640809b7..a7d643987f710 100644 --- a/src/test/ui/issues/issue-23302-3.stderr +++ b/src/test/ui/issues/issue-23302-3.stderr @@ -10,36 +10,18 @@ note: ...which requires checking which parts of `A` are promotable to static... LL | const A: i32 = B; | ^ note: ...which requires const checking if rvalue is promotable to static `B`... - --> $DIR/issue-23302-3.rs:4:1 + --> $DIR/issue-23302-3.rs:3:1 | LL | const B: i32 = A; | ^^^^^^^^^^^^^^^^^ note: ...which requires checking which parts of `B` are promotable to static... - --> $DIR/issue-23302-3.rs:4:16 + --> $DIR/issue-23302-3.rs:3:16 | LL | const B: i32 = A; | ^ = note: ...which again requires const checking if rvalue is promotable to static `A`, completing the cycle = note: cycle used when running analysis passes on this crate -error[E0391]: cycle detected when processing `A` - --> $DIR/issue-23302-3.rs:1:16 - | -LL | const A: i32 = B; - | ^ - | -note: ...which requires processing `B`... - --> $DIR/issue-23302-3.rs:4:16 - | -LL | const B: i32 = A; - | ^ - = note: ...which again requires processing `A`, completing the cycle -note: cycle used when processing `A` - --> $DIR/issue-23302-3.rs:1:1 - | -LL | const A: i32 = B; - | ^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0391`. From a074ee193d6965e235c5090f33b19b2fd08a38b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 19 May 2019 17:27:28 +0200 Subject: [PATCH 12/19] Add a comment for arena_types! --- src/librustc/arena.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 06e82f0ae9cb9..51588953a2fbb 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -6,6 +6,15 @@ use std::cell::RefCell; use std::marker::PhantomData; use smallvec::SmallVec; +/// This declares a list of types which can be allocated by `Arena`. +/// +/// The `few` modifier will cause allocation to use the shared arena and recording the destructor. +/// This is faster and more memory efficient if there's only a few allocations of the type. +/// Leaving `few` out will cause the type to get its own dedicated `TypedArena` which is +/// faster and more memory efficient if there is lots of allocations. +/// +/// Specifying the `decode` modifier will add decode impls for &T and &[T] where T is the type +/// listed. These impls will appear in the implement_ty_decoder! macro. #[macro_export] macro_rules! arena_types { ($macro:path, $args:tt, $tcx:lifetime) => ( From 3aa4b3e78fa4133dc70225f26047c791ae9bff05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 19 May 2019 18:02:08 +0200 Subject: [PATCH 13/19] Make ArenaField private --- src/librustc/arena.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 51588953a2fbb..d2797e652407b 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -139,7 +139,7 @@ pub trait ArenaAllocatable {} impl ArenaAllocatable for T {} -pub unsafe trait ArenaField<'tcx>: Sized { +unsafe trait ArenaField<'tcx>: Sized { /// Returns a specific arena to allocate from. /// If None is returned, the DropArena will be used. fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a TypedArena>; From 6ad9f1bc5432ed665e2435d2e7e1ac250c9cdbb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 19 May 2019 18:02:55 +0200 Subject: [PATCH 14/19] Update Cargo.lock --- Cargo.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.lock b/Cargo.lock index db9f0069ced0c..7a7d8eecd71d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2877,6 +2877,7 @@ dependencies = [ "rustc_errors 0.0.0", "rustc_target 0.0.0", "serialize 0.0.0", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_ext 0.0.0", From e33c4415b3a504bd723328a38bce0f14786db61b Mon Sep 17 00:00:00 2001 From: MaulingMonkey Date: Sun, 19 May 2019 17:10:48 -0700 Subject: [PATCH 15/19] Add basic CDB support to debuginfo compiletest s, to help catch `*.natvis` regressions, like those fixed in #60687. Several Microsoft debuggers (VS, VS Code, WinDbg, CDB, ...) consume the `*.natvis` files we embed into rust `*.pdb` files. While this only tests CDB, that test coverage should help for all of them. CHANGES src\bootstrap - test.rs: Run CDB debuginfo tests on MSVC targets src\test\debuginfo - issue-13213.rs: CDB has trouble with this, skip for now (newly discovered regression?) - pretty-std.rs: Was ignored, re-enable for CDB only to start with, add CDB tests. - should-fail.rs: Add CDB tests. src\tools\compiletest: - Added "-cdb" option - Added Mode::DebugInfoCdb ("debuginfo-cdb") - Added run_debuginfo_cdb_test[_no_opt] - Renamed Mode::DebugInfoBoth -> DebugInfoGdbLldb ("debuginfo-gdb+lldb") since it's no longer clear what "Both" means. - Find CDB at the default Win10 SDK install path "C:\Program Files (x86)\Windows Kits\10\Debugger\*\cdb.exe" - Ignore CDB tests if CDB not found. ISSUES - `compute_stamp_hash`: not sure if there's any point in hashing `%ProgramFiles(x86)%` - `OsString` lacks any `*.natvis` entries (would be nice to add in a followup changelist) - DSTs (array/string slices) which work in VS & VS Code fail in CDB. - I've avoided `Mode::DebugInfoAll` as 3 debuggers leads to pow(2,3)=8 possible combinations. REFERENCE CDB is not part of the base Visual Studio install, but can be added via the Windows 10 SDK: https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk Installing just "Debugging Tools for Windows" is sufficient. CDB appears to already be installed on appveyor CI, where this changelist can find it, based on it's use here: https://github.com/rust-lang/rust/blob/0ffc57311030a1930edfa721fe57d0000a063af4/appveyor.yml#L227 CDB commands and command line reference: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-reference --- src/bootstrap/test.rs | 8 +- src/test/debuginfo/issue-13213.rs | 1 + src/test/debuginfo/pretty-std.rs | 53 ++++++++++++- src/test/debuginfo/should-fail.rs | 7 ++ src/tools/compiletest/src/common.rs | 16 +++- src/tools/compiletest/src/header.rs | 21 +++-- src/tools/compiletest/src/main.rs | 66 ++++++++++++++-- src/tools/compiletest/src/runtest.rs | 110 +++++++++++++++++++++++++-- 8 files changed, 251 insertions(+), 31 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 7826ac9471806..40105e0911738 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -976,14 +976,10 @@ impl Step for Compiletest { } if suite == "debuginfo" { - // Skip debuginfo tests on MSVC - if builder.config.build.contains("msvc") { - return; - } - + let msvc = builder.config.build.contains("msvc"); if mode == "debuginfo" { return builder.ensure(Compiletest { - mode: "debuginfo-both", + mode: if msvc { "debuginfo-cdb" } else { "debuginfo-gdb+lldb" }, ..self }); } diff --git a/src/test/debuginfo/issue-13213.rs b/src/test/debuginfo/issue-13213.rs index 3c9a365fd4f7b..393478460d48f 100644 --- a/src/test/debuginfo/issue-13213.rs +++ b/src/test/debuginfo/issue-13213.rs @@ -1,4 +1,5 @@ // min-lldb-version: 310 +// ignore-cdb: Fails with exit code 0xc0000135 ("the application failed to initialize properly") // aux-build:issue-13213-aux.rs diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index 82802eff08abb..f568371d68a1a 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -1,6 +1,5 @@ -// ignore-windows failing on win32 bot // ignore-freebsd: gdb package too new -// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 +// only-cdb // Test temporarily ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155 // ignore-android: FIXME(#10381) // compile-flags:-g // min-gdb-version 7.7 @@ -63,6 +62,56 @@ // lldb-check:[...]$5 = None +// === CDB TESTS ================================================================================== + +// cdb-command: g + +// cdb-command: dx slice,d +// cdb-check:slice,d [...] +// NOTE: While slices have a .natvis entry that works in VS & VS Code, it fails in CDB 10.0.18362.1 + +// cdb-command: dx vec,d +// cdb-check:vec,d [...] : { size=4 } [Type: [...]::Vec] +// cdb-check: [size] : 4 [Type: [...]] +// cdb-check: [capacity] : [...] [Type: [...]] +// cdb-check: [0] : 4 [Type: unsigned __int64] +// cdb-check: [1] : 5 [Type: unsigned __int64] +// cdb-check: [2] : 6 [Type: unsigned __int64] +// cdb-check: [3] : 7 [Type: unsigned __int64] + +// cdb-command: dx str_slice +// cdb-check:str_slice [...] +// NOTE: While string slices have a .natvis entry that works in VS & VS Code, it fails in CDB 10.0.18362.1 + +// cdb-command: dx string +// cdb-check:string : "IAMA string!" [Type: [...]::String] +// cdb-check: [] [Type: [...]::String] +// cdb-check: [size] : 0xc [Type: [...]] +// cdb-check: [capacity] : 0xc [Type: [...]] +// cdb-check: [0] : 73 'I' [Type: char] +// cdb-check: [1] : 65 'A' [Type: char] +// cdb-check: [2] : 77 'M' [Type: char] +// cdb-check: [3] : 65 'A' [Type: char] +// cdb-check: [4] : 32 ' ' [Type: char] +// cdb-check: [5] : 115 's' [Type: char] +// cdb-check: [6] : 116 't' [Type: char] +// cdb-check: [7] : 114 'r' [Type: char] +// cdb-check: [8] : 105 'i' [Type: char] +// cdb-check: [9] : 110 'n' [Type: char] +// cdb-check: [10] : 103 'g' [Type: char] +// cdb-check: [11] : 33 '!' [Type: char] + +// cdb-command: dx os_string +// cdb-check:os_string [Type: [...]::OsString] +// NOTE: OsString doesn't have a .natvis entry yet. + +// cdb-command: dx some +// cdb-check:some : { Some 8 } [Type: [...]::Option] +// cdb-command: dx none +// cdb-check:none : { None } [Type: [...]::Option] +// cdb-command: dx some_string +// cdb-check:some_string : { Some "IAMA optional string!" } [Type: [...]::Option<[...]::String>] + #![allow(unused_variables)] use std::ffi::OsString; diff --git a/src/test/debuginfo/should-fail.rs b/src/test/debuginfo/should-fail.rs index 8765c018b1022..1e0d22cbce404 100644 --- a/src/test/debuginfo/should-fail.rs +++ b/src/test/debuginfo/should-fail.rs @@ -18,6 +18,13 @@ // lldb-command:print x // lldb-check:[...]$0 = 5 +// === CDB TESTS ================================================================================== + +// cdb-command:g + +// cdb-command:dx x +// cdb-check:string [...] : 5 [Type: [...]] + fn main() { let x = 1; diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 4699dee1716a9..722979c3c1402 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -1,5 +1,6 @@ pub use self::Mode::*; +use std::ffi::OsString; use std::fmt; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -15,7 +16,8 @@ pub enum Mode { RunPass, RunPassValgrind, Pretty, - DebugInfoBoth, + DebugInfoCdb, + DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb, Codegen, @@ -33,9 +35,10 @@ impl Mode { pub fn disambiguator(self) -> &'static str { // Run-pass and pretty run-pass tests could run concurrently, and if they do, // they need to keep their output segregated. Same is true for debuginfo tests that - // can be run both on gdb and lldb. + // can be run on cdb, gdb, and lldb. match self { Pretty => ".pretty", + DebugInfoCdb => ".cdb", DebugInfoGdb => ".gdb", DebugInfoLldb => ".lldb", _ => "", @@ -52,7 +55,8 @@ impl FromStr for Mode { "run-pass" => Ok(RunPass), "run-pass-valgrind" => Ok(RunPassValgrind), "pretty" => Ok(Pretty), - "debuginfo-both" => Ok(DebugInfoBoth), + "debuginfo-cdb" => Ok(DebugInfoCdb), + "debuginfo-gdb+lldb" => Ok(DebugInfoGdbLldb), "debuginfo-lldb" => Ok(DebugInfoLldb), "debuginfo-gdb" => Ok(DebugInfoGdb), "codegen" => Ok(Codegen), @@ -77,7 +81,8 @@ impl fmt::Display for Mode { RunPass => "run-pass", RunPassValgrind => "run-pass-valgrind", Pretty => "pretty", - DebugInfoBoth => "debuginfo-both", + DebugInfoCdb => "debuginfo-cdb", + DebugInfoGdbLldb => "debuginfo-gdb+lldb", DebugInfoGdb => "debuginfo-gdb", DebugInfoLldb => "debuginfo-lldb", Codegen => "codegen", @@ -198,6 +203,9 @@ pub struct Config { /// Host triple for the compiler being invoked pub host: String, + /// Path to / name of the Microsoft Console Debugger (CDB) executable + pub cdb: Option, + /// Path to / name of the GDB executable pub gdb: Option, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index dbc477585cbfc..ab5594f36050d 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -57,9 +57,9 @@ enum ParsedNameDirective { NoMatch, /// Match. Match, - /// Mode was DebugInfoBoth and this matched gdb. + /// Mode was DebugInfoGdbLldb and this matched gdb. MatchGdb, - /// Mode was DebugInfoBoth and this matched lldb. + /// Mode was DebugInfoGdbLldb and this matched lldb. MatchLldb, } @@ -81,13 +81,17 @@ impl EarlyProps { revisions: vec![], }; - if config.mode == common::DebugInfoBoth { + if config.mode == common::DebugInfoGdbLldb { if config.lldb_python_dir.is_none() { props.ignore = props.ignore.no_lldb(); } if config.gdb_version.is_none() { props.ignore = props.ignore.no_gdb(); } + } else if config.mode == common::DebugInfoCdb { + if config.cdb.is_none() { + props.ignore = Ignore::Ignore; + } } let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some(); @@ -133,12 +137,12 @@ impl EarlyProps { } } - if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoBoth) && + if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoGdbLldb) && props.ignore.can_run_gdb() && ignore_gdb(config, ln) { props.ignore = props.ignore.no_gdb(); } - if (config.mode == common::DebugInfoLldb || config.mode == common::DebugInfoBoth) && + if (config.mode == common::DebugInfoLldb || config.mode == common::DebugInfoGdbLldb) && props.ignore.can_run_lldb() && ignore_lldb(config, ln) { props.ignore = props.ignore.no_lldb(); } @@ -804,7 +808,7 @@ impl Config { ParsedNameDirective::Match } else { match self.mode { - common::DebugInfoBoth => { + common::DebugInfoGdbLldb => { if name == "gdb" { ParsedNameDirective::MatchGdb } else if name == "lldb" { @@ -813,6 +817,11 @@ impl Config { ParsedNameDirective::NoMatch } }, + common::DebugInfoCdb => if name == "cdb" { + ParsedNameDirective::Match + } else { + ParsedNameDirective::NoMatch + }, common::DebugInfoGdb => if name == "gdb" { ParsedNameDirective::Match } else { diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 442e58bfd74e1..631ed067c341a 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -1,5 +1,6 @@ #![crate_name = "compiletest"] #![feature(test)] +#![feature(path_buf_capacity)] #![feature(vec_remove_item)] #![deny(warnings, rust_2018_idioms)] @@ -8,7 +9,7 @@ extern crate test; use crate::common::CompareMode; use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS}; use crate::common::{Config, TestPaths}; -use crate::common::{DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Mode, Pretty}; +use crate::common::{DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb, Mode, Pretty}; use getopts::Options; use std::env; use std::ffi::OsString; @@ -164,6 +165,12 @@ pub fn parse_config(args: Vec) -> Config { .optopt("", "logfile", "file to log test execution to", "FILE") .optopt("", "target", "the target to build for", "TARGET") .optopt("", "host", "the host to build for", "HOST") + .optopt( + "", + "cdb", + "path to CDB to use for CDB debuginfo tests", + "PATH", + ) .optopt( "", "gdb", @@ -273,6 +280,7 @@ pub fn parse_config(args: Vec) -> Config { let target = opt_str2(matches.opt_str("target")); let android_cross_path = opt_path(matches, "android-cross-path"); + let cdb = analyze_cdb(matches.opt_str("cdb"), &target); let (gdb, gdb_version, gdb_native_rust) = analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path); let (lldb_version, lldb_native_rust) = extract_lldb_version(matches.opt_str("lldb-version")); @@ -319,6 +327,7 @@ pub fn parse_config(args: Vec) -> Config { target_rustcflags: matches.opt_str("target-rustcflags"), target: target, host: opt_str2(matches.opt_str("host")), + cdb, gdb, gdb_version, gdb_native_rust, @@ -421,7 +430,7 @@ pub fn opt_str2(maybestr: Option) -> String { pub fn run_tests(config: &Config) { if config.target.contains("android") { - if config.mode == DebugInfoGdb || config.mode == DebugInfoBoth { + if config.mode == DebugInfoGdb || config.mode == DebugInfoGdbLldb { println!( "{} debug-info test uses tcp 5039 port.\ please reserve it", @@ -440,8 +449,8 @@ pub fn run_tests(config: &Config) { match config.mode { // Note that we don't need to emit the gdb warning when - // DebugInfoBoth, so it is ok to list that here. - DebugInfoBoth | DebugInfoLldb => { + // DebugInfoGdbLldb, so it is ok to list that here. + DebugInfoGdbLldb | DebugInfoLldb => { if let Some(lldb_version) = config.lldb_version.as_ref() { if is_blacklisted_lldb_version(&lldb_version[..]) { println!( @@ -470,7 +479,8 @@ pub fn run_tests(config: &Config) { return; } } - _ => { /* proceed */ } + + DebugInfoCdb | _ => { /* proceed */ } } // FIXME(#33435) Avoid spurious failures in codegen-units/partitioning tests. @@ -667,7 +677,7 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> Vec, ) -> test::TestFn { let mut config = config.clone(); - if config.mode == DebugInfoBoth { + if config.mode == DebugInfoGdbLldb { // If both gdb and lldb were ignored, then the test as a whole // would be ignored. if !ignore.can_run_gdb() { @@ -841,6 +851,48 @@ fn is_android_gdb_target(target: &String) -> bool { } } +/// Returns `true` if the given target is a MSVC target for the purpouses of CDB testing. +fn is_pc_windows_msvc_target(target: &String) -> bool { + target.ends_with("-pc-windows-msvc") +} + +fn find_cdb(target: &String) -> Option { + if cfg!(windows) && is_pc_windows_msvc_target(target) { + let pf86 = env::var_os("ProgramFiles(x86)").or(env::var_os("ProgramFiles"))?; + let cdb_arch = if cfg!(target_arch="x86") { + "x86" + } else if cfg!(target_arch="x86_64") { + "x64" + } else if cfg!(target_arch="aarch64") { + "arm64" + } else if cfg!(target_arch="arm") { + "arm" + } else { + return None; // No compatible CDB.exe in the Windows 10 SDK + }; + + let mut path = PathBuf::with_capacity(64); + path.push(pf86); + path.push(r"Windows Kits\10\Debuggers"); // We could check more known install locations (8.1?) + path.push(cdb_arch); + path.push(r"cdb.exe"); + + if path.exists() { + Some(path.into_os_string()) + } else { + None + } + } + else { + None + } +} + +/// Returns Path to CDB +fn analyze_cdb(cdb: Option, target: &String) -> Option { + cdb.map(|s| OsString::from(s)).or(find_cdb(target)) +} + /// Returns (Path to GDB, GDB Version, GDB has Rust Support) fn analyze_gdb(gdb: Option, target: &String, android_cross_path: &PathBuf) -> (Option, Option, bool) { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 2082de7cbce34..c0dedccdff8a3 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3,7 +3,7 @@ use crate::common::CompareMode; use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT}; use crate::common::{output_base_dir, output_base_name, output_testname_unique}; -use crate::common::{Codegen, CodegenUnits, DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Rustdoc}; +use crate::common::{Codegen, CodegenUnits, DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb, Rustdoc}; use crate::common::{CompileFail, Pretty, RunFail, RunPass, RunPassValgrind}; use crate::common::{Config, TestPaths}; use crate::common::{Incremental, MirOpt, RunMake, Ui, JsDocTest, Assembly}; @@ -242,7 +242,15 @@ pub fn compute_stamp_hash(config: &Config) -> String { let mut hash = DefaultHasher::new(); config.stage_id.hash(&mut hash); - if config.mode == DebugInfoGdb || config.mode == DebugInfoBoth { + if config.mode == DebugInfoCdb { + match config.cdb { + None => env::var_os("ProgramFiles(x86)").hash(&mut hash), + Some(ref s) if s.is_empty() => env::var_os("ProgramFiles(x86)").hash(&mut hash), + Some(ref s) => s.hash(&mut hash), + } + } + + if config.mode == DebugInfoGdb || config.mode == DebugInfoGdbLldb { match config.gdb { None => env::var_os("PATH").hash(&mut hash), Some(ref s) if s.is_empty() => env::var_os("PATH").hash(&mut hash), @@ -250,7 +258,7 @@ pub fn compute_stamp_hash(config: &Config) -> String { }; } - if config.mode == DebugInfoLldb || config.mode == DebugInfoBoth { + if config.mode == DebugInfoLldb || config.mode == DebugInfoGdbLldb { env::var_os("PATH").hash(&mut hash); env::var_os("PYTHONPATH").hash(&mut hash); } @@ -285,10 +293,11 @@ impl<'test> TestCx<'test> { RunFail => self.run_rfail_test(), RunPassValgrind => self.run_valgrind_test(), Pretty => self.run_pretty_test(), - DebugInfoBoth => { + DebugInfoGdbLldb => { self.run_debuginfo_gdb_test(); self.run_debuginfo_lldb_test(); }, + DebugInfoCdb => self.run_debuginfo_cdb_test(), DebugInfoGdb => self.run_debuginfo_gdb_test(), DebugInfoLldb => self.run_debuginfo_lldb_test(), Codegen => self.run_codegen_test(), @@ -656,6 +665,95 @@ impl<'test> TestCx<'test> { self.compose_and_run_compiler(rustc, Some(src)) } + fn run_debuginfo_cdb_test(&self) { + assert!(self.revision.is_none(), "revisions not relevant here"); + + let config = Config { + target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags), + host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags), + mode: DebugInfoCdb, + ..self.config.clone() + }; + + let test_cx = TestCx { + config: &config, + ..*self + }; + + test_cx.run_debuginfo_cdb_test_no_opt(); + } + + fn run_debuginfo_cdb_test_no_opt(&self) { + // compile test file (it should have 'compile-flags:-g' in the header) + let compile_result = self.compile_test(); + if !compile_result.status.success() { + self.fatal_proc_rec("compilation failed!", &compile_result); + } + + let exe_file = self.make_exe_name(); + + let prefixes = { + static PREFIXES: &'static [&'static str] = &["cdb", "cdbg"]; + // No "native rust support" variation for CDB yet. + PREFIXES + }; + + // Parse debugger commands etc from test files + let DebuggerCommands { + commands, + check_lines, + breakpoint_lines, + .. + } = self.parse_debugger_commands(prefixes); + + // https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-commands + let mut script_str = String::with_capacity(2048); + script_str.push_str("version\n"); // List CDB (and more) version info in test output + script_str.push_str(".nvlist\n"); // List loaded `*.natvis` files (bulk of MSVC debugger customizations) + + // Set breakpoints on every line that contains the string "#break" + let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy(); + for line in &breakpoint_lines { + script_str.push_str(&format!( + "bp `{}:{}`\n", + source_file_name, line + )); + } + + // Append the other `cdb-command:`s + for line in &commands { + script_str.push_str(line); + script_str.push_str("\n"); + } + + script_str.push_str("\nqq\n"); // Quit the debugger (including remote debugger, if any) + + // Write the script into a file + debug!("script_str = {}", script_str); + self.dump_output_file(&script_str, "debugger.script"); + let debugger_script = self.make_out_name("debugger.script"); + + let cdb_path = &self.config.cdb.as_ref().unwrap(); + let mut cdb = Command::new(cdb_path); + cdb + .arg("-lines") // Enable source line debugging. + .arg("-cf").arg(&debugger_script) + .arg(&exe_file); + + let debugger_run_result = self.compose_and_run( + cdb, + self.config.run_lib_path.to_str().unwrap(), + None, // aux_path + None // input + ); + + if !debugger_run_result.status.success() { + self.fatal_proc_rec("Error while running CDB", &debugger_run_result); + } + + self.check_debugger_output(&debugger_run_result, &check_lines); + } + fn run_debuginfo_gdb_test(&self) { assert!(self.revision.is_none(), "revisions not relevant here"); @@ -1429,7 +1527,7 @@ impl<'test> TestCx<'test> { RunPass | Ui => self.should_run_successfully(), Incremental => self.revision.unwrap().starts_with("r"), RunFail | RunPassValgrind | MirOpt | - DebugInfoBoth | DebugInfoGdb | DebugInfoLldb => true, + DebugInfoCdb | DebugInfoGdbLldb | DebugInfoGdb | DebugInfoLldb => true, _ => false, }; let output_file = if will_execute { @@ -1870,7 +1968,7 @@ impl<'test> TestCx<'test> { rustc.arg(dir_opt); } - RunFail | RunPassValgrind | Pretty | DebugInfoBoth | DebugInfoGdb | DebugInfoLldb + RunFail | RunPassValgrind | Pretty | DebugInfoCdb | DebugInfoGdbLldb | DebugInfoGdb | DebugInfoLldb | Codegen | Rustdoc | RunMake | CodegenUnits | JsDocTest | Assembly => { // do not use JSON output } From 0a423a70bb303195f09753dfdc5a7c4e149e29ff Mon Sep 17 00:00:00 2001 From: MaulingMonkey Date: Mon, 20 May 2019 02:44:26 -0700 Subject: [PATCH 16/19] Fix CDB support tidy check line length failures. --- src/test/debuginfo/pretty-std.rs | 6 +++--- src/tools/compiletest/src/main.rs | 2 +- src/tools/compiletest/src/runtest.rs | 9 +++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index f568371d68a1a..a684d3b88fd07 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -1,5 +1,5 @@ // ignore-freebsd: gdb package too new -// only-cdb // Test temporarily ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155 +// only-cdb // "Temporarily" ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155 // ignore-android: FIXME(#10381) // compile-flags:-g // min-gdb-version 7.7 @@ -81,7 +81,7 @@ // cdb-command: dx str_slice // cdb-check:str_slice [...] -// NOTE: While string slices have a .natvis entry that works in VS & VS Code, it fails in CDB 10.0.18362.1 +// NOTE: While string slices have a .natvis entry that works in VS & VS Code, it fails in CDB // cdb-command: dx string // cdb-check:string : "IAMA string!" [Type: [...]::String] @@ -110,7 +110,7 @@ // cdb-command: dx none // cdb-check:none : { None } [Type: [...]::Option] // cdb-command: dx some_string -// cdb-check:some_string : { Some "IAMA optional string!" } [Type: [...]::Option<[...]::String>] +// cdb-check:some_string : { Some "IAMA optional string!" } [[...]::Option<[...]::String>] #![allow(unused_variables)] use std::ffi::OsString; diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 631ed067c341a..48ecd5a914223 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -873,7 +873,7 @@ fn find_cdb(target: &String) -> Option { let mut path = PathBuf::with_capacity(64); path.push(pf86); - path.push(r"Windows Kits\10\Debuggers"); // We could check more known install locations (8.1?) + path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too? path.push(cdb_arch); path.push(r"cdb.exe"); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c0dedccdff8a3..c940e2de665ab 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3,7 +3,8 @@ use crate::common::CompareMode; use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT}; use crate::common::{output_base_dir, output_base_name, output_testname_unique}; -use crate::common::{Codegen, CodegenUnits, DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb, Rustdoc}; +use crate::common::{Codegen, CodegenUnits, Rustdoc}; +use crate::common::{DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb}; use crate::common::{CompileFail, Pretty, RunFail, RunPass, RunPassValgrind}; use crate::common::{Config, TestPaths}; use crate::common::{Incremental, MirOpt, RunMake, Ui, JsDocTest, Assembly}; @@ -709,7 +710,7 @@ impl<'test> TestCx<'test> { // https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-commands let mut script_str = String::with_capacity(2048); script_str.push_str("version\n"); // List CDB (and more) version info in test output - script_str.push_str(".nvlist\n"); // List loaded `*.natvis` files (bulk of MSVC debugger customizations) + script_str.push_str(".nvlist\n"); // List loaded `*.natvis` files, bulk of custom MSVC debug // Set breakpoints on every line that contains the string "#break" let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy(); @@ -1968,8 +1969,8 @@ impl<'test> TestCx<'test> { rustc.arg(dir_opt); } - RunFail | RunPassValgrind | Pretty | DebugInfoCdb | DebugInfoGdbLldb | DebugInfoGdb | DebugInfoLldb - | Codegen | Rustdoc | RunMake | CodegenUnits | JsDocTest | Assembly => { + RunFail | RunPassValgrind | Pretty | DebugInfoCdb | DebugInfoGdbLldb | DebugInfoGdb + | DebugInfoLldb | Codegen | Rustdoc | RunMake | CodegenUnits | JsDocTest | Assembly => { // do not use JSON output } } From 56b18ce6370a7e3376fce2d1c404532a887eb5b6 Mon Sep 17 00:00:00 2001 From: MaulingMonkey Date: Mon, 20 May 2019 15:00:36 -0700 Subject: [PATCH 17/19] Address CDB review feedback - Don't add path_buf_capacity feature. - Convert `find_cdb` to early return style, reducing indentation - Simplify `compute_stamp_hash` for CDB to just hash it's path, if any. --- src/tools/compiletest/src/main.rs | 52 +++++++++++++--------------- src/tools/compiletest/src/runtest.rs | 6 +--- 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 48ecd5a914223..d0dc9d11d3963 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -1,6 +1,5 @@ #![crate_name = "compiletest"] #![feature(test)] -#![feature(path_buf_capacity)] #![feature(vec_remove_item)] #![deny(warnings, rust_2018_idioms)] @@ -857,35 +856,34 @@ fn is_pc_windows_msvc_target(target: &String) -> bool { } fn find_cdb(target: &String) -> Option { - if cfg!(windows) && is_pc_windows_msvc_target(target) { - let pf86 = env::var_os("ProgramFiles(x86)").or(env::var_os("ProgramFiles"))?; - let cdb_arch = if cfg!(target_arch="x86") { - "x86" - } else if cfg!(target_arch="x86_64") { - "x64" - } else if cfg!(target_arch="aarch64") { - "arm64" - } else if cfg!(target_arch="arm") { - "arm" - } else { - return None; // No compatible CDB.exe in the Windows 10 SDK - }; + if !(cfg!(windows) && is_pc_windows_msvc_target(target)) { + return None; + } + + let pf86 = env::var_os("ProgramFiles(x86)").or(env::var_os("ProgramFiles"))?; + let cdb_arch = if cfg!(target_arch="x86") { + "x86" + } else if cfg!(target_arch="x86_64") { + "x64" + } else if cfg!(target_arch="aarch64") { + "arm64" + } else if cfg!(target_arch="arm") { + "arm" + } else { + return None; // No compatible CDB.exe in the Windows 10 SDK + }; - let mut path = PathBuf::with_capacity(64); - path.push(pf86); - path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too? - path.push(cdb_arch); - path.push(r"cdb.exe"); + let mut path = PathBuf::new(); + path.push(pf86); + path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too? + path.push(cdb_arch); + path.push(r"cdb.exe"); - if path.exists() { - Some(path.into_os_string()) - } else { - None - } - } - else { - None + if !path.exists() { + return None; } + + Some(path.into_os_string()) } /// Returns Path to CDB diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c940e2de665ab..d87bd66a1ac70 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -244,11 +244,7 @@ pub fn compute_stamp_hash(config: &Config) -> String { config.stage_id.hash(&mut hash); if config.mode == DebugInfoCdb { - match config.cdb { - None => env::var_os("ProgramFiles(x86)").hash(&mut hash), - Some(ref s) if s.is_empty() => env::var_os("ProgramFiles(x86)").hash(&mut hash), - Some(ref s) => s.hash(&mut hash), - } + config.cdb.hash(&mut hash); } if config.mode == DebugInfoGdb || config.mode == DebugInfoGdbLldb { From 3a132ea380fd8ce7b881aa1c59289f2d072d2c5a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 11:00:34 -0700 Subject: [PATCH 18/19] Bump compiler-builtins to 0.1.15 This commit bumps the `compiler-builtins` dependency to 0.1.15 which expects to have the source for `compiler-rt` provided externally if the `c` feature is enabled. This then plumbs through the necessary support in the build system to ensure that if the `llvm-project` directory is checked out and present that we enable the `c` feature of `compiler-builtins` and compile in all the C intrinsics. --- Cargo.lock | 34 +++++++++++++++---------------- src/bootstrap/compile.rs | 29 +++++++++++++++++++++++++- src/build_helper/lib.rs | 6 +++--- src/libprofiler_builtins/build.rs | 4 +--- src/libstd/Cargo.toml | 6 +++--- 5 files changed, 52 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db9f0069ced0c..b651faac90281 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,7 +25,7 @@ dependencies = [ name = "alloc" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -123,7 +123,7 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -462,7 +462,7 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -744,7 +744,7 @@ name = "dlmalloc" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -910,7 +910,7 @@ name = "fortanix-sgx-abi" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -1071,7 +1071,7 @@ name = "hashbrown" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-alloc 1.0.0", "rustc-std-workspace-core 1.0.0", ] @@ -1772,7 +1772,7 @@ dependencies = [ name = "panic_abort" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1782,7 +1782,7 @@ name = "panic_unwind" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "unwind 0.0.0", @@ -1967,7 +1967,7 @@ name = "profiler_builtins" version = "0.0.0" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2492,7 +2492,7 @@ name = "rustc-demangle" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -2620,7 +2620,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2850,7 +2850,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2912,7 +2912,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3029,7 +3029,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3298,7 +3298,7 @@ dependencies = [ "alloc 0.0.0", "backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3889,7 +3889,7 @@ name = "unwind" version = "0.0.0" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4087,7 +4087,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" -"checksum compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "e3f235c329e5cb9fa3d2ca2cc36256ba9a7f23fa76e0f4db6f68c23b73b2ac69" +"checksum compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "e899b947d7e71c3d35c0b6194d64025b84946640510e215090c815b20828964e" "checksum compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "f40ecc9332b68270998995c00f8051ee856121764a0d3230e64c9efd059d27b6" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887" diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index e1cdd226fd6e5..2da5e1c5902c1 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -161,7 +161,33 @@ pub fn std_cargo(builder: &Builder<'_>, cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } + // Determine if we're going to compile in optimized C intrinsics to + // the `compiler-builtins` crate. These intrinsics live in LLVM's + // `compiler-rt` repository, but our `src/llvm-project` submodule isn't + // always checked out, so we need to conditionally look for this. (e.g. if + // an external LLVM is used we skip the LLVM submodule checkout). + // + // Note that this shouldn't affect the correctness of `compiler-builtins`, + // but only its speed. Some intrinsics in C haven't been translated to Rust + // yet but that's pretty rare. Other intrinsics have optimized + // implementations in C which have only had slower versions ported to Rust, + // so we favor the C version where we can, but it's not critical. + // + // If `compiler-rt` is available ensure that the `c` feature of the + // `compiler-builtins` crate is enabled and it's configured to learn where + // `compiler-rt` is located. + let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt"); + let compiler_builtins_c_feature = if compiler_builtins_root.exists() { + cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root); + " compiler-builtins-c".to_string() + } else { + String::new() + }; + if builder.no_std(target) == Some(true) { + let mut features = "compiler-builtins-mem".to_string(); + features.push_str(&compiler_builtins_c_feature); + // for no-std targets we only compile a few no_std crates cargo .args(&["-p", "alloc"]) @@ -170,7 +196,8 @@ pub fn std_cargo(builder: &Builder<'_>, .arg("--features") .arg("compiler-builtins-mem compiler-builtins-c"); } else { - let features = builder.std_features(); + let mut features = builder.std_features(); + features.push_str(&compiler_builtins_c_feature); if compiler.stage != 0 && builder.config.sanitizers { // This variable is used by the sanitizer runtime crates, e.g. diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 60911d917899f..8b00c1d81b08c 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -288,9 +288,9 @@ pub fn sanitizer_lib_boilerplate(sanitizer_name: &str) } else { format!("static={}", link_name) }; - // The source for `compiler-rt` comes from the `compiler-builtins` crate, so - // load our env var set by cargo to find the source code. - let dir = env::var_os("DEP_COMPILER_RT_COMPILER_RT").unwrap(); + // This env var is provided by rustbuild to tell us where `compiler-rt` + // lives. + let dir = env::var_os("RUST_COMPILER_RT_ROOT").unwrap(); let lib = native_lib_boilerplate( dir.as_ref(), sanitizer_name, diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs index 331edb73d6df9..491986480deba 100644 --- a/src/libprofiler_builtins/build.rs +++ b/src/libprofiler_builtins/build.rs @@ -57,9 +57,7 @@ fn main() { cfg.define("COMPILER_RT_HAS_ATOMICS", Some("1")); } - // The source for `compiler-rt` comes from the `compiler-builtins` crate, so - // load our env var set by cargo to find the source code. - let root = env::var_os("DEP_COMPILER_RT_COMPILER_RT").unwrap(); + let root = env::var_os("RUST_COMPILER_RT_ROOT").unwrap(); let root = Path::new(&root); for src in profile_sources { diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 55e8b39974e09..c4c1170e539ae 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -19,7 +19,7 @@ panic_unwind = { path = "../libpanic_unwind", optional = true } panic_abort = { path = "../libpanic_abort" } core = { path = "../libcore" } libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of-std'] } -compiler_builtins = { version = "0.1.14" } +compiler_builtins = { version = "0.1.15" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } hashbrown = { version = "0.3.0", features = ['rustc-dep-of-std'] } @@ -49,12 +49,12 @@ fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] } cc = "1.0" [features] -default = ["compiler_builtins_c", "std_detect_file_io", "std_detect_dlsym_getauxval"] +default = ["std_detect_file_io", "std_detect_dlsym_getauxval"] backtrace = ["backtrace-sys"] panic-unwind = ["panic_unwind"] profiler = ["profiler_builtins"] -compiler_builtins_c = ["alloc/compiler-builtins-c"] +compiler-builtins-c = ["alloc/compiler-builtins-c"] llvm-libunwind = ["unwind/llvm-libunwind"] # Make panics and failed asserts immediately abort without formatting any message From 6c3862594210cc0a5e60fbad32d3aab7a4fb512c Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 21 May 2019 12:38:46 -0700 Subject: [PATCH 19/19] Make -Zemit-artifact-notifications also emit the artifact type This is easier for tooling to handle than trying to reverse-engineer it from the filename extension. --- src/librustc_codegen_ssa/back/link.rs | 2 +- src/librustc_errors/emitter.rs | 2 +- src/librustc_errors/lib.rs | 4 ++-- src/librustc_interface/passes.rs | 3 ++- src/libsyntax/json.rs | 6 ++++-- src/test/ui/emit-artifact-notifications.nll.stderr | 2 +- src/test/ui/emit-artifact-notifications.stderr | 2 +- 7 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index d5a56f6a09e02..c1ec2071789eb 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -96,7 +96,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, } } if sess.opts.debugging_opts.emit_artifact_notifications { - sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename); + sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename, "link"); } } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 59cbd65f05c68..b56162deaf1cc 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -56,7 +56,7 @@ pub trait Emitter { /// Emit a notification that an artifact has been output. /// This is currently only supported for the JSON format, /// other formats can, and will, simply ignore it. - fn emit_artifact_notification(&mut self, _path: &Path) {} + fn emit_artifact_notification(&mut self, _path: &Path, _artifact_type: &str) {} /// Checks if should show explanations about "rustc --explain" fn should_show_explain(&self) -> bool { diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 3aa87fad07174..2dcf7be2aa8b1 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -769,8 +769,8 @@ impl Handler { } } - pub fn emit_artifact_notification(&self, path: &Path) { - self.emitter.borrow_mut().emit_artifact_notification(path); + pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { + self.emitter.borrow_mut().emit_artifact_notification(path, artifact_type); } } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index c5ac8860ccd9b..f17554b1fbdc9 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -1052,7 +1052,8 @@ fn encode_and_write_metadata<'tcx>( tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); } if tcx.sess.opts.debugging_opts.emit_artifact_notifications { - tcx.sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename); + tcx.sess.parse_sess.span_diagnostic + .emit_artifact_notification(&out_filename, "metadata"); } } diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 2dd2ecb749300..767ab74355e66 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -92,8 +92,8 @@ impl Emitter for JsonEmitter { } } - fn emit_artifact_notification(&mut self, path: &Path) { - let data = ArtifactNotification { artifact: path }; + fn emit_artifact_notification(&mut self, path: &Path, artifact_type: &str) { + let data = ArtifactNotification { artifact: path, emit: artifact_type }; let result = if self.pretty { writeln!(&mut self.dst, "{}", as_pretty_json(&data)) } else { @@ -185,6 +185,8 @@ struct DiagnosticCode { struct ArtifactNotification<'a> { /// The path of the artifact. artifact: &'a Path, + /// What kind of artifact we're emitting. + emit: &'a str, } impl Diagnostic { diff --git a/src/test/ui/emit-artifact-notifications.nll.stderr b/src/test/ui/emit-artifact-notifications.nll.stderr index 347d9aeac2307..5547631a4b022 100644 --- a/src/test/ui/emit-artifact-notifications.nll.stderr +++ b/src/test/ui/emit-artifact-notifications.nll.stderr @@ -1 +1 @@ -{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications.nll/libemit_artifact_notifications.rmeta"} +{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications.nll/libemit_artifact_notifications.rmeta","emit":"metadata"} diff --git a/src/test/ui/emit-artifact-notifications.stderr b/src/test/ui/emit-artifact-notifications.stderr index 56c977181ff51..260d41b8f15cc 100644 --- a/src/test/ui/emit-artifact-notifications.stderr +++ b/src/test/ui/emit-artifact-notifications.stderr @@ -1 +1 @@ -{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications/libemit_artifact_notifications.rmeta"} +{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications/libemit_artifact_notifications.rmeta","emit":"metadata"}