Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_metadata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(proc_macro_internals)]
#![feature(result_option_map_or_default)]
#![feature(trusted_len)]
// tidy-alphabetical-end

Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1295,6 +1295,21 @@ impl<'a> CrateMetadataRef<'a> {
}
}

fn get_ambig_module_children(
self,
id: DefIndex,
sess: &Session,
) -> impl Iterator<Item = AmbigModChild> {
gen move {
let children = self.root.tables.ambig_module_children.get(self, id);
if !children.is_default() {
for child in children.decode((self, sess)) {
yield child;
}
}
}
}

fn is_ctfe_mir_available(self, id: DefIndex) -> bool {
self.root.tables.mir_for_ctfe.get(self, id).is_some()
}
Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::bug;
use rustc_middle::metadata::ModChild;
use rustc_middle::metadata::{AmbigModChild, ModChild};
use rustc_middle::middle::exported_symbols::ExportedSymbol;
use rustc_middle::middle::stability::DeprecationEntry;
use rustc_middle::query::{ExternProviders, LocalCrate};
Expand Down Expand Up @@ -584,6 +584,14 @@ impl CStore {
self.get_crate_data(def_id.krate).get_expn_that_defined(def_id.index, sess)
}

pub fn ambig_module_children_untracked(
&self,
def_id: DefId,
sess: &Session,
) -> impl Iterator<Item = AmbigModChild> {
self.get_crate_data(def_id.krate).get_ambig_module_children(def_id.index, sess)
}

/// Only public-facing way to traverse all the definitions in a non-local crate.
/// Critically useful for this third-party project: <https://github.com/hacspec/hacspec>.
/// See <https://github.com/rust-lang/rust/pull/85889> for context.
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1731,6 +1731,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {

record_defaulted_array!(self.tables.module_children_reexports[def_id] <-
module_children.iter().filter(|child| !child.reexport_chain.is_empty()));

let ambig_module_children = tcx
.resolutions(())
.ambig_module_children
.get(&local_def_id)
.map_or_default(|v| &v[..]);
record_defaulted_array!(self.tables.ambig_module_children[def_id] <-
ambig_module_children);
}
}

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use rustc_index::bit_set::DenseBitSet;
use rustc_macros::{
Decodable, Encodable, MetadataDecodable, MetadataEncodable, TyDecodable, TyEncodable,
};
use rustc_middle::metadata::ModChild;
use rustc_middle::metadata::{AmbigModChild, ModChild};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs;
Expand Down Expand Up @@ -399,6 +399,7 @@ define_tables! {
// That's why the encoded list needs to contain `ModChild` structures describing all the names
// individually instead of `DefId`s.
module_children_reexports: Table<DefIndex, LazyArray<ModChild>>,
ambig_module_children: Table<DefIndex, LazyArray<AmbigModChild>>,
cross_crate_inlinable: Table<DefIndex, bool>,
asyncness: Table<DefIndex, ty::Asyncness>,
constness: Table<DefIndex, hir::Constness>,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_metadata/src/rmeta/parameterized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ trivially_parameterized_over_tcx! {
rustc_hir::def_id::DefIndex,
rustc_hir::definitions::DefKey,
rustc_index::bit_set::DenseBitSet<u32>,
rustc_middle::metadata::AmbigModChild,
rustc_middle::metadata::ModChild,
rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs,
rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile,
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_middle/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,17 @@ pub struct ModChild {
/// Empty if the module child is a proper item.
pub reexport_chain: SmallVec<[Reexport; 2]>,
}

#[derive(Debug, TyEncodable, TyDecodable, HashStable)]
pub enum AmbigModChildKind {
GlobVsGlob,
GlobVsExpanded,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming this means logic should be able to preserve globvsexpanded ambiguities across crate boundaries but I don't see any tests exercising this logic. Can you add one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a test.
In any case, cross-crate GlobVsExpanded is unnecessary and will be removed in #149681.

}

/// Same as `ModChild`, however, it includes ambiguity error.
#[derive(Debug, TyEncodable, TyDecodable, HashStable)]
pub struct AmbigModChild {
pub main: ModChild,
pub second: ModChild,
pub kind: AmbigModChildKind,
}
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ pub use self::typeck_results::{
Rust2024IncompatiblePatInfo, TypeckResults, UserType, UserTypeAnnotationIndex, UserTypeKind,
};
use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
use crate::metadata::ModChild;
use crate::metadata::{AmbigModChild, ModChild};
use crate::middle::privacy::EffectiveVisibilities;
use crate::mir::{Body, CoroutineLayout, CoroutineSavedLocal, SourceInfo};
use crate::query::{IntoQueryParam, Providers};
Expand Down Expand Up @@ -173,6 +173,7 @@ pub struct ResolverGlobalCtxt {
pub extern_crate_map: UnordMap<LocalDefId, CrateNum>,
pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
pub module_children: LocalDefIdMap<Vec<ModChild>>,
pub ambig_module_children: LocalDefIdMap<Vec<AmbigModChild>>,
pub glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
pub main_def: Option<MainDefinition>,
pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
Expand Down
79 changes: 57 additions & 22 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use rustc_hir::def::{self, *};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
use rustc_index::bit_set::DenseBitSet;
use rustc_metadata::creader::LoadedMacro;
use rustc_middle::metadata::ModChild;
use rustc_middle::metadata::{AmbigModChildKind, ModChild, Reexport};
use rustc_middle::ty::{Feed, Visibility};
use rustc_middle::{bug, span_bug};
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
Expand All @@ -36,9 +36,9 @@ use crate::imports::{ImportData, ImportKind};
use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
use crate::ref_mut::CmCell;
use crate::{
BindingKey, ExternPreludeEntry, Finalize, MacroData, Module, ModuleKind, ModuleOrUniformRoot,
NameBinding, ParentScope, PathResult, ResolutionError, Resolver, Segment, Used,
VisResolutionError, errors,
AmbiguityKind, BindingKey, ExternPreludeEntry, Finalize, MacroData, Module, ModuleKind,
ModuleOrUniformRoot, NameBinding, NameBindingData, NameBindingKind, ParentScope, PathResult,
ResolutionError, Resolver, Segment, Used, VisResolutionError, errors,
};

type Res = def::Res<NodeId>;
Expand Down Expand Up @@ -81,9 +81,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
res: Res,
vis: Visibility<DefId>,
span: Span,
expn_id: LocalExpnId,
expansion: LocalExpnId,
ambiguity: Option<(NameBinding<'ra>, AmbiguityKind)>,
) {
let binding = self.arenas.new_res_binding(res, vis, span, expn_id);
let binding = self.arenas.alloc_name_binding(NameBindingData {
kind: NameBindingKind::Res(res),
ambiguity,
// External ambiguities always report the `AMBIGUOUS_GLOB_IMPORTS` lint at the moment.
warn_ambiguity: true,
vis,
span,
expansion,
});
// 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.
Expand Down Expand Up @@ -232,9 +241,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}

pub(crate) fn build_reduced_graph_external(&self, module: Module<'ra>) {
for (i, child) in self.tcx.module_children(module.def_id()).into_iter().enumerate() {
let parent_scope = ParentScope::module(module, self.arenas);
self.build_reduced_graph_for_external_crate_res(child, parent_scope, i)
let def_id = module.def_id();
let children = self.tcx.module_children(def_id);
let parent_scope = ParentScope::module(module, self.arenas);
for (i, child) in children.iter().enumerate() {
self.build_reduced_graph_for_external_crate_res(child, parent_scope, i, None)
}
for (i, child) in
self.cstore().ambig_module_children_untracked(def_id, self.tcx.sess).enumerate()
{
self.build_reduced_graph_for_external_crate_res(
&child.main,
parent_scope,
children.len() + i,
Some((&child.second, child.kind)),
)
}
}

Expand All @@ -244,18 +265,36 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
child: &ModChild,
parent_scope: ParentScope<'ra>,
child_index: usize,
ambig_child: Option<(&ModChild, AmbigModChildKind)>,
) {
let parent = parent_scope.module;
let child_span = |this: &Self, reexport_chain: &[Reexport], res: def::Res<_>| {
this.def_span(
reexport_chain
.first()
.and_then(|reexport| reexport.id())
.unwrap_or_else(|| res.def_id()),
)
};
let ModChild { ident, res, vis, ref reexport_chain } = *child;
let span = self.def_span(
reexport_chain
.first()
.and_then(|reexport| reexport.id())
.unwrap_or_else(|| res.def_id()),
);
let span = child_span(self, reexport_chain, res);
let res = res.expect_non_local();
let expansion = parent_scope.expansion;
let ambig = ambig_child.map(|(ambig_child, ambig_kind)| {
let ModChild { ident: _, res, vis, ref reexport_chain } = *ambig_child;
let span = child_span(self, reexport_chain, res);
let res = res.expect_non_local();
let ambig_kind = match ambig_kind {
AmbigModChildKind::GlobVsGlob => AmbiguityKind::GlobVsGlob,
AmbigModChildKind::GlobVsExpanded => AmbiguityKind::GlobVsExpanded,
};
(self.arenas.new_res_binding(res, vis, span, expansion), ambig_kind)
});

// Record primary definitions.
let define_extern = |ns| {
self.define_extern(parent, ident, ns, child_index, res, vis, span, expansion, ambig)
};
match res {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: When I was reviewing this section I felt like there was a high signal to noise ratio with the way this match is structured. As far as I can tell the only difference between the different define_extern calls is the namespace argument. I'd recommend changing this match to evaluate to the namespace and pass that ns local into a single shared invocation of define_extern regardless of res defkind.

Especially with the new field changing the formatting to be one line per argument, its even more difficult now to visually tell what is different and what isn't between those invocations.

Feel free to ignore this one, just thought I'd share my experience.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can factor the define_extern calls into a closure.
I'd like to preserve the exhaustive match because of the bug!("unexpected resolution: {:?}", res) part.

Res::Def(
DefKind::Mod
Expand All @@ -272,9 +311,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
_,
)
| Res::PrimTy(..)
| Res::ToolMod => {
self.define_extern(parent, ident, TypeNS, child_index, res, vis, span, expansion)
}
| Res::ToolMod => define_extern(TypeNS),
Res::Def(
DefKind::Fn
| DefKind::AssocFn
Expand All @@ -283,10 +320,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
| DefKind::AssocConst
| DefKind::Ctor(..),
_,
) => self.define_extern(parent, ident, ValueNS, child_index, res, vis, span, expansion),
Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => {
self.define_extern(parent, ident, MacroNS, child_index, res, vis, span, expansion)
}
) => define_extern(ValueNS),
Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => define_extern(MacroNS),
Res::Def(
DefKind::TyParam
| DefKind::ConstParam
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let diag = self.ambiguity_diagnostic(ambiguity_error);

if ambiguity_error.warning {
let NameBindingKind::Import { import, .. } = ambiguity_error.b1.0.kind else {
unreachable!()
let node_id = match ambiguity_error.b1.0.kind {
NameBindingKind::Import { import, .. } => import.root_id,
NameBindingKind::Res(_) => CRATE_NODE_ID,
};
self.lint_buffer.buffer_lint(
AMBIGUOUS_GLOB_IMPORTS,
import.root_id,
node_id,
diag.ident.span,
diag,
);
Expand Down
50 changes: 36 additions & 14 deletions compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc_errors::codes::*;
use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err};
use rustc_hir::def::{self, DefKind, PartialRes};
use rustc_hir::def_id::{DefId, LocalDefIdMap};
use rustc_middle::metadata::{ModChild, Reexport};
use rustc_middle::metadata::{AmbigModChild, AmbigModChildKind, ModChild, Reexport};
use rustc_middle::span_bug;
use rustc_middle::ty::Visibility;
use rustc_session::lint::BuiltinLintDiag;
Expand All @@ -21,7 +21,6 @@ use rustc_session::parse::feature_err;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::hygiene::LocalExpnId;
use rustc_span::{Ident, Span, Symbol, kw, sym};
use smallvec::SmallVec;
use tracing::debug;

use crate::Namespace::{self, *};
Expand Down Expand Up @@ -227,7 +226,7 @@ impl<'ra> ImportData<'ra> {
}
}

fn simplify(&self, r: &Resolver<'_, '_>) -> Reexport {
pub(crate) fn simplify(&self, r: &Resolver<'_, '_>) -> Reexport {
let to_def_id = |id| r.local_def_id(id).to_def_id();
match self.kind {
ImportKind::Single { id, .. } => Reexport::Single(to_def_id(id)),
Expand Down Expand Up @@ -571,10 +570,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {

pub(crate) fn finalize_imports(&mut self) {
let mut module_children = Default::default();
let mut ambig_module_children = Default::default();
for module in &self.local_modules {
self.finalize_resolutions_in(*module, &mut module_children);
self.finalize_resolutions_in(*module, &mut module_children, &mut ambig_module_children);
}
self.module_children = module_children;
self.ambig_module_children = ambig_module_children;

let mut seen_spans = FxHashSet::default();
let mut errors = vec![];
Expand Down Expand Up @@ -1546,33 +1547,54 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
&self,
module: Module<'ra>,
module_children: &mut LocalDefIdMap<Vec<ModChild>>,
ambig_module_children: &mut LocalDefIdMap<Vec<AmbigModChild>>,
) {
// Since import resolution is finished, globs will not define any more names.
*module.globs.borrow_mut(self) = Vec::new();

let Some(def_id) = module.opt_def_id() else { return };

let mut children = Vec::new();
let mut ambig_children = Vec::new();

module.for_each_child(self, |this, ident, _, binding| {
let res = binding.res().expect_non_local();
let error_ambiguity = binding.is_ambiguity_recursive() && !binding.warn_ambiguity;
if res != def::Res::Err && !error_ambiguity {
let mut reexport_chain = SmallVec::new();
let mut next_binding = binding;
while let NameBindingKind::Import { binding, import, .. } = next_binding.kind {
reexport_chain.push(import.simplify(this));
next_binding = binding;
}
if res != def::Res::Err {
let child = |reexport_chain| ModChild {
ident: ident.0,
res,
vis: binding.vis,
reexport_chain,
};
if let Some((ambig_binding1, ambig_binding2, ambig_kind)) =
binding.descent_to_ambiguity()
{
let main = child(ambig_binding1.reexport_chain(this));
let second = ModChild {
ident: ident.0,
res: ambig_binding2.res().expect_non_local(),
vis: ambig_binding2.vis,
reexport_chain: ambig_binding2.reexport_chain(this),
};
let kind = match ambig_kind {
AmbiguityKind::GlobVsGlob => AmbigModChildKind::GlobVsGlob,
AmbiguityKind::GlobVsExpanded => AmbigModChildKind::GlobVsExpanded,
_ => unreachable!(),
};

children.push(ModChild { ident: ident.0, res, vis: binding.vis, reexport_chain });
ambig_children.push(AmbigModChild { main, second, kind })
} else {
children.push(child(binding.reexport_chain(this)));
}
}
});

if !children.is_empty() {
// Should be fine because this code is only called for local modules.
module_children.insert(def_id.expect_local(), children);
}
if !ambig_children.is_empty() {
ambig_module_children.insert(def_id.expect_local(), ambig_children);
}
}
}

Expand Down
Loading
Loading