1
Fork 0

resolve: Turn enum Finalize into an optional struct

This commit is contained in:
Vadim Petrochenkov 2022-04-30 16:26:36 +03:00
parent 637b3f6807
commit 900607f49a
8 changed files with 59 additions and 92 deletions

View file

@ -298,7 +298,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
&segments,
Some(TypeNS),
parent_scope,
if finalize { Finalize::SimplePath(id, path.span) } else { Finalize::No },
finalize.then(|| Finalize::new(id, path.span)),
None,
) {
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {

View file

@ -417,15 +417,12 @@ impl<'a> Resolver<'a> {
crate fn lint_if_path_starts_with_module(
&mut self,
finalize: Finalize,
finalize: Option<Finalize>,
path: &[Segment],
second_binding: Option<&NameBinding<'_>>,
) {
let (diag_id, diag_span) = match finalize {
Finalize::No => return,
Finalize::SimplePath(id, path_span) => (id, path_span),
Finalize::UsePath { root_id, root_span, .. } => (root_id, root_span),
Finalize::QPathTrait { qpath_id, qpath_span, .. } => (qpath_id, qpath_span),
let Some(Finalize { node_id, root_span, .. }) = finalize else {
return;
};
let first_name = match path.get(0) {
@ -463,11 +460,11 @@ impl<'a> Resolver<'a> {
}
}
let diag = BuiltinLintDiagnostics::AbsPathWithModule(diag_span);
let diag = BuiltinLintDiagnostics::AbsPathWithModule(root_span);
self.lint_buffer.buffer_lint_with_diagnostic(
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
diag_id,
diag_span,
node_id,
root_span,
"absolute paths must start with `self`, `super`, \
`crate`, or an external crate name in the 2018 edition",
diag,
@ -1873,7 +1870,7 @@ impl<'a> Resolver<'a> {
ident,
ns_to_try,
parent_scope,
Finalize::No,
None,
&ribs[ns_to_try],
unusable_binding,
) {
@ -1921,7 +1918,7 @@ impl<'a> Resolver<'a> {
ident,
ValueNS,
parent_scope,
Finalize::No,
None,
&ribs[ValueNS],
unusable_binding,
)

View file

@ -279,7 +279,7 @@ impl<'a> Resolver<'a> {
mut ident: Ident,
ns: Namespace,
parent_scope: &ParentScope<'a>,
finalize_full: Finalize,
finalize_full: Option<Finalize>,
ribs: &[Rib<'a>],
unusable_binding: Option<&'a NameBinding<'a>>,
) -> Option<LexicalScopeBinding<'a>> {
@ -302,7 +302,7 @@ impl<'a> Resolver<'a> {
let normalized_ident = Ident { span: normalized_span, ..ident };
// Walk backwards up the ribs in scope.
let finalize = finalize_full.path_span();
let finalize = finalize_full.map(|finalize| finalize.path_span);
let mut module = self.graph_root;
for i in (0..ribs.len()).rev() {
debug!("walk rib\n{:?}", ribs[i].bindings);
@ -354,7 +354,7 @@ impl<'a> Resolver<'a> {
}
self.early_resolve_ident_in_lexical_scope(
orig_ident,
ScopeSet::Late(ns, module, finalize_full.node_id()),
ScopeSet::Late(ns, module, finalize_full.map(|finalize| finalize.node_id)),
parent_scope,
finalize,
finalize.is_some(),
@ -1371,7 +1371,7 @@ impl<'a> Resolver<'a> {
opt_ns: Option<Namespace>, // `None` indicates a module path in import
parent_scope: &ParentScope<'a>,
) -> PathResult<'a> {
self.resolve_path_with_ribs(path, opt_ns, parent_scope, Finalize::No, None, None)
self.resolve_path_with_ribs(path, opt_ns, parent_scope, None, None, None)
}
#[tracing::instrument(level = "debug", skip(self))]
@ -1380,7 +1380,7 @@ impl<'a> Resolver<'a> {
path: &[Segment],
opt_ns: Option<Namespace>, // `None` indicates a module path in import
parent_scope: &ParentScope<'a>,
finalize: Finalize,
finalize: Option<Finalize>,
unusable_binding: Option<&'a NameBinding<'a>>,
) -> PathResult<'a> {
self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, unusable_binding)
@ -1391,13 +1391,13 @@ impl<'a> Resolver<'a> {
path: &[Segment],
opt_ns: Option<Namespace>, // `None` indicates a module path in import
parent_scope: &ParentScope<'a>,
finalize_full: Finalize,
finalize_full: Option<Finalize>,
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
unusable_binding: Option<&'a NameBinding<'a>>,
) -> PathResult<'a> {
debug!("resolve_path(path={:?}, opt_ns={:?}, finalize={:?})", path, opt_ns, finalize_full);
let finalize = finalize_full.path_span();
let finalize = finalize_full.map(|finalize| finalize.path_span);
let mut module = None;
let mut allow_super = true;
let mut second_binding = None;

View file

@ -594,11 +594,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
_ => None,
};
let prev_ambiguity_errors_len = self.r.ambiguity_errors.len();
let finalize = Finalize::UsePath {
root_id: import.root_id,
root_span: import.root_span,
path_span: import.span,
};
let finalize =
Some(Finalize::with_root_span(import.root_id, import.span, import.root_span));
let path_res = self.r.resolve_path(
&import.module_path,
None,

View file

@ -578,7 +578,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
.resolve_ident_in_lexical_scope(
self_ty,
TypeNS,
Finalize::SimplePath(ty.id, ty.span),
Some(Finalize::new(ty.id, ty.span)),
None,
)
.map_or(Res::Err, |d| d.res());
@ -958,7 +958,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ident,
ns,
&self.parent_scope,
Finalize::No,
None,
&self.ribs[ns],
None,
)
@ -968,7 +968,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
&mut self,
ident: Ident,
ns: Namespace,
finalize: Finalize,
finalize: Option<Finalize>,
unusable_binding: Option<&'a NameBinding<'a>>,
) -> Option<LexicalScopeBinding<'a>> {
self.r.resolve_ident_in_lexical_scope(
@ -985,7 +985,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
&mut self,
path: &[Segment],
opt_ns: Option<Namespace>, // `None` indicates a module path in import
finalize: Finalize,
finalize: Option<Finalize>,
) -> PathResult<'a> {
self.r.resolve_path_with_ribs(
path,
@ -1299,11 +1299,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
partial_res: PartialRes,
path: &[Segment],
source: PathSource<'_>,
finalize: Finalize,
path_span: Span,
) {
let Some(path_span) = finalize.path_span() else {
return;
};
let proj_start = path.len() - partial_res.unresolved_segments();
for (i, segment) in path.iter().enumerate() {
if segment.has_lifetime_args {
@ -1576,8 +1573,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
report_error(self, ns);
}
Some(LexicalScopeBinding::Item(binding)) => {
if let Some(LexicalScopeBinding::Res(..)) = self
.resolve_ident_in_lexical_scope(ident, ns, Finalize::No, Some(binding))
if let Some(LexicalScopeBinding::Res(..)) =
self.resolve_ident_in_lexical_scope(ident, ns, None, Some(binding))
{
report_error(self, ns);
}
@ -1979,7 +1976,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
None,
&path,
PathSource::Trait(AliasPossibility::No),
Finalize::SimplePath(trait_ref.ref_id, trait_ref.path.span),
Finalize::new(trait_ref.ref_id, trait_ref.path.span),
);
if let Some(def_id) = res.base_res().opt_def_id() {
new_id = Some(def_id);
@ -2653,7 +2650,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
qself,
&Segment::from_path(path),
source,
Finalize::SimplePath(id, path.span),
Finalize::new(id, path.span),
);
}
@ -2672,8 +2669,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
);
let ns = source.namespace();
let (id, path_span) =
finalize.node_id_and_path_span().expect("unexpected speculative resolution");
let Finalize { node_id, path_span, .. } = finalize;
let report_errors = |this: &mut Self, res: Option<Res>| {
if this.should_report_errs() {
let (err, candidates) =
@ -2787,7 +2783,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
if ns == ValueNS {
let item_name = path.last().unwrap().ident;
let traits = self.traits_in_scope(item_name, ns);
self.r.trait_map.insert(id, traits);
self.r.trait_map.insert(node_id, traits);
}
if PrimTy::from_name(path[0].ident.name).is_some() {
@ -2796,7 +2792,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
std_path.push(Segment::from_ident(Ident::with_dummy_span(sym::std)));
std_path.extend(path);
if let PathResult::Module(_) | PathResult::NonModule(_) =
self.resolve_path(&std_path, Some(ns), Finalize::No)
self.resolve_path(&std_path, Some(ns), None)
{
// Check if we wrote `str::from_utf8` instead of `std::str::from_utf8`
let item_span =
@ -2823,8 +2819,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
if !matches!(source, PathSource::TraitItem(..)) {
// Avoid recording definition of `A::B` in `<T as A>::B::C`.
self.r.record_partial_res(id, partial_res);
self.resolve_elided_lifetimes_in_path(id, partial_res, path, source, finalize);
self.r.record_partial_res(node_id, partial_res);
self.resolve_elided_lifetimes_in_path(node_id, partial_res, path, source, path_span);
}
partial_res
@ -2932,21 +2928,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// the trait (the slice upto and including
// `qself.position`). And then we recursively resolve that,
// but with `qself` set to `None`.
//
// However, setting `qself` to none (but not changing the
// span) loses the information about where this path
// *actually* appears, so for the purposes of the crate
// lint we pass along information that this is the trait
// name from a fully qualified path, and this also
// contains the full span (the `Finalize::QPathTrait`).
let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
let partial_res = self.smart_resolve_path_fragment(
None,
&path[..=qself.position],
PathSource::TraitItem(ns),
finalize.node_id_and_path_span().map_or(Finalize::No, |(qpath_id, path_span)| {
Finalize::QPathTrait { qpath_id, qpath_span: qself.path_span, path_span }
}),
Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span),
);
// The remaining segments (the `C` in our example) will
@ -2958,7 +2945,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
)));
}
let result = match self.resolve_path(&path, Some(ns), finalize) {
let result = match self.resolve_path(&path, Some(ns), Some(finalize)) {
PathResult::NonModule(path_res) => path_res,
PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => {
PartialRes::new(module.res().unwrap())
@ -2996,10 +2983,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
&& result.base_res() != Res::Err
&& path[0].ident.name != kw::PathRoot
&& path[0].ident.name != kw::DollarCrate
&& let Some((id, path_span)) = finalize.node_id_and_path_span()
{
let unqualified_result = {
match self.resolve_path(&[*path.last().unwrap()], Some(ns), Finalize::No) {
match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) {
PathResult::NonModule(path_res) => path_res.base_res(),
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
module.res().unwrap()
@ -3009,7 +2995,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
};
if result.base_res() == unqualified_result {
let lint = lint::builtin::UNUSED_QUALIFICATIONS;
self.r.lint_buffer.buffer_lint(lint, id, path_span, "unnecessary qualification")
self.r.lint_buffer.buffer_lint(
lint,
finalize.node_id,
finalize.path_span,
"unnecessary qualification",
)
}
}

View file

@ -3,7 +3,7 @@ use crate::late::lifetimes::{ElisionFailureInfo, LifetimeContext};
use crate::late::{AliasPossibility, LateResolutionVisitor, RibKind};
use crate::late::{LifetimeBinderKind, LifetimeRibKind};
use crate::path_names_to_string;
use crate::{Finalize, Module, ModuleKind, ModuleOrUniformRoot};
use crate::{Module, ModuleKind, ModuleOrUniformRoot};
use crate::{PathResult, PathSource, Segment};
use rustc_ast::visit::FnKind;
@ -189,7 +189,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
(String::new(), "the crate root".to_string())
} else {
let mod_path = &path[..path.len() - 1];
let mod_prefix = match self.resolve_path(mod_path, Some(TypeNS), Finalize::No) {
let mod_prefix = match self.resolve_path(mod_path, Some(TypeNS), None) {
PathResult::Module(ModuleOrUniformRoot::Module(module)) => module.res(),
_ => None,
}
@ -648,7 +648,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
if let crate::PathSource::TraitItem(_) = source {
let mod_path = &path[..path.len() - 1];
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
self.resolve_path(mod_path, None, Finalize::No)
self.resolve_path(mod_path, None, None)
{
let resolutions = self.r.resolutions(module).borrow();
let targets: Vec<_> =
@ -1362,7 +1362,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
// Search in module.
let mod_path = &path[..path.len() - 1];
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
self.resolve_path(mod_path, Some(TypeNS), Finalize::No)
self.resolve_path(mod_path, Some(TypeNS), None)
{
self.r.add_module_candidates(module, &mut names, &filter_fn);
}

View file

@ -2044,42 +2044,24 @@ fn module_to_string(module: Module<'_>) -> Option<String> {
}
#[derive(Copy, Clone, Debug)]
enum Finalize {
/// Do not issue the lint.
No,
/// This lint applies to some arbitrary path; e.g., `impl ::foo::Bar`.
/// In this case, we can take the span of that path.
SimplePath(NodeId, Span),
/// This lint comes from a `use` statement. In this case, what we
/// care about really is the *root* `use` statement; e.g., if we
/// have nested things like `use a::{b, c}`, we care about the
/// `use a` part.
UsePath { root_id: NodeId, root_span: Span, path_span: Span },
/// This is the "trait item" from a fully qualified path. For example,
/// we might be resolving `X::Y::Z` from a path like `<T as X::Y>::Z`.
/// The `path_span` is the span of the to the trait itself (`X::Y`).
QPathTrait { qpath_id: NodeId, qpath_span: Span, path_span: Span },
struct Finalize {
/// Node ID for linting.
node_id: NodeId,
/// Span of the whole path or some its characteristic fragment.
/// E.g. span of `b` in `foo::{a, b, c}`, or full span for regular paths.
path_span: Span,
/// Span of the path start, suitable for prepending something to to it.
/// E.g. span of `foo` in `foo::{a, b, c}`, or full span for regular paths.
root_span: Span,
}
impl Finalize {
fn node_id_and_path_span(&self) -> Option<(NodeId, Span)> {
match *self {
Finalize::No => None,
Finalize::SimplePath(id, path_span)
| Finalize::UsePath { root_id: id, path_span, .. }
| Finalize::QPathTrait { qpath_id: id, path_span, .. } => Some((id, path_span)),
}
fn new(node_id: NodeId, path_span: Span) -> Finalize {
Finalize { node_id, path_span, root_span: path_span }
}
fn node_id(&self) -> Option<NodeId> {
self.node_id_and_path_span().map(|(id, _)| id)
}
fn path_span(&self) -> Option<Span> {
self.node_id_and_path_span().map(|(_, path_span)| path_span)
fn with_root_span(node_id: NodeId, path_span: Span, root_span: Span) -> Finalize {
Finalize { node_id, path_span, root_span }
}
}

View file

@ -673,7 +673,7 @@ impl<'a> Resolver<'a> {
&path,
Some(MacroNS),
&parent_scope,
Finalize::SimplePath(ast::CRATE_NODE_ID, path_span),
Some(Finalize::new(ast::CRATE_NODE_ID, path_span)),
None,
) {
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {