From 294510e1bb7e03bd462f6a6db2fab5f56fae1c8c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 5 Sep 2021 23:37:15 +0300 Subject: [PATCH] rustc: Remove local variable IDs from `Export`s Local variables can never be exported. --- compiler/rustc_data_structures/src/lib.rs | 1 + .../src/stable_hasher.rs | 6 +++ compiler/rustc_hir/src/def.rs | 5 +++ compiler/rustc_metadata/src/rmeta/decoder.rs | 5 +-- .../src/rmeta/decoder/cstore_impl.rs | 40 ++++++++----------- compiler/rustc_metadata/src/rmeta/encoder.rs | 9 +---- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/hir/exports.rs | 13 ++---- compiler/rustc_middle/src/query/mod.rs | 4 +- compiler/rustc_middle/src/ty/mod.rs | 2 +- .../rustc_resolve/src/build_reduced_graph.rs | 4 +- compiler/rustc_resolve/src/imports.rs | 5 +-- compiler/rustc_resolve/src/lib.rs | 3 +- compiler/rustc_serialize/src/serialize.rs | 12 ++++++ .../rustc_typeck/src/check/method/suggest.rs | 2 +- src/librustdoc/clean/inline.rs | 11 +++-- src/librustdoc/clean/types.rs | 9 +++-- src/librustdoc/visit_lib.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 4 +- 19 files changed, 71 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index d128a688e75..dd6a17b92ae 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -21,6 +21,7 @@ #![feature(iter_map_while)] #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] +#![feature(never_type)] #![feature(type_alias_impl_trait)] #![feature(new_uninit)] #![feature(nll)] diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index 18b352cf3b0..354f9dd93cc 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -209,6 +209,12 @@ impl_stable_hash_via_hash!(i128); impl_stable_hash_via_hash!(char); impl_stable_hash_via_hash!(()); +impl HashStable for ! { + fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) { + unreachable!() + } +} + impl HashStable for ::std::num::NonZeroU32 { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { self.get().hash_stable(ctx, hasher) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 853415c4173..cb668eb35e0 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -598,6 +598,11 @@ impl Res { } } + #[track_caller] + pub fn expect_non_local(self) -> Res { + self.map_id(|_| panic!("unexpected `Res::Local`")) + } + pub fn macro_kind(self) -> Option { match self { Res::Def(DefKind::Macro(kind), _) => Some(kind), diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index dd44e0cb1fa..0c284269c2f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1019,10 +1019,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } /// Iterates over each child of the given item. - fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Session) - where - F: FnMut(Export), - { + fn each_child_of_item(&self, id: DefIndex, mut callback: impl FnMut(Export), sess: &Session) { if let Some(data) = &self.root.proc_macro_data { /* If we are loading as a proc macro, we want to return the view of this crate * as a proc macro crate. diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 41839c58021..80341b16e14 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -5,7 +5,6 @@ use crate::rmeta::encoder; use rustc_ast as ast; use rustc_data_structures::stable_map::FxHashMap; -use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; @@ -326,28 +325,27 @@ pub fn provide(providers: &mut Providers) { // (restrict scope of mutable-borrow of `visible_parent_map`) { let visible_parent_map = &mut visible_parent_map; - let mut add_child = - |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| { - if child.vis != ty::Visibility::Public { - return; - } + let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| { + if child.vis != ty::Visibility::Public { + return; + } - if let Some(child) = child.res.opt_def_id() { - match visible_parent_map.entry(child) { - Entry::Occupied(mut entry) => { - // If `child` is defined in crate `cnum`, ensure - // that it is mapped to a parent in `cnum`. - if child.is_local() && entry.get().is_local() { - entry.insert(parent); - } - } - Entry::Vacant(entry) => { + if let Some(child) = child.res.opt_def_id() { + match visible_parent_map.entry(child) { + Entry::Occupied(mut entry) => { + // If `child` is defined in crate `cnum`, ensure + // that it is mapped to a parent in `cnum`. + if child.is_local() && entry.get().is_local() { entry.insert(parent); - bfs_queue.push_back(child); } } + Entry::Vacant(entry) => { + entry.insert(parent); + bfs_queue.push_back(child); + } } - }; + } + }; while let Some(def) = bfs_queue.pop_front() { for child in tcx.item_children(def).iter() { @@ -393,11 +391,7 @@ impl CStore { self.get_crate_data(def.krate).get_visibility(def.index) } - pub fn item_children_untracked( - &self, - def_id: DefId, - sess: &Session, - ) -> Vec> { + pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec { let mut result = vec![]; self.get_crate_data(def_id.krate).each_child_of_item( def_id.index, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index d8b9a479976..52c6193940d 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1065,14 +1065,7 @@ impl EncodeContext<'a, 'tcx> { // items - we encode information about proc-macros later on. let reexports = if !self.is_proc_macro { match tcx.module_exports(local_def_id) { - Some(exports) => { - let hir = self.tcx.hir(); - self.lazy( - exports - .iter() - .map(|export| export.map_id(|id| hir.local_def_id_to_hir_id(id))), - ) - } + Some(exports) => self.lazy(exports), _ => Lazy::empty(), } } else { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a487753f462..fe0bf5b64ba 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -359,7 +359,7 @@ struct RenderedConst(String); #[derive(MetadataEncodable, MetadataDecodable)] struct ModData { - reexports: Lazy<[Export]>, + reexports: Lazy<[Export]>, expansion: ExpnId, } diff --git a/compiler/rustc_middle/src/hir/exports.rs b/compiler/rustc_middle/src/hir/exports.rs index be9e38aca65..f37b976fba6 100644 --- a/compiler/rustc_middle/src/hir/exports.rs +++ b/compiler/rustc_middle/src/hir/exports.rs @@ -11,23 +11,18 @@ use std::fmt::Debug; /// This is the replacement export map. It maps a module to all of the exports /// within. -pub type ExportMap = FxHashMap>>; +pub type ExportMap = FxHashMap>; #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] -pub struct Export { +pub struct Export { /// The name of the target. pub ident: Ident, /// The resolution of the target. - pub res: Res, + /// Local variables cannot be exported, so this `Res` doesn't need the ID parameter. + pub res: Res, /// The span of the target. pub span: Span, /// The visibility of the export. /// We include non-`pub` exports for hygienic macros that get used from extern crates. pub vis: ty::Visibility, } - -impl Export { - pub fn map_id(self, map: impl FnMut(Id) -> R) -> Export { - Export { ident: self.ident, res: self.res.map_id(map), span: self.span, vis: self.vis } - } -} diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index c93996162e3..3b07be460db 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1181,7 +1181,7 @@ rustc_queries! { desc { "traits in scope at a block" } } - query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export]> { + query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export]> { desc { |tcx| "looking up items exported by `{}`", tcx.def_path_str(def_id.to_def_id()) } } @@ -1393,7 +1393,7 @@ rustc_queries! { eval_always desc { "fetching what a crate is named" } } - query item_children(def_id: DefId) -> &'tcx [Export] { + query item_children(def_id: DefId) -> &'tcx [Export] { desc { |tcx| "collecting child items of `{}`", tcx.def_path_str(def_id) } } query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index fddfd6e435c..cd1e38445ae 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -127,7 +127,7 @@ pub struct ResolverOutputs { pub extern_crate_map: FxHashMap, pub maybe_unused_trait_imports: FxHashSet, pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, - pub export_map: ExportMap, + pub export_map: ExportMap, pub glob_map: FxHashMap>, /// Extern prelude entries. The value is `true` if the entry was introduced /// via `extern crate` item and not `--extern` option or compiler built-in. diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 2ee483d850e..55f2b04c4f1 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -228,7 +228,6 @@ impl<'a> Resolver<'a> { crate fn build_reduced_graph_external(&mut self, module: Module<'a>) { let def_id = module.def_id().expect("unpopulated module without a def-id"); for child in self.cstore().item_children_untracked(def_id, self.session) { - let child = child.map_id(|_| panic!("unexpected id")); let parent_scope = ParentScope::module(module, self); BuildReducedGraphVisitor { r: self, parent_scope } .build_reduced_graph_for_external_crate_res(child); @@ -946,9 +945,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } /// Builds the reduced graph for a single item in an external crate. - fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) { + fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) { let parent = self.parent_scope.module; let Export { ident, res, vis, span } = child; + let res = res.expect_non_local(); let expansion = self.parent_scope.expansion; // Record primary definitions. match res { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index dfb6d89a0d1..d4782edbc13 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -11,7 +11,6 @@ use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBindin use rustc_ast::unwrap_or; use rustc_ast::NodeId; -use rustc_ast_lowering::ResolverAstLowering; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::ptr_key::PtrKey; use rustc_errors::{pluralize, struct_span_err, Applicability}; @@ -1387,13 +1386,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut reexports = Vec::new(); - module.for_each_child(self.r, |this, ident, _, binding| { + module.for_each_child(self.r, |_, ident, _, binding| { // Filter away ambiguous imports and anything that has def-site hygiene. // FIXME: Implement actual cross-crate hygiene. let is_good_import = binding.is_import() && !binding.is_ambiguity() && !ident.span.from_expansion(); if is_good_import || binding.is_macro_def() { - let res = binding.res().map_id(|id| this.local_def_id(id)); + let res = binding.res().expect_non_local(); if res != def::Res::Err { reexports.push(Export { ident, res, span: binding.span, vis: binding.vis }); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 6d2961db9e3..912f0bf13fe 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -14,6 +14,7 @@ #![feature(crate_visibility_modifier)] #![feature(format_args_capture)] #![feature(iter_zip)] +#![feature(never_type)] #![feature(nll)] #![recursion_limit = "256"] #![allow(rustdoc::private_intra_doc_links)] @@ -911,7 +912,7 @@ pub struct Resolver<'a> { /// `CrateNum` resolutions of `extern crate` items. extern_crate_map: FxHashMap, - export_map: ExportMap, + export_map: ExportMap, trait_map: Option>>, /// A map from nodes to anonymous modules. diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index ecc8dae0480..e32e4493726 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -366,6 +366,18 @@ direct_serialize_impls! { char emit_char read_char } +impl Encodable for ! { + fn encode(&self, _s: &mut S) -> Result<(), S::Error> { + unreachable!() + } +} + +impl Decodable for ! { + fn decode(_d: &mut D) -> Result { + unreachable!() + } +} + impl Encodable for ::std::num::NonZeroU32 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u32(self.get()) diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index a746ad7ad4b..9744f4f6483 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -1655,7 +1655,7 @@ fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] { tcx: TyCtxt<'_>, traits: &mut Vec, external_mods: &mut FxHashSet, - res: Res, + res: Res, ) { match res { Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => { diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 0c81a558430..b8633f0dcfd 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -482,12 +482,13 @@ fn build_module( // visit each node at most once. for &item in cx.tcx.item_children(did).iter() { if item.vis == ty::Visibility::Public { - if let Some(def_id) = item.res.mod_def_id() { + let res = item.res.expect_non_local(); + if let Some(def_id) = res.mod_def_id() { if did == def_id || !visited.insert(def_id) { continue; } } - if let Res::PrimTy(p) = item.res { + if let Res::PrimTy(p) = res { // Primitive types can't be inlined so generate an import instead. let prim_ty = clean::PrimitiveType::from(p); items.push(clean::Item { @@ -500,7 +501,7 @@ fn build_module( clean::ImportSource { path: clean::Path { global: false, - res: item.res, + res, segments: vec![clean::PathSegment { name: prim_ty.as_sym(), args: clean::GenericArgs::AngleBracketed { @@ -515,9 +516,7 @@ fn build_module( ))), cfg: None, }); - } else if let Some(i) = - try_inline(cx, did, None, item.res, item.ident.name, None, visited) - { + } else if let Some(i) = try_inline(cx, did, None, res, item.ident.name, None, visited) { items.extend(i) } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 5eff56a2200..8f31a42e1a2 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -212,7 +212,7 @@ impl ExternalCrate { crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> { let root = self.def_id(); - let as_keyword = |res: Res| { + let as_keyword = |res: Res| { if let Res::Def(DefKind::Mod, def_id) = res { let attrs = tcx.get_attrs(def_id); let mut keyword = None; @@ -243,7 +243,8 @@ impl ExternalCrate { hir::ItemKind::Use(ref path, hir::UseKind::Single) if item.vis.node.is_pub() => { - as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim)) + as_keyword(path.res.expect_non_local()) + .map(|(_, prim)| (id.def_id.to_def_id(), prim)) } _ => None, } @@ -274,7 +275,7 @@ impl ExternalCrate { // Also note that this does not attempt to deal with modules tagged // duplicately for the same primitive. This is handled later on when // rendering by delegating everything to a hash map. - let as_primitive = |res: Res| { + let as_primitive = |res: Res| { if let Res::Def(DefKind::Mod, def_id) = res { let attrs = tcx.get_attrs(def_id); let mut prim = None; @@ -309,7 +310,7 @@ impl ExternalCrate { hir::ItemKind::Use(ref path, hir::UseKind::Single) if item.vis.node.is_pub() => { - as_primitive(path.res).map(|(_, prim)| { + as_primitive(path.res.expect_non_local()).map(|(_, prim)| { // Pretend the primitive is local. (id.def_id.to_def_id(), prim) }) diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 3e06b417314..3e98ba08fb9 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { } } - fn visit_item(&mut self, res: Res) { + fn visit_item(&mut self, res: Res) { let def_id = res.def_id(); let vis = self.tcx.visibility(def_id); let inherited_item_level = if vis == Visibility::Public { self.prev_level } else { None }; diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index da259511fe0..3a94f472983 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -520,7 +520,7 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res { } }; } - fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export> { + fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export> { tcx.item_children(def_id) .iter() .find(|item| item.ident.name.as_str() == name) @@ -557,7 +557,7 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res { None } }); - try_res!(last).res + try_res!(last).res.expect_non_local() } /// Convenience function to get the `DefId` of a trait by path.