From 4a77a62e5611890dd275e17de0fb1694e4ff9a28 Mon Sep 17 00:00:00 2001 From: David Mládek Date: Tue, 15 Jul 2025 15:26:18 +0200 Subject: rustc_resolve: rename `check_hidden_glob_reexports` to `lint_reexports` --- compiler/rustc_resolve/src/imports.rs | 5 +---- compiler/rustc_resolve/src/lib.rs | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'compiler/rustc_resolve/src') diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 40c63a3edf3..b2f6ee6563c 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -634,10 +634,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - pub(crate) fn check_hidden_glob_reexports( - &mut self, - exported_ambiguities: FxHashSet>, - ) { + pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet>) { for module in self.arenas.local_modules().iter() { for (key, resolution) in self.resolutions(*module).borrow().iter() { let resolution = resolution.borrow(); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index c2b3451d4a1..87963295c2d 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1775,9 +1775,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let exported_ambiguities = self.tcx.sess.time("compute_effective_visibilities", || { EffectiveVisibilitiesVisitor::compute_effective_visibilities(self, krate) }); - self.tcx.sess.time("check_hidden_glob_reexports", || { - self.check_hidden_glob_reexports(exported_ambiguities) - }); + self.tcx.sess.time("lint_reexports", || self.lint_reexports(exported_ambiguities)); self.tcx .sess .time("finalize_macro_resolutions", || self.finalize_macro_resolutions(krate)); -- cgit 1.4.1-3-g733a5 From 8b868fa534a8b660a5b8051a5c883d4c15c5b70e Mon Sep 17 00:00:00 2001 From: David Mládek Date: Sat, 12 Jul 2025 16:44:34 +0200 Subject: Implement resolver warnings about reexporting private dependencies --- compiler/rustc_lint/messages.ftl | 3 ++ compiler/rustc_lint/src/early/diagnostics.rs | 3 ++ compiler/rustc_lint/src/lints.rs | 8 +++++ compiler/rustc_lint_defs/src/lib.rs | 5 +++ compiler/rustc_resolve/src/imports.rs | 25 ++++++++++++-- tests/ui/privacy/pub-priv-dep/pub-priv1.rs | 14 ++++---- tests/ui/privacy/pub-priv-dep/pub-priv1.stderr | 46 +++++++++++++++++++++++--- 7 files changed, 90 insertions(+), 14 deletions(-) (limited to 'compiler/rustc_resolve/src') diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 8d9f2385b71..183db43ca76 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -744,6 +744,9 @@ lint_redundant_semicolons_suggestion = remove {$multiple_semicolons -> *[false] this semicolon } +lint_reexport_private_dependency = + {$kind} `{$name}` from private dependency '{$krate}' is re-exported + lint_remove_mut_from_pattern = remove `mut` from the parameter lint_removed_lint = lint `{$name}` has been removed: {$reason} diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 653559009cc..f0fbf5bc81e 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -351,6 +351,9 @@ pub fn decorate_builtin_lint( } .decorate_lint(diag); } + BuiltinLintDiag::ReexportPrivateDependency { name, kind, krate } => { + lints::ReexportPrivateDependency { name, kind, krate }.decorate_lint(diag); + } BuiltinLintDiag::UnusedQualifications { removal_span } => { lints::UnusedQualifications { removal_span }.decorate_lint(diag); } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 21148833eaf..fc3c1073259 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3080,6 +3080,14 @@ pub(crate) struct HiddenGlobReexports { pub namespace: String, } +#[derive(LintDiagnostic)] +#[diag(lint_reexport_private_dependency)] +pub(crate) struct ReexportPrivateDependency { + pub name: String, + pub kind: String, + pub krate: Symbol, +} + #[derive(LintDiagnostic)] #[diag(lint_unnecessary_qualification)] pub(crate) struct UnusedQualifications { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index cd402c9234f..fe068d96b74 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -739,6 +739,11 @@ pub enum BuiltinLintDiag { /// The local binding that shadows the glob reexport. private_item_span: Span, }, + ReexportPrivateDependency { + name: String, + kind: String, + krate: Symbol, + }, UnusedQualifications { /// The span of the unnecessarily-qualified path to remove. removal_span: Span, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index b2f6ee6563c..9e8eac75fa1 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -14,8 +14,8 @@ use rustc_middle::metadata::{ModChild, Reexport}; use rustc_middle::{span_bug, ty}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ - AMBIGUOUS_GLOB_REEXPORTS, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE, - REDUNDANT_IMPORTS, UNUSED_IMPORTS, + AMBIGUOUS_GLOB_REEXPORTS, EXPORTED_PRIVATE_DEPENDENCIES, HIDDEN_GLOB_REEXPORTS, + PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_IMPORTS, UNUSED_IMPORTS, }; use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; @@ -696,6 +696,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } } + + if let NameBindingKind::Import { import, .. } = binding.kind + && let Some(binding_id) = import.id() + && let import_def_id = self.local_def_id(binding_id) + && self.effective_visibilities.is_exported(import_def_id) + && let Res::Def(reexported_kind, reexported_def_id) = binding.res() + && !matches!(reexported_kind, DefKind::Ctor(..)) + && !reexported_def_id.is_local() + && self.tcx.is_private_dep(reexported_def_id.krate) + { + self.lint_buffer.buffer_lint( + EXPORTED_PRIVATE_DEPENDENCIES, + binding_id, + binding.span, + BuiltinLintDiag::ReexportPrivateDependency { + kind: binding.res().descr().to_string(), + name: key.ident.name.to_string(), + krate: self.tcx.crate_name(reexported_def_id.krate), + }, + ); + } } } } diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs index 877029f3de3..192ca0db8bd 100644 --- a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs @@ -9,10 +9,10 @@ #![deny(exported_private_dependencies)] // This crate is a private dependency -// FIXME: This should trigger. pub extern crate priv_dep; +//~^ ERROR crate `priv_dep` from private dependency 'priv_dep' is re-exported // This crate is a public dependency -extern crate pub_dep; +pub extern crate pub_dep; // This crate is a private dependency extern crate pm; @@ -91,16 +91,16 @@ pub struct AllowedPrivType { pub allowed: OtherType, } -// FIXME: This should trigger. pub use priv_dep::m; -// FIXME: This should trigger. +//~^ ERROR macro `m` from private dependency 'priv_dep' is re-exported pub use pm::fn_like; -// FIXME: This should trigger. +//~^ ERROR macro `fn_like` from private dependency 'pm' is re-exported pub use pm::PmDerive; -// FIXME: This should trigger. +//~^ ERROR macro `PmDerive` from private dependency 'pm' is re-exported pub use pm::pm_attr; +//~^ ERROR macro `pm_attr` from private dependency 'pm' is re-exported -// FIXME: This should trigger. pub use priv_dep::E::V1; +//~^ ERROR variant `V1` from private dependency 'priv_dep' is re-exported fn main() {} diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr index adfe13424cd..9da47827be4 100644 --- a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr @@ -1,8 +1,8 @@ -error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:29:5 +error: crate `priv_dep` from private dependency 'priv_dep' is re-exported + --> $DIR/pub-priv1.rs:12:1 | -LL | pub field: OtherType, - | ^^^^^^^^^^^^^^^^^^^^ +LL | pub extern crate priv_dep; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/pub-priv1.rs:9:9 @@ -10,6 +10,42 @@ note: the lint level is defined here LL | #![deny(exported_private_dependencies)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: macro `m` from private dependency 'priv_dep' is re-exported + --> $DIR/pub-priv1.rs:94:9 + | +LL | pub use priv_dep::m; + | ^^^^^^^^^^^ + +error: macro `fn_like` from private dependency 'pm' is re-exported + --> $DIR/pub-priv1.rs:96:9 + | +LL | pub use pm::fn_like; + | ^^^^^^^^^^^ + +error: derive macro `PmDerive` from private dependency 'pm' is re-exported + --> $DIR/pub-priv1.rs:98:9 + | +LL | pub use pm::PmDerive; + | ^^^^^^^^^^^^ + +error: attribute macro `pm_attr` from private dependency 'pm' is re-exported + --> $DIR/pub-priv1.rs:100:9 + | +LL | pub use pm::pm_attr; + | ^^^^^^^^^^^ + +error: variant `V1` from private dependency 'priv_dep' is re-exported + --> $DIR/pub-priv1.rs:103:9 + | +LL | pub use priv_dep::E::V1; + | ^^^^^^^^^^^^^^^ + +error: type `OtherType` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:29:5 + | +LL | pub field: OtherType, + | ^^^^^^^^^^^^^^^^^^^^ + error: type `OtherType` from private dependency 'priv_dep' in public interface --> $DIR/pub-priv1.rs:36:5 | @@ -90,5 +126,5 @@ LL | impl PubTraitOnPrivate for OtherType {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 14 previous errors +error: aborting due to 20 previous errors -- cgit 1.4.1-3-g733a5 From 8e400f97e59211732ba67518199432ae22685cb5 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 15 Jul 2025 19:07:37 +0200 Subject: Fix ice for feature-gated cfg attributes applied to the crate Signed-off-by: Jonathan Brouwer --- compiler/rustc_attr_parsing/src/attributes/cfg.rs | 53 +++++++++++++---------- compiler/rustc_attr_parsing/src/context.rs | 27 ++++++++++-- compiler/rustc_attr_parsing/src/lib.rs | 2 +- compiler/rustc_expand/src/config.rs | 22 +++++++--- compiler/rustc_expand/src/expand.rs | 4 +- compiler/rustc_resolve/src/def_collector.rs | 4 +- 6 files changed, 74 insertions(+), 38 deletions(-) (limited to 'compiler/rustc_resolve/src') diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index a56855b3bd3..6373cf6e08a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -9,7 +9,7 @@ use rustc_session::parse::feature_err; use rustc_span::{Span, Symbol, sym}; use thin_vec::ThinVec; -use crate::context::{AcceptContext, Stage}; +use crate::context::{AcceptContext, ShouldEmit, Stage}; use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser}; use crate::{ CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics, try_gate_cfg, @@ -90,7 +90,7 @@ fn parse_cfg_entry_version( list: &MetaItemListParser<'_>, meta_span: Span, ) -> Option { - try_gate_cfg(sym::version, meta_span, cx.sess(), Some(cx.features())); + try_gate_cfg(sym::version, meta_span, cx.sess(), cx.features_option()); let Some(version) = list.single() else { cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span }); return None; @@ -119,7 +119,9 @@ fn parse_cfg_entry_target( list: &MetaItemListParser<'_>, meta_span: Span, ) -> Option { - if !cx.features().cfg_target_compact() { + if let Some(features) = cx.features_option() + && !features.cfg_target_compact() + { feature_err( cx.sess(), sym::cfg_target_compact, @@ -186,12 +188,13 @@ pub fn eval_config_entry( cfg_entry: &CfgEntry, id: NodeId, features: Option<&Features>, + emit_lints: ShouldEmit, ) -> EvalConfigResult { match cfg_entry { CfgEntry::All(subs, ..) => { let mut all = None; for sub in subs { - let res = eval_config_entry(sess, sub, id, features); + let res = eval_config_entry(sess, sub, id, features, emit_lints); // We cannot short-circuit because `eval_config_entry` emits some lints if !res.as_bool() { all.get_or_insert(res); @@ -202,7 +205,7 @@ pub fn eval_config_entry( CfgEntry::Any(subs, span) => { let mut any = None; for sub in subs { - let res = eval_config_entry(sess, sub, id, features); + let res = eval_config_entry(sess, sub, id, features, emit_lints); // We cannot short-circuit because `eval_config_entry` emits some lints if res.as_bool() { any.get_or_insert(res); @@ -214,7 +217,7 @@ pub fn eval_config_entry( }) } CfgEntry::Not(sub, span) => { - if eval_config_entry(sess, sub, id, features).as_bool() { + if eval_config_entry(sess, sub, id, features, emit_lints).as_bool() { EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span } } else { EvalConfigResult::True @@ -228,24 +231,28 @@ pub fn eval_config_entry( } } CfgEntry::NameValue { name, name_span, value, span } => { - match sess.psess.check_config.expecteds.get(name) { - Some(ExpectedValues::Some(values)) if !values.contains(&value.map(|(v, _)| v)) => { - id.emit_span_lint( - sess, - UNEXPECTED_CFGS, - *span, - BuiltinLintDiag::UnexpectedCfgValue((*name, *name_span), *value), - ); + if let ShouldEmit::ErrorsAndLints = emit_lints { + match sess.psess.check_config.expecteds.get(name) { + Some(ExpectedValues::Some(values)) + if !values.contains(&value.map(|(v, _)| v)) => + { + id.emit_span_lint( + sess, + UNEXPECTED_CFGS, + *span, + BuiltinLintDiag::UnexpectedCfgValue((*name, *name_span), *value), + ); + } + None if sess.psess.check_config.exhaustive_names => { + id.emit_span_lint( + sess, + UNEXPECTED_CFGS, + *span, + BuiltinLintDiag::UnexpectedCfgName((*name, *name_span), *value), + ); + } + _ => { /* not unexpected */ } } - None if sess.psess.check_config.exhaustive_names => { - id.emit_span_lint( - sess, - UNEXPECTED_CFGS, - *span, - BuiltinLintDiag::UnexpectedCfgName((*name, *name_span), *value), - ); - } - _ => { /* not unexpected */ } } if sess.psess.config.contains(&(*name, value.map(|(v, _)| v))) { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 567341d1517..dc80d408b27 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -223,7 +223,7 @@ impl Stage for Early { sess: &'sess Session, diag: impl for<'x> Diagnostic<'x>, ) -> ErrorGuaranteed { - if self.emit_errors { + if self.emit_errors.should_emit() { sess.dcx().emit_err(diag) } else { sess.dcx().create_err(diag).delay_as_bug() @@ -254,7 +254,7 @@ pub struct Early { /// Whether to emit errors or delay them as a bug /// For most attributes, the attribute will be parsed again in the `Late` stage and in this case the errors should be delayed /// But for some, such as `cfg`, the attribute will be removed before the `Late` stage so errors must be emitted - pub emit_errors: bool, + pub emit_errors: ShouldEmit, } /// used when parsing attributes during ast lowering pub struct Late; @@ -555,6 +555,25 @@ pub enum OmitDoc { Skip, } +#[derive(Copy, Clone)] +pub enum ShouldEmit { + /// The operation will emit errors and lints. + /// This is usually what you need. + ErrorsAndLints, + /// The operation will emit *not* errors and lints. + /// Use this if you are *sure* that this operation will be called at a different time with `ShouldEmit::Emit`. + Nothing, +} + +impl ShouldEmit { + pub fn should_emit(&self) -> bool { + match self { + ShouldEmit::ErrorsAndLints => true, + ShouldEmit::Nothing => false, + } + } +} + /// Context created once, for example as part of the ast lowering /// context, through which all attributes can be lowered. pub struct AttributeParser<'sess, S: Stage = Late> { @@ -597,7 +616,7 @@ impl<'sess> AttributeParser<'sess, Early> { tools: Vec::new(), parse_only: Some(sym), sess, - stage: Early { emit_errors: false }, + stage: Early { emit_errors: ShouldEmit::Nothing }, }; let mut parsed = p.parse_attribute_list( attrs, @@ -620,7 +639,7 @@ impl<'sess> AttributeParser<'sess, Early> { target_span: Span, target_node_id: NodeId, features: Option<&'sess Features>, - emit_errors: bool, + emit_errors: ShouldEmit, parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> T, template: &AttributeTemplate, ) -> T { diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index 2102a26108b..dc54cb6b840 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -95,7 +95,7 @@ pub use attributes::cfg_old::*; pub use attributes::util::{ find_crate_name, is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version, }; -pub use context::{AttributeParser, Early, Late, OmitDoc}; +pub use context::{AttributeParser, Early, Late, OmitDoc, ShouldEmit}; pub use lints::emit_attribute_lint; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 6922ddfd6bd..83a8d601afe 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -12,7 +12,7 @@ use rustc_ast::{ }; use rustc_attr_parsing as attr; use rustc_attr_parsing::{ - AttributeParser, CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg_attr, + AttributeParser, CFG_TEMPLATE, EvalConfigResult, ShouldEmit, eval_config_entry, parse_cfg_attr, }; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_feature::{ @@ -167,7 +167,9 @@ pub fn pre_configure_attrs(sess: &Session, attrs: &[Attribute]) -> ast::AttrVec .flat_map(|attr| strip_unconfigured.process_cfg_attr(attr)) .take_while(|attr| { !is_cfg(attr) - || strip_unconfigured.cfg_true(attr, strip_unconfigured.lint_node_id).as_bool() + || strip_unconfigured + .cfg_true(attr, strip_unconfigured.lint_node_id, ShouldEmit::Nothing) + .as_bool() }) .collect() } @@ -401,10 +403,18 @@ impl<'a> StripUnconfigured<'a> { /// Determines if a node with the given attributes should be included in this configuration. fn in_cfg(&self, attrs: &[Attribute]) -> bool { - attrs.iter().all(|attr| !is_cfg(attr) || self.cfg_true(attr, self.lint_node_id).as_bool()) + attrs.iter().all(|attr| { + !is_cfg(attr) + || self.cfg_true(attr, self.lint_node_id, ShouldEmit::ErrorsAndLints).as_bool() + }) } - pub(crate) fn cfg_true(&self, attr: &Attribute, node: NodeId) -> EvalConfigResult { + pub(crate) fn cfg_true( + &self, + attr: &Attribute, + node: NodeId, + emit_errors: ShouldEmit, + ) -> EvalConfigResult { // We need to run this to do basic validation of the attribute, such as that lits are valid, etc // FIXME(jdonszelmann) this should not be necessary in the future match validate_attr::parse_meta(&self.sess.psess, attr) { @@ -428,7 +438,7 @@ impl<'a> StripUnconfigured<'a> { attr.span, node, self.features, - true, + emit_errors, parse_cfg_attr, &CFG_TEMPLATE, ) else { @@ -436,7 +446,7 @@ impl<'a> StripUnconfigured<'a> { return EvalConfigResult::True; }; - eval_config_entry(self.sess, &cfg, self.lint_node_id, self.features) + eval_config_entry(self.sess, &cfg, self.lint_node_id, self.features, emit_errors) } /// If attributes are not allowed on expressions, emit an error for `attr` diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index f99060e9a21..79ec79a2fdf 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -13,7 +13,7 @@ use rustc_ast::{ MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token, }; use rustc_ast_pretty::pprust; -use rustc_attr_parsing::EvalConfigResult; +use rustc_attr_parsing::{EvalConfigResult, ShouldEmit}; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_errors::PResult; use rustc_feature::Features; @@ -2171,7 +2171,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { attr: ast::Attribute, pos: usize, ) -> EvalConfigResult { - let res = self.cfg().cfg_true(&attr, node.node_id()); + let res = self.cfg().cfg_true(&attr, node.node_id(), ShouldEmit::ErrorsAndLints); if res.as_bool() { // A trace attribute left in AST in place of the original `cfg` attribute. // It can later be used by lints or other diagnostics. diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 781e2ce9704..7d51fef28d3 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -2,7 +2,7 @@ use std::mem; use rustc_ast::visit::FnKind; use rustc_ast::*; -use rustc_attr_parsing::{AttributeParser, Early, OmitDoc}; +use rustc_attr_parsing::{AttributeParser, Early, OmitDoc, ShouldEmit}; use rustc_expand::expand::AstFragment; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; @@ -132,7 +132,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { &self.resolver.tcx.sess, self.resolver.tcx.features(), Vec::new(), - Early { emit_errors: false }, + Early { emit_errors: ShouldEmit::Nothing }, ); let attrs = parser.parse_attribute_list( &i.attrs, -- cgit 1.4.1-3-g733a5 From fb7aa9e4fdb88a4833274303899b9801ef924100 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 27 May 2025 15:51:47 +1000 Subject: Improve path segment joining. There are many places that join path segments with `::` to produce a string. A lot of these use `join("::")`. Many in rustdoc use `join_with_double_colon`, and a few use `.joined("..")`. One in Clippy uses `itertools::join`. A couple of them look for `kw::PathRoot` in the first segment, which can be important. This commit introduces `rustc_ast::join_path_{syms,ident}` to do the joining for everyone. `rustc_ast` is as good a location for these as any, being the earliest-running of the several crates with a `Path` type. Two functions are needed because `Ident` printing is more complex than simple `Symbol` printing. The commit also removes `join_with_double_colon`, and `estimate_item_path_byte_length` with it. There are still a handful of places that join strings with "::" that are unchanged. They are not that important: some of them are in tests, and some of them first split a path around "::" and then rejoin with "::". This fixes one test case where `{{root}}` shows up in an error message. --- compiler/rustc_ast/src/ast.rs | 55 +++++++++++++++++++++- compiler/rustc_builtin_macros/src/source_util.rs | 4 +- compiler/rustc_builtin_macros/src/test.rs | 9 +--- compiler/rustc_hir/src/hir.rs | 4 +- .../src/method/prelude_edition_lints.rs | 11 ++--- compiler/rustc_passes/src/check_attr.rs | 6 +-- compiler/rustc_resolve/src/diagnostics.rs | 29 ++++++------ compiler/rustc_resolve/src/rustdoc.rs | 10 ++-- src/librustdoc/clean/utils.rs | 11 ++--- src/librustdoc/formats/cache.rs | 4 +- src/librustdoc/html/format.rs | 23 +++------ src/librustdoc/html/render/context.rs | 4 +- src/librustdoc/html/render/mod.rs | 9 ++-- src/librustdoc/html/render/print_item.rs | 9 ++-- src/librustdoc/html/render/search_index.rs | 14 +++--- src/librustdoc/html/render/write_shared.rs | 4 +- src/librustdoc/html/url_parts_builder.rs | 12 +---- .../src/methods/from_iter_instead_of_collect.rs | 3 +- src/tools/clippy/clippy_utils/src/lib.rs | 17 +++---- tests/ui/asm/naked-invalid-attr.stderr | 2 +- 20 files changed, 130 insertions(+), 110 deletions(-) (limited to 'compiler/rustc_resolve/src') diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 3c576316f62..fa542a810dc 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -18,7 +18,7 @@ //! - [`Attribute`]: Metadata associated with item. //! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators. -use std::borrow::Cow; +use std::borrow::{Borrow, Cow}; use std::{cmp, fmt}; pub use GenericArgs::*; @@ -155,6 +155,59 @@ impl Path { } } +/// Joins multiple symbols with "::" into a path, e.g. "a::b::c". If the first +/// segment is `kw::PathRoot` it will be printed as empty, e.g. "::b::c". +/// +/// The generics on the `path` argument mean it can accept many forms, such as: +/// - `&[Symbol]` +/// - `Vec` +/// - `Vec<&Symbol>` +/// - `impl Iterator` +/// - `impl Iterator` +/// +/// Panics if `path` is empty or a segment after the first is `kw::PathRoot`. +pub fn join_path_syms(path: impl IntoIterator>) -> String { + // This is a guess at the needed capacity that works well in practice. It is slightly faster + // than (a) starting with an empty string, or (b) computing the exact capacity required. + // `8` works well because it's about the right size and jemalloc's size classes are all + // multiples of 8. + let mut iter = path.into_iter(); + let len_hint = iter.size_hint().1.unwrap_or(1); + let mut s = String::with_capacity(len_hint * 8); + + let first_sym = *iter.next().unwrap().borrow(); + if first_sym != kw::PathRoot { + s.push_str(first_sym.as_str()); + } + for sym in iter { + let sym = *sym.borrow(); + debug_assert_ne!(sym, kw::PathRoot); + s.push_str("::"); + s.push_str(sym.as_str()); + } + s +} + +/// Like `join_path_syms`, but for `Ident`s. This function is necessary because +/// `Ident::to_string` does more than just print the symbol in the `name` field. +pub fn join_path_idents(path: impl IntoIterator>) -> String { + let mut iter = path.into_iter(); + let len_hint = iter.size_hint().1.unwrap_or(1); + let mut s = String::with_capacity(len_hint * 8); + + let first_ident = *iter.next().unwrap().borrow(); + if first_ident.name != kw::PathRoot { + s.push_str(&first_ident.to_string()); + } + for ident in iter { + let ident = *ident.borrow(); + debug_assert_ne!(ident.name, kw::PathRoot); + s.push_str("::"); + s.push_str(&ident.to_string()); + } + s +} + /// A segment of a path: an identifier, an optional lifetime, and a set of types. /// /// E.g., `std`, `String` or `Box`. diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index cebfffa1e16..ecfd46a84ec 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -4,8 +4,8 @@ use std::sync::Arc; use rustc_ast as ast; use rustc_ast::ptr::P; -use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; +use rustc_ast::{join_path_idents, token}; use rustc_ast_pretty::pprust; use rustc_expand::base::{ DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult, resolve_path, @@ -100,7 +100,7 @@ pub(crate) fn expand_mod( let sp = cx.with_def_site_ctxt(sp); check_zero_tts(cx, sp, tts, "module_path!"); let mod_path = &cx.current_expansion.module.mod_path; - let string = mod_path.iter().map(|x| x.to_string()).collect::>().join("::"); + let string = join_path_idents(mod_path); ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string)))) } diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index b067578794b..ba3d8368b2a 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -5,7 +5,7 @@ use std::assert_matches::assert_matches; use std::iter; use rustc_ast::ptr::P; -use rustc_ast::{self as ast, GenericParamKind, attr}; +use rustc_ast::{self as ast, GenericParamKind, attr, join_path_idents}; use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, Diag, Level}; use rustc_expand::base::*; @@ -446,12 +446,7 @@ fn get_location_info(cx: &ExtCtxt<'_>, fn_: &ast::Fn) -> (Symbol, usize, usize, } fn item_path(mod_path: &[Ident], item_ident: &Ident) -> String { - mod_path - .iter() - .chain(iter::once(item_ident)) - .map(|x| x.to_string()) - .collect::>() - .join("::") + join_path_idents(mod_path.iter().chain(iter::once(item_ident))) } enum ShouldPanic { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 159518a8d87..ace2259aec3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -7,7 +7,7 @@ use rustc_ast::token::CommentKind; use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{ self as ast, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label, LitIntType, - LitKind, TraitObjectSyntax, UintTy, UnsafeBinderCastKind, + LitKind, TraitObjectSyntax, UintTy, UnsafeBinderCastKind, join_path_idents, }; pub use rustc_ast::{ AssignOp, AssignOpKind, AttrId, AttrStyle, BinOp, BinOpKind, BindingMode, BorrowKind, @@ -1168,7 +1168,7 @@ impl AttrPath { impl fmt::Display for AttrPath { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.segments.iter().map(|i| i.to_string()).collect::>().join("::")) + write!(f, "{}", join_path_idents(&self.segments)) } } diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs index 0037d5ac042..38413cca633 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs @@ -2,6 +2,7 @@ use std::fmt::Write; use hir::def_id::DefId; use hir::{HirId, ItemKind}; +use rustc_ast::join_path_idents; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER}; @@ -383,13 +384,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // All that is left is `_`! We need to use the full path. It doesn't matter which one we // pick, so just take the first one. match import_items[0].kind { - ItemKind::Use(path, _) => Some( - path.segments - .iter() - .map(|segment| segment.ident.to_string()) - .collect::>() - .join("::"), - ), + ItemKind::Use(path, _) => { + Some(join_path_idents(path.segments.iter().map(|seg| seg.ident))) + } _ => { span_bug!(span, "unexpected item kind, expected a use: {:?}", import_items[0].kind); } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 2009ddc1e2d..5b2b9c152aa 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -10,7 +10,7 @@ use std::collections::hash_map::Entry; use std::slice; use rustc_abi::{Align, ExternAbi, Size}; -use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, ast}; +use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, ast, join_path_syms}; use rustc_attr_data_structures::{AttributeKind, InlineAttr, ReprAttr, find_attr}; use rustc_attr_parsing::{AttributeParser, Late}; use rustc_data_structures::fx::FxHashMap; @@ -678,9 +678,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { allowed_target: Target, ) { if target != allowed_target { - let path = attr.path(); - let path: Vec<_> = path.iter().map(|s| s.as_str()).collect(); - let attr_name = path.join("::"); + let attr_name = join_path_syms(attr.path()); self.tcx.emit_node_span_lint( UNUSED_ATTRIBUTES, hir_id, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 11e4a729ae2..5a162b5d2b9 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1,6 +1,8 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; -use rustc_ast::{self as ast, CRATE_NODE_ID, Crate, ItemKind, ModKind, NodeId, Path}; +use rustc_ast::{ + self as ast, CRATE_NODE_ID, Crate, ItemKind, ModKind, NodeId, Path, join_path_idents, +}; use rustc_ast_pretty::pprust; use rustc_attr_data_structures::{ self as attr, AttributeKind, CfgEntry, Stability, StrippedCfgItem, find_attr, @@ -2018,7 +2020,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - let mut sugg_paths = vec![]; + let mut sugg_paths: Vec<(Vec, bool)> = vec![]; if let Some(mut def_id) = res.opt_def_id() { // We can't use `def_path_str` in resolve. let mut path = vec![def_id]; @@ -2031,16 +2033,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } // We will only suggest importing directly if it is accessible through that path. - let path_names: Option> = path + let path_names: Option> = path .iter() .rev() .map(|def_id| { - self.tcx.opt_item_name(*def_id).map(|n| { - if def_id.is_top_level_module() { - "crate".to_string() + self.tcx.opt_item_name(*def_id).map(|name| { + Ident::with_dummy_span(if def_id.is_top_level_module() { + kw::Crate } else { - n.to_string() - } + name + }) }) }) .collect(); @@ -2084,13 +2086,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { match binding.kind { NameBindingKind::Import { import, .. } => { for segment in import.module_path.iter().skip(1) { - path.push(segment.ident.to_string()); + path.push(segment.ident); } sugg_paths.push(( - path.iter() - .cloned() - .chain(vec![ident.to_string()].into_iter()) - .collect::>(), + path.iter().cloned().chain(std::iter::once(ident)).collect::>(), true, // re-export )); } @@ -2126,7 +2125,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { err.subdiagnostic(note); } // We prioritize shorter paths, non-core imports and direct imports over the alternatives. - sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0] == "core", *reexport)); + sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0].name == sym::core, *reexport)); for (sugg, reexport) in sugg_paths { if not_publicly_reexported { break; @@ -2136,7 +2135,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // `tests/ui/imports/issue-55884-2.rs` continue; } - let path = sugg.join("::"); + let path = join_path_idents(sugg); let sugg = if reexport { errors::ImportIdent::ThroughReExport { span: dedup_span, ident, path } } else { diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index f61cd1f0adf..24e15ded94f 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -7,6 +7,7 @@ use pulldown_cmark::{ }; use rustc_ast as ast; use rustc_ast::attr::AttributeExt; +use rustc_ast::join_path_syms; use rustc_ast::util::comments::beautify_doc_string; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::UnordSet; @@ -259,7 +260,7 @@ pub fn main_body_opts() -> Options { | Options::ENABLE_SMART_PUNCTUATION } -fn strip_generics_from_path_segment(segment: Vec) -> Result { +fn strip_generics_from_path_segment(segment: Vec) -> Result { let mut stripped_segment = String::new(); let mut param_depth = 0; @@ -284,7 +285,7 @@ fn strip_generics_from_path_segment(segment: Vec) -> Result>` Err(MalformedGenerics::UnbalancedAngleBrackets) @@ -346,9 +347,8 @@ pub fn strip_generics_from_path(path_str: &str) -> Result, MalformedGen debug!("path_str: {path_str:?}\nstripped segments: {stripped_segments:?}"); - let stripped_path = stripped_segments.join("::"); - - if !stripped_path.is_empty() { + if !stripped_segments.is_empty() { + let stripped_path = join_path_syms(stripped_segments); Ok(stripped_path.into()) } else { Err(MalformedGenerics::MissingType) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index bf3f7607274..fd1b17b6476 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -3,6 +3,7 @@ use std::fmt::{self, Display, Write as _}; use std::sync::LazyLock as Lazy; use std::{ascii, mem}; +use rustc_ast::join_path_idents; use rustc_ast::tokenstream::TokenTree; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; @@ -24,7 +25,7 @@ use crate::clean::{ clean_middle_ty, inline, }; use crate::core::DocContext; -use crate::display::{Joined as _, MaybeDisplay as _}; +use crate::display::Joined as _; #[cfg(test)] mod tests; @@ -251,13 +252,7 @@ pub(crate) fn qpath_to_string(p: &hir::QPath<'_>) -> String { hir::QPath::LangItem(lang_item, ..) => return lang_item.name().to_string(), }; - fmt::from_fn(|f| { - segments - .iter() - .map(|seg| (seg.ident.name != kw::PathRoot).then_some(seg.ident).maybe_display()) - .joined("::", f) - }) - .to_string() + join_path_idents(segments.iter().map(|seg| seg.ident)) } pub(crate) fn build_deref_target_impls( diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 4989bd718c9..5191120ebdb 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -1,5 +1,6 @@ use std::mem; +use rustc_ast::join_path_syms; use rustc_attr_data_structures::StabilityLevel; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet}; @@ -13,7 +14,6 @@ use crate::core::DocContext; use crate::fold::DocFolder; use crate::formats::Impl; use crate::formats::item_type::ItemType; -use crate::html::format::join_with_double_colon; use crate::html::markdown::short_markdown_summary; use crate::html::render::IndexItem; use crate::html::render::search_index::get_function_type_for_search; @@ -558,7 +558,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It clean::ItemKind::ImportItem(import) => import.source.did.unwrap_or(item_def_id), _ => item_def_id, }; - let path = join_with_double_colon(parent_path); + let path = join_path_syms(parent_path); let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() { item_id.as_def_id() } else { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index bcb3e57c844..b16485107a0 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -14,6 +14,7 @@ use std::slice; use itertools::{Either, Itertools}; use rustc_abi::ExternAbi; +use rustc_ast::join_path_syms; use rustc_attr_data_structures::{ConstStability, StabilityLevel, StableSince}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; @@ -25,7 +26,7 @@ use rustc_span::symbol::kw; use rustc_span::{Symbol, sym}; use tracing::{debug, trace}; -use super::url_parts_builder::{UrlPartsBuilder, estimate_item_path_byte_length}; +use super::url_parts_builder::UrlPartsBuilder; use crate::clean::types::ExternalLocation; use crate::clean::utils::find_nearest_parent_module; use crate::clean::{self, ExternalCrate, PrimitiveType}; @@ -369,18 +370,6 @@ pub(crate) enum HrefError { NotInExternalCache, } -// Panics if `syms` is empty. -pub(crate) fn join_with_double_colon(syms: &[Symbol]) -> String { - let mut s = String::with_capacity(estimate_item_path_byte_length(syms.len())); - // NOTE: using `Joined::joined` here causes a noticeable perf regression - s.push_str(syms[0].as_str()); - for sym in &syms[1..] { - s.push_str("::"); - s.push_str(sym.as_str()); - } - s -} - /// This function is to get the external macro path because they are not in the cache used in /// `href_with_root_path`. fn generate_macro_def_id_path( @@ -672,7 +661,7 @@ pub(crate) fn link_tooltip( write!(f, "{}", cx.tcx().item_name(id))?; } else if !fqp.is_empty() { write!(f, "{shortty} ")?; - fqp.iter().joined("::", f)?; + write!(f, "{}", join_path_syms(fqp))?; } Ok(()) }) @@ -703,7 +692,7 @@ fn resolved_path( write!( f, "{path}::{anchor}", - path = join_with_double_colon(&fqp[..fqp.len() - 1]), + path = join_path_syms(&fqp[..fqp.len() - 1]), anchor = print_anchor(did, *fqp.last().unwrap(), cx) ) } else { @@ -835,7 +824,7 @@ pub(crate) fn print_anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl D write!( f, r#"{text}"#, - path = join_with_double_colon(&fqp), + path = join_path_syms(fqp), text = EscapeBodyText(text.as_str()), ) } else { @@ -1095,7 +1084,7 @@ impl clean::QPathData { title=\"type {path}::{name}\">{name}", shortty = ItemType::AssocType, name = assoc.name, - path = join_with_double_colon(&path), + path = join_path_syms(path), ) } else { write!(f, "{}", assoc.name) diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 3b4dae841ee..7b814701a73 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -6,6 +6,7 @@ use std::path::{Path, PathBuf}; use std::sync::mpsc::{Receiver, channel}; use askama::Template; +use rustc_ast::join_path_syms; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE}; use rustc_middle::ty::TyCtxt; @@ -27,7 +28,6 @@ use crate::formats::FormatRenderer; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::escape::Escape; -use crate::html::format::join_with_double_colon; use crate::html::markdown::{self, ErrorCodes, IdMap, plain_text_summary}; use crate::html::render::write_shared::write_shared; use crate::html::url_parts_builder::UrlPartsBuilder; @@ -211,7 +211,7 @@ impl<'tcx> Context<'tcx> { title.push_str(" in "); } // No need to include the namespace for primitive types and keywords - title.push_str(&join_with_double_colon(&self.current)); + title.push_str(&join_path_syms(&self.current)); }; title.push_str(" - Rust"); let tyname = it.type_(); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 06de4944d97..d8c37137bbc 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -49,6 +49,7 @@ use std::{fs, str}; use askama::Template; use itertools::Either; +use rustc_ast::join_path_syms; use rustc_attr_data_structures::{ ConstStability, DeprecatedSince, Deprecation, RustcVersion, StabilityLevel, StableSince, }; @@ -74,9 +75,9 @@ use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::escape::Escape; use crate::html::format::{ - Ending, HrefError, PrintWithSpace, href, join_with_double_colon, print_abi_with_space, - print_constness_with_space, print_default_space, print_generic_bounds, print_where_clause, - visibility_print_with_space, write_str, + Ending, HrefError, PrintWithSpace, href, print_abi_with_space, print_constness_with_space, + print_default_space, print_generic_bounds, print_where_clause, visibility_print_with_space, + write_str, }; use crate::html::markdown::{ HeadingOffset, IdMap, Markdown, MarkdownItemInfo, MarkdownSummaryLine, @@ -2555,7 +2556,7 @@ fn collect_paths_for_type(first_ty: &clean::Type, cache: &Cache) -> Vec let fqp = cache.exact_paths.get(&did).or_else(get_extern); if let Some(path) = fqp { - out.push(join_with_double_colon(path)); + out.push(join_path_syms(path)); } }; diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 667d39e9bc2..5fbda4797cc 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -4,6 +4,7 @@ use std::iter; use askama::Template; use rustc_abi::VariantIdx; +use rustc_ast::join_path_syms; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_hir as hir; use rustc_hir::def::CtorKind; @@ -30,8 +31,8 @@ use crate::formats::Impl; use crate::formats::item_type::ItemType; use crate::html::escape::{Escape, EscapeBodyTextWithWbr}; use crate::html::format::{ - Ending, PrintWithSpace, join_with_double_colon, print_abi_with_space, - print_constness_with_space, print_where_clause, visibility_print_with_space, + Ending, PrintWithSpace, print_abi_with_space, print_constness_with_space, print_where_clause, + visibility_print_with_space, }; use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine}; use crate::html::render::{document_full, document_item_info}; @@ -1424,7 +1425,7 @@ fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> iter::repeat_n("..", cx.current.len()).chain(iter::once("type.impl")).collect(); js_src_path.extend(target_fqp[..target_fqp.len() - 1].iter().copied()); js_src_path.push_fmt(format_args!("{target_type}.{}.js", target_fqp.last().unwrap())); - let self_path = fmt::from_fn(|f| self_fqp.iter().joined("::", f)); + let self_path = join_path_syms(self_fqp); write!( w, "", @@ -2256,7 +2257,7 @@ pub(crate) fn compare_names(left: &str, right: &str) -> Ordering { } pub(super) fn full_path(cx: &Context<'_>, item: &clean::Item) -> String { - let mut s = join_with_double_colon(&cx.current); + let mut s = join_path_syms(&cx.current); s.push_str("::"); s.push_str(item.name.unwrap().as_str()); s diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index aff8684ee3a..80a59fa218c 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -4,6 +4,7 @@ use std::collections::hash_map::Entry; use std::collections::{BTreeMap, VecDeque}; use encode::{bitmap_to_string, write_vlqhex_to_string}; +use rustc_ast::join_path_syms; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::DefId; @@ -17,7 +18,6 @@ use crate::clean::types::{Function, Generics, ItemId, Type, WherePredicate}; use crate::clean::{self, utils}; use crate::formats::cache::{Cache, OrphanImplItem}; use crate::formats::item_type::ItemType; -use crate::html::format::join_with_double_colon; use crate::html::markdown::short_markdown_summary; use crate::html::render::ordered_json::OrderedJson; use crate::html::render::{self, IndexItem, IndexItemFunctionType, RenderType, RenderTypeId}; @@ -78,7 +78,7 @@ pub(crate) fn build_index( ty: item.type_(), defid: item.item_id.as_def_id(), name: item.name.unwrap(), - path: join_with_double_colon(&fqp[..fqp.len() - 1]), + path: join_path_syms(&fqp[..fqp.len() - 1]), desc, parent: Some(parent), parent_idx: None, @@ -416,7 +416,7 @@ pub(crate) fn build_index( if fqp.len() < 2 { return None; } - join_with_double_colon(&fqp[..fqp.len() - 1]) + join_path_syms(&fqp[..fqp.len() - 1]) }; if path == item.path { return None; @@ -427,10 +427,10 @@ pub(crate) fn build_index( let i = >::try_into(parent_idx).unwrap(); item.path = { let p = &crate_paths[i].1; - join_with_double_colon(&p[..p.len() - 1]) + join_path_syms(&p[..p.len() - 1]) }; item.exact_path = - crate_paths[i].2.as_ref().map(|xp| join_with_double_colon(&xp[..xp.len() - 1])); + crate_paths[i].2.as_ref().map(|xp| join_path_syms(&xp[..xp.len() - 1])); } // Omit the parent path if it is same to that of the prior item. @@ -549,11 +549,11 @@ pub(crate) fn build_index( }); continue; } - let full_path = join_with_double_colon(&path[..path.len() - 1]); + let full_path = join_path_syms(&path[..path.len() - 1]); let full_exact_path = exact .as_ref() .filter(|exact| exact.last() == path.last() && exact.len() >= 2) - .map(|exact| join_with_double_colon(&exact[..exact.len() - 1])); + .map(|exact| join_path_syms(&exact[..exact.len() - 1])); let exact_path = extra_paths.len() + self.items.len(); let exact_path = full_exact_path.as_ref().map(|full_exact_path| match extra_paths .entry(full_exact_path.clone()) diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 0078671fcc5..1f691392b17 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -26,6 +26,7 @@ use std::{fmt, fs}; use indexmap::IndexMap; use regex::Regex; +use rustc_ast::join_path_syms; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_middle::ty::TyCtxt; @@ -43,7 +44,6 @@ use crate::docfs::PathError; use crate::error::Error; use crate::formats::Impl; use crate::formats::item_type::ItemType; -use crate::html::format::join_with_double_colon; use crate::html::layout; use crate::html::render::ordered_json::{EscapedJson, OrderedJson}; use crate::html::render::search_index::{SerializedSearchIndex, build_index}; @@ -608,7 +608,7 @@ impl TypeAliasPart { for &(type_alias_fqp, type_alias_item) in type_aliases { cx.id_map.borrow_mut().clear(); cx.deref_id_map.borrow_mut().clear(); - let type_alias_fqp = join_with_double_colon(&type_alias_fqp); + let type_alias_fqp = join_path_syms(type_alias_fqp); if let Some(ret) = &mut ret { ret.aliases.push(type_alias_fqp); } else { diff --git a/src/librustdoc/html/url_parts_builder.rs b/src/librustdoc/html/url_parts_builder.rs index 9a533827441..705fa498e8d 100644 --- a/src/librustdoc/html/url_parts_builder.rs +++ b/src/librustdoc/html/url_parts_builder.rs @@ -117,7 +117,7 @@ impl UrlPartsBuilder { /// This is just a guess at the average length of a URL part, /// used for [`String::with_capacity`] calls in the [`FromIterator`] -/// and [`Extend`] impls, and for [estimating item path lengths]. +/// and [`Extend`] impls. /// /// The value `8` was chosen for two main reasons: /// @@ -125,18 +125,8 @@ impl UrlPartsBuilder { /// * jemalloc's size classes are all multiples of eight, /// which means that the amount of memory it allocates will often match /// the amount requested, avoiding wasted bytes. -/// -/// [estimating item path lengths]: estimate_item_path_byte_length const AVG_PART_LENGTH: usize = 8; -/// Estimate the number of bytes in an item's path, based on how many segments it has. -/// -/// **Note:** This is only to be used with, e.g., [`String::with_capacity()`]; -/// the return value is just a rough estimate. -pub(crate) const fn estimate_item_path_byte_length(segment_count: usize) -> usize { - AVG_PART_LENGTH * segment_count -} - impl<'a> FromIterator<&'a str> for UrlPartsBuilder { fn from_iter>(iter: T) -> Self { let iter = iter.into_iter(); diff --git a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs index 045363058d1..d664eaaac70 100644 --- a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs @@ -4,6 +4,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::implements_trait; use clippy_utils::{is_path_diagnostic_item, sugg}; +use rustc_ast::join_path_idents; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{self as hir, Expr, ExprKind, GenericArg, QPath, TyKind}; @@ -47,7 +48,7 @@ fn build_full_type(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, app: &mut Applica && let QPath::Resolved(None, ty_path) = &ty_qpath && let Res::Def(_, ty_did) = ty_path.res { - let mut ty_str = itertools::join(ty_path.segments.iter().map(|s| s.ident), "::"); + let mut ty_str = join_path_idents(ty_path.segments.iter().map(|seg| seg.ident)); let mut first = true; let mut append = |arg: &str| { write!(&mut ty_str, "{}{arg}", [", ", "<"][usize::from(first)]).unwrap(); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index ad8c816e204..ff1ee663f9b 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -89,6 +89,7 @@ use std::sync::{Mutex, MutexGuard, OnceLock}; use itertools::Itertools; use rustc_abi::Integer; +use rustc_ast::join_path_syms; use rustc_ast::ast::{self, LitKind, RangeLimits}; use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::fx::FxHashMap; @@ -3245,8 +3246,8 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St // a::b::c ::d::sym refers to // e::f::sym:: :: // result should be super::super::super::super::e::f - if let DefPathData::TypeNs(s) = l { - path.push(s.to_string()); + if let DefPathData::TypeNs(sym) = l { + path.push(sym); } if let DefPathData::TypeNs(_) = r { go_up_by += 1; @@ -3256,7 +3257,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St // a::b::sym:: :: refers to // c::d::e ::f::sym // when looking at `f` - Left(DefPathData::TypeNs(sym)) => path.push(sym.to_string()), + Left(DefPathData::TypeNs(sym)) => path.push(sym), // consider: // a::b::c ::d::sym refers to // e::f::sym:: :: @@ -3268,17 +3269,17 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St if go_up_by > max_super { // `super` chain would be too long, just use the absolute path instead - once(String::from("crate")) - .chain(to.data.iter().filter_map(|el| { + join_path_syms( + once(kw::Crate).chain(to.data.iter().filter_map(|el| { if let DefPathData::TypeNs(sym) = el.data { - Some(sym.to_string()) + Some(sym) } else { None } })) - .join("::") + ) } else { - repeat_n(String::from("super"), go_up_by).chain(path).join("::") + join_path_syms(repeat_n(kw::Super, go_up_by).chain(path)) } } diff --git a/tests/ui/asm/naked-invalid-attr.stderr b/tests/ui/asm/naked-invalid-attr.stderr index 915b54b3fc2..2571c8fa989 100644 --- a/tests/ui/asm/naked-invalid-attr.stderr +++ b/tests/ui/asm/naked-invalid-attr.stderr @@ -8,7 +8,7 @@ error[E0736]: attribute incompatible with `#[unsafe(naked)]` --> $DIR/naked-invalid-attr.rs:56:3 | LL | #[::a] - | ^^^ the `{{root}}::a` attribute is incompatible with `#[unsafe(naked)]` + | ^^^ the `::a` attribute is incompatible with `#[unsafe(naked)]` ... LL | #[unsafe(naked)] | ---------------- function marked with `#[unsafe(naked)]` here -- cgit 1.4.1-3-g733a5 From 5d611e55489b70482295419888844c29af11b2ee Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 6 Jul 2025 23:17:01 +0300 Subject: resolve: Move `self_binding` to `ModuleData` --- compiler/rustc_resolve/src/ident.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 39 ++++++++++++++----------------------- 2 files changed, 16 insertions(+), 25 deletions(-) (limited to 'compiler/rustc_resolve/src') diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 84d66c15f00..6ac3034d1d9 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -841,7 +841,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if ns == TypeNS { if ident.name == kw::Crate || ident.name == kw::DollarCrate { let module = self.resolve_crate_root(ident); - return Ok(self.module_self_bindings[&module]); + return Ok(module.self_binding.unwrap()); } else if ident.name == kw::Super || ident.name == kw::SelfLower { // FIXME: Implement these with renaming requirements so that e.g. // `use super;` doesn't work, but `use super as name;` does. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index b0b29bc2eae..73a6d4c0c3e 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -585,6 +585,10 @@ struct ModuleData<'ra> { span: Span, expansion: ExpnId, + + /// Binding for implicitly declared names that come with a module, + /// like `self` (not yet used), or `crate`/`$crate` (for root modules). + self_binding: Option>, } /// All modules are unique and allocated on a same arena, @@ -613,6 +617,7 @@ impl<'ra> ModuleData<'ra> { expansion: ExpnId, span: Span, no_implicit_prelude: bool, + self_binding: Option>, ) -> Self { let is_foreign = match kind { ModuleKind::Def(_, def_id, _) => !def_id.is_local(), @@ -630,6 +635,7 @@ impl<'ra> ModuleData<'ra> { traits: RefCell::new(None), span, expansion, + self_binding, } } } @@ -1101,10 +1107,6 @@ pub struct Resolver<'ra, 'tcx> { builtin_types_bindings: FxHashMap>, builtin_attrs_bindings: FxHashMap>, registered_tool_bindings: FxHashMap>, - /// Binding for implicitly declared names that come with a module, - /// like `self` (not yet used), or `crate`/`$crate` (for root modules). - module_self_bindings: FxHashMap, NameBinding<'ra>>, - used_extern_options: FxHashSet, macro_names: FxHashSet, builtin_macros: FxHashMap, @@ -1264,24 +1266,27 @@ impl<'ra> ResolverArenas<'ra> { span: Span, no_implicit_prelude: bool, module_map: &mut FxIndexMap>, - module_self_bindings: &mut FxHashMap, NameBinding<'ra>>, ) -> Module<'ra> { + let (def_id, self_binding) = match kind { + ModuleKind::Def(def_kind, def_id, _) => ( + Some(def_id), + Some(self.new_pub_res_binding(Res::Def(def_kind, def_id), span, LocalExpnId::ROOT)), + ), + ModuleKind::Block => (None, None), + }; let module = Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new( parent, kind, expn_id, span, no_implicit_prelude, + self_binding, )))); - let def_id = module.opt_def_id(); if def_id.is_none_or(|def_id| def_id.is_local()) { self.local_modules.borrow_mut().push(module); } if let Some(def_id) = def_id { module_map.insert(def_id, module); - let res = module.res().unwrap(); - let binding = self.new_pub_res_binding(res, module.span, LocalExpnId::ROOT); - module_self_bindings.insert(module, binding); } module } @@ -1424,7 +1429,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) -> Resolver<'ra, 'tcx> { let root_def_id = CRATE_DEF_ID.to_def_id(); let mut module_map = FxIndexMap::default(); - let mut module_self_bindings = FxHashMap::default(); let graph_root = arenas.new_module( None, ModuleKind::Def(DefKind::Mod, root_def_id, None), @@ -1432,7 +1436,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { crate_span, attr::contains_name(attrs, sym::no_implicit_prelude), &mut module_map, - &mut module_self_bindings, ); let empty_module = arenas.new_module( None, @@ -1441,7 +1444,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { DUMMY_SP, true, &mut Default::default(), - &mut Default::default(), ); let mut node_id_to_def_id = NodeMap::default(); @@ -1544,8 +1546,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { (*ident, binding) }) .collect(), - module_self_bindings, - used_extern_options: Default::default(), macro_names: FxHashSet::default(), builtin_macros: Default::default(), @@ -1617,16 +1617,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { no_implicit_prelude: bool, ) -> Module<'ra> { let module_map = &mut self.module_map; - let module_self_bindings = &mut self.module_self_bindings; - self.arenas.new_module( - parent, - kind, - expn_id, - span, - no_implicit_prelude, - module_map, - module_self_bindings, - ) + self.arenas.new_module(parent, kind, expn_id, span, no_implicit_prelude, module_map) } fn new_local_macro(&mut self, def_id: LocalDefId, macro_data: MacroData) -> &'ra MacroData { -- cgit 1.4.1-3-g733a5 From 8d7193973f5beede7893969197b1661b43f254be Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 6 Jul 2025 23:47:19 +0300 Subject: resolve: Use `module_map` and `get_module` less --- compiler/rustc_resolve/src/diagnostics.rs | 38 ++++++++++++---------- .../rustc_resolve/src/effective_visibilities.rs | 3 +- compiler/rustc_resolve/src/late/diagnostics.rs | 20 +++++------- 3 files changed, 31 insertions(+), 30 deletions(-) (limited to 'compiler/rustc_resolve/src') diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 11e4a729ae2..d263ab25045 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2771,7 +2771,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } /// Finds a cfg-ed out item inside `module` with the matching name. - pub(crate) fn find_cfg_stripped(&self, err: &mut Diag<'_>, segment: &Symbol, module: DefId) { + pub(crate) fn find_cfg_stripped( + &mut self, + err: &mut Diag<'_>, + segment: &Symbol, + module: DefId, + ) { let local_items; let symbols = if module.is_local() { local_items = self @@ -2797,7 +2802,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn comes_from_same_module_for_glob( - r: &Resolver<'_, '_>, + r: &mut Resolver<'_, '_>, parent_module: DefId, module: DefId, visited: &mut FxHashMap, @@ -2809,24 +2814,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return cached; } visited.insert(parent_module, false); - let res = r.module_map.get(&parent_module).is_some_and(|m| { - for importer in m.glob_importers.borrow().iter() { - if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id() + let m = r.expect_module(parent_module); + let mut res = false; + for importer in m.glob_importers.borrow().iter() { + if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id() { + if next_parent_module == module + || comes_from_same_module_for_glob( + r, + next_parent_module, + module, + visited, + ) { - if next_parent_module == module - || comes_from_same_module_for_glob( - r, - next_parent_module, - module, - visited, - ) - { - return true; - } + res = true; + break; } } - false - }); + } visited.insert(parent_module, res); res } diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 5de80de3f8d..741671b6d2f 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -113,8 +113,7 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { /// Update effective visibilities of bindings in the given module, /// including their whole reexport chains. fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) { - assert!(self.r.module_map.contains_key(&module_id.to_def_id())); - let module = self.r.get_module(module_id.to_def_id()).unwrap(); + let module = self.r.expect_module(module_id.to_def_id()); let resolutions = self.r.resolutions(module); for (_, name_resolution) in resolutions.borrow().iter() { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a4601cb44eb..70a7dbf1b04 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -926,7 +926,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { continue; }; if let Res::Def(DefKind::Mod, module) = res.expect_full_res() - && let Some(module) = self.r.get_module(module) + && let module = self.r.expect_module(module) && let item = path[idx + 1].ident && let Some(did) = find_doc_alias_name(self.r, module, item.name) { @@ -2531,16 +2531,14 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // FIXME: this is not totally accurate, but mostly works suggestion.candidate != following_seg.ident.name } - Res::Def(DefKind::Mod, def_id) => self.r.get_module(def_id).map_or_else( - || false, - |module| { - self.r - .resolutions(module) - .borrow() - .iter() - .any(|(key, _)| key.ident.name == following_seg.ident.name) - }, - ), + Res::Def(DefKind::Mod, def_id) => { + let module = self.r.expect_module(def_id); + self.r + .resolutions(module) + .borrow() + .iter() + .any(|(key, _)| key.ident.name == following_seg.ident.name) + } _ => true, }); } -- cgit 1.4.1-3-g733a5 From 8b8889df2550fac573cbaddb1db1419080118d63 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 7 Jul 2025 00:15:13 +0300 Subject: resolve: Split `module_map` into two maps for local and extern modules --- compiler/rustc_resolve/src/build_reduced_graph.rs | 57 ++++++++++++----------- compiler/rustc_resolve/src/diagnostics.rs | 11 ++++- compiler/rustc_resolve/src/lib.rs | 42 +++++++++++------ 3 files changed, 69 insertions(+), 41 deletions(-) (limited to 'compiler/rustc_resolve/src') diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 5a1be618cee..676acd78ea7 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -102,33 +102,36 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// or trait), then this function returns that module's resolver representation, otherwise it /// returns `None`. pub(crate) fn get_module(&mut self, def_id: DefId) -> Option> { - if let module @ Some(..) = self.module_map.get(&def_id) { - return module.copied(); - } + match def_id.as_local() { + Some(local_def_id) => self.local_module_map.get(&local_def_id).copied(), + None => { + if let module @ Some(..) = self.extern_module_map.borrow().get(&def_id) { + return module.copied(); + } - if !def_id.is_local() { - // Query `def_kind` is not used because query system overhead is too expensive here. - let def_kind = self.cstore().def_kind_untracked(def_id); - if def_kind.is_module_like() { - let parent = self - .tcx - .opt_parent(def_id) - .map(|parent_id| self.get_nearest_non_block_module(parent_id)); - // Query `expn_that_defined` is not used because - // hashing spans in its result is expensive. - let expn_id = self.cstore().expn_that_defined_untracked(def_id, self.tcx.sess); - return Some(self.new_module( - parent, - ModuleKind::Def(def_kind, def_id, Some(self.tcx.item_name(def_id))), - expn_id, - self.def_span(def_id), - // FIXME: Account for `#[no_implicit_prelude]` attributes. - parent.is_some_and(|module| module.no_implicit_prelude), - )); + // Query `def_kind` is not used because query system overhead is too expensive here. + let def_kind = self.cstore().def_kind_untracked(def_id); + if def_kind.is_module_like() { + let parent = self + .tcx + .opt_parent(def_id) + .map(|parent_id| self.get_nearest_non_block_module(parent_id)); + // Query `expn_that_defined` is not used because + // hashing spans in its result is expensive. + let expn_id = self.cstore().expn_that_defined_untracked(def_id, self.tcx.sess); + return Some(self.new_extern_module( + parent, + ModuleKind::Def(def_kind, def_id, Some(self.tcx.item_name(def_id))), + expn_id, + self.def_span(def_id), + // FIXME: Account for `#[no_implicit_prelude]` attributes. + parent.is_some_and(|module| module.no_implicit_prelude), + )); + } + + None } } - - None } pub(crate) fn expn_def_scope(&mut self, expn_id: ExpnId) -> Module<'ra> { @@ -758,7 +761,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { if let ast::ModKind::Loaded(_, _, _, Err(_)) = mod_kind { self.r.mods_with_parse_errors.insert(def_id); } - self.parent_scope.module = self.r.new_module( + self.parent_scope.module = self.r.new_local_module( Some(parent), ModuleKind::Def(def_kind, def_id, Some(ident.name)), expansion.to_expn_id(), @@ -790,7 +793,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ItemKind::Enum(ident, _, _) | ItemKind::Trait(box ast::Trait { ident, .. }) => { self.r.define(parent, ident, TypeNS, res, vis, sp, expansion); - self.parent_scope.module = self.r.new_module( + self.parent_scope.module = self.r.new_local_module( Some(parent), ModuleKind::Def(def_kind, def_id, Some(ident.name)), expansion.to_expn_id(), @@ -986,7 +989,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; if self.block_needs_anonymous_module(block) { - let module = self.r.new_module( + let module = self.r.new_local_module( Some(parent), ModuleKind::Block, expansion.to_expn_id(), diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index d263ab25045..9e9ab7356b8 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2159,7 +2159,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .keys() .map(|ident| ident.name) .chain( - self.module_map + self.local_module_map + .iter() + .filter(|(_, module)| { + current_module.is_ancestor_of(**module) && current_module != **module + }) + .flat_map(|(_, module)| module.kind.name()), + ) + .chain( + self.extern_module_map + .borrow() .iter() .filter(|(_, module)| { current_module.is_ancestor_of(**module) && current_module != **module diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 73a6d4c0c3e..98786c1e6f9 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1081,7 +1081,10 @@ pub struct Resolver<'ra, 'tcx> { /// some AST passes can generate identifiers that only resolve to local or /// lang items. empty_module: Module<'ra>, - module_map: FxIndexMap>, + /// Eagerly populated map of all local non-block modules. + local_module_map: FxIndexMap>, + /// Lazily populated cache of modules loaded from external crates. + extern_module_map: RefCell>>, binding_parent_modules: FxHashMap, Module<'ra>>, underscore_disambiguator: u32, @@ -1112,8 +1115,9 @@ pub struct Resolver<'ra, 'tcx> { builtin_macros: FxHashMap, registered_tools: &'tcx RegisteredTools, macro_use_prelude: FxIndexMap>, + /// Eagerly populated map of all local macro definitions. local_macro_map: FxHashMap, - /// Lazily populated cache of macros loaded from external crates. + /// Lazily populated cache of macro definitions loaded from external crates. extern_macro_map: RefCell>, dummy_ext_bang: Arc, dummy_ext_derive: Arc, @@ -1265,7 +1269,6 @@ impl<'ra> ResolverArenas<'ra> { expn_id: ExpnId, span: Span, no_implicit_prelude: bool, - module_map: &mut FxIndexMap>, ) -> Module<'ra> { let (def_id, self_binding) = match kind { ModuleKind::Def(def_kind, def_id, _) => ( @@ -1285,9 +1288,6 @@ impl<'ra> ResolverArenas<'ra> { if def_id.is_none_or(|def_id| def_id.is_local()) { self.local_modules.borrow_mut().push(module); } - if let Some(def_id) = def_id { - module_map.insert(def_id, module); - } module } fn local_modules(&'ra self) -> std::cell::Ref<'ra, Vec>> { @@ -1428,22 +1428,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { arenas: &'ra ResolverArenas<'ra>, ) -> Resolver<'ra, 'tcx> { let root_def_id = CRATE_DEF_ID.to_def_id(); - let mut module_map = FxIndexMap::default(); + let mut local_module_map = FxIndexMap::default(); let graph_root = arenas.new_module( None, ModuleKind::Def(DefKind::Mod, root_def_id, None), ExpnId::root(), crate_span, attr::contains_name(attrs, sym::no_implicit_prelude), - &mut module_map, ); + local_module_map.insert(CRATE_DEF_ID, graph_root); let empty_module = arenas.new_module( None, ModuleKind::Def(DefKind::Mod, root_def_id, None), ExpnId::root(), DUMMY_SP, true, - &mut Default::default(), ); let mut node_id_to_def_id = NodeMap::default(); @@ -1504,7 +1503,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { trait_map: NodeMap::default(), underscore_disambiguator: 0, empty_module, - module_map, + local_module_map, + extern_module_map: Default::default(), block_map: Default::default(), binding_parent_modules: FxHashMap::default(), ast_transform_scopes: FxHashMap::default(), @@ -1608,7 +1608,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { resolver } - fn new_module( + fn new_local_module( + &mut self, + parent: Option>, + kind: ModuleKind, + expn_id: ExpnId, + span: Span, + no_implicit_prelude: bool, + ) -> Module<'ra> { + let module = self.arenas.new_module(parent, kind, expn_id, span, no_implicit_prelude); + if let Some(def_id) = module.opt_def_id() { + self.local_module_map.insert(def_id.expect_local(), module); + } + module + } + + fn new_extern_module( &mut self, parent: Option>, kind: ModuleKind, @@ -1616,8 +1631,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span: Span, no_implicit_prelude: bool, ) -> Module<'ra> { - let module_map = &mut self.module_map; - self.arenas.new_module(parent, kind, expn_id, span, no_implicit_prelude, module_map) + let module = self.arenas.new_module(parent, kind, expn_id, span, no_implicit_prelude); + self.extern_module_map.borrow_mut().insert(module.def_id(), module); + module } fn new_local_macro(&mut self, def_id: LocalDefId, macro_data: MacroData) -> &'ra MacroData { -- cgit 1.4.1-3-g733a5 From 6849f816b1c908b446698a08b5cd27d258bad073 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 7 Jul 2025 00:39:07 +0300 Subject: resolve: Change `&mut Resolver` to `&Resolver` when possible --- compiler/rustc_expand/src/base.rs | 2 +- compiler/rustc_resolve/src/build_reduced_graph.rs | 14 ++++++------- compiler/rustc_resolve/src/diagnostics.rs | 15 +++++--------- .../rustc_resolve/src/effective_visibilities.rs | 6 +++--- compiler/rustc_resolve/src/ident.rs | 4 ++-- compiler/rustc_resolve/src/imports.rs | 2 +- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_resolve/src/late/diagnostics.rs | 24 +++++++++------------- compiler/rustc_resolve/src/lib.rs | 6 +++--- compiler/rustc_resolve/src/macros.rs | 4 ++-- 10 files changed, 35 insertions(+), 44 deletions(-) (limited to 'compiler/rustc_resolve/src') diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index ce3006c2604..1928cfd9048 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1062,7 +1062,7 @@ pub trait ResolverExpand { fn next_node_id(&mut self) -> NodeId; fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId; - fn resolve_dollar_crates(&mut self); + fn resolve_dollar_crates(&self); fn visit_ast_fragment_with_placeholders( &mut self, expn_id: LocalExpnId, diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 676acd78ea7..e56aabfd414 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -85,7 +85,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Reachable macros with block module parents exist due to `#[macro_export] macro_rules!`, /// but they cannot use def-site hygiene, so the assumption holds /// (). - pub(crate) fn get_nearest_non_block_module(&mut self, mut def_id: DefId) -> Module<'ra> { + pub(crate) fn get_nearest_non_block_module(&self, mut def_id: DefId) -> Module<'ra> { loop { match self.get_module(def_id) { Some(module) => return module, @@ -94,14 +94,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - pub(crate) fn expect_module(&mut self, def_id: DefId) -> Module<'ra> { + pub(crate) fn expect_module(&self, def_id: DefId) -> Module<'ra> { self.get_module(def_id).expect("argument `DefId` is not a module") } /// If `def_id` refers to a module (in resolver's sense, i.e. a module item, crate root, enum, /// or trait), then this function returns that module's resolver representation, otherwise it /// returns `None`. - pub(crate) fn get_module(&mut self, def_id: DefId) -> Option> { + pub(crate) fn get_module(&self, def_id: DefId) -> Option> { match def_id.as_local() { Some(local_def_id) => self.local_module_map.get(&local_def_id).copied(), None => { @@ -134,7 +134,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - pub(crate) fn expn_def_scope(&mut self, expn_id: ExpnId) -> Module<'ra> { + pub(crate) fn expn_def_scope(&self, expn_id: ExpnId) -> Module<'ra> { match expn_id.expn_data().macro_def_id { Some(def_id) => self.macro_def_scope(def_id), None => expn_id @@ -144,7 +144,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - pub(crate) fn macro_def_scope(&mut self, def_id: DefId) -> Module<'ra> { + pub(crate) fn macro_def_scope(&self, def_id: DefId) -> Module<'ra> { if let Some(id) = def_id.as_local() { self.local_macro_def_scopes[&id] } else { @@ -406,7 +406,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.field_visibility_spans.insert(def_id, field_vis); } - fn block_needs_anonymous_module(&mut self, block: &Block) -> bool { + fn block_needs_anonymous_module(&self, block: &Block) -> bool { // If any statements are items, we need to create an anonymous module block .stmts @@ -1121,7 +1121,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } /// Returns `true` if this attribute list contains `macro_use`. - fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool { + fn contains_macro_use(&self, attrs: &[ast::Attribute]) -> bool { for attr in attrs { if attr.has_name(sym::macro_escape) { let inner_attribute = matches!(attr.style, ast::AttrStyle::Inner); diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 9e9ab7356b8..aa12a842e6e 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2150,7 +2150,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } pub(crate) fn find_similarly_named_module_or_crate( - &mut self, + &self, ident: Symbol, current_module: Module<'ra>, ) -> Option { @@ -2444,7 +2444,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn undeclared_module_suggest_declare( - &mut self, + &self, ident: Ident, path: std::path::PathBuf, ) -> Option<(Vec<(Span, String)>, String, Applicability)> { @@ -2459,7 +2459,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { )) } - fn undeclared_module_exists(&mut self, ident: Ident) -> Option { + fn undeclared_module_exists(&self, ident: Ident) -> Option { let map = self.tcx.sess.source_map(); let src = map.span_to_filename(ident.span).into_local_path()?; @@ -2780,12 +2780,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } /// Finds a cfg-ed out item inside `module` with the matching name. - pub(crate) fn find_cfg_stripped( - &mut self, - err: &mut Diag<'_>, - segment: &Symbol, - module: DefId, - ) { + pub(crate) fn find_cfg_stripped(&self, err: &mut Diag<'_>, segment: &Symbol, module: DefId) { let local_items; let symbols = if module.is_local() { local_items = self @@ -2811,7 +2806,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn comes_from_same_module_for_glob( - r: &mut Resolver<'_, '_>, + r: &Resolver<'_, '_>, parent_module: DefId, module: DefId, visited: &mut FxHashMap, diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 741671b6d2f..34d1e9552fd 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -38,11 +38,11 @@ pub(crate) struct EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { } impl Resolver<'_, '_> { - fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId { + fn nearest_normal_mod(&self, def_id: LocalDefId) -> LocalDefId { self.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local() } - fn private_vis_import(&mut self, binding: NameBinding<'_>) -> Visibility { + fn private_vis_import(&self, binding: NameBinding<'_>) -> Visibility { let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() }; Visibility::Restricted( import @@ -52,7 +52,7 @@ impl Resolver<'_, '_> { ) } - fn private_vis_def(&mut self, def_id: LocalDefId) -> Visibility { + fn private_vis_def(&self, def_id: LocalDefId) -> Visibility { // For mod items `nearest_normal_mod` returns its argument, but we actually need its parent. let normal_mod_id = self.nearest_normal_mod(def_id); if normal_mod_id == def_id { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 6ac3034d1d9..34941398a2b 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -219,7 +219,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn hygienic_lexical_parent( - &mut self, + &self, module: Module<'ra>, ctxt: &mut SyntaxContext, derive_fallback_lint_id: Option, @@ -885,7 +885,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); } - let check_usable = |this: &mut Self, binding: NameBinding<'ra>| { + let check_usable = |this: &Self, binding: NameBinding<'ra>| { let usable = this.is_accessible_from(binding.vis, parent_scope.module); if usable { Ok(binding) } else { Err((Determined, Weak::No)) } }; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 9a031ee03e0..4b20d50c427 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -456,7 +456,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { f: F, ) -> T where - F: FnOnce(&mut Resolver<'ra, 'tcx>, &mut NameResolution<'ra>) -> T, + F: FnOnce(&Resolver<'ra, 'tcx>, &mut NameResolution<'ra>) -> T, { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, // during which the resolution might end up getting re-defined via a glob cycle. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 3ef98100d09..753b9365cd8 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2491,7 +2491,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { /// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved /// label and reports an error if the label is not found or is unreachable. - fn resolve_label(&mut self, mut label: Ident) -> Result<(NodeId, Span), ResolutionError<'ra>> { + fn resolve_label(&self, mut label: Ident) -> Result<(NodeId, Span), ResolutionError<'ra>> { let mut suggestion = None; for i in (0..self.label_ribs.len()).rev() { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 70a7dbf1b04..ee462d90764 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -939,7 +939,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } fn suggest_trait_and_bounds( - &mut self, + &self, err: &mut Diag<'_>, source: PathSource<'_, '_, '_>, res: Option, @@ -1140,7 +1140,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { /// Emit special messages for unresolved `Self` and `self`. fn suggest_self_ty( - &mut self, + &self, err: &mut Diag<'_>, source: PathSource<'_, '_, '_>, path: &[Segment], @@ -1256,7 +1256,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } fn detect_missing_binding_available_from_pattern( - &mut self, + &self, err: &mut Diag<'_>, path: &[Segment], following_seg: Option<&Segment>, @@ -1302,11 +1302,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } - fn suggest_at_operator_in_slice_pat_with_range( - &mut self, - err: &mut Diag<'_>, - path: &[Segment], - ) { + fn suggest_at_operator_in_slice_pat_with_range(&self, err: &mut Diag<'_>, path: &[Segment]) { let Some(pat) = self.diag_metadata.current_pat else { return }; let (bound, side, range) = match &pat.kind { ast::PatKind::Range(Some(bound), None, range) => (bound, Side::Start, range), @@ -1367,7 +1363,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } fn explain_functions_in_pattern( - &mut self, + &self, err: &mut Diag<'_>, res: Option, source: PathSource<'_, '_, '_>, @@ -1379,7 +1375,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } fn suggest_changing_type_to_const_param( - &mut self, + &self, err: &mut Diag<'_>, res: Option, source: PathSource<'_, '_, '_>, @@ -1429,7 +1425,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } fn suggest_pattern_match_with_let( - &mut self, + &self, err: &mut Diag<'_>, source: PathSource<'_, '_, '_>, span: Span, @@ -1485,7 +1481,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } /// Given `where ::Baz: String`, suggest `where T: Bar`. - fn restrict_assoc_type_in_where_clause(&mut self, span: Span, err: &mut Diag<'_>) -> bool { + fn restrict_assoc_type_in_where_clause(&self, span: Span, err: &mut Diag<'_>) -> bool { // Detect that we are actually in a `where` predicate. let (bounded_ty, bounds, where_span) = if let Some(ast::WherePredicate { kind: @@ -1633,7 +1629,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let ns = source.namespace(); let is_expected = &|res| source.is_expected(res); - let path_sep = |this: &mut Self, err: &mut Diag<'_>, expr: &Expr, kind: DefKind| { + let path_sep = |this: &Self, err: &mut Diag<'_>, expr: &Expr, kind: DefKind| { const MESSAGE: &str = "use the path separator to refer to an item"; let (lhs_span, rhs_span) = match &expr.kind { @@ -2587,7 +2583,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // try to give a suggestion for this pattern: `name = blah`, which is common in other languages // suggest `let name = blah` to introduce a new binding - fn let_binding_suggestion(&mut self, err: &mut Diag<'_>, ident_span: Span) -> bool { + fn let_binding_suggestion(&self, err: &mut Diag<'_>, ident_span: Span) -> bool { if ident_span.from_expansion() { return false; } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 98786c1e6f9..3202d31fdbc 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1624,7 +1624,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn new_extern_module( - &mut self, + &self, parent: Option>, kind: ModuleKind, expn_id: ExpnId, @@ -2021,7 +2021,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - fn resolve_crate_root(&mut self, ident: Ident) -> Module<'ra> { + fn resolve_crate_root(&self, ident: Ident) -> Module<'ra> { debug!("resolve_crate_root({:?})", ident); let mut ctxt = ident.span.ctxt(); let mark = if ident.name == kw::DollarCrate { @@ -2094,7 +2094,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module } - fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'ra>) -> Module<'ra> { + fn resolve_self(&self, ctxt: &mut SyntaxContext, module: Module<'ra>) -> Module<'ra> { let mut module = self.expect_module(module.nearest_parent_mod()); while module.span.ctxt().normalize_to_macros_2_0() != *ctxt { let parent = module.parent.unwrap_or_else(|| self.expn_def_scope(ctxt.remove_mark())); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index c17d74659db..77ef7f56c09 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -170,7 +170,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { self.invocation_parents[&id].parent_def } - fn resolve_dollar_crates(&mut self) { + fn resolve_dollar_crates(&self) { hygiene::update_dollar_crate_names(|ctxt| { let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt)); match self.resolve_crate_root(ident).kind { @@ -835,7 +835,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } pub(crate) fn finalize_macro_resolutions(&mut self, krate: &Crate) { - let check_consistency = |this: &mut Self, + let check_consistency = |this: &Self, path: &[Segment], span, kind: MacroKind, -- cgit 1.4.1-3-g733a5 From 998df3a3e851908afd05c3318f16d99849af5c55 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 15 Jul 2025 23:42:35 +0300 Subject: resolve: Make disambiguators for underscore bindings module-local --- compiler/rustc_resolve/src/build_reduced_graph.rs | 30 ++++++++++-------- compiler/rustc_resolve/src/imports.rs | 38 +++++++++++++++-------- compiler/rustc_resolve/src/lib.rs | 33 +++++++++----------- compiler/rustc_resolve/src/macros.rs | 2 +- 4 files changed, 58 insertions(+), 45 deletions(-) (limited to 'compiler/rustc_resolve/src') diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 5a1be618cee..9a5c18247e7 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -49,8 +49,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ns: Namespace, binding: NameBinding<'ra>, ) { - let key = self.new_disambiguated_key(ident, ns); - if let Err(old_binding) = self.try_define(parent, key, binding, false) { + if let Err(old_binding) = self.try_define(parent, ident, ns, binding, false) { self.report_conflict(parent, ident, ns, old_binding, binding); } } @@ -439,16 +438,18 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.indeterminate_imports.push(import); match import.kind { - // Don't add unresolved underscore imports to modules - ImportKind::Single { target: Ident { name: kw::Underscore, .. }, .. } => {} ImportKind::Single { target, type_ns_only, .. } => { - self.r.per_ns(|this, ns| { - if !type_ns_only || ns == TypeNS { - let key = BindingKey::new(target, ns); - let mut resolution = this.resolution(current_module, key).borrow_mut(); - resolution.single_imports.insert(import); - } - }); + // Don't add underscore imports to `single_imports` + // because they cannot define any usable names. + if target.name != kw::Underscore { + self.r.per_ns(|this, ns| { + if !type_ns_only || ns == TypeNS { + let key = BindingKey::new(target, ns); + let mut resolution = this.resolution(current_module, key).borrow_mut(); + resolution.single_imports.insert(import); + } + }); + } } // We don't add prelude imports to the globs since they only affect lexical scopes, // which are not relevant to import resolution. @@ -1402,9 +1403,12 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; self.r.define(parent, ident, ns, self.res(def_id), vis, item.span, expansion); - } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) { + } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) + && ident.name != kw::Underscore + { + // Don't add underscore names, they cannot be looked up anyway. let impl_def_id = self.r.tcx.local_parent(local_def_id); - let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns); + let key = BindingKey::new(ident, ns); self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key); } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index c3e39d2071b..888322c0fd6 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -25,7 +25,7 @@ use rustc_span::{Ident, Span, Symbol, kw, sym}; use smallvec::SmallVec; use tracing::debug; -use crate::Namespace::*; +use crate::Namespace::{self, *}; use crate::diagnostics::{DiagMode, Suggestion, import_candidates}; use crate::errors::{ CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate, @@ -338,13 +338,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn try_define( &mut self, module: Module<'ra>, - key: BindingKey, + ident: Ident, + ns: Namespace, binding: NameBinding<'ra>, warn_ambiguity: bool, ) -> Result<(), NameBinding<'ra>> { let res = binding.res(); - self.check_reserved_macro_name(key.ident, res); + self.check_reserved_macro_name(ident, res); self.set_binding_parent_module(binding, module); + // Even if underscore names cannot be looked up, we still need to add them to modules, + // because they can be fetched by glob imports from those modules, and bring traits + // into scope both directly and through glob imports. + let key = BindingKey::new_disambiguated(ident, ns, || { + (module.0.0.lazy_resolutions.borrow().len() + 1).try_into().unwrap() + }); self.update_resolution(module, key, warn_ambiguity, |this, resolution| { if let Some(old_binding) = resolution.best_binding() { if res == Res::Err && old_binding.res() != Res::Err { @@ -383,7 +390,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { (old_glob @ true, false) | (old_glob @ false, true) => { let (glob_binding, non_glob_binding) = if old_glob { (old_binding, binding) } else { (binding, old_binding) }; - if key.ns == MacroNS + if ns == MacroNS && non_glob_binding.expansion != LocalExpnId::ROOT && glob_binding.res() != non_glob_binding.res() { @@ -489,10 +496,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; if self.is_accessible_from(binding.vis, scope) { let imported_binding = self.import(binding, *import); - let key = BindingKey { ident, ..key }; let _ = self.try_define( import.parent_scope.module, - key, + ident, + key.ns, imported_binding, warn_ambiguity, ); @@ -514,11 +521,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let dummy_binding = self.dummy_binding; let dummy_binding = self.import(dummy_binding, import); self.per_ns(|this, ns| { - let key = BindingKey::new(target, ns); - let _ = this.try_define(import.parent_scope.module, key, dummy_binding, false); - this.update_resolution(import.parent_scope.module, key, false, |_, resolution| { - resolution.single_imports.swap_remove(&import); - }) + let module = import.parent_scope.module; + let _ = this.try_define(module, target, ns, dummy_binding, false); + // Don't remove underscores from `single_imports`, they were never added. + if target.name != kw::Underscore { + let key = BindingKey::new(target, ns); + this.update_resolution(module, key, false, |_, resolution| { + resolution.single_imports.swap_remove(&import); + }) + } }); self.record_use(target, dummy_binding, Used::Other); } else if import.imported_module.get().is_none() { @@ -895,7 +906,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { PendingBinding::Ready(Some(imported_binding)) } Err(Determinacy::Determined) => { - // Don't update the resolution for underscores, because it was never added. + // Don't remove underscores from `single_imports`, they were never added. if target.name != kw::Underscore { let key = BindingKey::new(target, ns); this.update_resolution(parent, key, false, |_, resolution| { @@ -1510,7 +1521,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .is_some_and(|binding| binding.warn_ambiguity_recursive()); let _ = self.try_define( import.parent_scope.module, - key, + key.ident, + key.ns, imported_binding, warn_ambiguity, ); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f904f326296..81907881f44 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -532,15 +532,26 @@ struct BindingKey { /// identifier. ident: Ident, ns: Namespace, - /// 0 if ident is not `_`, otherwise a value that's unique to the specific - /// `_` in the expanded AST that introduced this binding. + /// When we add an underscore binding (with ident `_`) to some module, this field has + /// a non-zero value that uniquely identifies this binding in that module. + /// For non-underscore bindings this field is zero. + /// When a key is constructed for name lookup (as opposed to name definition), this field is + /// also zero, even for underscore names, so for underscores the lookup will never succeed. disambiguator: u32, } impl BindingKey { fn new(ident: Ident, ns: Namespace) -> Self { - let ident = ident.normalize_to_macros_2_0(); - BindingKey { ident, ns, disambiguator: 0 } + BindingKey { ident: ident.normalize_to_macros_2_0(), ns, disambiguator: 0 } + } + + fn new_disambiguated( + ident: Ident, + ns: Namespace, + disambiguator: impl FnOnce() -> u32, + ) -> BindingKey { + let disambiguator = if ident.name == kw::Underscore { disambiguator() } else { 0 }; + BindingKey { ident: ident.normalize_to_macros_2_0(), ns, disambiguator } } } @@ -1078,8 +1089,6 @@ pub struct Resolver<'ra, 'tcx> { module_map: FxIndexMap>, binding_parent_modules: FxHashMap, Module<'ra>>, - underscore_disambiguator: u32, - /// Maps glob imports to the names of items actually imported. glob_map: FxIndexMap>, glob_error: Option, @@ -1500,7 +1509,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { extern_crate_map: Default::default(), module_children: Default::default(), trait_map: NodeMap::default(), - underscore_disambiguator: 0, empty_module, module_map, block_map: Default::default(), @@ -1880,17 +1888,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { import_ids } - fn new_disambiguated_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey { - let ident = ident.normalize_to_macros_2_0(); - let disambiguator = if ident.name == kw::Underscore { - self.underscore_disambiguator += 1; - self.underscore_disambiguator - } else { - 0 - }; - BindingKey { ident, ns, disambiguator } - } - fn resolutions(&mut self, module: Module<'ra>) -> &'ra Resolutions<'ra> { if module.populate_on_access.get() { module.populate_on_access.set(false); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index c17d74659db..2b5632805b6 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -530,7 +530,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { target_trait.for_each_child(self, |this, ident, ns, _binding| { // FIXME: Adjust hygiene for idents from globs, like for glob imports. if let Some(overriding_keys) = this.impl_binding_keys.get(&impl_def_id) - && overriding_keys.contains(&BindingKey::new(ident.normalize_to_macros_2_0(), ns)) + && overriding_keys.contains(&BindingKey::new(ident, ns)) { // The name is overridden, do not produce it from the glob delegation. } else { -- cgit 1.4.1-3-g733a5 From 848d4a5a381ddda172a5629d8050a58388ecb2b9 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Tue, 1 Jul 2025 20:49:07 +0800 Subject: Remove similar errors about raw underscore lifetime Signed-off-by: xizheyin --- compiler/rustc_resolve/src/late.rs | 14 +++++++++++++- tests/ui/underscore-lifetime/raw-underscore-lifetime.rs | 1 - .../ui/underscore-lifetime/raw-underscore-lifetime.stderr | 9 +-------- 3 files changed, 14 insertions(+), 10 deletions(-) (limited to 'compiler/rustc_resolve/src') diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 753b9365cd8..93cec8daa5a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2899,9 +2899,21 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } if param.ident.name == kw::UnderscoreLifetime { + // To avoid emitting two similar errors, + // we need to check if the span is a raw underscore lifetime, see issue #143152 + let is_raw_underscore_lifetime = self + .r + .tcx + .sess + .psess + .raw_identifier_spans + .iter() + .any(|span| span == param.span()); + self.r .dcx() - .emit_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span }); + .create_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span }) + .emit_unless(is_raw_underscore_lifetime); // Record lifetime res, so lowering knows there is something fishy. self.record_lifetime_param(param.id, LifetimeRes::Error); continue; diff --git a/tests/ui/underscore-lifetime/raw-underscore-lifetime.rs b/tests/ui/underscore-lifetime/raw-underscore-lifetime.rs index 9ab040f2eab..874b3d2c48d 100644 --- a/tests/ui/underscore-lifetime/raw-underscore-lifetime.rs +++ b/tests/ui/underscore-lifetime/raw-underscore-lifetime.rs @@ -5,6 +5,5 @@ fn f<'r#_>(){} //~^ ERROR `_` cannot be a raw lifetime -//~| ERROR `'_` cannot be used here [E0637] fn main() {} diff --git a/tests/ui/underscore-lifetime/raw-underscore-lifetime.stderr b/tests/ui/underscore-lifetime/raw-underscore-lifetime.stderr index 39627d8a476..bdb357a47f4 100644 --- a/tests/ui/underscore-lifetime/raw-underscore-lifetime.stderr +++ b/tests/ui/underscore-lifetime/raw-underscore-lifetime.stderr @@ -4,12 +4,5 @@ error: `_` cannot be a raw lifetime LL | fn f<'r#_>(){} | ^^^^ -error[E0637]: `'_` cannot be used here - --> $DIR/raw-underscore-lifetime.rs:6:6 - | -LL | fn f<'r#_>(){} - | ^^^^ `'_` is a reserved lifetime name - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0637`. -- cgit 1.4.1-3-g733a5 From 466d33cb5cc79b74691db619d448f80a97baff61 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Tue, 15 Jul 2025 16:34:57 +0200 Subject: inline CrateLoader inside of CStore --- compiler/rustc_metadata/src/creader.rs | 286 +++++++++++----------- compiler/rustc_resolve/src/build_reduced_graph.rs | 9 +- compiler/rustc_resolve/src/diagnostics.rs | 3 +- compiler/rustc_resolve/src/late/diagnostics.rs | 3 +- compiler/rustc_resolve/src/lib.rs | 26 +- 5 files changed, 169 insertions(+), 158 deletions(-) (limited to 'compiler/rustc_resolve/src') diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index e65c7a68426..438eff33054 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -12,7 +12,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::owned_slice::OwnedSlice; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{self, FreezeReadGuard, FreezeWriteGuard}; -use rustc_errors::DiagCtxtHandle; use rustc_expand::base::SyntaxExtension; use rustc_fs_util::try_canonicalize; use rustc_hir as hir; @@ -23,8 +22,10 @@ use rustc_middle::bug; use rustc_middle::ty::data_structures::IndexSet; use rustc_middle::ty::{TyCtxt, TyCtxtFeed}; use rustc_proc_macro::bridge::client::ProcMacro; +use rustc_session::Session; use rustc_session::config::{ - CrateType, ExtendedTargetModifierInfo, ExternLocation, OptionsTargetModifiers, TargetModifier, + CrateType, ExtendedTargetModifierInfo, ExternLocation, Externs, OptionsTargetModifiers, + TargetModifier, }; use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource}; use rustc_session::lint::{self, BuiltinLintDiag}; @@ -70,6 +71,8 @@ pub struct CStore { /// Unused externs of the crate unused_externs: Vec, + + used_extern_options: FxHashSet, } impl std::fmt::Debug for CStore { @@ -78,28 +81,6 @@ impl std::fmt::Debug for CStore { } } -pub struct CrateLoader<'a, 'tcx: 'a> { - // Immutable configuration. - tcx: TyCtxt<'tcx>, - // Mutable output. - cstore: &'a mut CStore, - used_extern_options: &'a mut FxHashSet, -} - -impl<'a, 'tcx> std::ops::Deref for CrateLoader<'a, 'tcx> { - type Target = TyCtxt<'tcx>; - - fn deref(&self) -> &Self::Target { - &self.tcx - } -} - -impl<'a, 'tcx> CrateLoader<'a, 'tcx> { - fn dcx(&self) -> DiagCtxtHandle<'tcx> { - self.tcx.dcx() - } -} - pub enum LoadedMacro { MacroDef { def: MacroDef, @@ -227,8 +208,8 @@ impl CStore { fn intern_stable_crate_id<'tcx>( &mut self, - root: &CrateRoot, tcx: TyCtxt<'tcx>, + root: &CrateRoot, ) -> Result, CrateError> { assert_eq!(self.metas.len(), tcx.untracked().stable_crate_ids.read().len()); let num = tcx.create_crate_num(root.stable_crate_id()).map_err(|existing| { @@ -495,21 +476,18 @@ impl CStore { has_global_allocator: false, has_alloc_error_handler: false, unused_externs: Vec::new(), + used_extern_options: Default::default(), } } -} -impl<'a, 'tcx> CrateLoader<'a, 'tcx> { - pub fn new( - tcx: TyCtxt<'tcx>, - cstore: &'a mut CStore, - used_extern_options: &'a mut FxHashSet, - ) -> Self { - CrateLoader { tcx, cstore, used_extern_options } - } - - fn existing_match(&self, name: Symbol, hash: Option, kind: PathKind) -> Option { - for (cnum, data) in self.cstore.iter_crate_data() { + fn existing_match( + &self, + externs: &Externs, + name: Symbol, + hash: Option, + kind: PathKind, + ) -> Option { + for (cnum, data) in self.iter_crate_data() { if data.name() != name { trace!("{} did not match {}", data.name(), name); continue; @@ -533,8 +511,8 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // We're also sure to compare *paths*, not actual byte slices. The // `source` stores paths which are normalized which may be different // from the strings on the command line. - let source = self.cstore.get_crate_data(cnum).cdata.source(); - if let Some(entry) = self.sess.opts.externs.get(name.as_str()) { + let source = self.get_crate_data(cnum).cdata.source(); + if let Some(entry) = externs.get(name.as_str()) { // Only use `--extern crate_name=path` here, not `--extern crate_name`. if let Some(mut files) = entry.files() { if files.any(|l| { @@ -587,6 +565,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { /// command parameter is set to `public-dependency` fn is_private_dep( &self, + externs: &Externs, name: Symbol, private_dep: Option, origin: CrateOrigin<'_>, @@ -595,7 +574,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { return true; } - let extern_private = self.sess.opts.externs.get(name.as_str()).map(|e| e.is_private_dep); + let extern_private = externs.get(name.as_str()).map(|e| e.is_private_dep); match (extern_private, private_dep) { // Explicit non-private via `--extern`, explicit non-private from metadata, or // unspecified with default to public. @@ -605,8 +584,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } - fn register_crate( + fn register_crate<'tcx>( &mut self, + tcx: TyCtxt<'tcx>, host_lib: Option, origin: CrateOrigin<'_>, lib: Library, @@ -615,15 +595,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { private_dep: Option, ) -> Result { let _prof_timer = - self.sess.prof.generic_activity_with_arg("metadata_register_crate", name.as_str()); + tcx.sess.prof.generic_activity_with_arg("metadata_register_crate", name.as_str()); let Library { source, metadata } = lib; let crate_root = metadata.get_root(); let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); - let private_dep = self.is_private_dep(name, private_dep, origin); + let private_dep = self.is_private_dep(&tcx.sess.opts.externs, name, private_dep, origin); // Claim this crate number and cache it - let feed = self.cstore.intern_stable_crate_id(&crate_root, self.tcx)?; + let feed = self.intern_stable_crate_id(tcx, &crate_root)?; let cnum = feed.key(); info!( @@ -643,8 +623,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { &crate_paths }; - let cnum_map = - self.resolve_crate_deps(dep_root, &crate_root, &metadata, cnum, dep_kind, private_dep)?; + let cnum_map = self.resolve_crate_deps( + tcx, + dep_root, + &crate_root, + &metadata, + cnum, + dep_kind, + private_dep, + )?; let raw_proc_macros = if crate_root.is_proc_macro_crate() { let temp_root; @@ -656,14 +643,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { None => (&source, &crate_root), }; let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate"); - Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.stable_crate_id())?) + Some(self.dlsym_proc_macros(tcx.sess, &dlsym_dylib.0, dlsym_root.stable_crate_id())?) } else { None }; let crate_metadata = CrateMetadata::new( - self.sess, - self.cstore, + tcx.sess, + self, metadata, crate_root, raw_proc_macros, @@ -675,13 +662,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { host_hash, ); - self.cstore.set_crate_data(cnum, crate_metadata); + self.set_crate_data(cnum, crate_metadata); Ok(cnum) } - fn load_proc_macro<'b>( + fn load_proc_macro<'a, 'b>( &self, + sess: &'a Session, locator: &mut CrateLocator<'b>, crate_rejections: &mut CrateRejections, path_kind: PathKind, @@ -690,13 +678,13 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { where 'a: 'b, { - if self.sess.opts.unstable_opts.dual_proc_macros { + if sess.opts.unstable_opts.dual_proc_macros { // Use a new crate locator and crate rejections so trying to load a proc macro doesn't // affect the error message we emit let mut proc_macro_locator = locator.clone(); // Try to load a proc macro - proc_macro_locator.for_target_proc_macro(self.sess, path_kind); + proc_macro_locator.for_target_proc_macro(sess, path_kind); // Load the proc macro crate for the target let target_result = @@ -713,7 +701,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { *crate_rejections = CrateRejections::default(); // Load the proc macro crate for the host - locator.for_proc_macro(self.sess, path_kind); + locator.for_proc_macro(sess, path_kind); locator.hash = host_hash; @@ -734,7 +722,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let mut proc_macro_locator = locator.clone(); // Load the proc macro crate for the host - proc_macro_locator.for_proc_macro(self.sess, path_kind); + proc_macro_locator.for_proc_macro(sess, path_kind); let Some(host_result) = self.load(&mut proc_macro_locator, &mut CrateRejections::default())? @@ -746,32 +734,39 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } - fn resolve_crate( + fn resolve_crate<'tcx>( &mut self, + tcx: TyCtxt<'tcx>, name: Symbol, span: Span, dep_kind: CrateDepKind, origin: CrateOrigin<'_>, ) -> Option { self.used_extern_options.insert(name); - match self.maybe_resolve_crate(name, dep_kind, origin) { + match self.maybe_resolve_crate(tcx, name, dep_kind, origin) { Ok(cnum) => { - self.cstore.set_used_recursively(cnum); + self.set_used_recursively(cnum); Some(cnum) } Err(err) => { debug!("failed to resolve crate {} {:?}", name, dep_kind); let missing_core = self - .maybe_resolve_crate(sym::core, CrateDepKind::Explicit, CrateOrigin::Extern) + .maybe_resolve_crate( + tcx, + sym::core, + CrateDepKind::Explicit, + CrateOrigin::Extern, + ) .is_err(); - err.report(self.sess, span, missing_core); + err.report(tcx.sess, span, missing_core); None } } } - fn maybe_resolve_crate<'b>( + fn maybe_resolve_crate<'b, 'tcx>( &'b mut self, + tcx: TyCtxt<'tcx>, name: Symbol, mut dep_kind: CrateDepKind, origin: CrateOrigin<'b>, @@ -789,17 +784,19 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let path_kind = if dep.is_some() { PathKind::Dependency } else { PathKind::Crate }; let private_dep = origin.private_dep(); - let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { + let result = if let Some(cnum) = + self.existing_match(&tcx.sess.opts.externs, name, hash, path_kind) + { (LoadResult::Previous(cnum), None) } else { info!("falling back to a load"); let mut locator = CrateLocator::new( - self.sess, - &*self.cstore.metadata_loader, + tcx.sess, + &*self.metadata_loader, name, // The all loop is because `--crate-type=rlib --crate-type=rlib` is // legal and produces both inside this type. - self.tcx.crate_types().iter().all(|c| *c == CrateType::Rlib), + tcx.crate_types().iter().all(|c| *c == CrateType::Rlib), hash, extra_filename, path_kind, @@ -812,6 +809,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { info!("falling back to loading proc_macro"); dep_kind = CrateDepKind::MacrosOnly; match self.load_proc_macro( + tcx.sess, &mut locator, &mut crate_rejections, path_kind, @@ -831,8 +829,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // not specified by `--extern` on command line parameters, it may be // `private-dependency` when `register_crate` is called for the first time. Then it must be updated to // `public-dependency` here. - let private_dep = self.is_private_dep(name, private_dep, origin); - let data = self.cstore.get_crate_data_mut(cnum); + let private_dep = + self.is_private_dep(&tcx.sess.opts.externs, name, private_dep, origin); + let data = self.get_crate_data_mut(cnum); if data.is_proc_macro_crate() { dep_kind = CrateDepKind::MacrosOnly; } @@ -842,7 +841,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } (LoadResult::Loaded(library), host_library) => { info!("register newly loaded library for `{}`", name); - self.register_crate(host_library, origin, library, dep_kind, name, private_dep) + self.register_crate(tcx, host_library, origin, library, dep_kind, name, private_dep) } _ => panic!(), } @@ -863,7 +862,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // duplicates by just using the first crate. let root = library.metadata.get_root(); let mut result = LoadResult::Loaded(library); - for (cnum, data) in self.cstore.iter_crate_data() { + for (cnum, data) in self.iter_crate_data() { if data.name() == root.name() && root.hash() == data.hash() { assert!(locator.hash.is_none()); info!("load success, going to previous cnum: {}", cnum); @@ -877,6 +876,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { /// Go through the crate metadata and load any crates that it references. fn resolve_crate_deps( &mut self, + tcx: TyCtxt<'_>, dep_root: &CratePaths, crate_root: &CrateRoot, metadata: &MetadataBlob, @@ -913,6 +913,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { _ => dep.kind, }; let cnum = self.maybe_resolve_crate( + tcx, dep.name, dep_kind, CrateOrigin::IndirectDependency { @@ -930,10 +931,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { fn dlsym_proc_macros( &self, + sess: &Session, path: &Path, stable_crate_id: StableCrateId, ) -> Result<&'static [ProcMacro], CrateError> { - let sym_name = self.sess.generate_proc_macro_decls_symbol(stable_crate_id); + let sym_name = sess.generate_proc_macro_decls_symbol(stable_crate_id); debug!("trying to dlsym proc_macros {} for symbol `{}`", path.display(), sym_name); unsafe { @@ -955,10 +957,10 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } - fn inject_panic_runtime(&mut self, krate: &ast::Crate) { + fn inject_panic_runtime(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) { // If we're only compiling an rlib, then there's no need to select a // panic runtime, so we just skip this section entirely. - let only_rlib = self.tcx.crate_types().iter().all(|ct| *ct == CrateType::Rlib); + let only_rlib = tcx.crate_types().iter().all(|ct| *ct == CrateType::Rlib); if only_rlib { info!("panic runtime injection skipped, only generating rlib"); return; @@ -968,7 +970,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // the same time we perform some general validation of the DAG we've got // going such as ensuring everything has a compatible panic strategy. let mut needs_panic_runtime = attr::contains_name(&krate.attrs, sym::needs_panic_runtime); - for (_cnum, data) in self.cstore.iter_crate_data() { + for (_cnum, data) in self.iter_crate_data() { needs_panic_runtime |= data.needs_panic_runtime(); } @@ -987,7 +989,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // Also note that we have yet to perform validation of the crate graph // in terms of everyone has a compatible panic runtime format, that's // performed later as part of the `dependency_format` module. - let desired_strategy = self.sess.panic_strategy(); + let desired_strategy = tcx.sess.panic_strategy(); let name = match desired_strategy { PanicStrategy::Unwind => sym::panic_unwind, PanicStrategy::Abort => sym::panic_abort, @@ -995,64 +997,64 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { info!("panic runtime not found -- loading {}", name); let Some(cnum) = - self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected) + self.resolve_crate(tcx, name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected) else { return; }; - let data = self.cstore.get_crate_data(cnum); + let data = self.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. if !data.is_panic_runtime() { - self.dcx().emit_err(errors::CrateNotPanicRuntime { crate_name: name }); + tcx.dcx().emit_err(errors::CrateNotPanicRuntime { crate_name: name }); } if data.required_panic_strategy() != Some(desired_strategy) { - self.dcx() + tcx.dcx() .emit_err(errors::NoPanicStrategy { crate_name: name, strategy: desired_strategy }); } - self.cstore.injected_panic_runtime = Some(cnum); + self.injected_panic_runtime = Some(cnum); } - fn inject_profiler_runtime(&mut self) { + fn inject_profiler_runtime(&mut self, tcx: TyCtxt<'_>) { let needs_profiler_runtime = - self.sess.instrument_coverage() || self.sess.opts.cg.profile_generate.enabled(); - if !needs_profiler_runtime || self.sess.opts.unstable_opts.no_profiler_runtime { + tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled(); + if !needs_profiler_runtime || tcx.sess.opts.unstable_opts.no_profiler_runtime { return; } info!("loading profiler"); - let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime); + let name = Symbol::intern(&tcx.sess.opts.unstable_opts.profiler_runtime); let Some(cnum) = - self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected) + self.resolve_crate(tcx, name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected) else { return; }; - let data = self.cstore.get_crate_data(cnum); + let data = self.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.is_profiler_runtime() { - self.dcx().emit_err(errors::NotProfilerRuntime { crate_name: name }); + tcx.dcx().emit_err(errors::NotProfilerRuntime { crate_name: name }); } } - fn inject_allocator_crate(&mut self, krate: &ast::Crate) { - self.cstore.has_global_allocator = + fn inject_allocator_crate(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) { + self.has_global_allocator = match &*fn_spans(krate, Symbol::intern(&global_fn_name(sym::alloc))) { [span1, span2, ..] => { - self.dcx() + tcx.dcx() .emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); true } spans => !spans.is_empty(), }; - self.cstore.has_alloc_error_handler = match &*fn_spans( + self.has_alloc_error_handler = match &*fn_spans( krate, Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)), ) { [span1, span2, ..] => { - self.dcx() + tcx.dcx() .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 }); true } @@ -1063,7 +1065,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // about through the `#![needs_allocator]` attribute and is typically // written down in liballoc. if !attr::contains_name(&krate.attrs, sym::needs_allocator) - && !self.cstore.iter_crate_data().any(|(_, data)| data.needs_allocator()) + && !self.iter_crate_data().any(|(_, data)| data.needs_allocator()) { return; } @@ -1071,7 +1073,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // At this point we've determined that we need an allocator. Let's see // if our compilation session actually needs an allocator based on what // we're emitting. - let all_rlib = self.tcx.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib)); + let all_rlib = tcx.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib)); if all_rlib { return; } @@ -1086,12 +1088,12 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { #[allow(rustc::symbol_intern_string_literal)] let this_crate = Symbol::intern("this crate"); - let mut global_allocator = self.cstore.has_global_allocator.then_some(this_crate); - for (_, data) in self.cstore.iter_crate_data() { + let mut global_allocator = self.has_global_allocator.then_some(this_crate); + for (_, data) in self.iter_crate_data() { if data.has_global_allocator() { match global_allocator { Some(other_crate) => { - self.dcx().emit_err(errors::ConflictingGlobalAlloc { + tcx.dcx().emit_err(errors::ConflictingGlobalAlloc { crate_name: data.name(), other_crate_name: other_crate, }); @@ -1100,12 +1102,12 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } } - let mut alloc_error_handler = self.cstore.has_alloc_error_handler.then_some(this_crate); - for (_, data) in self.cstore.iter_crate_data() { + let mut alloc_error_handler = self.has_alloc_error_handler.then_some(this_crate); + for (_, data) in self.iter_crate_data() { if data.has_alloc_error_handler() { match alloc_error_handler { Some(other_crate) => { - self.dcx().emit_err(errors::ConflictingAllocErrorHandler { + tcx.dcx().emit_err(errors::ConflictingAllocErrorHandler { crate_name: data.name(), other_crate_name: other_crate, }); @@ -1116,35 +1118,36 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } if global_allocator.is_some() { - self.cstore.allocator_kind = Some(AllocatorKind::Global); + self.allocator_kind = Some(AllocatorKind::Global); } else { // Ok we haven't found a global allocator but we still need an // allocator. At this point our allocator request is typically fulfilled // by the standard library, denoted by the `#![default_lib_allocator]` // attribute. if !attr::contains_name(&krate.attrs, sym::default_lib_allocator) - && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) + && !self.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) { - self.dcx().emit_err(errors::GlobalAllocRequired); + tcx.dcx().emit_err(errors::GlobalAllocRequired); } - self.cstore.allocator_kind = Some(AllocatorKind::Default); + self.allocator_kind = Some(AllocatorKind::Default); } if alloc_error_handler.is_some() { - self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Global); + self.alloc_error_handler_kind = Some(AllocatorKind::Global); } else { // The alloc crate provides a default allocation error handler if // one isn't specified. - self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Default); + self.alloc_error_handler_kind = Some(AllocatorKind::Default); } } - fn inject_forced_externs(&mut self) { - for (name, entry) in self.sess.opts.externs.iter() { + fn inject_forced_externs(&mut self, tcx: TyCtxt<'_>) { + for (name, entry) in tcx.sess.opts.externs.iter() { if entry.force { let name_interned = Symbol::intern(name); if !self.used_extern_options.contains(&name_interned) { self.resolve_crate( + tcx, name_interned, DUMMY_SP, CrateDepKind::Explicit, @@ -1156,7 +1159,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } /// Inject the `compiler_builtins` crate if it is not already in the graph. - fn inject_compiler_builtins(&mut self, krate: &ast::Crate) { + fn inject_compiler_builtins(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) { // `compiler_builtins` does not get extern builtins, nor do `#![no_core]` crates if attr::contains_name(&krate.attrs, sym::compiler_builtins) || attr::contains_name(&krate.attrs, sym::no_core) @@ -1167,7 +1170,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // If a `#![compiler_builtins]` crate already exists, avoid injecting it twice. This is // the common case since usually it appears as a dependency of `std` or `alloc`. - for (cnum, cmeta) in self.cstore.iter_crate_data() { + for (cnum, cmeta) in self.iter_crate_data() { if cmeta.is_compiler_builtins() { info!("`compiler_builtins` already exists (cnum = {cnum}); skipping injection"); return; @@ -1176,6 +1179,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // `compiler_builtins` is not yet in the graph; inject it. Error on resolution failure. let Some(cnum) = self.resolve_crate( + tcx, sym::compiler_builtins, krate.spans.inner_span.shrink_to_lo(), CrateDepKind::Explicit, @@ -1186,17 +1190,17 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { }; // Sanity check that the loaded crate is `#![compiler_builtins]` - let cmeta = self.cstore.get_crate_data(cnum); + let cmeta = self.get_crate_data(cnum); if !cmeta.is_compiler_builtins() { - self.dcx().emit_err(errors::CrateNotCompilerBuiltins { crate_name: cmeta.name() }); + tcx.dcx().emit_err(errors::CrateNotCompilerBuiltins { crate_name: cmeta.name() }); } } - fn report_unused_deps(&mut self, krate: &ast::Crate) { + fn report_unused_deps_in_crate(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) { // Make a point span rather than covering the whole file let span = krate.spans.inner_span.shrink_to_lo(); // Complain about anything left over - for (name, entry) in self.sess.opts.externs.iter() { + for (name, entry) in tcx.sess.opts.externs.iter() { if let ExternLocation::FoundInLibrarySearchDirectories = entry.location { // Don't worry about pathless `--extern foo` sysroot references continue; @@ -1211,25 +1215,25 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } // Got a real unused --extern - if self.sess.opts.json_unused_externs.is_enabled() { - self.cstore.unused_externs.push(name_interned); + if tcx.sess.opts.json_unused_externs.is_enabled() { + self.unused_externs.push(name_interned); continue; } - self.sess.psess.buffer_lint( + tcx.sess.psess.buffer_lint( lint::builtin::UNUSED_CRATE_DEPENDENCIES, span, ast::CRATE_NODE_ID, BuiltinLintDiag::UnusedCrateDependency { extern_crate: name_interned, - local_crate: self.tcx.crate_name(LOCAL_CRATE), + local_crate: tcx.crate_name(LOCAL_CRATE), }, ); } } - fn report_future_incompatible_deps(&self, krate: &ast::Crate) { - let name = self.tcx.crate_name(LOCAL_CRATE); + fn report_future_incompatible_deps(&self, tcx: TyCtxt<'_>, krate: &ast::Crate) { + let name = tcx.crate_name(LOCAL_CRATE); if name.as_str() == "wasm_bindgen" { let major = env::var("CARGO_PKG_VERSION_MAJOR") @@ -1257,26 +1261,27 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // Make a point span rather than covering the whole file let span = krate.spans.inner_span.shrink_to_lo(); - self.sess.dcx().emit_err(errors::WasmCAbi { span }); + tcx.sess.dcx().emit_err(errors::WasmCAbi { span }); } } - pub fn postprocess(&mut self, krate: &ast::Crate) { - self.inject_compiler_builtins(krate); - self.inject_forced_externs(); - self.inject_profiler_runtime(); - self.inject_allocator_crate(krate); - self.inject_panic_runtime(krate); + pub fn postprocess(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) { + self.inject_compiler_builtins(tcx, krate); + self.inject_forced_externs(tcx); + self.inject_profiler_runtime(tcx); + self.inject_allocator_crate(tcx, krate); + self.inject_panic_runtime(tcx, krate); - self.report_unused_deps(krate); - self.report_future_incompatible_deps(krate); + self.report_unused_deps_in_crate(tcx, krate); + self.report_future_incompatible_deps(tcx, krate); - info!("{:?}", CrateDump(self.cstore)); + info!("{:?}", CrateDump(self)); } /// Process an `extern crate foo` AST node. pub fn process_extern_crate( &mut self, + tcx: TyCtxt<'_>, item: &ast::Item, def_id: LocalDefId, definitions: &Definitions, @@ -1286,7 +1291,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", ident, orig_name); let name = match orig_name { Some(orig_name) => { - validate_crate_name(self.sess, orig_name, Some(item.span)); + validate_crate_name(tcx.sess, orig_name, Some(item.span)); orig_name } None => ident.name, @@ -1297,10 +1302,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { CrateDepKind::Explicit }; - let cnum = self.resolve_crate(name, item.span, dep_kind, CrateOrigin::Extern)?; + let cnum = + self.resolve_crate(tcx, name, item.span, dep_kind, CrateOrigin::Extern)?; let path_len = definitions.def_path(def_id).data.len(); - self.cstore.update_extern_crate( + self.update_extern_crate( cnum, ExternCrate { src: ExternCrateSource::Extern(def_id.to_def_id()), @@ -1315,10 +1321,16 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } - pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option { - let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit, CrateOrigin::Extern)?; + pub fn process_path_extern( + &mut self, + tcx: TyCtxt<'_>, + name: Symbol, + span: Span, + ) -> Option { + let cnum = + self.resolve_crate(tcx, name, span, CrateDepKind::Explicit, CrateOrigin::Extern)?; - self.cstore.update_extern_crate( + self.update_extern_crate( cnum, ExternCrate { src: ExternCrateSource::Path, @@ -1332,8 +1344,8 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { Some(cnum) } - pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option { - self.maybe_resolve_crate(name, CrateDepKind::Explicit, CrateOrigin::Extern).ok() + pub fn maybe_process_path_extern(&mut self, tcx: TyCtxt<'_>, name: Symbol) -> Option { + self.maybe_resolve_crate(tcx, name, CrateDepKind::Explicit, CrateOrigin::Extern).ok() } } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index e56aabfd414..737577baa7a 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -897,9 +897,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { Some(self.r.graph_root) } else { let tcx = self.r.tcx; - let crate_id = self.r.crate_loader(|c| { - c.process_extern_crate(item, local_def_id, &tcx.definitions_untracked()) - }); + let crate_id = self.r.cstore_mut().process_extern_crate( + self.r.tcx, + item, + local_def_id, + &tcx.definitions_untracked(), + ); crate_id.map(|crate_id| { self.r.extern_crate_map.insert(local_def_id, crate_id); self.r.expect_module(crate_id.as_def_id()) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index f6f45adabe9..d72fbc189e7 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1425,7 +1425,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // otherwise cause duplicate suggestions. continue; } - let Some(crate_id) = self.crate_loader(|c| c.maybe_process_path_extern(ident.name)) + let Some(crate_id) = + self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name) else { continue; }; diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index ee462d90764..69095942f52 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2485,7 +2485,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let extern_prelude = self.r.extern_prelude.clone(); names.extend(extern_prelude.iter().flat_map(|(ident, _)| { self.r - .crate_loader(|c| c.maybe_process_path_extern(ident.name)) + .cstore_mut() + .maybe_process_path_extern(self.r.tcx, ident.name) .and_then(|crate_id| { let crate_mod = Res::Def(DefKind::Mod, crate_id.as_def_id()); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index dae30b77ec1..0d41a822e8a 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -45,7 +45,7 @@ use rustc_attr_data_structures::StrippedCfgItem; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::FreezeReadGuard; +use rustc_data_structures::sync::{FreezeReadGuard, FreezeWriteGuard}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed}; use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind}; @@ -58,7 +58,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, use rustc_hir::definitions::DisambiguatorState; use rustc_hir::{PrimTy, TraitCandidate}; use rustc_index::bit_set::DenseBitSet; -use rustc_metadata::creader::{CStore, CrateLoader}; +use rustc_metadata::creader::CStore; use rustc_middle::metadata::ModChild; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::query::Providers; @@ -1110,7 +1110,6 @@ pub struct Resolver<'ra, 'tcx> { builtin_types_bindings: FxHashMap>, builtin_attrs_bindings: FxHashMap>, registered_tool_bindings: FxHashMap>, - used_extern_options: FxHashSet, macro_names: FxHashSet, builtin_macros: FxHashMap, registered_tools: &'tcx RegisteredTools, @@ -1546,7 +1545,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { (*ident, binding) }) .collect(), - used_extern_options: Default::default(), macro_names: FxHashSet::default(), builtin_macros: Default::default(), registered_tools, @@ -1733,18 +1731,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { StableHashingContext::new(self.tcx.sess, self.tcx.untracked()) } - fn crate_loader(&mut self, f: impl FnOnce(&mut CrateLoader<'_, '_>) -> T) -> T { - f(&mut CrateLoader::new( - self.tcx, - &mut CStore::from_tcx_mut(self.tcx), - &mut self.used_extern_options, - )) - } - fn cstore(&self) -> FreezeReadGuard<'_, CStore> { CStore::from_tcx(self.tcx) } + fn cstore_mut(&self) -> FreezeWriteGuard<'_, CStore> { + CStore::from_tcx_mut(self.tcx) + } + fn dummy_ext(&self, macro_kind: MacroKind) -> Arc { match macro_kind { MacroKind::Bang => Arc::clone(&self.dummy_ext_bang), @@ -1790,7 +1784,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.tcx.sess.time("resolve_report_errors", || self.report_errors(krate)); self.tcx .sess - .time("resolve_postprocess", || self.crate_loader(|c| c.postprocess(krate))); + .time("resolve_postprocess", || self.cstore_mut().postprocess(self.tcx, krate)); }); // Make sure we don't mutate the cstore from here on. @@ -2156,7 +2150,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Some(if let Some(binding) = entry.binding { if finalize { if !entry.is_import() { - self.crate_loader(|c| c.process_path_extern(ident.name, ident.span)); + self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span); } else if entry.introduced_by_item { self.record_use(ident, binding, Used::Other); } @@ -2165,13 +2159,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } else { let crate_id = if finalize { let Some(crate_id) = - self.crate_loader(|c| c.process_path_extern(ident.name, ident.span)) + self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span) else { return Some(self.dummy_binding); }; crate_id } else { - self.crate_loader(|c| c.maybe_process_path_extern(ident.name))? + self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)? }; let res = Res::Def(DefKind::Mod, crate_id.as_def_id()); self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT) -- cgit 1.4.1-3-g733a5 From c58e0bd09368a96dbde1ec1f30e36764e1431125 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Sat, 19 Jul 2025 01:49:19 +0800 Subject: rename `emit_unless` to `emit_unless_delay` Signed-off-by: xizheyin --- compiler/rustc_errors/src/diagnostic.rs | 2 +- compiler/rustc_hir_analysis/src/check/compare_impl_item.rs | 14 +++++++------- .../rustc_hir_analysis/src/collect/resolve_bound_vars.rs | 2 +- .../rustc_hir_analysis/src/hir_ty_lowering/generics.rs | 2 +- compiler/rustc_hir_typeck/src/coercion.rs | 2 +- compiler/rustc_hir_typeck/src/expr.rs | 6 +++--- compiler/rustc_resolve/src/late.rs | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) (limited to 'compiler/rustc_resolve/src') diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a128f8d31a1..96c7ba6ed27 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1421,7 +1421,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// /// See `emit` and `delay_as_bug` for details. #[track_caller] - pub fn emit_unless(mut self, delay: bool) -> G::EmitResult { + pub fn emit_unless_delay(mut self, delay: bool) -> G::EmitResult { if delay { self.downgrade_to_delayed_bug(); } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 87db80f2423..e24426f9fed 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1173,7 +1173,7 @@ fn check_region_bounds_on_impl_item<'tcx>( bounds_span, where_span, }) - .emit_unless(delay); + .emit_unless_delay(delay); Err(reported) } @@ -1481,7 +1481,7 @@ fn compare_self_type<'tcx>( } else { err.note_trait_signature(trait_m.name(), trait_m.signature(tcx)); } - return Err(err.emit_unless(delay)); + return Err(err.emit_unless_delay(delay)); } (true, false) => { @@ -1502,7 +1502,7 @@ fn compare_self_type<'tcx>( err.note_trait_signature(trait_m.name(), trait_m.signature(tcx)); } - return Err(err.emit_unless(delay)); + return Err(err.emit_unless_delay(delay)); } } @@ -1662,7 +1662,7 @@ fn compare_number_of_generics<'tcx>( err.span_label(*span, "`impl Trait` introduces an implicit type parameter"); } - let reported = err.emit_unless(delay); + let reported = err.emit_unless_delay(delay); err_occurred = Some(reported); } } @@ -1745,7 +1745,7 @@ fn compare_number_of_method_arguments<'tcx>( ), ); - return Err(err.emit_unless(delay)); + return Err(err.emit_unless_delay(delay)); } Ok(()) @@ -1872,7 +1872,7 @@ fn compare_synthetic_generics<'tcx>( ); }; } - error_found = Some(err.emit_unless(delay)); + error_found = Some(err.emit_unless_delay(delay)); } } if let Some(reported) = error_found { Err(reported) } else { Ok(()) } @@ -1974,7 +1974,7 @@ fn compare_generic_param_kinds<'tcx>( err.span_label(impl_header_span, ""); err.span_label(param_impl_span, make_param_message("found", param_impl)); - let reported = err.emit_unless(delay); + let reported = err.emit_unless_delay(delay); return Err(reported); } } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 77e63e38c8c..eb3492f5de6 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -2495,7 +2495,7 @@ fn deny_non_region_late_bound( format!("late-bound {what} parameter not allowed on {where_}"), ); - let guar = diag.emit_unless(!tcx.features().non_lifetime_binders() || !first); + let guar = diag.emit_unless_delay(!tcx.features().non_lifetime_binders() || !first); first = false; *arg = ResolvedArg::Error(guar); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index 8c7c3750865..fc519c194bb 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -570,7 +570,7 @@ pub(crate) fn check_generic_arg_count( gen_args, def_id, )) - .emit_unless(all_params_are_binded) + .emit_unless_delay(all_params_are_binded) }); Err(reported) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index b2a229ad651..6d67535da5f 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1775,7 +1775,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { ); } - let reported = err.emit_unless(unsized_return); + let reported = err.emit_unless_delay(unsized_return); self.final_ty = Some(Ty::new_error(fcx.tcx, reported)); } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 067ee0f0eb0..08e8164078c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1549,7 +1549,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the assignment expression itself is ill-formed, don't // bother emitting another error - err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error()) + err.emit_unless_delay(lhs_ty.references_error() || rhs_ty.references_error()) } pub(super) fn check_expr_let( @@ -3865,7 +3865,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.dcx() .create_err(NoVariantNamed { span: ident.span, ident, ty: container }) .with_span_label(field.span, "variant not found") - .emit_unless(container.references_error()); + .emit_unless_delay(container.references_error()); break; }; let Some(&subfield) = fields.next() else { @@ -3897,7 +3897,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { enum_span: field.span, field_span: subident.span, }) - .emit_unless(container.references_error()); + .emit_unless_delay(container.references_error()); break; }; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 93cec8daa5a..a3a770502de 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2913,7 +2913,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.r .dcx() .create_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span }) - .emit_unless(is_raw_underscore_lifetime); + .emit_unless_delay(is_raw_underscore_lifetime); // Record lifetime res, so lowering knows there is something fishy. self.record_lifetime_param(param.id, LifetimeRes::Error); continue; -- cgit 1.4.1-3-g733a5 From 9613ce02c393104ba7ebd4655d004e5f6da3db18 Mon Sep 17 00:00:00 2001 From: Rémy Rakic Date: Sat, 19 Jul 2025 09:30:39 +0000 Subject: Revert "resolve: Make disambiguators for underscore bindings module-local" This reverts commit 998df3a3e851908afd05c3318f16d99849af5c55. --- compiler/rustc_resolve/src/build_reduced_graph.rs | 30 ++++++++---------- compiler/rustc_resolve/src/imports.rs | 38 ++++++++--------------- compiler/rustc_resolve/src/lib.rs | 33 +++++++++++--------- compiler/rustc_resolve/src/macros.rs | 2 +- 4 files changed, 45 insertions(+), 58 deletions(-) (limited to 'compiler/rustc_resolve/src') diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index c3bfd759f4c..737577baa7a 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -49,7 +49,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ns: Namespace, binding: NameBinding<'ra>, ) { - if let Err(old_binding) = self.try_define(parent, ident, ns, binding, false) { + let key = self.new_disambiguated_key(ident, ns); + if let Err(old_binding) = self.try_define(parent, key, binding, false) { self.report_conflict(parent, ident, ns, old_binding, binding); } } @@ -441,18 +442,16 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.indeterminate_imports.push(import); match import.kind { + // Don't add unresolved underscore imports to modules + ImportKind::Single { target: Ident { name: kw::Underscore, .. }, .. } => {} ImportKind::Single { target, type_ns_only, .. } => { - // Don't add underscore imports to `single_imports` - // because they cannot define any usable names. - if target.name != kw::Underscore { - self.r.per_ns(|this, ns| { - if !type_ns_only || ns == TypeNS { - let key = BindingKey::new(target, ns); - let mut resolution = this.resolution(current_module, key).borrow_mut(); - resolution.single_imports.insert(import); - } - }); - } + self.r.per_ns(|this, ns| { + if !type_ns_only || ns == TypeNS { + let key = BindingKey::new(target, ns); + let mut resolution = this.resolution(current_module, key).borrow_mut(); + resolution.single_imports.insert(import); + } + }); } // We don't add prelude imports to the globs since they only affect lexical scopes, // which are not relevant to import resolution. @@ -1409,12 +1408,9 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; self.r.define(parent, ident, ns, self.res(def_id), vis, item.span, expansion); - } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) - && ident.name != kw::Underscore - { - // Don't add underscore names, they cannot be looked up anyway. + } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) { let impl_def_id = self.r.tcx.local_parent(local_def_id); - let key = BindingKey::new(ident, ns); + let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns); self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key); } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index b4c15ed1ca7..0a4c25b0eb0 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -25,7 +25,7 @@ use rustc_span::{Ident, Span, Symbol, kw, sym}; use smallvec::SmallVec; use tracing::debug; -use crate::Namespace::{self, *}; +use crate::Namespace::*; use crate::diagnostics::{DiagMode, Suggestion, import_candidates}; use crate::errors::{ CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate, @@ -338,20 +338,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn try_define( &mut self, module: Module<'ra>, - ident: Ident, - ns: Namespace, + key: BindingKey, binding: NameBinding<'ra>, warn_ambiguity: bool, ) -> Result<(), NameBinding<'ra>> { let res = binding.res(); - self.check_reserved_macro_name(ident, res); + self.check_reserved_macro_name(key.ident, res); self.set_binding_parent_module(binding, module); - // Even if underscore names cannot be looked up, we still need to add them to modules, - // because they can be fetched by glob imports from those modules, and bring traits - // into scope both directly and through glob imports. - let key = BindingKey::new_disambiguated(ident, ns, || { - (module.0.0.lazy_resolutions.borrow().len() + 1).try_into().unwrap() - }); self.update_resolution(module, key, warn_ambiguity, |this, resolution| { if let Some(old_binding) = resolution.best_binding() { if res == Res::Err && old_binding.res() != Res::Err { @@ -390,7 +383,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { (old_glob @ true, false) | (old_glob @ false, true) => { let (glob_binding, non_glob_binding) = if old_glob { (old_binding, binding) } else { (binding, old_binding) }; - if ns == MacroNS + if key.ns == MacroNS && non_glob_binding.expansion != LocalExpnId::ROOT && glob_binding.res() != non_glob_binding.res() { @@ -496,10 +489,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; if self.is_accessible_from(binding.vis, scope) { let imported_binding = self.import(binding, *import); + let key = BindingKey { ident, ..key }; let _ = self.try_define( import.parent_scope.module, - ident, - key.ns, + key, imported_binding, warn_ambiguity, ); @@ -521,15 +514,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let dummy_binding = self.dummy_binding; let dummy_binding = self.import(dummy_binding, import); self.per_ns(|this, ns| { - let module = import.parent_scope.module; - let _ = this.try_define(module, target, ns, dummy_binding, false); - // Don't remove underscores from `single_imports`, they were never added. - if target.name != kw::Underscore { - let key = BindingKey::new(target, ns); - this.update_resolution(module, key, false, |_, resolution| { - resolution.single_imports.swap_remove(&import); - }) - } + let key = BindingKey::new(target, ns); + let _ = this.try_define(import.parent_scope.module, key, dummy_binding, false); + this.update_resolution(import.parent_scope.module, key, false, |_, resolution| { + resolution.single_imports.swap_remove(&import); + }) }); self.record_use(target, dummy_binding, Used::Other); } else if import.imported_module.get().is_none() { @@ -906,7 +895,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { PendingBinding::Ready(Some(imported_binding)) } Err(Determinacy::Determined) => { - // Don't remove underscores from `single_imports`, they were never added. + // Don't update the resolution for underscores, because it was never added. if target.name != kw::Underscore { let key = BindingKey::new(target, ns); this.update_resolution(parent, key, false, |_, resolution| { @@ -1521,8 +1510,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .is_some_and(|binding| binding.warn_ambiguity_recursive()); let _ = self.try_define( import.parent_scope.module, - key.ident, - key.ns, + key, imported_binding, warn_ambiguity, ); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 948b67a3798..0d41a822e8a 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -532,26 +532,15 @@ struct BindingKey { /// identifier. ident: Ident, ns: Namespace, - /// When we add an underscore binding (with ident `_`) to some module, this field has - /// a non-zero value that uniquely identifies this binding in that module. - /// For non-underscore bindings this field is zero. - /// When a key is constructed for name lookup (as opposed to name definition), this field is - /// also zero, even for underscore names, so for underscores the lookup will never succeed. + /// 0 if ident is not `_`, otherwise a value that's unique to the specific + /// `_` in the expanded AST that introduced this binding. disambiguator: u32, } impl BindingKey { fn new(ident: Ident, ns: Namespace) -> Self { - BindingKey { ident: ident.normalize_to_macros_2_0(), ns, disambiguator: 0 } - } - - fn new_disambiguated( - ident: Ident, - ns: Namespace, - disambiguator: impl FnOnce() -> u32, - ) -> BindingKey { - let disambiguator = if ident.name == kw::Underscore { disambiguator() } else { 0 }; - BindingKey { ident: ident.normalize_to_macros_2_0(), ns, disambiguator } + let ident = ident.normalize_to_macros_2_0(); + BindingKey { ident, ns, disambiguator: 0 } } } @@ -1098,6 +1087,8 @@ pub struct Resolver<'ra, 'tcx> { extern_module_map: RefCell>>, binding_parent_modules: FxHashMap, Module<'ra>>, + underscore_disambiguator: u32, + /// Maps glob imports to the names of items actually imported. glob_map: FxIndexMap>, glob_error: Option, @@ -1509,6 +1500,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { extern_crate_map: Default::default(), module_children: Default::default(), trait_map: NodeMap::default(), + underscore_disambiguator: 0, empty_module, local_module_map, extern_module_map: Default::default(), @@ -1889,6 +1881,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { import_ids } + fn new_disambiguated_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey { + let ident = ident.normalize_to_macros_2_0(); + let disambiguator = if ident.name == kw::Underscore { + self.underscore_disambiguator += 1; + self.underscore_disambiguator + } else { + 0 + }; + BindingKey { ident, ns, disambiguator } + } + fn resolutions(&mut self, module: Module<'ra>) -> &'ra Resolutions<'ra> { if module.populate_on_access.get() { module.populate_on_access.set(false); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 0e8904a7dea..77ef7f56c09 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -530,7 +530,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { target_trait.for_each_child(self, |this, ident, ns, _binding| { // FIXME: Adjust hygiene for idents from globs, like for glob imports. if let Some(overriding_keys) = this.impl_binding_keys.get(&impl_def_id) - && overriding_keys.contains(&BindingKey::new(ident, ns)) + && overriding_keys.contains(&BindingKey::new(ident.normalize_to_macros_2_0(), ns)) { // The name is overridden, do not produce it from the glob delegation. } else { -- cgit 1.4.1-3-g733a5