diff --git a/Cargo.lock b/Cargo.lock index ef4800a226136..5d5d5523a89a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3474,6 +3474,7 @@ dependencies = [ "rustc_errors", "rustc_hir", "rustc_index", + "rustc_middle", "rustc_query_system", "rustc_session", "rustc_span", @@ -3808,6 +3809,7 @@ name = "rustc_hir" version = "0.0.0" dependencies = [ "odht", + "rustc_arena", "rustc_ast", "rustc_data_structures", "rustc_error_messages", @@ -3901,6 +3903,7 @@ dependencies = [ "rustc_expand", "rustc_hir", "rustc_incremental", + "rustc_index", "rustc_lint", "rustc_metadata", "rustc_middle", @@ -4276,7 +4279,6 @@ dependencies = [ "bitflags", "rustc_arena", "rustc_ast", - "rustc_ast_lowering", "rustc_ast_pretty", "rustc_attr", "rustc_data_structures", diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 7989af24d9986..e344d8a7637c4 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -14,6 +14,7 @@ rustc_hir = { path = "../rustc_hir" } rustc_target = { path = "../rustc_target" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } +rustc_middle = { path = "../rustc_middle" } rustc_query_system = { path = "../rustc_query_system" } rustc_span = { path = "../rustc_span" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index ae3e367596258..49778f1eef147 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -1,4 +1,4 @@ -use crate::{ImplTraitContext, ImplTraitPosition, ParamMode}; +use crate::{ImplTraitContext, ImplTraitPosition, ParamMode, ResolverAstLoweringExt}; use super::LoweringContext; @@ -16,7 +16,7 @@ use rustc_target::asm; use std::collections::hash_map::Entry; use std::fmt::Write; -impl<'a, 'hir> LoweringContext<'a, 'hir> { +impl<'hir> LoweringContext<'hir> { crate fn lower_inline_asm(&mut self, sp: Span, asm: &InlineAsm) -> &'hir hir::InlineAsm<'hir> { // Rustdoc needs to support asm! from foreign architectures: don't try // lowering the register constraints in this case. @@ -238,8 +238,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Wrap the expression in an AnonConst. let parent_def_id = self.current_hir_id_owner; - let node_id = self.resolver.next_node_id(); - self.resolver.create_def( + let node_id = self.next_node_id(); + self.create_def( parent_def_id, node_id, DefPathData::AnonConst, diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 3a7e0a70585f1..bc076f386147e 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -6,7 +6,7 @@ use rustc_span::{sym, DesugaringKind}; use smallvec::SmallVec; -impl<'a, 'hir> LoweringContext<'a, 'hir> { +impl<'hir> LoweringContext<'hir> { pub(super) fn lower_block( &mut self, b: &Block, diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 37ae41fabf987..3c4fc39f249cc 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1,6 +1,6 @@ -use crate::{FnDeclKind, ImplTraitPosition}; - +use super::ResolverAstLoweringExt; use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; +use crate::{FnDeclKind, ImplTraitPosition}; use rustc_ast::attr; use rustc_ast::ptr::P as AstP; @@ -16,7 +16,7 @@ use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; use rustc_span::symbol::{sym, Ident}; use rustc_span::DUMMY_SP; -impl<'hir> LoweringContext<'_, 'hir> { +impl<'hir> LoweringContext<'hir> { fn lower_exprs(&mut self, exprs: &[AstP]) -> &'hir [hir::Expr<'hir>] { self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x))) } @@ -339,10 +339,10 @@ impl<'hir> LoweringContext<'_, 'hir> { for (idx, arg) in args.into_iter().enumerate() { if legacy_args_idx.contains(&idx) { let parent_def_id = self.current_hir_id_owner; - let node_id = self.resolver.next_node_id(); + let node_id = self.next_node_id(); // Add a definition for the in-band const def. - self.resolver.create_def( + self.create_def( parent_def_id, node_id, DefPathData::AnonConst, @@ -702,7 +702,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }; // `::std::task::Poll::Ready(result) => break result` - let loop_node_id = self.resolver.next_node_id(); + let loop_node_id = self.next_node_id(); let loop_hir_id = self.lower_node_id(loop_node_id); let ready_arm = { let x_ident = Ident::with_dummy_span(sym::result); @@ -947,7 +947,7 @@ impl<'hir> LoweringContext<'_, 'hir> { whole_span: Span, ) -> hir::ExprKind<'hir> { // Return early in case of an ordinary assignment. - fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool { + fn is_ordinary(lower_ctx: &mut LoweringContext<'_>, lhs: &Expr) -> bool { match &lhs.kind { ExprKind::Array(..) | ExprKind::Struct(..) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index c506360aa8a13..53e125d248883 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -6,6 +6,7 @@ use rustc_hir::definitions; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::*; use rustc_index::vec::{Idx, IndexVec}; +use rustc_middle::span_bug; use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::{Span, DUMMY_SP}; @@ -75,7 +76,8 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { // owner of that node. if cfg!(debug_assertions) { if hir_id.owner != self.owner { - panic!( + span_bug!( + span, "inconsistent DepNode at `{:?}` for `{:?}`: \ current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})", self.source_map.span_to_diagnostic_string(span), diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 8ae07982f6f58..0978e1e55a2cb 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1,6 +1,6 @@ -use super::{AstOwner, ImplTraitContext, ImplTraitPosition, ResolverAstLowering}; -use super::{LoweringContext, ParamMode}; -use crate::{Arena, FnDeclKind}; +use super::ResolverAstLoweringExt; +use super::{FnDeclKind, LoweringContext, ParamMode}; +use super::{ImplTraitContext, ImplTraitPosition}; use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; @@ -10,10 +10,9 @@ use rustc_data_structures::sorted_map::SortedMap; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_hir::def_id::CRATE_DEF_ID; +use rustc_middle::ty::{DefIdTree, ResolverOutputs, TyCtxt}; use rustc_session::utils::NtToTokenstream; -use rustc_session::Session; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; @@ -23,13 +22,10 @@ use tracing::debug; use std::iter; -pub(super) struct ItemLowerer<'a, 'hir> { - pub(super) sess: &'a Session, - pub(super) resolver: &'a mut dyn ResolverAstLowering, +pub(super) struct ItemLowerer<'hir> { + pub(super) tcx: TyCtxt<'hir>, + pub(super) resolver: &'hir ResolverOutputs, pub(super) nt_to_tokenstream: NtToTokenstream, - pub(super) arena: &'hir Arena<'hir>, - pub(super) ast_index: &'a IndexVec>, - pub(super) owners: &'a mut IndexVec>>, } /// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span @@ -52,28 +48,34 @@ fn add_ty_alias_where_clause( } } -impl<'a, 'hir> ItemLowerer<'a, 'hir> { +impl<'hir> ItemLowerer<'hir> { fn with_lctx( &mut self, owner: NodeId, - f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>, - ) { + f: impl FnOnce(&mut LoweringContext<'hir>) -> hir::OwnerNode<'hir>, + ) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> { + let current_hir_id_owner = self.resolver.node_id_to_def_id[&owner]; let mut lctx = LoweringContext { // Pseudo-globals. - sess: &self.sess, + tcx: self.tcx, + sess: &self.tcx.sess, resolver: self.resolver, nt_to_tokenstream: self.nt_to_tokenstream, - arena: self.arena, + arena: self.tcx.hir_arena, // HirId handling. bodies: Vec::new(), attrs: SortedMap::default(), children: FxHashMap::default(), - current_hir_id_owner: CRATE_DEF_ID, - item_local_id_counter: hir::ItemLocalId::new(0), - node_id_to_local_id: Default::default(), local_id_to_def_id: SortedMap::new(), trait_map: Default::default(), + local_node_id_to_def_id: FxHashMap::default(), + next_node_id: self.resolver.next_node_id, + + // HirId management. + current_hir_id_owner, + node_id_to_local_id: [(owner, hir::ItemLocalId::from_u32(0))].into_iter().collect(), + item_local_id_counter: hir::ItemLocalId::from_u32(1), // 0 is `current_hir_id_owner`. // Lowering state. catch_scope: None, @@ -89,37 +91,16 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { allow_gen_future: Some([sym::gen_future][..].into()), allow_into_future: Some([sym::into_future][..].into()), }; - lctx.with_hir_id_owner(owner, |lctx| f(lctx)); - for (def_id, info) in lctx.children { - self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); - debug_assert!(matches!(self.owners[def_id], hir::MaybeOwner::Phantom)); - self.owners[def_id] = info; - } - } - - pub(super) fn lower_node( - &mut self, - def_id: LocalDefId, - ) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> { - self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); - if let hir::MaybeOwner::Phantom = self.owners[def_id] { - let node = self.ast_index[def_id]; - match node { - AstOwner::NonOwner => {} - AstOwner::Crate(c) => self.lower_crate(c), - AstOwner::Item(item) => self.lower_item(item), - AstOwner::AssocItem(item, ctxt) => self.lower_assoc_item(item, ctxt), - AstOwner::ForeignItem(item) => self.lower_foreign_item(item), - } - } + let item = f(&mut lctx); + debug_assert_eq!(current_hir_id_owner, item.def_id()); - self.owners[def_id] + let info = lctx.make_owner_info(item); + hir::MaybeOwner::Owner(self.tcx.hir_arena.alloc(info)) } - fn lower_crate(&mut self, c: &Crate) { - debug_assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID); - + pub(super) fn lower_crate(&mut self, c: &Crate) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> { + debug_assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID); self.with_lctx(CRATE_NODE_ID, |lctx| { let module = lctx.lower_mod(&c.items, &c.spans); lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs); @@ -127,25 +108,28 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { }) } - fn lower_item(&mut self, item: &Item) { + pub(super) fn lower_item( + &mut self, + item: &Item, + ) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> { self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item))) } - fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) { - let def_id = self.resolver.local_def_id(item.id); + pub(super) fn lower_assoc_item( + &mut self, + item: &AssocItem, + ctxt: AssocCtxt, + ) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> { + let def_id = self.resolver.node_id_to_def_id[&item.id]; - let parent_id = { - let parent = self.resolver.definitions().def_key(def_id).parent; - let local_def_index = parent.unwrap(); - LocalDefId { local_def_index } - }; + let parent_id = self.tcx.local_parent(def_id).unwrap(); - let parent_hir = self.lower_node(parent_id).unwrap(); + let parent_hir = self.tcx.hir().expect_item(parent_id); self.with_lctx(item.id, |lctx| { // Evaluate with the lifetimes in `params` in-scope. // This is used to track which lifetimes have already been defined, // and which need to be replicated when lowering an async fn. - match parent_hir.node().expect_item().kind { + match parent_hir.kind { hir::ItemKind::Impl(hir::Impl { ref of_trait, .. }) => { lctx.is_in_trait_impl = of_trait.is_some(); } @@ -159,12 +143,15 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { }) } - fn lower_foreign_item(&mut self, item: &ForeignItem) { + pub(super) fn lower_foreign_item( + &mut self, + item: &ForeignItem, + ) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> { self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))) } } -impl<'hir> LoweringContext<'_, 'hir> { +impl<'hir> LoweringContext<'hir> { pub(super) fn lower_mod(&mut self, items: &[P], spans: &ModSpans) -> hir::Mod<'hir> { hir::Mod { spans: hir::ModSpans { @@ -176,7 +163,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { - let mut node_ids = smallvec![hir::ItemId { def_id: self.resolver.local_def_id(i.id) }]; + let mut node_ids = smallvec![hir::ItemId { def_id: self.local_def_id(i.id) }]; if let ItemKind::Use(ref use_tree) = &i.kind { self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids); } @@ -192,7 +179,7 @@ impl<'hir> LoweringContext<'_, 'hir> { match tree.kind { UseTreeKind::Nested(ref nested_vec) => { for &(ref nested, id) in nested_vec { - vec.push(hir::ItemId { def_id: self.resolver.local_def_id(id) }); + vec.push(hir::ItemId { def_id: self.local_def_id(id) }); self.lower_item_id_use_tree(nested, id, vec); } } @@ -201,7 +188,7 @@ impl<'hir> LoweringContext<'_, 'hir> { for (_, &id) in iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2]) { - vec.push(hir::ItemId { def_id: self.resolver.local_def_id(id) }); + vec.push(hir::ItemId { def_id: self.local_def_id(id) }); } } } @@ -459,7 +446,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ), ItemKind::MacroDef(MacroDef { ref body, macro_rules }) => { let body = P(self.lower_mac_args(body)); - let macro_kind = self.resolver.decl_macro_kind(self.resolver.local_def_id(id)); + let macro_kind = self.resolver.decl_macro_kind(self.local_def_id(id)); hir::ItemKind::Macro(ast::MacroDef { body, macro_rules }, macro_kind) } ItemKind::MacCall(..) => { @@ -520,7 +507,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Essentially a single `use` which imports two names is desugared into // two imports. for new_node_id in [id1, id2] { - let new_id = self.resolver.local_def_id(new_node_id); + let new_id = self.local_def_id(new_node_id); let Some(res) = resolutions.next() else { // Associate an HirId to both ids even if there is no resolution. let _old = self.children.insert( @@ -533,7 +520,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ident = *ident; let mut path = path.clone(); for seg in &mut path.segments { - seg.id = self.resolver.next_node_id(); + seg.id = self.next_node_id(); } let span = path.span; @@ -542,7 +529,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let path = this.lower_path_extra(res, &path, ParamMode::Explicit); let kind = hir::ItemKind::Use(path, hir::UseKind::Single); if let Some(attrs) = attrs { - this.attrs.insert(hir::ItemLocalId::new(0), attrs); + this.attrs.insert(hir::ItemLocalId::from_u32(0), attrs); } let item = hir::Item { @@ -596,13 +583,13 @@ impl<'hir> LoweringContext<'_, 'hir> { // Add all the nested `PathListItem`s to the HIR. for &(ref use_tree, id) in trees { - let new_hir_id = self.resolver.local_def_id(id); + let new_hir_id = self.local_def_id(id); let mut prefix = prefix.clone(); // Give the segments new node-ids since they are being cloned. for seg in &mut prefix.segments { - seg.id = self.resolver.next_node_id(); + seg.id = self.next_node_id(); } // Each `use` import is an item and thus are owners of the @@ -616,7 +603,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let kind = this.lower_use_tree(use_tree, &prefix, id, vis_span, &mut ident, attrs); if let Some(attrs) = attrs { - this.attrs.insert(hir::ItemLocalId::new(0), attrs); + this.attrs.insert(hir::ItemLocalId::from_u32(0), attrs); } let item = hir::Item { @@ -675,7 +662,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef { hir::ForeignItemRef { - id: hir::ForeignItemId { def_id: self.resolver.local_def_id(i.id) }, + id: hir::ForeignItemId { def_id: self.local_def_id(i.id) }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), } @@ -830,7 +817,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } AssocItemKind::MacCall(..) => unimplemented!(), }; - let id = hir::TraitItemId { def_id: self.resolver.local_def_id(i.id) }; + let id = hir::TraitItemId { def_id: self.local_def_id(i.id) }; let defaultness = hir::Defaultness::Default { has_value: has_default }; hir::TraitItemRef { id, @@ -910,7 +897,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); hir::ImplItemRef { - id: hir::ImplItemId { def_id: self.resolver.local_def_id(i.id) }, + id: hir::ImplItemId { def_id: self.local_def_id(i.id) }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), defaultness, @@ -1313,7 +1300,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics .params .iter() - .any(|p| def_id == self.resolver.local_def_id(p.id).to_def_id()) + .any(|p| def_id == self.local_def_id(p.id).to_def_id()) } // Either the `bounded_ty` is not a plain type parameter, or // it's not found in the generic type parameters list. @@ -1419,7 +1406,7 @@ pub(super) struct GenericsCtor<'hir> { } impl<'hir> GenericsCtor<'hir> { - pub(super) fn into_generics(self, arena: &'hir Arena<'hir>) -> hir::Generics<'hir> { + pub(super) fn into_generics(self, arena: &'hir hir::Arena<'hir>) -> hir::Generics<'hir> { hir::Generics { params: arena.alloc_from_iter(self.params), where_clause: self.where_clause, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index de4f8e04b1689..d0d14a82de3e6 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -46,17 +46,19 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res}; -use rustc_hir::def_id::{DefId, DefPathHash, LocalDefId, CRATE_DEF_ID}; -use rustc_hir::definitions::{DefKey, DefPathData, Definitions}; +use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; +use rustc_hir::definitions::DefPathData; use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; use rustc_index::vec::{Idx, IndexVec}; -use rustc_query_system::ich::StableHashingContext; +use rustc_middle::ty::{AstOwner, DefIdTree, ResolverOutputs, TyCtxt}; use rustc_session::parse::feature_err; use rustc_session::utils::{FlattenNonterminals, NtToTokenstream}; use rustc_session::Session; @@ -82,14 +84,14 @@ mod index; mod item; mod pat; mod path; +mod query; -rustc_hir::arena_types!(rustc_arena::declare_arena); +pub use query::provide; -struct LoweringContext<'a, 'hir: 'a> { - /// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes. - sess: &'a Session, - - resolver: &'a mut dyn ResolverAstLowering, +struct LoweringContext<'hir> { + tcx: TyCtxt<'hir>, + sess: &'hir Session, + resolver: &'hir ResolverOutputs, /// HACK(Centril): there is a cyclic dependency between the parser and lowering /// if we don't have this function pointer. To avoid that dependency so that @@ -97,7 +99,7 @@ struct LoweringContext<'a, 'hir: 'a> { nt_to_tokenstream: NtToTokenstream, /// Used to allocate HIR nodes. - arena: &'hir Arena<'hir>, + arena: &'hir hir::Arena<'hir>, /// Bodies inside the owner being lowered. bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>, @@ -128,56 +130,20 @@ struct LoweringContext<'a, 'hir: 'a> { current_hir_id_owner: LocalDefId, item_local_id_counter: hir::ItemLocalId, local_id_to_def_id: SortedMap, - trait_map: FxHashMap>, + trait_map: FxHashMap, /// NodeIds that are lowered inside the current HIR owner. node_id_to_local_id: FxHashMap, + // The next_node_id is reset for each item. + next_node_id: ast::NodeId, + local_node_id_to_def_id: FxHashMap, + allow_try_trait: Option>, allow_gen_future: Option>, allow_into_future: Option>, } -/// Resolution for a lifetime appearing in a type. -#[derive(Copy, Clone, Debug)] -pub enum LifetimeRes { - /// Successfully linked the lifetime to a generic parameter. - Param { - /// Id of the generic parameter that introduced it. - param: LocalDefId, - /// Id of the introducing place. That can be: - /// - an item's id, for the item's generic parameters; - /// - a TraitRef's ref_id, identifying the `for<...>` binder; - /// - a BareFn type's id; - /// - a Path's id when this path has parenthesized generic args. - /// - /// This information is used for impl-trait lifetime captures, to know when to or not to - /// capture any given lifetime. - binder: NodeId, - }, - /// Created a generic parameter for an anonymous lifetime. - Fresh { - /// Id of the generic parameter that introduced it. - param: LocalDefId, - /// Id of the introducing place. See `Param`. - binder: NodeId, - }, - /// This variant is used for anonymous lifetimes that we did not resolve during - /// late resolution. Shifting the work to the HIR lifetime resolver. - Anonymous { - /// Id of the introducing place. See `Param`. - binder: NodeId, - /// Whether this lifetime was spelled or elided. - elided: bool, - }, - /// Explicit `'static` lifetime. - Static, - /// Resolution failure. - Error, - /// HACK: This is used to recover the NodeId of an elided lifetime. - ElidedAnchor { start: NodeId, end: NodeId }, -} - /// When we lower a lifetime, it is inserted in `captures`, and the resolution is modified so /// to point to the lifetime parameter impl-trait will generate. /// When traversing `for<...>` binders, they are inserted in `binders_to_ignore` so we know *not* @@ -200,54 +166,75 @@ struct LifetimeCaptureContext { binders_to_ignore: FxHashSet, } -pub trait ResolverAstLowering { - fn def_key(&self, id: DefId) -> DefKey; - - fn def_span(&self, id: LocalDefId) -> Span; - - fn item_generics_num_lifetimes(&self, def: DefId) -> usize; - - fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option>; - - /// Obtains resolution for a `NodeId` with a single resolution. +trait ResolverAstLoweringExt { + fn legacy_const_generic_args(&self, expr: &Expr) -> Option>; fn get_partial_res(&self, id: NodeId) -> Option; - - /// Obtains per-namespace resolutions for `use` statement with the given `NodeId`. fn get_import_res(&self, id: NodeId) -> PerNS>>; - - /// Obtains resolution for a label with the given `NodeId`. fn get_label_res(&self, id: NodeId) -> Option; - - /// Obtains resolution for a lifetime with the given `NodeId`. fn get_lifetime_res(&self, id: NodeId) -> Option; + fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, LifetimeRes)]; + fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind; +} - /// Obtain the list of lifetimes parameters to add to an item. - fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>; +impl ResolverAstLoweringExt for ResolverOutputs { + fn legacy_const_generic_args(&self, expr: &Expr) -> Option> { + if let ExprKind::Path(None, path) = &expr.kind { + // Don't perform legacy const generics rewriting if the path already + // has generic arguments. + if path.segments.last().unwrap().args.is_some() { + return None; + } - fn create_stable_hashing_context(&self) -> StableHashingContext<'_>; + let partial_res = self.partial_res_map.get(&expr.id)?; + if partial_res.unresolved_segments() != 0 { + return None; + } - fn definitions(&self) -> &Definitions; + if let Res::Def(DefKind::Fn, def_id) = partial_res.base_res() { + // We only support cross-crate argument rewriting. Uses + // within the same crate should be updated to use the new + // const generics style. + if def_id.is_local() { + return None; + } - fn next_node_id(&mut self) -> NodeId; + if let Some(v) = self.legacy_const_generic_args.get(&def_id) { + return v.clone(); + } + } + } + + None + } - fn take_trait_map(&mut self, node: NodeId) -> Option>; + /// Obtains resolution for a `NodeId` with a single resolution. + fn get_partial_res(&self, id: NodeId) -> Option { + self.partial_res_map.get(&id).copied() + } - fn opt_local_def_id(&self, node: NodeId) -> Option; + /// Obtains per-namespace resolutions for `use` statement with the given `NodeId`. + fn get_import_res(&self, id: NodeId) -> PerNS>> { + self.import_res_map.get(&id).copied().unwrap_or_default() + } - fn local_def_id(&self, node: NodeId) -> LocalDefId; + /// Obtains resolution for a label with the given `NodeId`. + fn get_label_res(&self, id: NodeId) -> Option { + self.label_res_map.get(&id).copied() + } - fn def_path_hash(&self, def_id: DefId) -> DefPathHash; + /// Obtains resolution for a lifetime with the given `NodeId`. + fn get_lifetime_res(&self, id: NodeId) -> Option { + self.lifetimes_res_map.get(&id).copied() + } - fn create_def( - &mut self, - parent: LocalDefId, - node_id: ast::NodeId, - data: DefPathData, - expn_id: ExpnId, - span: Span, - ) -> LocalDefId; + /// Obtain the list of lifetimes parameters to add to an item. + fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, LifetimeRes)] { + self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..]) + } - fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind; + fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind { + self.builtin_macro_kinds.get(&def_id).copied().unwrap_or(MacroKind::Bang) + } } /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, @@ -359,110 +346,125 @@ impl FnDeclKind { } } -#[derive(Copy, Clone)] -enum AstOwner<'a> { - NonOwner, - Crate(&'a ast::Crate), - Item(&'a ast::Item), - AssocItem(&'a ast::AssocItem, visit::AssocCtxt), - ForeignItem(&'a ast::ForeignItem), -} - -fn index_crate<'a>( - resolver: &dyn ResolverAstLowering, - krate: &'a Crate, -) -> IndexVec> { - let mut indexer = Indexer { resolver, index: IndexVec::new() }; - indexer.index.ensure_contains_elem(CRATE_DEF_ID, || AstOwner::NonOwner); - indexer.index[CRATE_DEF_ID] = AstOwner::Crate(krate); - visit::walk_crate(&mut indexer, krate); +pub fn index_crate( + node_id_to_def_id: &FxHashMap, + krate: Lrc, +) -> IndexVec> { + let mut indexer = + Indexer { node_id_to_def_id, krate: OwningRef::new(krate.clone()), index: IndexVec::new() }; + indexer.index.ensure_contains_elem(CRATE_DEF_ID, || Steal::new(AstOwner::NonOwner)); + indexer.index[CRATE_DEF_ID] = Steal::new(AstOwner::Crate(krate.clone())); + visit::walk_crate(&mut indexer, &krate); return indexer.index; - struct Indexer<'s, 'a> { - resolver: &'s dyn ResolverAstLowering, - index: IndexVec>, + struct Indexer<'s> { + node_id_to_def_id: &'s FxHashMap, + krate: OwningRef, Crate>, + index: IndexVec>, + } + + impl Indexer<'_> { + fn visit_item_id_use_tree(&mut self, tree: &UseTree, parent: LocalDefId) { + match tree.kind { + UseTreeKind::Glob => {} + UseTreeKind::Simple(_, id1, id2) => { + for id in &[id1, id2] { + let def_id = self.node_id_to_def_id[id]; + self.index.ensure_contains_elem(def_id, || Steal::new(AstOwner::NonOwner)); + self.index[def_id] = Steal::new(AstOwner::Synthetic(parent)); + } + } + UseTreeKind::Nested(ref nested_vec) => { + for &(ref nested, id) in nested_vec { + let def_id = self.node_id_to_def_id[&id]; + self.index.ensure_contains_elem(def_id, || Steal::new(AstOwner::NonOwner)); + self.index[def_id] = Steal::new(AstOwner::Synthetic(parent)); + + self.visit_item_id_use_tree(nested, def_id); + } + } + } + } } - impl<'a> visit::Visitor<'a> for Indexer<'_, 'a> { + impl<'a> visit::Visitor<'a> for Indexer<'_> { fn visit_attribute(&mut self, _: &'a Attribute) { // We do not want to lower expressions that appear in attributes, // as they are not accessible to the rest of the HIR. } fn visit_item(&mut self, item: &'a ast::Item) { - let def_id = self.resolver.local_def_id(item.id); - self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner); - self.index[def_id] = AstOwner::Item(item); + let def_id = self.node_id_to_def_id[&item.id]; + // SAFETY: the visitor guarantees the item ref comes from krate. + let item_ref = self.krate.clone().map(|_| unsafe { &*(item as *const _) }); + self.index.ensure_contains_elem(def_id, || Steal::new(AstOwner::NonOwner)); + self.index[def_id] = Steal::new(AstOwner::Item(item_ref)); + if let ItemKind::Use(ref use_tree) = item.kind { + self.visit_item_id_use_tree(use_tree, def_id); + } visit::walk_item(self, item) } fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: visit::AssocCtxt) { - let def_id = self.resolver.local_def_id(item.id); - self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner); - self.index[def_id] = AstOwner::AssocItem(item, ctxt); + let def_id = self.node_id_to_def_id[&item.id]; + // SAFETY: the visitor guarantees the item ref comes from krate. + let item_ref = self.krate.clone().map(|_| unsafe { &*(item as *const _) }); + self.index.ensure_contains_elem(def_id, || Steal::new(AstOwner::NonOwner)); + self.index[def_id] = Steal::new(AstOwner::AssocItem(item_ref, ctxt)); visit::walk_assoc_item(self, item, ctxt); } fn visit_foreign_item(&mut self, item: &'a ast::ForeignItem) { - let def_id = self.resolver.local_def_id(item.id); - self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner); - self.index[def_id] = AstOwner::ForeignItem(item); + let def_id = self.node_id_to_def_id[&item.id]; + // SAFETY: the visitor guarantees the item ref comes from krate. + let item_ref = self.krate.clone().map(|_| unsafe { &*(item as *const _) }); + self.index.ensure_contains_elem(def_id, || Steal::new(AstOwner::NonOwner)); + self.index[def_id] = Steal::new(AstOwner::ForeignItem(item_ref)); visit::walk_foreign_item(self, item); } } } -/// Compute the hash for the HIR of the full crate. -/// This hash will then be part of the crate_hash which is stored in the metadata. -fn compute_hir_hash( - resolver: &mut dyn ResolverAstLowering, - owners: &IndexVec>>, -) -> Fingerprint { - let mut hir_body_nodes: Vec<_> = owners - .iter_enumerated() - .filter_map(|(def_id, info)| { - let info = info.as_owner()?; - let def_path_hash = resolver.definitions().def_path_hash(def_id); - Some((def_path_hash, info)) - }) - .collect(); - hir_body_nodes.sort_unstable_by_key(|bn| bn.0); +pub fn lower_to_hir<'hir>( + tcx: TyCtxt<'hir>, + def_id: LocalDefId, + nt_to_tokenstream: NtToTokenstream, +) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> { + let _prof_timer = tcx.sess.prof.verbose_generic_activity("hir_lowering"); - let mut stable_hasher = StableHasher::new(); - let mut hcx = resolver.create_stable_hashing_context(); - hir_body_nodes.hash_stable(&mut hcx, &mut stable_hasher); - stable_hasher.finish() -} + let resolver = tcx.resolutions(()); + let node = tcx.untracked_crate.get(def_id); -pub fn lower_crate<'a, 'hir>( - sess: &'a Session, - krate: &'a Crate, - resolver: &'a mut dyn ResolverAstLowering, - nt_to_tokenstream: NtToTokenstream, - arena: &'hir Arena<'hir>, -) -> &'hir hir::Crate<'hir> { - let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering"); - - let ast_index = index_crate(resolver, krate); - - let mut owners = - IndexVec::from_fn_n(|_| hir::MaybeOwner::Phantom, resolver.definitions().def_index_count()); - - for def_id in ast_index.indices() { - item::ItemLowerer { - sess, - resolver, - nt_to_tokenstream, - arena, - ast_index: &ast_index, - owners: &mut owners, - } - .lower_node(def_id); - } + let mut item_lowerer = item::ItemLowerer { tcx, resolver, nt_to_tokenstream }; - let hir_hash = compute_hir_hash(resolver, &owners); - let krate = hir::Crate { owners, hir_hash }; - arena.alloc(krate) + let node = node.map(Steal::steal); + + // The item existed in the AST. + let parent_id = match node { + Some(AstOwner::Crate(c)) => return item_lowerer.lower_crate(&c), + Some(AstOwner::Item(item)) => return item_lowerer.lower_item(&item), + Some(AstOwner::AssocItem(item, ctxt)) => { + return item_lowerer.lower_assoc_item(&item, ctxt); + } + Some(AstOwner::ForeignItem(item)) => return item_lowerer.lower_foreign_item(&item), + Some(AstOwner::Synthetic(parent_id)) => parent_id, + Some(AstOwner::NonOwner) | None => tcx.local_parent(def_id).unwrap(), + }; + + // The item did not exist in the AST, it was created by its parent. + let mut parent_info = tcx.lower_to_hir(parent_id); + if let hir::MaybeOwner::NonOwner(hir_id) = parent_info { + parent_info = tcx.lower_to_hir(hir_id.owner); + } + + let parent_info = parent_info.unwrap(); + *parent_info.children.get(&def_id).unwrap_or_else(|| { + panic!( + "{:?} does not appear in children of {:?}", + def_id, + parent_info.nodes.node().def_id() + ) + }) } #[derive(Copy, Clone, PartialEq)] @@ -480,13 +482,60 @@ enum ParenthesizedGenericArgs { Err, } -impl<'a, 'hir> LoweringContext<'a, 'hir> { +impl<'hir> LoweringContext<'hir> { + fn create_def( + &mut self, + parent: LocalDefId, + node_id: ast::NodeId, + data: DefPathData, + expn_id: ExpnId, + span: Span, + ) -> LocalDefId { + debug_assert_ne!(node_id, ast::DUMMY_NODE_ID); + assert!( + self.opt_local_def_id(node_id).is_none(), + "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", + node_id, + data, + self.tcx.hir().def_key(self.local_def_id(node_id)), + ); + + let def_id = self.tcx.create_def(parent, data, expn_id, span); + + debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); + self.local_node_id_to_def_id.insert(node_id, def_id); + + def_id + } + + fn next_node_id(&mut self) -> NodeId { + let next = self + .next_node_id + .as_usize() + .checked_add(1) + .expect("input too large; ran out of NodeIds"); + self.next_node_id = NodeId::from_usize(next); + self.next_node_id + } + + fn opt_local_def_id(&self, node: NodeId) -> Option { + if node <= self.resolver.next_node_id { + self.resolver.node_id_to_def_id.get(&node).copied() + } else { + self.local_node_id_to_def_id.get(&node).copied() + } + } + + fn local_def_id(&self, node: NodeId) -> LocalDefId { + self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node)) + } + fn with_hir_id_owner( &mut self, owner: NodeId, f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>, ) { - let def_id = self.resolver.local_def_id(owner); + let def_id = self.local_def_id(owner); let current_attrs = std::mem::take(&mut self.attrs); let current_bodies = std::mem::take(&mut self.bodies); @@ -496,6 +545,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let current_owner = std::mem::replace(&mut self.current_hir_id_owner, def_id); let current_local_counter = std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1)); + let current_children = std::mem::take(&mut self.children); + // Do not reset `next_node_id` and `node_id_to_def_id` as we want to refer to the + // subdefinitions' nodes. // Always allocate the first `HirId` for the owner itself. let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::new(0)); @@ -512,6 +564,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.trait_map = current_trait_map; self.current_hir_id_owner = current_owner; self.item_local_id_counter = current_local_counter; + self.children = current_children; + self.children.extend(&info.children); let _old = self.children.insert(def_id, hir::MaybeOwner::Owner(info)); debug_assert!(_old.is_none()) @@ -522,6 +576,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut bodies = std::mem::take(&mut self.bodies); let local_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id); let trait_map = std::mem::take(&mut self.trait_map); + let children = std::mem::take(&mut self.children); #[cfg(debug_assertions)] for (id, attrs) in attrs.iter() { @@ -535,7 +590,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let bodies = SortedMap::from_presorted_elements(bodies); let (hash_including_bodies, hash_without_bodies) = self.hash_owner(node, &bodies); let (nodes, parenting) = - index::index_hir(self.sess, self.resolver.definitions(), node, &bodies); + index::index_hir(self.tcx.sess, &*self.tcx.definitions_untracked(), node, &bodies); let nodes = hir::OwnerNodes { hash_including_bodies, hash_without_bodies, @@ -544,14 +599,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { local_id_to_def_id, }; let attrs = { - let mut hcx = self.resolver.create_stable_hashing_context(); - let mut stable_hasher = StableHasher::new(); - attrs.hash_stable(&mut hcx, &mut stable_hasher); - let hash = stable_hasher.finish(); + let hash = self.tcx.with_stable_hashing_context(|mut hcx| { + let mut stable_hasher = StableHasher::new(); + attrs.hash_stable(&mut hcx, &mut stable_hasher); + stable_hasher.finish() + }); hir::AttributeMap { map: attrs, hash } }; - self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map }) + self.tcx.hir_arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map, children }) } /// Hash the HIR node twice, one deep and one shallow hash. This allows to differentiate @@ -561,18 +617,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node: hir::OwnerNode<'hir>, bodies: &SortedMap>, ) -> (Fingerprint, Fingerprint) { - let mut hcx = self.resolver.create_stable_hashing_context(); - let mut stable_hasher = StableHasher::new(); - hcx.with_hir_bodies(true, node.def_id(), bodies, |hcx| { - node.hash_stable(hcx, &mut stable_hasher) - }); - let hash_including_bodies = stable_hasher.finish(); - let mut stable_hasher = StableHasher::new(); - hcx.with_hir_bodies(false, node.def_id(), bodies, |hcx| { - node.hash_stable(hcx, &mut stable_hasher) - }); - let hash_without_bodies = stable_hasher.finish(); - (hash_including_bodies, hash_without_bodies) + self.tcx.with_stable_hashing_context(|mut hcx| { + let mut stable_hasher = StableHasher::new(); + hcx.with_hir_bodies(true, node.def_id(), bodies, |hcx| { + node.hash_stable(hcx, &mut stable_hasher) + }); + let hash_including_bodies = stable_hasher.finish(); + let mut stable_hasher = StableHasher::new(); + hcx.with_hir_bodies(false, node.def_id(), bodies, |hcx| { + node.hash_stable(hcx, &mut stable_hasher) + }); + let hash_without_bodies = stable_hasher.finish(); + (hash_including_bodies, hash_without_bodies) + }) } /// This method allocates a new `HirId` for the given `NodeId` and stores it in @@ -598,14 +655,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.item_local_id_counter.increment_by(1); assert_ne!(local_id, hir::ItemLocalId::new(0)); - if let Some(def_id) = self.resolver.opt_local_def_id(ast_node_id) { + if let Some(def_id) = self.opt_local_def_id(ast_node_id) { // Do not override a `MaybeOwner::Owner` that may already here. self.children.entry(def_id).or_insert(hir::MaybeOwner::NonOwner(hir_id)); self.local_id_to_def_id.insert(local_id, def_id); } - if let Some(traits) = self.resolver.take_trait_map(ast_node_id) { - self.trait_map.insert(hir_id.local_id, traits.into_boxed_slice()); + if let Some(traits) = self.resolver.trait_map.get(&ast_node_id) { + self.trait_map.insert(hir_id.local_id, &traits[..]); } hir_id @@ -613,9 +670,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } + /// Generate a new `HirId` without a backing `NodeId`. fn next_id(&mut self) -> hir::HirId { - let node_id = self.resolver.next_node_id(); - self.lower_node_id(node_id) + let owner = self.current_hir_id_owner; + let local_id = self.item_local_id_counter; + assert_ne!(local_id, hir::ItemLocalId::new(0)); + self.item_local_id_counter.increment_by(1); + hir::HirId { owner, local_id } } fn lower_res(&mut self, res: Res) -> Res { @@ -657,12 +718,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, allow_internal_unstable: Option>, ) -> Span { - span.mark_with_reason( - allow_internal_unstable, - reason, - self.sess.edition(), - self.resolver.create_stable_hashing_context(), - ) + self.tcx.with_stable_hashing_context(|hcx| { + span.mark_with_reason(allow_internal_unstable, reason, self.sess.edition(), hcx) + }) } /// Intercept all spans entering HIR. @@ -727,11 +785,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); let res = f(self, &mut impl_trait_defs); - let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id); + let extra_lifetimes = self.resolver.extra_lifetime_params(parent_node_id); lowered_generics.params.extend( extra_lifetimes .into_iter() - .filter_map(|(ident, node_id, res)| { + .filter_map(|&(ident, node_id, res)| { self.lifetime_res_to_generic_param(ident, node_id, res) }) .chain(impl_trait_defs), @@ -1028,8 +1086,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by // constructing the HIR for `impl bounds...` and then lowering that. - let impl_trait_node_id = self.resolver.next_node_id(); - self.resolver.create_def( + let impl_trait_node_id = self.next_node_id(); + self.create_def( parent_def_id, impl_trait_node_id, DefPathData::ImplTrait, @@ -1038,7 +1096,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); self.with_dyn_type_scope(false, |this| { - let node_id = this.resolver.next_node_id(); + let node_id = this.next_node_id(); let ty = this.lower_ty( &Ty { id: node_id, @@ -1101,10 +1159,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Construct an AnonConst where the expr is the "ty"'s path. let parent_def_id = self.current_hir_id_owner; - let node_id = self.resolver.next_node_id(); + let node_id = self.next_node_id(); // Add a definition for the in-band const def. - self.resolver.create_def( + self.create_def( parent_def_id, node_id, DefPathData::AnonConst, @@ -1276,7 +1334,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ImplTraitContext::Universal(in_band_ty_params, parent_def_id) => { // Add a definition for the in-band `Param`. - let def_id = self.resolver.local_def_id(def_node_id); + let def_id = self.local_def_id(def_node_id); let hir_bounds = self.lower_param_bounds( bounds, @@ -1343,7 +1401,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // frequently opened issues show. let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); - let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id); + let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); let mut collected_lifetimes = FxHashMap::default(); self.with_hir_id_owner(opaque_ty_node_id, |lctx| { @@ -1361,7 +1419,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let lifetime_defs = lctx.arena.alloc_from_iter(collected_lifetimes.iter().map( |(_, &(span, p_id, p_name, _))| { let hir_id = lctx.lower_node_id(p_id); - debug_assert_ne!(lctx.resolver.opt_local_def_id(p_id), None); + debug_assert_ne!(lctx.opt_local_def_id(p_id), None); let kind = if p_name.ident().name == kw::UnderscoreLifetime { hir::LifetimeParamKind::Elided @@ -1398,7 +1456,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let lifetimes = self.arena.alloc_from_iter(collected_lifetimes.into_iter().map( |(_, (span, _, p_name, res))| { - let id = self.resolver.next_node_id(); + let id = self.next_node_id(); let ident = Ident::new(p_name.ident().name, span); let l = self.new_named_lifetime_with_res(id, span, ident, res); hir::GenericArg::Lifetime(l) @@ -1518,7 +1576,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnRetTy::Ty(ref ty) => { let context = match in_band_ty_params { Some((node_id, _)) if kind.impl_trait_return_allowed() => { - let fn_def_id = self.resolver.local_def_id(node_id); + let fn_def_id = self.local_def_id(node_id); ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), } @@ -1592,8 +1650,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); - let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id); - let fn_def_id = self.resolver.local_def_id(fn_node_id); + let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); + let fn_def_id = self.local_def_id(fn_node_id); // When we create the opaque type for this async fn, it is going to have // to capture all the lifetimes involved in the signature (including in the @@ -1639,15 +1697,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut captures = FxHashMap::default(); - let extra_lifetime_params = self.resolver.take_extra_lifetime_params(opaque_ty_node_id); + let extra_lifetime_params = self.resolver.extra_lifetime_params(opaque_ty_node_id); debug!(?extra_lifetime_params); - for (ident, outer_node_id, outer_res) in extra_lifetime_params { + for &(ident, outer_node_id, outer_res) in extra_lifetime_params { let Ident { name, span } = ident; - let outer_def_id = self.resolver.local_def_id(outer_node_id); - let inner_node_id = self.resolver.next_node_id(); + let outer_def_id = self.local_def_id(outer_node_id); + let inner_node_id = self.next_node_id(); // Add a definition for the in scope lifetime def. - self.resolver.create_def( + self.create_def( opaque_ty_def_id, inner_node_id, DefPathData::LifetimeNs(name), @@ -1695,7 +1753,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let generic_params = this.arena.alloc_from_iter(captures.iter().map(|(_, &(span, p_id, p_name, _))| { let hir_id = this.lower_node_id(p_id); - debug_assert_ne!(this.resolver.opt_local_def_id(p_id), None); + debug_assert_ne!(this.opt_local_def_id(p_id), None); let kind = if p_name.ident().name == kw::UnderscoreLifetime { hir::LifetimeParamKind::Elided @@ -1745,7 +1803,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // generate `'_`. let generic_args = self.arena.alloc_from_iter(captures.into_iter().map(|(_, (span, _, p_name, res))| { - let id = self.resolver.next_node_id(); + let id = self.next_node_id(); let ident = Ident::new(p_name.ident().name, span); let l = self.new_named_lifetime_with_res(id, span, ident, res); hir::GenericArg::Lifetime(l) @@ -1838,79 +1896,81 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Param { param, binder } => { debug_assert_ne!(ident.name, kw::UnderscoreLifetime); let p_name = ParamName::Plain(ident); - if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) = - &mut self.captured_lifetimes - && !binders_to_ignore.contains(&binder) - { - match captures.entry(param) { - Entry::Occupied(_) => {} - Entry::Vacant(v) => { - let p_id = self.resolver.next_node_id(); - self.resolver.create_def( - *parent_def_id, - p_id, - DefPathData::LifetimeNs(p_name.ident().name), - ExpnId::root(), - span.with_parent(None), - ); - - v.insert((span, p_id, p_name, res)); + if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { + if !captured_lifetimes.binders_to_ignore.contains(&binder) { + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(_) => {} + Entry::Vacant(v) => { + let p_id = self.next_node_id(); + self.create_def( + captured_lifetimes.parent_def_id, + p_id, + DefPathData::LifetimeNs(p_name.ident().name), + ExpnId::root(), + span.with_parent(None), + ); + + v.insert((span, p_id, p_name, res)); + } } } + + self.captured_lifetimes = Some(captured_lifetimes); } hir::LifetimeName::Param(p_name) } LifetimeRes::Fresh { mut param, binder } => { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); - if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) = - &mut self.captured_lifetimes - && !binders_to_ignore.contains(&binder) - { - match captures.entry(param) { - Entry::Occupied(o) => param = self.resolver.local_def_id(o.get().1), - Entry::Vacant(v) => { - let p_id = self.resolver.next_node_id(); - let p_def_id = self.resolver.create_def( - *parent_def_id, - p_id, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), - ExpnId::root(), - span.with_parent(None), - ); - - let p_name = ParamName::Fresh(param); - v.insert((span, p_id, p_name, res)); - param = p_def_id; + if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { + if !captured_lifetimes.binders_to_ignore.contains(&binder) { + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(o) => param = self.local_def_id(o.get().1), + Entry::Vacant(v) => { + let p_id = self.next_node_id(); + let p_def_id = self.create_def( + captured_lifetimes.parent_def_id, + p_id, + DefPathData::LifetimeNs(kw::UnderscoreLifetime), + ExpnId::root(), + span.with_parent(None), + ); + + let p_name = ParamName::Fresh(param); + v.insert((span, p_id, p_name, res)); + param = p_def_id; + } } } + + self.captured_lifetimes = Some(captured_lifetimes); } let p_name = ParamName::Fresh(param); hir::LifetimeName::Param(p_name) } LifetimeRes::Anonymous { binder, elided } => { - let l_name = if elided { + let mut l_name = if elided { hir::LifetimeName::Implicit } else { hir::LifetimeName::Underscore }; - if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) = - &mut self.captured_lifetimes - && !binders_to_ignore.contains(&binder) - { - let p_id = self.resolver.next_node_id(); - let p_def_id = self.resolver.create_def( - *parent_def_id, - p_id, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), - ExpnId::root(), - span.with_parent(None), - ); - let p_name = ParamName::Fresh(p_def_id); - captures.insert(p_def_id, (span, p_id, p_name, res)); - hir::LifetimeName::Param(p_name) - } else { - l_name + if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { + if !captured_lifetimes.binders_to_ignore.contains(&binder) { + let p_id = self.next_node_id(); + let p_def_id = self.create_def( + captured_lifetimes.parent_def_id, + p_id, + DefPathData::LifetimeNs(kw::UnderscoreLifetime), + ExpnId::root(), + span.with_parent(None), + ); + let p_name = ParamName::Fresh(p_def_id); + captured_lifetimes.captures.insert(p_def_id, (span, p_id, p_name, res)); + l_name = hir::LifetimeName::Param(p_name) + } + + self.captured_lifetimes = Some(captured_lifetimes); } + l_name } LifetimeRes::Static => hir::LifetimeName::Static, LifetimeRes::Error => hir::LifetimeName::Error, @@ -1924,7 +1984,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &'s mut self, params: &'s [GenericParam], mut itctx: ImplTraitContext<'s, 'hir>, - ) -> impl Iterator> + Captures<'a> + Captures<'s> { + ) -> impl Iterator> + Captures<'s> { params.iter().map(move |param| self.lower_generic_param(param, itctx.reborrow())) } @@ -2038,7 +2098,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &'s mut self, bounds: &'s [GenericBound], mut itctx: ImplTraitContext<'s, 'hir>, - ) -> impl Iterator> + Captures<'s> + Captures<'a> { + ) -> impl Iterator> + Captures<'s> { bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx.reborrow())) } @@ -2307,7 +2367,7 @@ impl<'hir> GenericArgsCtor<'hir> { self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized } - fn into_generic_args(self, this: &LoweringContext<'_, 'hir>) -> &'hir hir::GenericArgs<'hir> { + fn into_generic_args(self, this: &LoweringContext<'hir>) -> &'hir hir::GenericArgs<'hir> { let ga = hir::GenericArgs { args: this.arena.alloc_from_iter(self.args), bindings: self.bindings, diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 2c331767b8958..a88855cbbbe8a 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -1,6 +1,6 @@ -use crate::ImplTraitPosition; - +use super::ResolverAstLoweringExt; use super::{ImplTraitContext, LoweringContext, ParamMode}; +use crate::ImplTraitPosition; use rustc_ast::ptr::P; use rustc_ast::*; @@ -11,7 +11,7 @@ use rustc_hir::def::Res; use rustc_span::symbol::Ident; use rustc_span::{source_map::Spanned, Span}; -impl<'a, 'hir> LoweringContext<'a, 'hir> { +impl<'hir> LoweringContext<'hir> { crate fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> { self.arena.alloc(self.lower_pat_mut(pattern)) } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 3c9399c1fdf80..82d2458c477c5 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -1,5 +1,6 @@ use crate::ImplTraitPosition; +use super::ResolverAstLoweringExt; use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs}; use super::{ImplTraitContext, LoweringContext, ParamMode}; @@ -14,7 +15,7 @@ use rustc_span::{BytePos, Span, DUMMY_SP}; use smallvec::smallvec; use tracing::debug; -impl<'a, 'hir> LoweringContext<'a, 'hir> { +impl<'hir> LoweringContext<'hir> { crate fn lower_qpath( &mut self, id: NodeId, diff --git a/compiler/rustc_ast_lowering/src/query.rs b/compiler/rustc_ast_lowering/src/query.rs new file mode 100644 index 0000000000000..c9c80623e8448 --- /dev/null +++ b/compiler/rustc_ast_lowering/src/query.rs @@ -0,0 +1,265 @@ +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::svh::Svh; +use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::{Crate, ForeignItem, ImplItem, Item, ItemKind, Mod, TraitItem}; +use rustc_hir::{ForeignItemId, HirId, ImplItemId, ItemId, ModuleItems, TraitItemId}; +use rustc_middle::hir::nested_filter; +use rustc_middle::ty::query::Providers; +use rustc_middle::ty::TyCtxt; +use rustc_span::{Span, DUMMY_SP}; + +pub fn provide(providers: &mut Providers) { + *providers = + Providers { hir_crate, crate_hash, hir_module_items, hir_crate_items, ..*providers }; +} + +fn hir_crate<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> Crate<'tcx> { + let mut collector = CrateCollector { tcx, owners: vec![CRATE_DEF_ID] }; + tcx.hir().walk_toplevel_module(&mut collector); + let owners = tcx.arena.alloc_from_iter(collector.owners); + + // Discard hygiene data, which isn't required after lowering to HIR. + if !tcx.sess.opts.debugging_opts.keep_hygiene_data { + rustc_span::hygiene::clear_syntax_context_map(); + } + + return Crate { owners }; + + struct CrateCollector<'tcx> { + tcx: TyCtxt<'tcx>, + owners: Vec, + } + + impl<'hir> Visitor<'hir> for CrateCollector<'hir> { + type NestedFilter = nested_filter::All; + + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() + } + + fn visit_item(&mut self, item: &'hir Item<'hir>) { + self.owners.push(item.def_id); + intravisit::walk_item(self, item) + } + + fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { + self.owners.push(item.def_id); + intravisit::walk_trait_item(self, item) + } + + fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { + self.owners.push(item.def_id); + intravisit::walk_impl_item(self, item) + } + + fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { + self.owners.push(item.def_id); + intravisit::walk_foreign_item(self, item) + } + } +} + +fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { + debug_assert_eq!(crate_num, LOCAL_CRATE); + let krate = tcx.hir_crate(()); + let definitions = tcx.definitions_untracked(); + + let mut hir_body_nodes: Vec<_> = krate + .owners + .iter() + .map(|&def_id| { + let def_path_hash = tcx.hir().def_path_hash(def_id); + let info = tcx.lower_to_hir(def_id).unwrap(); + let span = if tcx.sess.opts.debugging_opts.incremental_relative_spans { + definitions.def_span(def_id) + } else { + DUMMY_SP + }; + debug_assert_eq!(span.parent(), None); + (def_path_hash, info, span) + }) + .collect(); + hir_body_nodes.sort_unstable_by_key(|bn| bn.0); + + let upstream_crates = upstream_crates(tcx); + + // We hash the final, remapped names of all local source files so we + // don't have to include the path prefix remapping commandline args. + // If we included the full mapping in the SVH, we could only have + // reproducible builds by compiling from the same directory. So we just + // hash the result of the mapping instead of the mapping itself. + let mut source_file_names: Vec<_> = tcx + .sess + .source_map() + .files() + .iter() + .filter(|source_file| source_file.cnum == LOCAL_CRATE) + .map(|source_file| source_file.name_hash) + .collect(); + + source_file_names.sort_unstable(); + + let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| { + let mut stable_hasher = StableHasher::new(); + hir_body_nodes.hash_stable(&mut hcx, &mut stable_hasher); + upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); + source_file_names.hash_stable(&mut hcx, &mut stable_hasher); + tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); + tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher); + // Hash visibility information since it does not appear in HIR. + let resolutions = tcx.resolutions(()); + resolutions.visibilities.hash_stable(&mut hcx, &mut stable_hasher); + resolutions.has_pub_restricted.hash_stable(&mut hcx, &mut stable_hasher); + stable_hasher.finish() + }); + + Svh::new(crate_hash.to_smaller_hash()) +} + +fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { + let mut upstream_crates: Vec<_> = tcx + .crates(()) + .iter() + .map(|&cnum| { + let stable_crate_id = tcx.stable_crate_id(cnum); + let hash = tcx.crate_hash(cnum); + (stable_crate_id, hash) + }) + .collect(); + upstream_crates.sort_unstable_by_key(|&(stable_crate_id, _)| stable_crate_id); + upstream_crates +} + +fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems { + let mut collector = ModuleCollector { + tcx, + submodules: Vec::default(), + items: Vec::default(), + trait_items: Vec::default(), + impl_items: Vec::default(), + foreign_items: Vec::default(), + }; + + let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id); + collector.visit_mod(hir_mod, span, hir_id); + + let ModuleCollector { submodules, items, trait_items, impl_items, foreign_items, .. } = + collector; + return ModuleItems { + submodules: submodules.into_boxed_slice(), + items: items.into_boxed_slice(), + trait_items: trait_items.into_boxed_slice(), + impl_items: impl_items.into_boxed_slice(), + foreign_items: foreign_items.into_boxed_slice(), + }; + + struct ModuleCollector<'tcx> { + tcx: TyCtxt<'tcx>, + submodules: Vec, + items: Vec, + trait_items: Vec, + impl_items: Vec, + foreign_items: Vec, + } + + impl<'hir> Visitor<'hir> for ModuleCollector<'hir> { + type NestedFilter = nested_filter::All; + + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() + } + + fn visit_item(&mut self, item: &'hir Item<'hir>) { + self.items.push(item.item_id()); + if let ItemKind::Mod(..) = item.kind { + // If this declares another module, do not recurse inside it. + self.submodules.push(item.def_id); + } else { + intravisit::walk_item(self, item) + } + } + + fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { + self.trait_items.push(item.trait_item_id()); + intravisit::walk_trait_item(self, item) + } + + fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { + self.impl_items.push(item.impl_item_id()); + intravisit::walk_impl_item(self, item) + } + + fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { + self.foreign_items.push(item.foreign_item_id()); + intravisit::walk_foreign_item(self, item) + } + } +} + +fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { + let mut collector = CrateCollector { + tcx, + submodules: Vec::default(), + items: Vec::default(), + trait_items: Vec::default(), + impl_items: Vec::default(), + foreign_items: Vec::default(), + }; + + tcx.hir().walk_toplevel_module(&mut collector); + + let CrateCollector { submodules, items, trait_items, impl_items, foreign_items, .. } = + collector; + + return ModuleItems { + submodules: submodules.into_boxed_slice(), + items: items.into_boxed_slice(), + trait_items: trait_items.into_boxed_slice(), + impl_items: impl_items.into_boxed_slice(), + foreign_items: foreign_items.into_boxed_slice(), + }; + + struct CrateCollector<'tcx> { + tcx: TyCtxt<'tcx>, + submodules: Vec, + items: Vec, + trait_items: Vec, + impl_items: Vec, + foreign_items: Vec, + } + + impl<'hir> Visitor<'hir> for CrateCollector<'hir> { + type NestedFilter = nested_filter::All; + + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() + } + + fn visit_item(&mut self, item: &'hir Item<'hir>) { + self.items.push(item.item_id()); + intravisit::walk_item(self, item) + } + + fn visit_mod(&mut self, m: &'hir Mod<'hir>, _s: Span, n: HirId) { + self.submodules.push(n.owner); + intravisit::walk_mod(self, m, n); + } + + fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { + self.foreign_items.push(item.foreign_item_id()); + intravisit::walk_foreign_item(self, item) + } + + fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { + self.trait_items.push(item.trait_item_id()); + intravisit::walk_trait_item(self, item) + } + + fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { + self.impl_items.push(item.impl_item_id()); + intravisit::walk_impl_item(self, item) + } + } +} diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index 87fbb737ea8a9..8fc8118849bae 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -93,8 +93,9 @@ impl<'tcx> UniqueTypeId<'tcx> { /// Right now this takes the form of a hex-encoded opaque hash value. pub fn generate_unique_id_string(self, tcx: TyCtxt<'tcx>) -> String { let mut hasher = StableHasher::new(); - let mut hcx = tcx.create_stable_hashing_context(); - hcx.while_hashing_spans(false, |hcx| self.hash_stable(hcx, &mut hasher)); + tcx.with_stable_hashing_context(|mut hcx| { + hcx.while_hashing_spans(false, |hcx| self.hash_stable(hcx, &mut hasher)) + }); hasher.finish::().to_hex() } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index ae43464791d23..4e277e4a7753f 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -701,12 +701,14 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S // If we cannot evaluate the constant to a known type, we fall back // to emitting a stable hash value of the constant. This isn't very pretty // but we get a deterministic, virtually unique value for the constant. - let hcx = &mut tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - hcx.while_hashing_spans(false, |hcx| ct.val().hash_stable(hcx, &mut hasher)); + // // Let's only emit 64 bits of the hash value. That should be plenty for // avoiding collisions and will make the emitted type names shorter. - let hash: u64 = hasher.finish(); + let hash: u64 = tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + hcx.while_hashing_spans(false, |hcx| ct.val().hash_stable(hcx, &mut hasher)); + hasher.finish() + }); if cpp_like_debuginfo(tcx) { write!(output, "CONST${:x}", hash) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 30a3ddc600303..ecae87712a92b 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -11,6 +11,7 @@ #![feature(associated_type_bounds)] #![feature(auto_traits)] #![feature(bool_to_option)] +#![feature(cell_leak)] #![feature(control_flow_enum)] #![feature(core_intrinsics)] #![feature(extend_one)] diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index f99ca53ab25df..512696fedbe39 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -536,6 +536,33 @@ impl RwLock { pub fn borrow_mut(&self) -> WriteGuard<'_, T> { self.write() } + + #[cfg(not(parallel_compiler))] + #[inline(always)] + pub fn clone_guard<'a>(rg: &ReadGuard<'a, T>) -> ReadGuard<'a, T> { + ReadGuard::clone(rg) + } + + #[cfg(parallel_compiler)] + #[inline(always)] + pub fn clone_guard<'a>(rg: &ReadGuard<'a, T>) -> ReadGuard<'a, T> { + ReadGuard::rwlock(&rg).read() + } + + #[cfg(not(parallel_compiler))] + #[inline(always)] + pub fn leak(&self) -> &T { + ReadGuard::leak(self.read()) + } + + #[cfg(parallel_compiler)] + #[inline(always)] + pub fn leak(&self) -> &T { + let guard = self.read(); + let ret = unsafe { &*(&*guard as *const T) }; + std::mem::forget(guard); + ret + } } // FIXME: Probably a bad idea diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index 12bac956adb55..e99eb2217cefb 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -461,7 +461,12 @@ pub fn print_after_hir_lowering<'tcx>( HirTree => { call_with_pp_support_hir(&PpHirMode::Normal, tcx, move |_annotation, hir_map| { debug!("pretty printing HIR tree"); - format!("{:#?}", hir_map.krate()) + hir_map + .krate() + .owners + .iter() + .map(|&owner| format!("{:#?} => {:#?}\n", owner, tcx.lower_to_hir(owner))) + .collect() }) } diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index 34d366f401332..cab4fb1f1c144 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" doctest = false [dependencies] +rustc_arena = { path = "../rustc_arena" } rustc_target = { path = "../rustc_target" } rustc_feature = { path = "../rustc_feature" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index 27ec461906419..396f12bb42618 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -9,7 +9,7 @@ macro_rules! arena_types { // HIR types [] hir_krate: rustc_hir::Crate<'tcx>, [] arm: rustc_hir::Arm<'tcx>, - [] asm_operand: (rustc_hir::InlineAsmOperand<'tcx>, Span), + [] asm_operand: (rustc_hir::InlineAsmOperand<'tcx>, rustc_span::Span), [] asm_template: rustc_ast::InlineAsmTemplatePiece, [] attribute: rustc_ast::Attribute, [] block: rustc_hir::Block<'tcx>, diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 324e110005717..58fba36779772 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -1,9 +1,9 @@ -use crate::def_id::DefId; use crate::hir; use rustc_ast as ast; use rustc_ast::NodeId; use rustc_macros::HashStable_Generic; +use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::hygiene::MacroKind; use rustc_span::Symbol; @@ -664,3 +664,43 @@ impl Res { matches!(self, Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(..)) } } + +/// Resolution for a lifetime appearing in a type. +#[derive(Copy, Clone, Debug)] +pub enum LifetimeRes { + /// Successfully linked the lifetime to a generic parameter. + Param { + /// Id of the generic parameter that introduced it. + param: LocalDefId, + /// Id of the introducing place. That can be: + /// - an item's id, for the item's generic parameters; + /// - a TraitRef's ref_id, identifying the `for<...>` binder; + /// - a BareFn type's id; + /// - a Path's id when this path has parenthesized generic args. + /// + /// This information is used for impl-trait lifetime captures, to know when to or not to + /// capture any given lifetime. + binder: NodeId, + }, + /// Created a generic parameter for an anonymous lifetime. + Fresh { + /// Id of the generic parameter that introduced it. + param: LocalDefId, + /// Id of the introducing place. See `Param`. + binder: NodeId, + }, + /// This variant is used for anonymous lifetimes that we did not resolve during + /// late resolution. Shifting the work to the HIR lifetime resolver. + Anonymous { + /// Id of the introducing place. See `Param`. + binder: NodeId, + /// Whether this lifetime was spelled or elided. + elided: bool, + }, + /// Explicit `'static` lifetime. + Static, + /// Resolution failure. + Error, + /// HACK: This is used to recover the NodeId of an elided lifetime. + ElidedAnchor { start: NodeId, end: NodeId }, +} diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 7d9203b70abe8..ac69e77c3954b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -755,7 +755,9 @@ pub struct OwnerInfo<'hir> { pub attrs: AttributeMap<'hir>, /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. - pub trait_map: FxHashMap>, + pub trait_map: FxHashMap, + /// Owners generated as side-effect by lowering. + pub children: FxHashMap>>, } impl<'tcx> OwnerInfo<'tcx> { @@ -769,15 +771,13 @@ impl<'tcx> OwnerInfo<'tcx> { pub enum MaybeOwner { Owner(T), NonOwner(HirId), - /// Used as a placeholder for unused LocalDefId. - Phantom, } impl MaybeOwner { pub fn as_owner(self) -> Option { match self { MaybeOwner::Owner(i) => Some(i), - MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => None, + MaybeOwner::NonOwner(_) => None, } } @@ -785,28 +785,56 @@ impl MaybeOwner { match self { MaybeOwner::Owner(i) => MaybeOwner::Owner(f(i)), MaybeOwner::NonOwner(hir_id) => MaybeOwner::NonOwner(hir_id), - MaybeOwner::Phantom => MaybeOwner::Phantom, } } pub fn unwrap(self) -> T { match self { MaybeOwner::Owner(i) => i, - MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => panic!("Not a HIR owner"), + MaybeOwner::NonOwner(_) => panic!("Not a HIR owner"), } } } +/// Gather the LocalDefId for each item-like within a module, including items contained within +/// bodies. The Ids are in visitor order. This is used to partition a pass between modules. +#[derive(Debug, HashStable_Generic)] +pub struct ModuleItems { + pub submodules: Box<[LocalDefId]>, + pub items: Box<[ItemId]>, + pub trait_items: Box<[TraitItemId]>, + pub impl_items: Box<[ImplItemId]>, + pub foreign_items: Box<[ForeignItemId]>, +} + +impl ModuleItems { + pub fn items(&self) -> impl Iterator + '_ { + self.items.iter().copied() + } + + pub fn trait_items(&self) -> impl Iterator + '_ { + self.trait_items.iter().copied() + } + + pub fn impl_items(&self) -> impl Iterator + '_ { + self.impl_items.iter().copied() + } + + pub fn foreign_items(&self) -> impl Iterator + '_ { + self.foreign_items.iter().copied() + } +} + /// The top-level data structure that stores the entire contents of /// the crate currently being compiled. /// /// For more details, see the [rustc dev guide]. /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html -#[derive(Debug)] +#[derive(Debug, HashStable_Generic)] pub struct Crate<'hir> { - pub owners: IndexVec>>, - pub hir_hash: Fingerprint, + /// List of all the definitions in visitor order. + pub owners: &'hir [LocalDefId], } /// A block of statements `{ .. }`, which may have a label (in this case the diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index d56230e1dc57d..1b6659c750d04 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -18,6 +18,8 @@ extern crate rustc_macros; #[macro_use] extern crate rustc_data_structures; +extern crate self as rustc_hir; + mod arena; pub mod def; pub mod def_path_hash_map; @@ -42,3 +44,5 @@ pub use hir_id::*; pub use lang_items::{LangItem, LanguageItems}; pub use stable_hash_impls::HashStableContext; pub use target::{MethodKind, Target}; + +arena_types!(rustc_arena::declare_arena); diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 8ccd59e8e37ff..2886621f2c61d 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -1,8 +1,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use crate::hir::{ - AttributeMap, BodyId, Crate, Expr, ForeignItemId, ImplItemId, ItemId, OwnerNodes, TraitItemId, - Ty, + AttributeMap, BodyId, Expr, ForeignItemId, ImplItemId, ItemId, OwnerNodes, TraitItemId, Ty, }; use crate::hir_id::{HirId, ItemLocalId}; use rustc_span::def_id::DefPathHash; @@ -134,10 +133,3 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable for AttributeMap hash.hash_stable(hcx, hasher); } } - -impl HashStable for Crate<'_> { - fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { - let Crate { owners: _, hir_hash } = self; - hir_hash.hash_stable(hcx, hasher) - } -} diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 29d1cd0e05467..3e83228614625 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -32,6 +32,7 @@ rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_codegen_llvm = { path = "../rustc_codegen_llvm", optional = true } rustc_hir = { path = "../rustc_hir" } +rustc_index = { path = "../rustc_index" } rustc_metadata = { path = "../rustc_metadata" } rustc_const_eval = { path = "../rustc_const_eval" } rustc_mir_build = { path = "../rustc_mir_build" } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 08987dff660a4..895cad36a92e3 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -13,7 +13,7 @@ use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, PResult}; use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; -use rustc_hir::Crate; +use rustc_hir::definitions::Definitions; use rustc_lint::{EarlyCheckNode, LintStore}; use rustc_metadata::creader::CStore; use rustc_metadata::{encode_metadata, EncodedMetadata}; @@ -29,7 +29,7 @@ use rustc_query_impl::{OnDiskCache, Queries as TcxQueries}; use rustc_resolve::{Resolver, ResolverArenas}; use rustc_serialize::json; use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType}; -use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn}; +use rustc_session::cstore::{CrateStoreDyn, MetadataLoader, MetadataLoaderDyn}; use rustc_session::output::{filename_for_input, filename_for_metadata}; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; @@ -141,7 +141,9 @@ mod boxed_resolver { f((&mut *resolver).as_mut().unwrap()) } - pub fn to_resolver_outputs(resolver: Rc>) -> ResolverOutputs { + pub fn to_resolver_outputs( + resolver: Rc>, + ) -> (Definitions, Box, ResolverOutputs) { match Rc::try_unwrap(resolver) { Ok(resolver) => { let mut resolver = resolver.into_inner(); @@ -487,32 +489,6 @@ pub fn configure_and_expand( Ok(krate) } -pub fn lower_to_hir<'res, 'tcx>( - sess: &'tcx Session, - resolver: &'res mut Resolver<'_>, - krate: Rc, - arena: &'tcx rustc_ast_lowering::Arena<'tcx>, -) -> &'tcx Crate<'tcx> { - // Lower AST to HIR. - let hir_crate = rustc_ast_lowering::lower_crate( - sess, - &*krate, - resolver, - rustc_parse::nt_to_tokenstream, - arena, - ); - - // Drop AST to free memory - sess.time("drop_ast", || std::mem::drop(krate)); - - // Discard hygiene data, which isn't required after lowering to HIR. - if !sess.opts.debugging_opts.keep_hygiene_data { - rustc_span::hygiene::clear_syntax_context_map(); - } - - hir_crate -} - // Returns all the paths that correspond to generated files. fn generated_output_paths( sess: &Session, @@ -777,6 +753,9 @@ pub fn prepare_outputs( pub static DEFAULT_QUERY_PROVIDERS: SyncLazy = SyncLazy::new(|| { let providers = &mut Providers::default(); providers.analysis = analysis; + providers.lower_to_hir = + |tcx, def_id| rustc_ast_lowering::lower_to_hir(tcx, def_id, rustc_parse::nt_to_tokenstream); + rustc_ast_lowering::provide(providers); proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); @@ -823,7 +802,7 @@ impl<'tcx> QueryContext<'tcx> { pub fn create_global_ctxt<'tcx>( compiler: &'tcx Compiler, lint_store: Lrc, - krate: Rc, + krate: Lrc, dep_graph: DepGraph, resolver: Rc>, outputs: OutputFilenames, @@ -831,18 +810,17 @@ pub fn create_global_ctxt<'tcx>( queries: &'tcx OnceCell>, global_ctxt: &'tcx OnceCell>, arena: &'tcx WorkerLocal>, - hir_arena: &'tcx WorkerLocal>, + hir_arena: &'tcx WorkerLocal>, ) -> QueryContext<'tcx> { // We're constructing the HIR here; we don't care what we will // read, since we haven't even constructed the *input* to // incr. comp. yet. dep_graph.assert_ignored(); - let sess = &compiler.session(); - let krate = - resolver.borrow_mut().access(|resolver| lower_to_hir(sess, resolver, krate, hir_arena)); - let resolver_outputs = BoxedResolver::to_resolver_outputs(resolver); + let (definitions, cstore, resolver_outputs) = BoxedResolver::to_resolver_outputs(resolver); + let krate = rustc_ast_lowering::index_crate(&resolver_outputs.node_id_to_def_id, krate); + let sess = &compiler.session(); let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); let codegen_backend = compiler.codegen_backend(); @@ -866,6 +844,9 @@ pub fn create_global_ctxt<'tcx>( sess, lint_store, arena, + hir_arena, + definitions, + cstore, resolver_outputs, krate, dep_graph, diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 22ab62ac372f2..1862235d79622 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -72,13 +72,13 @@ pub struct Queries<'tcx> { queries: OnceCell>, arena: WorkerLocal>, - hir_arena: WorkerLocal>, + hir_arena: WorkerLocal>, dep_graph_future: Query>, parse: Query, crate_name: Query, register_plugins: Query<(ast::Crate, Lrc)>, - expansion: Query<(Rc, Rc>, Lrc)>, + expansion: Query<(Lrc, Rc>, Lrc)>, dep_graph: Query, prepare_outputs: Query, global_ctxt: Query>, @@ -92,7 +92,7 @@ impl<'tcx> Queries<'tcx> { gcx: OnceCell::new(), queries: OnceCell::new(), arena: WorkerLocal::new(|_| Arena::default()), - hir_arena: WorkerLocal::new(|_| rustc_ast_lowering::Arena::default()), + hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()), dep_graph_future: Default::default(), parse: Default::default(), crate_name: Default::default(), @@ -164,7 +164,7 @@ impl<'tcx> Queries<'tcx> { pub fn expansion( &self, - ) -> Result<&Query<(Rc, Rc>, Lrc)>> { + ) -> Result<&Query<(Lrc, Rc>, Lrc)>> { tracing::trace!("expansion"); self.expansion.compute(|| { let crate_name = self.crate_name()?.peek().clone(); @@ -180,7 +180,7 @@ impl<'tcx> Queries<'tcx> { let krate = resolver.access(|resolver| { passes::configure_and_expand(sess, &lint_store, krate, &crate_name, resolver) })?; - Ok((Rc::new(krate), Rc::new(RefCell::new(resolver)), lint_store)) + Ok((Lrc::new(krate), Rc::new(RefCell::new(resolver)), lint_store)) }) } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 0ac636b878e0d..572ffad9f39cf 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -34,7 +34,7 @@ use tracing::debug; /// Extract the `LintStore` from the query context. /// This function exists because we've erased `LintStore` as `dyn Any` in the context. -crate fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore { +pub fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore { let store: &dyn Any = &*tcx.lint_store; store.downcast_ref().unwrap() } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 18f229564c2a3..396daf25cb977 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -102,7 +102,7 @@ pub use builtin::SoftLints; pub use context::{CheckLintNameResult, FindLintError, LintStore}; pub use context::{EarlyContext, LateContext, LintContext}; pub use early::{check_ast_node, EarlyCheckNode}; -pub use late::check_crate; +pub use late::{check_crate, unerased_lint_store}; pub use passes::{EarlyLintPass, LateLintPass}; pub use rustc_session::lint::Level::{self, *}; pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Lint, LintId}; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index ed49eebd16d9c..d8193e4362f26 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -455,7 +455,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_def_path_table(&mut self) { - let table = self.tcx.resolutions(()).definitions.def_path_table(); + let table = self.tcx.def_path_table(); if self.is_proc_macro { for def_index in std::iter::once(CRATE_DEF_INDEX) .chain(self.tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index)) @@ -475,9 +475,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_def_path_hash_map(&mut self) -> Lazy> { - self.lazy(DefPathHashMapRef::BorrowedFromTcx( - self.tcx.resolutions(()).definitions.def_path_hash_to_def_index_map(), - )) + self.lazy(DefPathHashMapRef::BorrowedFromTcx(self.tcx.def_path_hash_to_def_index_map())) } fn encode_source_map(&mut self) -> Lazy<[rustc_span::SourceFile]> { @@ -663,7 +661,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; // Encode the proc macro data. This affects 'tables', - // so we need to do this before we encode the tables + // so we need to do this before we encode the tables. + // This overwrites def_keys, so it must happen after encode_def_path_table. i = self.position(); let proc_macro_data = self.encode_proc_macros(); let proc_macro_data_bytes = self.position() - i; @@ -990,8 +989,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { return; } let tcx = self.tcx; - let hir = tcx.hir(); - for local_id in hir.iter_local_def_id() { + for local_id in tcx.iter_local_def_id() { let def_id = local_id.to_def_id(); let def_kind = tcx.opt_def_kind(local_id); let Some(def_kind) = def_kind else { continue }; @@ -1843,12 +1841,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { debug!("EncodeContext::encode_traits_and_impls()"); empty_proc_macro!(self); let tcx = self.tcx; - let mut ctx = tcx.create_stable_hashing_context(); let mut all_impls: Vec<_> = tcx.crate_inherent_impls(()).incoherent_impls.iter().collect(); - all_impls.sort_by_cached_key(|&(&simp, _)| { - let mut hasher = StableHasher::new(); - simp.hash_stable(&mut ctx, &mut hasher); - hasher.finish::(); + tcx.with_stable_hashing_context(|mut ctx| { + all_impls.sort_by_cached_key(|&(&simp, _)| { + let mut hasher = StableHasher::new(); + simp.hash_stable(&mut ctx, &mut hasher); + hasher.finish::() + }) }); let all_impls: Vec<_> = all_impls .into_iter() diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 6bfd1b7ffab24..8ad4c05ab9d5e 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -71,8 +71,8 @@ impl<'tcx> DepContext for TyCtxt<'tcx> { type DepKind = DepKind; #[inline] - fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { - TyCtxt::create_stable_hashing_context(*self) + fn with_stable_hashing_context(&self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R { + TyCtxt::with_stable_hashing_context(*self, f) } #[inline] diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index e0ed402283904..b589f9534606b 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,19 +1,14 @@ -use crate::hir::{ModuleItems, Owner}; +use crate::hir::Owner; use crate::ty::{DefIdTree, TyCtxt}; use rustc_ast as ast; -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{par_for_each_in, Send, Sync}; +use rustc_data_structures::sync::{par_for_each_in, par_iter, ParallelIterator, Send, Sync}; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::*; use rustc_index::vec::Idx; -use rustc_middle::hir::nested_filter; -use rustc_span::def_id::StableCrateId; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::spec::abi::Abi; @@ -167,7 +162,7 @@ impl<'hir> Map<'hir> { pub fn def_key(self, def_id: LocalDefId) -> DefKey { // Accessing the DefKey is ok, since it is part of DefPathHash. - self.tcx.untracked_resolutions.definitions.def_key(def_id) + self.tcx.definitions_untracked().def_key(def_id) } pub fn def_path_from_hir_id(self, id: HirId) -> Option { @@ -176,13 +171,13 @@ impl<'hir> Map<'hir> { pub fn def_path(self, def_id: LocalDefId) -> DefPath { // Accessing the DefPath is ok, since it is part of DefPathHash. - self.tcx.untracked_resolutions.definitions.def_path(def_id) + self.tcx.definitions_untracked().def_path(def_id) } #[inline] pub fn def_path_hash(self, def_id: LocalDefId) -> DefPathHash { // Accessing the DefPathHash is ok, it is incr. comp. stable. - self.tcx.untracked_resolutions.definitions.def_path_hash(def_id) + self.tcx.definitions_untracked().def_path_hash(def_id) } #[inline] @@ -215,13 +210,6 @@ impl<'hir> Map<'hir> { self.tcx.local_def_id_to_hir_id(def_id) } - pub fn iter_local_def_id(self) -> impl Iterator + 'hir { - // Create a dependency to the crate to be sure we re-execute this when the amount of - // definitions change. - self.tcx.ensure().hir_crate(()); - self.tcx.untracked_resolutions.definitions.iter_local_def_id() - } - pub fn opt_def_kind(self, local_def_id: LocalDefId) -> Option { let hir_id = self.local_def_id_to_hir_id(local_def_id); let def_kind = match self.find(hir_id)? { @@ -511,34 +499,24 @@ impl<'hir> Map<'hir> { /// crate. If you would prefer to iterate over the bodies /// themselves, you can do `self.hir().krate().body_ids.iter()`. pub fn body_owners(self) -> impl Iterator + 'hir { - self.krate() - .owners - .iter_enumerated() - .flat_map(move |(owner, owner_info)| { - let bodies = &owner_info.as_owner()?.nodes.bodies; - Some(bodies.iter().map(move |&(local_id, _)| { - let hir_id = HirId { owner, local_id }; - let body_id = BodyId { hir_id }; - self.body_owner_def_id(body_id) - })) + self.krate().owners.iter().flat_map(move |&owner| { + let bodies = &self.tcx.hir_owner_nodes(owner).unwrap().bodies; + bodies.iter().filter_map(move |(local_id, _)| { + let hir_id = HirId { owner, local_id: *local_id }; + let body_id = BodyId { hir_id }; + Some(self.body_owner_def_id(body_id)) }) - .flatten() + }) } pub fn par_body_owners(self, f: F) { - use rustc_data_structures::sync::{par_iter, ParallelIterator}; - #[cfg(parallel_compiler)] - use rustc_rayon::iter::IndexedParallelIterator; - - par_iter(&self.krate().owners.raw).enumerate().for_each(|(owner, owner_info)| { - let owner = LocalDefId::new(owner); - if let MaybeOwner::Owner(owner_info) = owner_info { - par_iter(owner_info.nodes.bodies.range(..)).for_each(|(local_id, _)| { - let hir_id = HirId { owner, local_id: *local_id }; - let body_id = BodyId { hir_id }; - f(self.body_owner_def_id(body_id)) - }) - } + par_iter(&*self.krate().owners).for_each(|&owner| { + let owner_info = self.tcx.lower_to_hir(owner).unwrap(); + par_iter(owner_info.nodes.bodies.range(..)).for_each(|(local_id, _)| { + let hir_id = HirId { owner, local_id: *local_id }; + let body_id = BodyId { hir_id }; + f(self.body_owner_def_id(body_id)) + }) }); } @@ -595,13 +573,12 @@ impl<'hir> Map<'hir> { /// Walks the attributes in a crate. pub fn walk_attributes(self, visitor: &mut impl Visitor<'hir>) { let krate = self.krate(); - for (owner, info) in krate.owners.iter_enumerated() { - if let MaybeOwner::Owner(info) = info { - for (local_id, attrs) in info.attrs.map.iter() { - let id = HirId { owner, local_id: *local_id }; - for a in *attrs { - visitor.visit_attribute(id, a) - } + for &owner in krate.owners.iter() { + let info = self.tcx.lower_to_hir(owner).unwrap(); + for (local_id, attrs) in info.attrs.map.iter() { + let id = HirId { owner, local_id: *local_id }; + for a in *attrs { + visitor.visit_attribute(id, a) } } } @@ -620,8 +597,9 @@ impl<'hir> Map<'hir> { V: itemlikevisit::ItemLikeVisitor<'hir>, { let krate = self.krate(); - for owner in krate.owners.iter().filter_map(|i| i.as_owner()) { - match owner.node() { + for &owner in krate.owners.iter() { + let info = self.tcx.hir_owner(owner).unwrap(); + match info.node { OwnerNode::Item(item) => visitor.visit_item(item), OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item), OwnerNode::ImplItem(item) => visitor.visit_impl_item(item), @@ -637,14 +615,12 @@ impl<'hir> Map<'hir> { V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send, { let krate = self.krate(); - par_for_each_in(&krate.owners.raw, |owner| match owner.map(OwnerInfo::node) { - MaybeOwner::Owner(OwnerNode::Item(item)) => visitor.visit_item(item), - MaybeOwner::Owner(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item), - MaybeOwner::Owner(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item), - MaybeOwner::Owner(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item), - MaybeOwner::Owner(OwnerNode::Crate(_)) - | MaybeOwner::NonOwner(_) - | MaybeOwner::Phantom => {} + par_for_each_in(&*krate.owners, |&owner| match self.tcx.hir_owner(owner).unwrap().node { + OwnerNode::Item(item) => visitor.visit_item(item), + OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item), + OwnerNode::ImplItem(item) => visitor.visit_impl_item(item), + OwnerNode::TraitItem(item) => visitor.visit_trait_item(item), + OwnerNode::Crate(_) => {} }) } @@ -686,7 +662,6 @@ impl<'hir> Map<'hir> { #[cfg(parallel_compiler)] pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + Sync) { - use rustc_data_structures::sync::{par_iter, ParallelIterator}; par_iter_submodules(self.tcx, CRATE_DEF_ID, &f); fn par_iter_submodules(tcx: TyCtxt<'_>, module: LocalDefId, f: &F) @@ -1075,75 +1050,6 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> { } } -pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { - debug_assert_eq!(crate_num, LOCAL_CRATE); - let krate = tcx.hir_crate(()); - let hir_body_hash = krate.hir_hash; - - let upstream_crates = upstream_crates(tcx); - - // We hash the final, remapped names of all local source files so we - // don't have to include the path prefix remapping commandline args. - // If we included the full mapping in the SVH, we could only have - // reproducible builds by compiling from the same directory. So we just - // hash the result of the mapping instead of the mapping itself. - let mut source_file_names: Vec<_> = tcx - .sess - .source_map() - .files() - .iter() - .filter(|source_file| source_file.cnum == LOCAL_CRATE) - .map(|source_file| source_file.name_hash) - .collect(); - - source_file_names.sort_unstable(); - - let mut hcx = tcx.create_stable_hashing_context(); - let mut stable_hasher = StableHasher::new(); - hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher); - upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); - source_file_names.hash_stable(&mut hcx, &mut stable_hasher); - if tcx.sess.opts.debugging_opts.incremental_relative_spans { - let definitions = &tcx.untracked_resolutions.definitions; - let mut owner_spans: Vec<_> = krate - .owners - .iter_enumerated() - .filter_map(|(def_id, info)| { - let _ = info.as_owner()?; - let def_path_hash = definitions.def_path_hash(def_id); - let span = definitions.def_span(def_id); - debug_assert_eq!(span.parent(), None); - Some((def_path_hash, span)) - }) - .collect(); - owner_spans.sort_unstable_by_key(|bn| bn.0); - owner_spans.hash_stable(&mut hcx, &mut stable_hasher); - } - tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); - tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher); - // Hash visibility information since it does not appear in HIR. - let resolutions = tcx.resolutions(()); - resolutions.visibilities.hash_stable(&mut hcx, &mut stable_hasher); - resolutions.has_pub_restricted.hash_stable(&mut hcx, &mut stable_hasher); - - let crate_hash: Fingerprint = stable_hasher.finish(); - Svh::new(crate_hash.to_smaller_hash()) -} - -fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { - let mut upstream_crates: Vec<_> = tcx - .crates(()) - .iter() - .map(|&cnum| { - let stable_crate_id = tcx.resolutions(()).cstore.stable_crate_id(cnum); - let hash = tcx.crate_hash(cnum); - (stable_crate_id, hash) - }) - .collect(); - upstream_crates.sort_unstable_by_key(|&(stable_crate_id, _)| stable_crate_id); - upstream_crates -} - fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { let id_str = format!(" (hir_id={})", id); @@ -1233,135 +1139,3 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { None => format!("unknown node{}", id_str), } } - -pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems { - let mut collector = ModuleCollector { - tcx, - submodules: Vec::default(), - items: Vec::default(), - trait_items: Vec::default(), - impl_items: Vec::default(), - foreign_items: Vec::default(), - }; - - let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id); - collector.visit_mod(hir_mod, span, hir_id); - - let ModuleCollector { submodules, items, trait_items, impl_items, foreign_items, .. } = - collector; - return ModuleItems { - submodules: submodules.into_boxed_slice(), - items: items.into_boxed_slice(), - trait_items: trait_items.into_boxed_slice(), - impl_items: impl_items.into_boxed_slice(), - foreign_items: foreign_items.into_boxed_slice(), - }; - - struct ModuleCollector<'tcx> { - tcx: TyCtxt<'tcx>, - submodules: Vec, - items: Vec, - trait_items: Vec, - impl_items: Vec, - foreign_items: Vec, - } - - impl<'hir> Visitor<'hir> for ModuleCollector<'hir> { - type NestedFilter = nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - - fn visit_item(&mut self, item: &'hir Item<'hir>) { - self.items.push(item.item_id()); - if let ItemKind::Mod(..) = item.kind { - // If this declares another module, do not recurse inside it. - self.submodules.push(item.def_id); - } else { - intravisit::walk_item(self, item) - } - } - - fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { - self.trait_items.push(item.trait_item_id()); - intravisit::walk_trait_item(self, item) - } - - fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { - self.impl_items.push(item.impl_item_id()); - intravisit::walk_impl_item(self, item) - } - - fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { - self.foreign_items.push(item.foreign_item_id()); - intravisit::walk_foreign_item(self, item) - } - } -} - -pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { - let mut collector = CrateCollector { - tcx, - submodules: Vec::default(), - items: Vec::default(), - trait_items: Vec::default(), - impl_items: Vec::default(), - foreign_items: Vec::default(), - }; - - tcx.hir().walk_toplevel_module(&mut collector); - - let CrateCollector { submodules, items, trait_items, impl_items, foreign_items, .. } = - collector; - - return ModuleItems { - submodules: submodules.into_boxed_slice(), - items: items.into_boxed_slice(), - trait_items: trait_items.into_boxed_slice(), - impl_items: impl_items.into_boxed_slice(), - foreign_items: foreign_items.into_boxed_slice(), - }; - - struct CrateCollector<'tcx> { - tcx: TyCtxt<'tcx>, - submodules: Vec, - items: Vec, - trait_items: Vec, - impl_items: Vec, - foreign_items: Vec, - } - - impl<'hir> Visitor<'hir> for CrateCollector<'hir> { - type NestedFilter = nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - - fn visit_item(&mut self, item: &'hir Item<'hir>) { - self.items.push(item.item_id()); - intravisit::walk_item(self, item) - } - - fn visit_mod(&mut self, m: &'hir Mod<'hir>, _s: Span, n: HirId) { - self.submodules.push(n.owner); - intravisit::walk_mod(self, m, n); - } - - fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { - self.foreign_items.push(item.foreign_item_id()); - intravisit::walk_foreign_item(self, item) - } - - fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { - self.trait_items.push(item.trait_item_id()); - intravisit::walk_trait_item(self, item) - } - - fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { - self.impl_items.push(item.impl_item_id()); - intravisit::walk_impl_item(self, item) - } - } -} diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index f18067145dd4a..e5f0c0746d8d3 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -7,7 +7,7 @@ pub mod nested_filter; pub mod place; use crate::ty::query::Providers; -use crate::ty::{ImplSubject, TyCtxt}; +use crate::ty::{DefIdTree, ImplSubject, TyCtxt}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -34,35 +34,6 @@ impl<'a, 'tcx> HashStable> for Owner<'tcx> { } } -/// Gather the LocalDefId for each item-like within a module, including items contained within -/// bodies. The Ids are in visitor order. This is used to partition a pass between modules. -#[derive(Debug, HashStable)] -pub struct ModuleItems { - submodules: Box<[LocalDefId]>, - items: Box<[ItemId]>, - trait_items: Box<[TraitItemId]>, - impl_items: Box<[ImplItemId]>, - foreign_items: Box<[ForeignItemId]>, -} - -impl ModuleItems { - pub fn items(&self) -> impl Iterator + '_ { - self.items.iter().copied() - } - - pub fn trait_items(&self) -> impl Iterator + '_ { - self.trait_items.iter().copied() - } - - pub fn impl_items(&self) -> impl Iterator + '_ { - self.impl_items.iter().copied() - } - - pub fn foreign_items(&self) -> impl Iterator + '_ { - self.foreign_items.iter().copied() - } -} - impl<'tcx> TyCtxt<'tcx> { #[inline(always)] pub fn hir(self) -> map::Map<'tcx> { @@ -85,42 +56,34 @@ pub fn provide(providers: &mut Providers) { let hir = tcx.hir(); hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)) }; - providers.hir_crate = |tcx, ()| tcx.untracked_crate; - providers.hir_crate_items = map::hir_crate_items; - providers.crate_hash = map::crate_hash; - providers.hir_module_items = map::hir_module_items; providers.hir_owner = |tcx, id| { - let owner = tcx.hir_crate(()).owners.get(id)?.as_owner()?; + let owner = tcx.lower_to_hir(id).as_owner()?; let node = owner.node(); Some(Owner { node, hash_without_bodies: owner.nodes.hash_without_bodies }) }; providers.local_def_id_to_hir_id = |tcx, id| { - let owner = tcx.hir_crate(()).owners[id].map(|_| ()); + let owner = tcx.lower_to_hir(id).map(|_| ()); match owner { MaybeOwner::Owner(_) => HirId::make_owner(id), - MaybeOwner::Phantom => bug!("No HirId for {:?}", id), MaybeOwner::NonOwner(hir_id) => hir_id, } }; - providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id].map(|i| &i.nodes); + providers.hir_owner_nodes = |tcx, id| tcx.lower_to_hir(id).map(|i| &i.nodes); providers.hir_owner_parent = |tcx, id| { // Accessing the def_key is ok since its value is hashed as part of `id`'s DefPathHash. - let parent = tcx.untracked_resolutions.definitions.def_key(id).parent; - let parent = parent.map_or(CRATE_HIR_ID, |local_def_index| { - let def_id = LocalDefId { local_def_index }; - let mut parent_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + tcx.local_parent(id).map_or(CRATE_HIR_ID, |parent| { + let mut parent_hir_id = tcx.hir().local_def_id_to_hir_id(parent); if let Some(local_id) = - tcx.hir_crate(()).owners[parent_hir_id.owner].unwrap().parenting.get(&id) + tcx.lower_to_hir(parent_hir_id.owner).unwrap().parenting.get(&id) { parent_hir_id.local_id = *local_id; } parent_hir_id - }); - parent + }) }; providers.hir_attrs = - |tcx, id| tcx.hir_crate(()).owners[id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs); - providers.source_span = |tcx, def_id| tcx.resolutions(()).definitions.def_span(def_id); + |tcx, id| tcx.lower_to_hir(id).as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs); + providers.source_span = |tcx, def_id| tcx.definitions_untracked().def_span(def_id); providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP); providers.fn_arg_names = |tcx, id| { let hir = tcx.hir(); @@ -141,8 +104,8 @@ pub fn provide(providers: &mut Providers) { providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls; providers.expn_that_defined = |tcx, id| { let id = id.expect_local(); - tcx.resolutions(()).definitions.expansion_that_defined(id) + tcx.definitions_untracked().expansion_that_defined(id) }; providers.in_scope_traits_map = - |tcx, id| tcx.hir_crate(()).owners[id].as_owner().map(|owner_info| &owner_info.trait_map); + |tcx, id| tcx.lower_to_hir(id).as_owner().map(|owner_info| &owner_info.trait_map); } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index cc80ab8f16e9c..4c290ecf731ac 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -31,22 +31,29 @@ rustc_queries! { /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside /// of rustc_middle::hir::source_map. query source_span(key: LocalDefId) -> Span { + eval_always desc { "get the source span" } } + query lower_to_hir(key: LocalDefId) -> hir::MaybeOwner<&'tcx hir::OwnerInfo<'tcx>> { + eval_always + desc { |tcx| "lower HIR for `{}`", tcx.def_path_str(key.to_def_id()) } + } + /// Represents crate as a whole (as distinct from the top-level crate module). /// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir().krate()`), /// we will have to assume that any change means that you need to be recompiled. /// This is because the `hir_crate` query gives you access to all other items. /// To avoid this fate, do not call `tcx.hir().krate()`; instead, /// prefer wrappers like `tcx.visit_all_items_in_krate()`. - query hir_crate(key: ()) -> &'tcx Crate<'tcx> { + query hir_crate(key: ()) -> Crate<'tcx> { + storage(ArenaCacheSelector<'tcx>) eval_always desc { "get the crate HIR" } } /// All items in the crate. - query hir_crate_items(_: ()) -> rustc_middle::hir::ModuleItems { + query hir_crate_items(_: ()) -> hir::ModuleItems { storage(ArenaCacheSelector<'tcx>) eval_always desc { "get HIR crate items" } @@ -56,7 +63,7 @@ rustc_queries! { /// /// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`. /// Avoid calling this query directly. - query hir_module_items(key: LocalDefId) -> rustc_middle::hir::ModuleItems { + query hir_module_items(key: LocalDefId) -> hir::ModuleItems { storage(ArenaCacheSelector<'tcx>) desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -862,6 +869,7 @@ rustc_queries! { /// Not meant to be used directly outside of coherence. query crate_inherent_impls(k: ()) -> CrateInherentImpls { storage(ArenaCacheSelector<'tcx>) + eval_always desc { "all inherent impls defined in crate" } } @@ -1328,7 +1336,7 @@ rustc_queries! { desc { "computing whether impls specialize one another" } } query in_scope_traits_map(_: LocalDefId) - -> Option<&'tcx FxHashMap>> { + -> Option<&'tcx FxHashMap> { desc { "traits in scope at a block" } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 30fe3ffa7e3c4..1396a8021f003 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -32,12 +32,13 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; +use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, RwLock, WorkerLocal}; use rustc_data_structures::vec_map::VecMap; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; +use rustc_hir::definitions::Definitions; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ @@ -50,6 +51,7 @@ use rustc_middle::mir::FakeReadCause; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames}; +use rustc_session::cstore::CrateStoreDyn; use rustc_session::lint::{Level, Lint}; use rustc_session::Limit; use rustc_session::Session; @@ -150,7 +152,8 @@ impl<'tcx> CtxtInterners<'tcx> { &self, kind: TyKind<'tcx>, sess: &Session, - resolutions: &ty::ResolverOutputs, + definitions: &rustc_hir::definitions::Definitions, + cstore: &CrateStoreDyn, ) -> Ty<'tcx> { Ty(Interned::new_unchecked( self.type_ @@ -165,11 +168,7 @@ impl<'tcx> CtxtInterners<'tcx> { Fingerprint::ZERO } else { let mut hasher = StableHasher::new(); - let mut hcx = StableHashingContext::ignore_spans( - sess, - &resolutions.definitions, - &*resolutions.cstore, - ); + let mut hcx = StableHashingContext::ignore_spans(sess, definitions, cstore); kind.hash_stable(&mut hcx, &mut hasher); hasher.finish() }; @@ -900,9 +899,10 @@ impl<'tcx> CommonTypes<'tcx> { fn new( interners: &CtxtInterners<'tcx>, sess: &Session, - resolutions: &ty::ResolverOutputs, + definitions: &rustc_hir::definitions::Definitions, + cstore: &CrateStoreDyn, ) -> CommonTypes<'tcx> { - let mk = |ty| interners.intern_ty(ty, sess, resolutions); + let mk = |ty| interners.intern_ty(ty, sess, definitions, cstore); CommonTypes { unit: mk(Tuple(List::empty())), @@ -999,6 +999,7 @@ impl<'tcx> Deref for TyCtxt<'tcx> { pub struct GlobalCtxt<'tcx> { pub arena: &'tcx WorkerLocal>, + pub hir_arena: &'tcx WorkerLocal>, interners: CtxtInterners<'tcx>, @@ -1023,10 +1024,12 @@ pub struct GlobalCtxt<'tcx> { /// Common consts, pre-interned for your convenience. pub consts: CommonConsts<'tcx>, + definitions: RwLock, + cstore: Box, + /// Output of the resolver. pub(crate) untracked_resolutions: ty::ResolverOutputs, - - pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>, + pub untracked_crate: IndexVec>, /// This provides access to the incremental compilation on-disk cache for query results. /// Do not access this directly. It is only meant to be used by @@ -1163,8 +1166,11 @@ impl<'tcx> TyCtxt<'tcx> { s: &'tcx Session, lint_store: Lrc, arena: &'tcx WorkerLocal>, - resolutions: ty::ResolverOutputs, - krate: &'tcx hir::Crate<'tcx>, + hir_arena: &'tcx WorkerLocal>, + definitions: Definitions, + cstore: Box, + untracked_resolutions: ty::ResolverOutputs, + untracked_crate: IndexVec>, dep_graph: DepGraph, on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, queries: &'tcx dyn query::QueryEngine<'tcx>, @@ -1176,7 +1182,7 @@ impl<'tcx> TyCtxt<'tcx> { s.fatal(&err); }); let interners = CtxtInterners::new(arena); - let common_types = CommonTypes::new(&interners, s, &resolutions); + let common_types = CommonTypes::new(&interners, s, &definitions, &*cstore); let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); @@ -1184,14 +1190,17 @@ impl<'tcx> TyCtxt<'tcx> { sess: s, lint_store, arena, + hir_arena, interners, dep_graph, - untracked_resolutions: resolutions, + definitions: RwLock::new(definitions), + cstore, prof: s.prof.clone(), types: common_types, lifetimes: common_lifetimes, consts: common_consts, - untracked_crate: krate, + untracked_resolutions, + untracked_crate, on_disk_cache, queries, query_caches: query::QueryCaches::default(), @@ -1287,9 +1296,9 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey { // Accessing the DefKey is ok, since it is part of DefPathHash. if let Some(id) = id.as_local() { - self.untracked_resolutions.definitions.def_key(id) + self.definitions_untracked().def_key(id) } else { - self.untracked_resolutions.cstore.def_key(id) + self.cstore.def_key(id) } } @@ -1301,9 +1310,9 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_path(self, id: DefId) -> rustc_hir::definitions::DefPath { // Accessing the DefPath is ok, since it is part of DefPathHash. if let Some(id) = id.as_local() { - self.untracked_resolutions.definitions.def_path(id) + self.definitions_untracked().def_path(id) } else { - self.untracked_resolutions.cstore.def_path(id) + self.cstore.def_path(id) } } @@ -1311,9 +1320,9 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash { // Accessing the DefPathHash is ok, it is incr. comp. stable. if let Some(def_id) = def_id.as_local() { - self.untracked_resolutions.definitions.def_path_hash(def_id) + self.definitions_untracked().def_path_hash(def_id) } else { - self.untracked_resolutions.cstore.def_path_hash(def_id) + self.cstore.def_path_hash(def_id) } } @@ -1322,7 +1331,7 @@ impl<'tcx> TyCtxt<'tcx> { if crate_num == LOCAL_CRATE { self.sess.local_stable_crate_id() } else { - self.untracked_resolutions.cstore.stable_crate_id(crate_num) + self.cstore.stable_crate_id(crate_num) } } @@ -1333,7 +1342,7 @@ impl<'tcx> TyCtxt<'tcx> { if stable_crate_id == self.sess.local_stable_crate_id() { LOCAL_CRATE } else { - self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id) + self.cstore.stable_crate_id_to_crate_num(stable_crate_id) } } @@ -1348,16 +1357,12 @@ impl<'tcx> TyCtxt<'tcx> { // If this is a DefPathHash from the local crate, we can look up the // DefId in the tcx's `Definitions`. if stable_crate_id == self.sess.local_stable_crate_id() { - self.untracked_resolutions - .definitions - .local_def_path_hash_to_def_id(hash, err) - .to_def_id() + self.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id() } else { // If this is a DefPathHash from an upstream crate, let the CrateStore map // it to a DefId. - let cstore = &self.untracked_resolutions.cstore; - let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id); - cstore.def_path_hash_to_def_id(cnum, hash) + let cnum = self.cstore.stable_crate_id_to_crate_num(stable_crate_id); + self.cstore.def_path_hash_to_def_id(cnum, hash) } } @@ -1369,7 +1374,7 @@ impl<'tcx> TyCtxt<'tcx> { let (crate_name, stable_crate_id) = if def_id.is_local() { (self.crate_name, self.sess.local_stable_crate_id()) } else { - let cstore = &self.untracked_resolutions.cstore; + let cstore = &self.cstore; (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate)) }; @@ -1383,32 +1388,94 @@ impl<'tcx> TyCtxt<'tcx> { ) } + /// Create a new definition within the incr. comp. engine. + pub fn create_def( + self, + parent: LocalDefId, + data: hir::definitions::DefPathData, + expn_id: rustc_span::ExpnId, + span: Span, + ) -> LocalDefId { + // The following call has the side effect of modifying the tables inside `definitions`. + // These very tables are relied on by the incr. comp. engine to decode DepNodes and to + // decode the on-disk cache. + let def_id = self.definitions.write().create_def(parent, data, expn_id, span); + + // We need to ensure that these side effects are re-run by the incr. comp. engine. + use rustc_query_system::dep_graph::DepNodeIndex; + self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); + + // Any LocalDefId which is used within queries, either as key or result, either: + // - has been created before the construction of the TyCtxt; + // - has been created by this call to `create_def`. + // As a consequence, this LocalDefId is always re-created before it is needed by the incr. + // comp. engine itself. + def_id + } + + pub fn iter_local_def_id(self) -> impl Iterator + 'tcx { + // Create a dependency to the crate to be sure we re-execute this when the amount of + // definitions change. + self.ensure().hir_crate(()); + // Leak a read lock once we start iterating on definitions, to prevent adding new onces + // while iterating. If some query needs to add definitions, it should be `ensure`d above. + let definitions = self.definitions.leak(); + definitions.iter_local_def_id() + } + + pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable { + // Create a dependency to the crate to be sure we reexcute this when the amount of + // definitions change. + self.ensure().hir_crate(()); + // Leak a read lock once we start iterating on definitions, to prevent adding new onces + // while iterating. If some query needs to add definitions, it should be `ensure`d above. + let definitions = self.definitions.leak(); + definitions.def_path_table() + } + + pub fn def_path_hash_to_def_index_map( + self, + ) -> &'tcx rustc_hir::def_path_hash_map::DefPathHashMap { + // Create a dependency to the crate to be sure we reexcute this when the amount of + // definitions change. + self.ensure().hir_crate(()); + // Leak a read lock once we start iterating on definitions, to prevent adding new onces + // while iterating. If some query needs to add definitions, it should be `ensure`d above. + let definitions = self.definitions.leak(); + definitions.def_path_hash_to_def_index_map() + } + /// Note that this is *untracked* and should only be used within the query /// system if the result is otherwise tracked through queries - pub fn cstore_untracked(self) -> &'tcx ty::CrateStoreDyn { - &*self.untracked_resolutions.cstore + pub fn cstore_untracked(self) -> &'tcx CrateStoreDyn { + &*self.cstore } /// Note that this is *untracked* and should only be used within the query /// system if the result is otherwise tracked through queries - pub fn definitions_untracked(self) -> &'tcx hir::definitions::Definitions { - &self.untracked_resolutions.definitions + #[inline] + pub fn definitions_untracked(self) -> ReadGuard<'tcx, Definitions> { + self.definitions.read() } #[inline(always)] - pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> { - let resolutions = &self.gcx.untracked_resolutions; - StableHashingContext::new(self.sess, &resolutions.definitions, &*resolutions.cstore) + pub fn with_stable_hashing_context( + self, + f: impl FnOnce(StableHashingContext<'_>) -> R, + ) -> R { + let definitions = self.definitions_untracked(); + let hcx = StableHashingContext::new(self.sess, &*definitions, &*self.cstore); + f(hcx) } #[inline(always)] - pub fn create_no_span_stable_hashing_context(self) -> StableHashingContext<'tcx> { - let resolutions = &self.gcx.untracked_resolutions; - StableHashingContext::ignore_spans( - self.sess, - &resolutions.definitions, - &*resolutions.cstore, - ) + pub fn with_no_span_stable_hashing_context( + self, + f: impl FnOnce(StableHashingContext<'_>) -> R, + ) -> R { + let definitions = self.definitions_untracked(); + let hcx = StableHashingContext::ignore_spans(self.sess, &*definitions, &*self.cstore); + f(hcx) } pub fn serialize_query_result_cache(self, encoder: &mut FileEncoder) -> FileEncodeResult { @@ -2237,7 +2304,7 @@ impl<'tcx> TyCtxt<'tcx> { #[allow(rustc::usage_of_ty_tykind)] #[inline] pub fn mk_ty(self, st: TyKind<'tcx>) -> Ty<'tcx> { - self.interners.intern_ty(st, self.sess, &self.gcx.untracked_resolutions) + self.interners.intern_ty(st, self.sess, &self.definitions.read(), &*self.cstore) } #[inline] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ec416722c214e..bf830edf798c0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -29,18 +29,22 @@ use crate::ty::fast_reject::SimplifiedType; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::util::Discr; use rustc_ast as ast; +use rustc_ast::node_id::NodeMap; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::intern::{Interned, WithStableHash}; +use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::sync::Lrc; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; -use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; +use rustc_hir::def::{CtorKind, CtorOf, DefKind, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap}; use rustc_hir::Node; +use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; -use rustc_session::cstore::CrateStoreDyn; +use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::abi::Align; @@ -126,10 +130,25 @@ mod sty; pub type RegisteredTools = FxHashSet; +/// Pointers to parts of the AST to index it. +/// We use OwningRef to release memory when all the owners have been taken. +pub enum AstOwner { + NonOwner, + Synthetic(LocalDefId), + Crate(Lrc), + Item(OwningRef, ast::Item>), + AssocItem(OwningRef, ast::AssocItem>, ast::visit::AssocCtxt), + ForeignItem(OwningRef, ast::ForeignItem>), +} + +impl AstOwner { + pub fn expect_crate(&self) -> &Lrc { + if let AstOwner::Crate(c) = self { c } else { panic!() } + } +} + #[derive(Debug)] pub struct ResolverOutputs { - pub definitions: rustc_hir::definitions::Definitions, - pub cstore: Box, pub visibilities: FxHashMap, /// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error. pub has_pub_restricted: bool, @@ -151,6 +170,30 @@ pub struct ResolverOutputs { /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. pub confused_type_with_std_module: FxHashMap, pub registered_tools: RegisteredTools, + pub item_generics_num_lifetimes: FxHashMap, + + pub legacy_const_generic_args: FxHashMap>>, + + /// Resolutions for nodes that have a single resolution. + pub partial_res_map: NodeMap, + /// Resolutions for import nodes, which have multiple resolutions in different namespaces. + pub import_res_map: NodeMap>>>, + /// Resolutions for labels (node IDs of their corresponding blocks or loops). + pub label_res_map: NodeMap, + /// Resolutions for lifetimes. + pub lifetimes_res_map: NodeMap, + /// Lifetime parameters that lowering will have to introduce. + pub extra_lifetime_params_map: NodeMap>, + + pub next_node_id: ast::NodeId, + + pub node_id_to_def_id: FxHashMap, + pub def_id_to_node_id: IndexVec, + + pub trait_map: NodeMap>, + /// A small map keeping true kinds of built-in macros that appear to be fn-like on + /// the surface (`macro` items in libcore), but are actually attributes or derives. + pub builtin_macro_kinds: FxHashMap, } #[derive(Clone, Copy, Debug)] diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 918fe49e8e3fc..2bccf0c9fdafa 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -127,16 +127,16 @@ impl<'tcx> TyCtxt<'tcx> { /// Creates a hash of the type `Ty` which will be the same no matter what crate /// context it's calculated within. This is used by the `type_id` intrinsic. pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 { - let mut hasher = StableHasher::new(); - let mut hcx = self.create_stable_hashing_context(); - // We want the type_id be independent of the types free regions, so we // erase them. The erase_regions() call will also anonymize bound // regions, which is desirable too. let ty = self.erase_regions(ty); - hcx.while_hashing_spans(false, |hcx| ty.hash_stable(hcx, &mut hasher)); - hasher.finish() + self.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + hcx.while_hashing_spans(false, |hcx| ty.hash_stable(hcx, &mut hasher)); + hasher.finish() + }) } pub fn res_generics_def_id(self, res: Res) -> Option { diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 2bb9f48f9b7c8..74e6d405c1149 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -15,7 +15,6 @@ use spans::{CoverageSpan, CoverageSpans}; use crate::MirPass; use rustc_data_structures::graph::WithNumNodes; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_index::vec::IndexVec; use rustc_middle::hir; @@ -576,12 +575,6 @@ fn get_body_span<'tcx>( fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 { // FIXME(cjgillot) Stop hashing HIR manually here. - let mut hcx = tcx.create_no_span_stable_hashing_context(); - let mut stable_hasher = StableHasher::new(); let owner = hir_body.id().hir_id.owner; - let bodies = &tcx.hir_owner_nodes(owner).unwrap().bodies; - hcx.with_hir_bodies(false, owner, bodies, |hcx| { - hir_body.value.hash_stable(hcx, &mut stable_hasher) - }); - stable_hasher.finish() + tcx.hir_owner_nodes(owner).unwrap().hash_including_bodies.to_smaller_hash() } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 5e6dabeba6da2..8a2841fdfe7f7 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -548,7 +548,7 @@ impl<'tcx> Inliner<'tcx> { ); expn_data.def_site = callee_body.span; let expn_data = - LocalExpnId::fresh(expn_data, self.tcx.create_stable_hashing_context()); + self.tcx.with_stable_hashing_context(|hcx| LocalExpnId::fresh(expn_data, hcx)); let mut integrator = Integrator { args: &args, new_locals: Local::new(caller_body.local_decls.len()).., diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index f2f895367ff82..f34440cb5ef96 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -655,12 +655,11 @@ impl<'a, 'tcx> Decodable> for ExpnId { #[cfg(debug_assertions)] { use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; - let mut hcx = decoder.tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - hcx.while_hashing_spans(true, |hcx| { - expn_id.expn_data().hash_stable(hcx, &mut hasher) + let local_hash: u64 = decoder.tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + expn_id.expn_data().hash_stable(&mut hcx, &mut hasher); + hasher.finish() }); - let local_hash: u64 = hasher.finish(); debug_assert_eq!(hash.local_hash(), local_hash); } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index bc82b0053b9ef..d3fae34a4cc6d 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -296,11 +296,12 @@ macro_rules! define_queries { .and_then(|def_id| def_id.as_local()) .and_then(|def_id| tcx.hir().opt_def_kind(def_id)); let hash = || { - let mut hcx = tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher); - key.hash_stable(&mut hcx, &mut hasher); - hasher.finish::() + tcx.with_stable_hashing_context(|mut hcx|{ + let mut hasher = StableHasher::new(); + std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher); + key.hash_stable(&mut hcx, &mut hasher); + hasher.finish::() + }) }; QueryStackFrame::new(name, description, span, def_kind, hash) diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index c274c2cc26c15..8c2ea7f54c835 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -131,12 +131,11 @@ where #[inline(always)] default fn to_fingerprint(&self, tcx: Ctxt) -> Fingerprint { - let mut hcx = tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - - self.hash_stable(&mut hcx, &mut hasher); - - hasher.finish() + tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + self.hash_stable(&mut hcx, &mut hasher); + hasher.finish() + }) } #[inline(always)] diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index f7655e55d3485..80b7e3a0f3eec 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -43,6 +43,7 @@ rustc_index::newtype_index! { impl DepNodeIndex { pub const INVALID: DepNodeIndex = DepNodeIndex::MAX; pub const SINGLETON_DEPENDENCYLESS_ANON_NODE: DepNodeIndex = DepNodeIndex::from_u32(0); + pub const FOREVER_RED_NODE: DepNodeIndex = DepNodeIndex::from_u32(1); } impl std::convert::From for QueryInvocationId { @@ -124,6 +125,8 @@ impl DepGraph { record_stats, ); + let colors = DepNodeColorMap::new(prev_graph_node_count); + // Instantiate a dependy-less node only once for anonymous queries. let _green_node_index = current.intern_new_node( profiler, @@ -133,6 +136,18 @@ impl DepGraph { ); debug_assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE); + // Instantiate a dependy-less red node only once for anonymous queries. + let (_red_node_index, _prev_and_index) = current.intern_node( + profiler, + &prev_graph, + DepNode { kind: DepKind::NULL, hash: Fingerprint::ZERO.into() }, + smallvec![], + None, + false, + ); + debug_assert_eq!(_red_node_index, DepNodeIndex::FOREVER_RED_NODE); + debug_assert!(matches!(_prev_and_index, None | Some((_, DepNodeColor::Red)))); + DepGraph { data: Some(Lrc::new(DepGraphData { previous_work_products: prev_work_products, @@ -140,7 +155,7 @@ impl DepGraph { current, processed_side_effects: Default::default(), previous: prev_graph, - colors: DepNodeColorMap::new(prev_graph_node_count), + colors, debug_loaded_from_disk: Default::default(), })), virtual_dep_node_index: Lrc::new(AtomicU32::new(0)), @@ -328,10 +343,8 @@ impl DepGraph { let dcx = cx.dep_context(); let hashing_timer = dcx.profiler().incr_result_hashing(); - let current_fingerprint = hash_result.map(|f| { - let mut hcx = dcx.create_stable_hashing_context(); - f(&mut hcx, &result) - }); + let current_fingerprint = + hash_result.map(|f| dcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, &result))); let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks; @@ -967,6 +980,9 @@ impl CurrentDepGraph { let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64; let mut stable_hasher = StableHasher::new(); nanos.hash(&mut stable_hasher); + let anon_id_seed = stable_hasher.finish(); + // We rely on the fact that `anon_id_seed` is not zero when creating static nodes. + debug_assert_ne!(anon_id_seed, Fingerprint::ZERO); #[cfg(debug_assertions)] let forbidden_edge = match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { @@ -1002,7 +1018,7 @@ impl CurrentDepGraph { ) }), prev_index_to_index: Lock::new(IndexVec::from_elem_n(None, prev_graph_node_count)), - anon_id_seed: stable_hasher.finish(), + anon_id_seed, #[cfg(debug_assertions)] forbidden_edge, total_read_count: AtomicU64::new(0), diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 5907ae309ca37..345ada263e4d2 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -23,7 +23,7 @@ pub trait DepContext: Copy { type DepKind: self::DepKind; /// Create a hashing context for hashing new results. - fn create_stable_hashing_context(&self) -> StableHashingContext<'_>; + fn with_stable_hashing_context(&self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R; /// Access the DepGraph. fn dep_graph(&self) -> &DepGraph; diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index 03ef8578eb701..31ec47c119aa7 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -1,4 +1,5 @@ use crate::ich; + use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sorted_map::SortedMap; @@ -117,13 +118,13 @@ impl<'a> StableHashingContext<'a> { &mut self, hash_bodies: bool, owner: LocalDefId, - bodies: &'a SortedMap>, - f: impl FnOnce(&mut Self), + bodies: &SortedMap>, + f: impl FnOnce(&mut StableHashingContext<'_>), ) { - let prev = self.body_resolver; - self.body_resolver = BodyResolver::Traverse { hash_bodies, owner, bodies }; - f(self); - self.body_resolver = prev; + f(&mut StableHashingContext { + body_resolver: BodyResolver::Traverse { hash_bodies, owner, bodies }, + ..self.clone() + }); } #[inline] diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 700290d67a41b..3d015c1ad4e76 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -540,8 +540,7 @@ fn incremental_verify_ich( debug!("BEGIN verify_ich({:?})", dep_node); let new_hash = query.hash_result.map_or(Fingerprint::ZERO, |f| { - let mut hcx = tcx.create_stable_hashing_context(); - f(&mut hcx, result) + tcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result)) }); let old_hash = tcx.dep_graph().prev_fingerprint_of(dep_node); debug!("END verify_ich({:?})", dep_node); diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index bd27c16c732a9..1127a42e600fb 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -13,7 +13,6 @@ tracing = "0.1" rustc_ast = { path = "../rustc_ast" } rustc_arena = { path = "../rustc_arena" } rustc_middle = { path = "../rustc_middle" } -rustc_ast_lowering = { path = "../rustc_ast_lowering" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_resolve/src/access_levels.rs b/compiler/rustc_resolve/src/access_levels.rs index 61a9b644cb8f5..3fba923d9fdf4 100644 --- a/compiler/rustc_resolve/src/access_levels.rs +++ b/compiler/rustc_resolve/src/access_levels.rs @@ -5,7 +5,6 @@ use rustc_ast::Crate; use rustc_ast::EnumDef; use rustc_ast::ForeignMod; use rustc_ast::NodeId; -use rustc_ast_lowering::ResolverAstLowering; use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_middle::middle::privacy::AccessLevel; diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 650a0dc82ce23..7ff245e380bac 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -16,7 +16,6 @@ use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind}; use rustc_ast::{Block, Fn, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId}; -use rustc_ast_lowering::ResolverAstLowering; use rustc_attr as attr; use rustc_data_structures::sync::Lrc; use rustc_errors::{struct_span_err, Applicability}; @@ -27,7 +26,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_metadata::creader::LoadedMacro; use rustc_middle::bug; use rustc_middle::metadata::ModChild; -use rustc_middle::ty; +use rustc_middle::ty::{self, DefIdTree}; use rustc_session::cstore::CrateStore; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind}; use rustc_span::source_map::{respan, Spanned}; @@ -112,10 +111,7 @@ impl<'a> Resolver<'a> { loop { match self.get_module(def_id) { Some(module) => return module, - None => { - def_id.index = - self.def_key(def_id).parent.expect("non-root `DefId` without parent") - } + None => def_id = self.parent(def_id).expect("non-root `DefId` without parent"), } } } diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 6503b97a1d31f..b88c527cdc334 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -30,7 +30,6 @@ use crate::Resolver; use rustc_ast as ast; use rustc_ast::node_id::NodeMap; use rustc_ast::visit::{self, Visitor}; -use rustc_ast_lowering::ResolverAstLowering; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, MultiSpan}; use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_IMPORTS}; diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 1e8cca6122c4c..6c9894d20d1ff 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -2,7 +2,6 @@ use crate::{ImplTraitContext, Resolver}; use rustc_ast::visit::{self, FnKind}; use rustc_ast::walk_list; use rustc_ast::*; -use rustc_ast_lowering::ResolverAstLowering; use rustc_expand::expand::AstFragment; use rustc_hir::def_id::LocalDefId; use rustc_hir::definitions::*; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 53bd589fdcde1..8d4fdf5812179 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -14,11 +14,10 @@ use crate::{ResolutionError, Resolver, Segment, UseError}; use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; -use rustc_ast_lowering::{LifetimeRes, ResolverAstLowering}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::DiagnosticId; use rustc_hir::def::Namespace::{self, *}; -use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS}; +use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::definitions::DefPathData; use rustc_hir::{PrimTy, TraitCandidate}; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index dbc4f337ad3b5..6a1145dcbdda9 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -29,17 +29,16 @@ use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::node_id::NodeMap; use rustc_ast::{self as ast, NodeId, CRATE_NODE_ID}; use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path}; -use rustc_ast_lowering::{LifetimeRes, ResolverAstLowering}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed}; use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind}; use rustc_hir::def::Namespace::*; -use rustc_hir::def::{self, CtorOf, DefKind, PartialRes}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefPathHash, LocalDefId}; +use rustc_hir::def::{self, CtorOf, DefKind, LifetimeRes, PartialRes}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; -use rustc_hir::definitions::{DefKey, DefPathData, Definitions}; +use rustc_hir::definitions::{DefPathData, Definitions}; use rustc_hir::TraitCandidate; use rustc_index::vec::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; @@ -49,7 +48,7 @@ use rustc_middle::span_bug; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools, ResolverOutputs}; use rustc_query_system::ich::StableHashingContext; -use rustc_session::cstore::{CrateStore, MetadataLoaderDyn}; +use rustc_session::cstore::{CrateStore, CrateStoreDyn, MetadataLoaderDyn}; use rustc_session::lint::LintBuffer; use rustc_session::Session; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; @@ -1118,85 +1117,15 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> { } } -/// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that -/// the resolver is no longer needed as all the relevant information is inline. -impl ResolverAstLowering for Resolver<'_> { - fn def_key(&self, id: DefId) -> DefKey { - if let Some(id) = id.as_local() { - self.definitions.def_key(id) - } else { - self.cstore().def_key(id) - } - } - - #[inline] - fn def_span(&self, id: LocalDefId) -> Span { - self.definitions.def_span(id) - } - - fn item_generics_num_lifetimes(&self, def_id: DefId) -> usize { - if let Some(def_id) = def_id.as_local() { - self.item_generics_num_lifetimes[&def_id] - } else { - self.cstore().item_generics_num_lifetimes(def_id, self.session) - } - } - - fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option> { - self.legacy_const_generic_args(expr) - } - - fn get_partial_res(&self, id: NodeId) -> Option { - self.partial_res_map.get(&id).cloned() - } - - fn get_import_res(&self, id: NodeId) -> PerNS> { - self.import_res_map.get(&id).cloned().unwrap_or_default() - } - - fn get_label_res(&self, id: NodeId) -> Option { - self.label_res_map.get(&id).cloned() - } - - fn get_lifetime_res(&self, id: NodeId) -> Option { - self.lifetimes_res_map.get(&id).copied() - } - - fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> { - self.extra_lifetime_params_map.remove(&id).unwrap_or_default() - } - - fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { - StableHashingContext::new(self.session, &self.definitions, self.crate_loader.cstore()) - } - - fn definitions(&self) -> &Definitions { - &self.definitions - } - - fn next_node_id(&mut self) -> NodeId { - self.next_node_id() - } - - fn take_trait_map(&mut self, node: NodeId) -> Option> { - self.trait_map.remove(&node) - } - +impl Resolver<'_> { fn opt_local_def_id(&self, node: NodeId) -> Option { self.node_id_to_def_id.get(&node).copied() } - fn local_def_id(&self, node: NodeId) -> LocalDefId { + pub fn local_def_id(&self, node: NodeId) -> LocalDefId { self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node)) } - fn def_path_hash(&self, def_id: DefId) -> DefPathHash { - match def_id.as_local() { - Some(def_id) => self.definitions.def_path_hash(def_id), - None => self.cstore().def_path_hash(def_id), - } - } - /// Adds a definition with a parent definition. fn create_def( &mut self, @@ -1228,8 +1157,12 @@ impl ResolverAstLowering for Resolver<'_> { def_id } - fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind { - self.builtin_macro_kinds.get(&def_id).copied().unwrap_or(MacroKind::Bang) + fn item_generics_num_lifetimes(&self, def_id: DefId) -> usize { + if let Some(def_id) = def_id.as_local() { + self.item_generics_num_lifetimes[&def_id] + } else { + self.cstore().item_generics_num_lifetimes(def_id, self.session) + } } } @@ -1435,9 +1368,10 @@ impl<'a> Resolver<'a> { Default::default() } - pub fn into_outputs(self) -> ResolverOutputs { + pub fn into_outputs(self) -> (Definitions, Box, ResolverOutputs) { let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect(); let definitions = self.definitions; + let cstore = Box::new(self.crate_loader.into_cstore()); let visibilities = self.visibilities; let has_pub_restricted = self.has_pub_restricted; let extern_crate_map = self.extern_crate_map; @@ -1448,9 +1382,7 @@ impl<'a> Resolver<'a> { let main_def = self.main_def; let confused_type_with_std_module = self.confused_type_with_std_module; let access_levels = self.access_levels; - ResolverOutputs { - definitions, - cstore: Box::new(self.crate_loader.into_cstore()), + let resolutions = ResolverOutputs { visibilities, has_pub_restricted, access_levels, @@ -1469,15 +1401,27 @@ impl<'a> Resolver<'a> { proc_macros, confused_type_with_std_module, registered_tools: self.registered_tools, - } + item_generics_num_lifetimes: self.item_generics_num_lifetimes, + legacy_const_generic_args: self.legacy_const_generic_args, + partial_res_map: self.partial_res_map, + import_res_map: self.import_res_map, + label_res_map: self.label_res_map, + lifetimes_res_map: self.lifetimes_res_map, + extra_lifetime_params_map: self.extra_lifetime_params_map, + next_node_id: self.next_node_id, + node_id_to_def_id: self.node_id_to_def_id, + def_id_to_node_id: self.def_id_to_node_id, + trait_map: self.trait_map, + builtin_macro_kinds: self.builtin_macro_kinds, + }; + (definitions, cstore, resolutions) } - pub fn clone_outputs(&self) -> ResolverOutputs { + pub fn clone_outputs(&self) -> (Definitions, Box, ResolverOutputs) { let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect(); - ResolverOutputs { - definitions: self.definitions.clone(), - access_levels: self.access_levels.clone(), - cstore: Box::new(self.cstore().clone()), + let definitions = self.definitions.clone(); + let cstore = Box::new(self.cstore().clone()); + let resolutions = ResolverOutputs { visibilities: self.visibilities.clone(), has_pub_restricted: self.has_pub_restricted, extern_crate_map: self.extern_crate_map.clone(), @@ -1495,7 +1439,25 @@ impl<'a> Resolver<'a> { proc_macros, confused_type_with_std_module: self.confused_type_with_std_module.clone(), registered_tools: self.registered_tools.clone(), - } + access_levels: self.access_levels.clone(), + item_generics_num_lifetimes: self.item_generics_num_lifetimes.clone(), + legacy_const_generic_args: self.legacy_const_generic_args.clone(), + partial_res_map: self.partial_res_map.clone(), + import_res_map: self.import_res_map.clone(), + label_res_map: self.label_res_map.clone(), + lifetimes_res_map: self.lifetimes_res_map.clone(), + extra_lifetime_params_map: self.extra_lifetime_params_map.clone(), + next_node_id: self.next_node_id.clone(), + node_id_to_def_id: self.node_id_to_def_id.clone(), + def_id_to_node_id: self.def_id_to_node_id.clone(), + trait_map: self.trait_map.clone(), + builtin_macro_kinds: self.builtin_macro_kinds.clone(), + }; + (definitions, cstore, resolutions) + } + + fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { + StableHashingContext::new(self.session, &self.definitions, self.crate_loader.cstore()) } pub fn cstore(&self) -> &CStore { diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 01f0b11f1ac3b..0a10bbf315aab 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -7,7 +7,6 @@ use crate::{BuiltinMacroState, Determinacy}; use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet}; use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment}; use rustc_ast::{self as ast, Inline, ItemKind, ModKind, NodeId}; -use rustc_ast_lowering::ResolverAstLowering; use rustc_ast_pretty::pprust; use rustc_attr::StabilityLevel; use rustc_data_structures::fx::FxHashSet; diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index b3773d5be2874..707cfb06bcab9 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -96,47 +96,48 @@ fn get_symbol_hash<'tcx>( let substs = instance.substs; debug!("get_symbol_hash(def_id={:?}, parameters={:?})", def_id, substs); - let mut hasher = StableHasher::new(); - let mut hcx = tcx.create_stable_hashing_context(); - - record_time(&tcx.sess.perf_stats.symbol_hash_time, || { - // the main symbol name is not necessarily unique; hash in the - // compiler's internal def-path, guaranteeing each symbol has a - // truly unique path - tcx.def_path_hash(def_id).hash_stable(&mut hcx, &mut hasher); - - // Include the main item-type. Note that, in this case, the - // assertions about `needs_subst` may not hold, but this item-type - // ought to be the same for every reference anyway. - assert!(!item_type.has_erasable_regions()); - hcx.while_hashing_spans(false, |hcx| { - item_type.hash_stable(hcx, &mut hasher); - - // If this is a function, we hash the signature as well. - // This is not *strictly* needed, but it may help in some - // situations, see the `run-make/a-b-a-linker-guard` test. - if let ty::FnDef(..) = item_type.kind() { - item_type.fn_sig(tcx).hash_stable(hcx, &mut hasher); - } + tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + + record_time(&tcx.sess.perf_stats.symbol_hash_time, || { + // the main symbol name is not necessarily unique; hash in the + // compiler's internal def-path, guaranteeing each symbol has a + // truly unique path + tcx.def_path_hash(def_id).hash_stable(&mut hcx, &mut hasher); + + // Include the main item-type. Note that, in this case, the + // assertions about `needs_subst` may not hold, but this item-type + // ought to be the same for every reference anyway. + assert!(!item_type.has_erasable_regions()); + hcx.while_hashing_spans(false, |hcx| { + item_type.hash_stable(hcx, &mut hasher); + + // If this is a function, we hash the signature as well. + // This is not *strictly* needed, but it may help in some + // situations, see the `run-make/a-b-a-linker-guard` test. + if let ty::FnDef(..) = item_type.kind() { + item_type.fn_sig(tcx).hash_stable(hcx, &mut hasher); + } - // also include any type parameters (for generic items) - substs.hash_stable(hcx, &mut hasher); + // also include any type parameters (for generic items) + substs.hash_stable(hcx, &mut hasher); - if let Some(instantiating_crate) = instantiating_crate { - tcx.def_path_hash(instantiating_crate.as_def_id()) - .stable_crate_id() - .hash_stable(hcx, &mut hasher); - } + if let Some(instantiating_crate) = instantiating_crate { + tcx.def_path_hash(instantiating_crate.as_def_id()) + .stable_crate_id() + .hash_stable(hcx, &mut hasher); + } - // We want to avoid accidental collision between different types of instances. - // Especially, `VtableShim`s and `ReifyShim`s may overlap with their original - // instances without this. - discriminant(&instance.def).hash_stable(hcx, &mut hasher); + // We want to avoid accidental collision between different types of instances. + // Especially, `VtableShim`s and `ReifyShim`s may overlap with their original + // instances without this. + discriminant(&instance.def).hash_stable(hcx, &mut hasher); + }); }); - }); - // 64 bits should be enough to avoid collisions. - hasher.finish::() + // 64 bits should be enough to avoid collisions. + hasher.finish::() + }) } // Follow C++ namespace-mangling style, see diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index cd196a0184799..3c708aba606d4 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -38,7 +38,6 @@ extern crate tracing; // Dependencies listed in Cargo.toml do not need `extern crate`. extern crate rustc_ast; -extern crate rustc_ast_lowering; extern crate rustc_ast_pretty; extern crate rustc_attr; extern crate rustc_const_eval; diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 23d947c4d7227..588b7fb8ab66d 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -49,7 +49,8 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { None, None, ); - let expn_id = LocalExpnId::fresh(expn_data, self.cx.tcx.create_stable_hashing_context()); + let expn_id = + self.cx.tcx.with_stable_hashing_context(|hcx| LocalExpnId::fresh(expn_data, hcx)); let span = DUMMY_SP.fresh_expansion(expn_id); let is_empty = rustc_driver::catch_fatal_errors(|| { diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs index 68e10e3a18c7e..ee12933abac1f 100644 --- a/src/librustdoc/passes/collect_intra_doc_links/early.rs +++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs @@ -5,7 +5,6 @@ use crate::passes::collect_intra_doc_links::PreprocessedMarkdownLink; use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast::{self as ast, ItemKind}; -use rustc_ast_lowering::ResolverAstLowering; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::Namespace::*; use rustc_hir::def::{DefKind, Namespace, Res}; diff --git a/src/test/incremental/hash-module-order.rs b/src/test/incremental/hash-module-order.rs index fe9af9eeb370c..a302fa8b7d2d6 100644 --- a/src/test/incremental/hash-module-order.rs +++ b/src/test/incremental/hash-module-order.rs @@ -19,7 +19,7 @@ mod foo { } #[cfg(rpass2)] -#[rustc_clean(cfg="rpass2",except="hir_owner")] +#[rustc_clean(cfg="rpass2",except="hir_owner,hir_owner_nodes")] mod foo { struct Second; struct First; diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index 717e9e8c8e111..14d939e43620e 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -404,7 +404,7 @@ trait TraitAddUnsafeModifier { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner", cfg="cfail5")] +#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddUnsafeModifier { #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] @@ -429,7 +429,7 @@ trait TraitAddExternModifier { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner", cfg="cfail5")] +#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddExternModifier { #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] diff --git a/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr b/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr index f5252084d6884..b966ccae81e47 100644 --- a/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr +++ b/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr @@ -143,36 +143,36 @@ LL | T: B + Trait + Copy, | ++++++++++++++ error[E0382]: use of moved value: `t` - --> $DIR/use_of_moved_value_copy_suggestions.rs:83:9 + --> $DIR/use_of_moved_value_copy_suggestions.rs:75:9 | -LL | fn existing_colon_in_where(t: T) - | - move occurs because `t` has type `T`, which does not implement the `Copy` trait -... +LL | fn existing_colon(t: T) { + | - move occurs because `t` has type `T`, which does not implement the `Copy` trait +LL | LL | [t, t]; | - ^ value used here after move | | | value moved here | -help: consider further restricting this bound +help: consider restricting type parameter `T` | -LL | T: Copy, - | ++++ +LL | fn existing_colon(t: T) { + | ++++ error[E0382]: use of moved value: `t` - --> $DIR/use_of_moved_value_copy_suggestions.rs:75:9 + --> $DIR/use_of_moved_value_copy_suggestions.rs:83:9 | -LL | fn existing_colon(t: T) { - | - move occurs because `t` has type `T`, which does not implement the `Copy` trait -LL | +LL | fn existing_colon_in_where(t: T) + | - move occurs because `t` has type `T`, which does not implement the `Copy` trait +... LL | [t, t]; | - ^ value used here after move | | | value moved here | -help: consider restricting type parameter `T` +help: consider further restricting this bound | -LL | fn existing_colon(t: T) { - | ++++ +LL | T: Copy, + | ++++ error: aborting due to 11 previous errors diff --git a/src/test/ui/proc-macro/attribute-with-error.stderr b/src/test/ui/proc-macro/attribute-with-error.stderr index 127c49957c1e5..7f3a7e670b9b7 100644 --- a/src/test/ui/proc-macro/attribute-with-error.stderr +++ b/src/test/ui/proc-macro/attribute-with-error.stderr @@ -1,11 +1,3 @@ -error[E0308]: mismatched types - --> $DIR/attribute-with-error.rs:25:22 - | -LL | let a: i32 = "foo"; - | --- ^^^^^ expected `i32`, found `&str` - | | - | expected due to this - error[E0308]: mismatched types --> $DIR/attribute-with-error.rs:10:18 | @@ -22,6 +14,14 @@ LL | let b: i32 = "f'oo"; | | | expected due to this +error[E0308]: mismatched types + --> $DIR/attribute-with-error.rs:25:22 + | +LL | let a: i32 = "foo"; + | --- ^^^^^ expected `i32`, found `&str` + | | + | expected due to this + error[E0308]: mismatched types --> $DIR/attribute-with-error.rs:35:22 | diff --git a/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr b/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr index 229c4b824f275..a763eb6f2f854 100644 --- a/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr +++ b/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr @@ -1,3 +1,22 @@ +error[E0277]: `::Item` doesn't implement `Debug` + --> $DIR/impl-trait-with-missing-bounds.rs:6:13 + | +LL | qux(constraint); + | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call + | + = help: the trait `Debug` is not implemented for `::Item` +note: required by a bound in `qux` + --> $DIR/impl-trait-with-missing-bounds.rs:50:16 + | +LL | fn qux(_: impl std::fmt::Debug) {} + | ^^^^^^^^^^^^^^^ required by this bound in `qux` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | fn foo(constraints: I) where ::Item: Debug { + | +++++++++++++ ~ ++++++++++++++++++++++++++++++++++ + error[E0277]: `::Item` doesn't implement `Debug` --> $DIR/impl-trait-with-missing-bounds.rs:14:13 | @@ -74,25 +93,6 @@ help: introduce a type parameter with a trait bound instead of using `impl Trait LL | fn bak(constraints: I) where ::Item: Debug { | +++++++++++++++++++++++++++++++ ~ ++++++++++++++++++++++++++++++++++ -error[E0277]: `::Item` doesn't implement `Debug` - --> $DIR/impl-trait-with-missing-bounds.rs:6:13 - | -LL | qux(constraint); - | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | | - | required by a bound introduced by this call - | - = help: the trait `Debug` is not implemented for `::Item` -note: required by a bound in `qux` - --> $DIR/impl-trait-with-missing-bounds.rs:50:16 - | -LL | fn qux(_: impl std::fmt::Debug) {} - | ^^^^^^^^^^^^^^^ required by this bound in `qux` -help: introduce a type parameter with a trait bound instead of using `impl Trait` - | -LL | fn foo(constraints: I) where ::Item: Debug { - | +++++++++++++ ~ ++++++++++++++++++++++++++++++++++ - error[E0277]: `::Item` doesn't implement `Debug` --> $DIR/impl-trait-with-missing-bounds.rs:45:13 | diff --git a/src/test/ui/suggestions/suggest-ref-macro.stderr b/src/test/ui/suggestions/suggest-ref-macro.stderr index b0ac770c06f0f..84cbc93571a71 100644 --- a/src/test/ui/suggestions/suggest-ref-macro.stderr +++ b/src/test/ui/suggestions/suggest-ref-macro.stderr @@ -1,3 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/suggest-ref-macro.rs:8:1 + | +LL | #[hello] + | ^^^^^^^^ + | | + | expected `&mut i32`, found integer + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/suggest-ref-macro.rs:8:1 + | +LL | #[hello] + | _-^^^^^^^ +LL | | fn abc() {} +LL | | +LL | | fn x(_: &mut i32) {} +LL | | +LL | | macro_rules! bla { + | |_____________- + = note: this error originates in the attribute macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + error[E0308]: mismatched types --> $DIR/suggest-ref-macro.rs:15:11 | @@ -36,28 +58,6 @@ note: function defined here LL | fn x(_: &mut i32) {} | ^ ----------- -error[E0308]: mismatched types - --> $DIR/suggest-ref-macro.rs:8:1 - | -LL | #[hello] - | ^^^^^^^^ - | | - | expected `&mut i32`, found integer - | arguments to this function are incorrect - | -note: function defined here - --> $DIR/suggest-ref-macro.rs:8:1 - | -LL | #[hello] - | _-^^^^^^^ -LL | | fn abc() {} -LL | | -LL | | fn x(_: &mut i32) {} -LL | | -LL | | macro_rules! bla { - | |_____________- - = note: this error originates in the attribute macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) - error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr index c242a7de7abfb..11650a28563cd 100644 --- a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr @@ -1,3 +1,20 @@ +error[E0277]: the trait bound `U1: Copy` is not satisfied + --> $DIR/union-derive-clone.rs:6:10 + | +LL | #[derive(Clone)] + | ^^^^^ the trait `Copy` is not implemented for `U1` + | +note: required by a bound in `AssertParamIsCopy` + --> $SRC_DIR/core/src/clone.rs:LL:COL + | +LL | pub struct AssertParamIsCopy { + | ^^^^ required by this bound in `AssertParamIsCopy` + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `U1` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + error[E0599]: the method `clone` exists for union `U5`, but its trait bounds were not satisfied --> $DIR/union-derive-clone.rs:38:15 | @@ -26,23 +43,6 @@ help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` LL | #[derive(Clone, Copy)] | -error[E0277]: the trait bound `U1: Copy` is not satisfied - --> $DIR/union-derive-clone.rs:6:10 - | -LL | #[derive(Clone)] - | ^^^^^ the trait `Copy` is not implemented for `U1` - | -note: required by a bound in `AssertParamIsCopy` - --> $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | pub struct AssertParamIsCopy { - | ^^^^ required by this bound in `AssertParamIsCopy` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider annotating `U1` with `#[derive(Copy)]` - | -LL | #[derive(Copy)] - | - error: aborting due to 2 previous errors Some errors have detailed explanations: E0277, E0599. diff --git a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr index c242a7de7abfb..11650a28563cd 100644 --- a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr @@ -1,3 +1,20 @@ +error[E0277]: the trait bound `U1: Copy` is not satisfied + --> $DIR/union-derive-clone.rs:6:10 + | +LL | #[derive(Clone)] + | ^^^^^ the trait `Copy` is not implemented for `U1` + | +note: required by a bound in `AssertParamIsCopy` + --> $SRC_DIR/core/src/clone.rs:LL:COL + | +LL | pub struct AssertParamIsCopy { + | ^^^^ required by this bound in `AssertParamIsCopy` + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `U1` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + error[E0599]: the method `clone` exists for union `U5`, but its trait bounds were not satisfied --> $DIR/union-derive-clone.rs:38:15 | @@ -26,23 +43,6 @@ help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` LL | #[derive(Clone, Copy)] | -error[E0277]: the trait bound `U1: Copy` is not satisfied - --> $DIR/union-derive-clone.rs:6:10 - | -LL | #[derive(Clone)] - | ^^^^^ the trait `Copy` is not implemented for `U1` - | -note: required by a bound in `AssertParamIsCopy` - --> $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | pub struct AssertParamIsCopy { - | ^^^^ required by this bound in `AssertParamIsCopy` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider annotating `U1` with `#[derive(Copy)]` - | -LL | #[derive(Copy)] - | - error: aborting due to 2 previous errors Some errors have detailed explanations: E0277, E0599.