Skip to content

resolve: Remove ScopeSet::Late #145597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
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
10 changes: 5 additions & 5 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1020,11 +1020,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
&mut self,
suggestions: &mut Vec<TypoSuggestion>,
scope_set: ScopeSet<'ra>,
parent_scope: &ParentScope<'ra>,
ps: &ParentScope<'ra>,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The formatting becomes awful if the visit_scopes call below becomes too long.

ctxt: SyntaxContext,
filter_fn: &impl Fn(Res) -> bool,
) {
self.cm().visit_scopes(scope_set, parent_scope, ctxt, |this, scope, use_prelude, _| {
self.cm().visit_scopes(scope_set, ps, ctxt, None, |this, scope, use_prelude, _| {
match scope {
Scope::DeriveHelpers(expn_id) => {
let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
Expand Down Expand Up @@ -1557,7 +1557,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
});
}
for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
let Ok(binding) = self.cm().early_resolve_ident_in_lexical_scope(
let Ok(binding) = self.cm().resolve_ident_in_scope_set(
ident,
ScopeSet::All(ns),
parent_scope,
Expand Down Expand Up @@ -2371,7 +2371,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
} else {
self.cm()
.early_resolve_ident_in_lexical_scope(
.resolve_ident_in_scope_set(
ident,
ScopeSet::All(ns_to_try),
parent_scope,
Expand Down Expand Up @@ -2474,7 +2474,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
},
)
});
if let Ok(binding) = self.cm().early_resolve_ident_in_lexical_scope(
if let Ok(binding) = self.cm().resolve_ident_in_scope_set(
ident,
ScopeSet::All(ValueNS),
parent_scope,
Expand Down
59 changes: 28 additions & 31 deletions compiler/rustc_resolve/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::{
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, CmResolver, Determinacy,
Finalize, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot,
NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError,
Resolver, Scope, ScopeSet, Segment, Used, Weak, errors,
Resolver, Scope, ScopeSet, Segment, Stage, Used, Weak, errors,
};

#[derive(Copy, Clone)]
Expand Down Expand Up @@ -49,6 +49,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
scope_set: ScopeSet<'ra>,
parent_scope: &ParentScope<'ra>,
ctxt: SyntaxContext,
derive_fallback_lint_id: Option<NodeId>,
mut visitor: impl FnMut(
&mut CmResolver<'r, 'ra, 'tcx>,
Scope<'ra>,
Expand Down Expand Up @@ -99,15 +100,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {

let rust_2015 = ctxt.edition().is_rust_2015();
let (ns, macro_kind) = match scope_set {
ScopeSet::All(ns)
| ScopeSet::ModuleAndExternPrelude(ns, _)
| ScopeSet::Late(ns, ..) => (ns, None),
ScopeSet::All(ns) | ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None),
ScopeSet::ExternPrelude => (TypeNS, None),
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
};
let module = match scope_set {
// Start with the specified module.
ScopeSet::Late(_, module, _) | ScopeSet::ModuleAndExternPrelude(_, module) => module,
ScopeSet::ModuleAndExternPrelude(_, module) => module,
// Jump out of trait or enum modules, they do not act as scopes.
_ => parent_scope.module.nearest_item_scope(),
};
Expand Down Expand Up @@ -193,10 +192,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
},
Scope::Module(module, prev_lint_id) => {
use_prelude = !module.no_implicit_prelude;
let derive_fallback_lint_id = match scope_set {
ScopeSet::Late(.., lint_id) => lint_id,
_ => None,
};
match self.hygienic_lexical_parent(module, &mut ctxt, derive_fallback_lint_id) {
Some((parent_module, lint_id)) => {
Scope::Module(parent_module, lint_id.or(prev_lint_id))
Expand Down Expand Up @@ -349,11 +344,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
return Some(LexicalScopeBinding::Item(binding));
} else if let RibKind::Module(module) = rib.kind {
// Encountered a module item, abandon ribs and look into that module and preludes.
let parent_scope = &ParentScope { module, ..*parent_scope };
let finalize = finalize.map(|f| Finalize { stage: Stage::Late, ..f });
return self
.cm()
.early_resolve_ident_in_lexical_scope(
.resolve_ident_in_scope_set(
orig_ident,
ScopeSet::Late(ns, module, finalize.map(|finalize| finalize.node_id)),
ScopeSet::All(ns),
parent_scope,
finalize,
finalize.is_some(),
Expand All @@ -376,13 +373,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
unreachable!()
}

/// Resolve an identifier in lexical scope.
/// This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during
/// expansion and import resolution (perhaps they can be merged in the future).
/// The function is used for resolving initial segments of macro paths (e.g., `foo` in
/// `foo::bar!();` or `foo!();`) and also for import paths on 2018 edition.
/// Resolve an identifier in the specified set of scopes.
#[instrument(level = "debug", skip(self))]
pub(crate) fn early_resolve_ident_in_lexical_scope<'r>(
pub(crate) fn resolve_ident_in_scope_set<'r>(
self: CmResolver<'r, 'ra, 'tcx>,
orig_ident: Ident,
scope_set: ScopeSet<'ra>,
Expand Down Expand Up @@ -411,9 +404,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}

let (ns, macro_kind) = match scope_set {
ScopeSet::All(ns)
| ScopeSet::ModuleAndExternPrelude(ns, _)
| ScopeSet::Late(ns, ..) => (ns, None),
ScopeSet::All(ns) | ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None),
ScopeSet::ExternPrelude => (TypeNS, None),
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
};
Expand All @@ -437,10 +428,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}

// Go through all the scopes and try to resolve the name.
let derive_fallback_lint_id = match finalize {
Some(Finalize { node_id, stage: Stage::Late, .. }) => Some(node_id),
_ => None,
};
let break_result = self.visit_scopes(
scope_set,
parent_scope,
orig_ident.span.ctxt(),
derive_fallback_lint_id,
|this, scope, use_prelude, ctxt| {
let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt));
let result = match scope {
Expand Down Expand Up @@ -510,11 +506,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ident,
ns,
adjusted_parent_scope,
if matches!(scope_set, ScopeSet::Late(..)) {
Shadowing::Unrestricted
} else {
Shadowing::Restricted
},
Shadowing::Restricted,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Replaced with a more fine-grained stage check in fn finalize_module_binding.

adjusted_finalize,
ignore_binding,
ignore_import,
Expand Down Expand Up @@ -643,7 +635,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
return None;
}

if finalize.is_none() || matches!(scope_set, ScopeSet::Late(..)) {
// Below we report various ambiguity errors.
// We do not need to report them if we are either in speculative resolution,
// or in late resolution when everything is already imported and expanded
// and no ambiguities exist.
if matches!(finalize, None | Some(Finalize { stage: Stage::Late, .. })) {
return Some(Ok(binding));
}

Expand Down Expand Up @@ -811,7 +807,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ModuleOrUniformRoot::Module(module) => module,
ModuleOrUniformRoot::ModuleAndExternPrelude(module) => {
assert_eq!(shadowing, Shadowing::Unrestricted);
let binding = self.early_resolve_ident_in_lexical_scope(
let binding = self.resolve_ident_in_scope_set(
ident,
ScopeSet::ModuleAndExternPrelude(ns, module),
parent_scope,
Expand All @@ -827,7 +823,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
return if ns != TypeNS {
Err((Determined, Weak::No))
} else {
let binding = self.early_resolve_ident_in_lexical_scope(
let binding = self.resolve_ident_in_scope_set(
ident,
ScopeSet::ExternPrelude,
parent_scope,
Expand All @@ -852,7 +848,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}

let binding = self.early_resolve_ident_in_lexical_scope(
let binding = self.resolve_ident_in_scope_set(
ident,
ScopeSet::All(ns),
parent_scope,
Expand Down Expand Up @@ -945,7 +941,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// Now we are in situation when new item/import can appear only from a glob or a macro
// expansion. With restricted shadowing names from globs and macro expansions cannot
// shadow names from outer scopes, so we can freely fallback from module search to search
// in outer scopes. For `early_resolve_ident_in_lexical_scope` to continue search in outer
// in outer scopes. For `resolve_ident_in_scope_set` to continue search in outer
// scopes we return `Undetermined` with `Weak::Yes`.

// Check if one of unexpanded macros can still define the name,
Expand Down Expand Up @@ -1040,6 +1036,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// Forbid expanded shadowing to avoid time travel.
if let Some(shadowed_glob) = shadowed_glob
&& shadowing == Shadowing::Restricted
&& finalize.stage == Stage::Early
&& binding.expansion != LocalExpnId::ROOT
&& binding.res() != shadowed_glob.res()
{
Expand Down Expand Up @@ -1635,7 +1632,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
_ => Err(Determinacy::determined(finalize.is_some())),
}
} else {
self.reborrow().early_resolve_ident_in_lexical_scope(
self.reborrow().resolve_ident_in_scope_set(
ident,
ScopeSet::All(ns),
parent_scope,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1446,7 +1446,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
return;
}

match this.cm().early_resolve_ident_in_lexical_scope(
match this.cm().resolve_ident_in_scope_set(
target,
ScopeSet::All(ns),
&import.parent_scope,
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ use crate::late::{
};
use crate::ty::fast_reject::SimplifiedType;
use crate::{
Module, ModuleKind, ModuleOrUniformRoot, PathResult, PathSource, Resolver, ScopeSet, Segment,
errors, path_names_to_string,
Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PathSource, Resolver,
ScopeSet, Segment, errors, path_names_to_string,
};

type Res = def::Res<ast::NodeId>;
Expand Down Expand Up @@ -2460,10 +2460,11 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt));
} else if let RibKind::Module(module) = rib.kind {
// Encountered a module item, abandon ribs and look into that module and preludes.
let parent_scope = &ParentScope { module, ..self.parent_scope };
self.r.add_scope_set_candidates(
&mut names,
ScopeSet::Late(ns, module, None),
&self.parent_scope,
ScopeSet::All(ns),
parent_scope,
ctxt,
filter_fn,
);
Expand Down
27 changes: 19 additions & 8 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,8 @@ enum ScopeSet<'ra> {
ModuleAndExternPrelude(Namespace, Module<'ra>),
/// Just two extern prelude scopes.
ExternPrelude,
/// All scopes with macro namespace and the given macro kind restriction.
/// Same as `All(MacroNS)`, but with the given macro kind restriction.
Macro(MacroKind),
/// All scopes with the given namespace, used for partially performing late resolution.
/// The node id enables lints and is used for reporting them.
Late(Namespace, Module<'ra>, Option<NodeId>),
}

/// Everything you need to know about a name's location to resolve it.
Expand Down Expand Up @@ -1888,7 +1885,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}

self.cm().visit_scopes(ScopeSet::All(TypeNS), parent_scope, ctxt, |this, scope, _, _| {
let scope_set = ScopeSet::All(TypeNS);
self.cm().visit_scopes(scope_set, parent_scope, ctxt, None, |this, scope, _, _| {
match scope {
Scope::Module(module, _) => {
this.get_mut().traits_in_module(module, assoc_item, &mut found_traits);
Expand Down Expand Up @@ -2455,6 +2453,17 @@ fn module_to_string(mut module: Module<'_>) -> Option<String> {
Some(names_to_string(names.iter().rev().copied()))
}

#[derive(Copy, Clone, PartialEq, Debug)]
enum Stage {
/// Resolving an import or a macro.
/// Used when macro expansion is either not yet finished, or we are finalizing its results.
/// Used by default as a more restrictive variant that can produce additional errors.
Early,
/// Resolving something in late resolution when all imports are resolved
/// and all macros are expanded.
Late,
}

#[derive(Copy, Clone, Debug)]
struct Finalize {
/// Node ID for linting.
Expand All @@ -2467,9 +2476,11 @@ struct Finalize {
root_span: Span,
/// Whether to report privacy errors or silently return "no resolution" for them,
/// similarly to speculative resolution.
report_private: bool,
report_private: bool = true,
/// Tracks whether an item is used in scope or used relatively to a module.
used: Used,
used: Used = Used::Other,
/// Finalizing early or late resolution.
stage: Stage = Stage::Early,
}

impl Finalize {
Expand All @@ -2478,7 +2489,7 @@ impl Finalize {
}

fn with_root_span(node_id: NodeId, path_span: Span, root_span: Span) -> Finalize {
Finalize { node_id, path_span, root_span, report_private: true, used: Used::Other }
Finalize { node_id, path_span, root_span, .. }
}
}

Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_resolve/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span);
res
} else {
let binding = self.reborrow().early_resolve_ident_in_lexical_scope(
let binding = self.reborrow().resolve_ident_in_scope_set(
path[0].ident,
ScopeSet::Macro(kind),
parent_scope,
Expand Down Expand Up @@ -951,7 +951,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// FIXME: Should be an output of Speculative Resolution.
let macro_resolutions = self.single_segment_macro_resolutions.take();
for (ident, kind, parent_scope, initial_binding, sugg_span) in macro_resolutions {
match self.cm().early_resolve_ident_in_lexical_scope(
match self.cm().resolve_ident_in_scope_set(
ident,
ScopeSet::Macro(kind),
&parent_scope,
Expand Down Expand Up @@ -1006,7 +1006,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {

let builtin_attrs = mem::take(&mut self.builtin_attrs);
for (ident, parent_scope) in builtin_attrs {
let _ = self.cm().early_resolve_ident_in_lexical_scope(
let _ = self.cm().resolve_ident_in_scope_set(
ident,
ScopeSet::Macro(MacroKind::Attr),
&parent_scope,
Expand Down Expand Up @@ -1112,7 +1112,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// If such resolution is successful and gives the same result
// (e.g. if the macro is re-imported), then silence the lint.
let no_macro_rules = self.arenas.alloc_macro_rules_scope(MacroRulesScope::Empty);
let fallback_binding = self.reborrow().early_resolve_ident_in_lexical_scope(
let fallback_binding = self.reborrow().resolve_ident_in_scope_set(
path.segments[0].ident,
ScopeSet::Macro(MacroKind::Bang),
&ParentScope { macro_rules: no_macro_rules, ..*parent_scope },
Expand Down
Loading