Auto merge of #96582 - petrochenkov:finalize, r=cjgillot
resolve: Cleanup path resolution finalization Some cleanup after https://github.com/rust-lang/rust/pull/95255 and https://github.com/rust-lang/rust/pull/95405. r? `@cjgillot`
This commit is contained in:
commit
a933de8398
@ -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)) => {
|
||||
|
@ -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,
|
||||
@ -1503,7 +1500,6 @@ impl<'a> Resolver<'a> {
|
||||
&parent_scope,
|
||||
None,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
) {
|
||||
let desc = match binding.res() {
|
||||
@ -1811,7 +1807,7 @@ impl<'a> Resolver<'a> {
|
||||
opt_ns: Option<Namespace>, // `None` indicates a module path in import
|
||||
parent_scope: &ParentScope<'a>,
|
||||
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
|
||||
unusable_binding: Option<&'a NameBinding<'a>>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
module: Option<ModuleOrUniformRoot<'a>>,
|
||||
i: usize,
|
||||
ident: Ident,
|
||||
@ -1863,8 +1859,7 @@ impl<'a> Resolver<'a> {
|
||||
ns_to_try,
|
||||
parent_scope,
|
||||
None,
|
||||
false,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
).ok()
|
||||
} else if let Some(ribs) = ribs
|
||||
&& let Some(TypeNS | ValueNS) = opt_ns
|
||||
@ -1873,9 +1868,9 @@ impl<'a> Resolver<'a> {
|
||||
ident,
|
||||
ns_to_try,
|
||||
parent_scope,
|
||||
Finalize::No,
|
||||
None,
|
||||
&ribs[ns_to_try],
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
) {
|
||||
// we found a locally-imported or available item/module
|
||||
Some(LexicalScopeBinding::Item(binding)) => Some(binding),
|
||||
@ -1889,8 +1884,7 @@ impl<'a> Resolver<'a> {
|
||||
parent_scope,
|
||||
None,
|
||||
false,
|
||||
false,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
).ok()
|
||||
};
|
||||
if let Some(binding) = binding {
|
||||
@ -1921,9 +1915,9 @@ impl<'a> Resolver<'a> {
|
||||
ident,
|
||||
ValueNS,
|
||||
parent_scope,
|
||||
Finalize::No,
|
||||
None,
|
||||
&ribs[ValueNS],
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
|
@ -279,9 +279,9 @@ impl<'a> Resolver<'a> {
|
||||
mut ident: Ident,
|
||||
ns: Namespace,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
finalize_full: Finalize,
|
||||
finalize: Option<Finalize>,
|
||||
ribs: &[Rib<'a>],
|
||||
unusable_binding: Option<&'a NameBinding<'a>>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
) -> Option<LexicalScopeBinding<'a>> {
|
||||
assert!(ns == TypeNS || ns == ValueNS);
|
||||
let orig_ident = ident;
|
||||
@ -302,7 +302,6 @@ 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 mut module = self.graph_root;
|
||||
for i in (0..ribs.len()).rev() {
|
||||
debug!("walk rib\n{:?}", ribs[i].bindings);
|
||||
@ -316,7 +315,7 @@ impl<'a> Resolver<'a> {
|
||||
i,
|
||||
rib_ident,
|
||||
*res,
|
||||
finalize,
|
||||
finalize.map(|finalize| finalize.path_span),
|
||||
*original_rib_ident_def,
|
||||
ribs,
|
||||
)));
|
||||
@ -344,8 +343,7 @@ impl<'a> Resolver<'a> {
|
||||
ns,
|
||||
parent_scope,
|
||||
finalize,
|
||||
false,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
);
|
||||
if let Ok(binding) = item {
|
||||
// The ident resolves to an item.
|
||||
@ -354,12 +352,11 @@ 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.map(|finalize| finalize.node_id)),
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
false,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
)
|
||||
.ok()
|
||||
.map(LexicalScopeBinding::Item)
|
||||
@ -376,10 +373,9 @@ impl<'a> Resolver<'a> {
|
||||
orig_ident: Ident,
|
||||
scope_set: ScopeSet<'a>,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
finalize: Option<Span>,
|
||||
finalize: Option<Finalize>,
|
||||
force: bool,
|
||||
last_import_segment: bool,
|
||||
unusable_binding: Option<&'a NameBinding<'a>>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
) -> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
bitflags::bitflags! {
|
||||
struct Flags: u8 {
|
||||
@ -499,8 +495,7 @@ impl<'a> Resolver<'a> {
|
||||
ns,
|
||||
parent_scope,
|
||||
finalize,
|
||||
last_import_segment,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
);
|
||||
match binding {
|
||||
Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)),
|
||||
@ -522,8 +517,7 @@ impl<'a> Resolver<'a> {
|
||||
adjusted_parent_scope,
|
||||
!matches!(scope_set, ScopeSet::Late(..)),
|
||||
finalize,
|
||||
last_import_segment,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
);
|
||||
match binding {
|
||||
Ok(binding) => {
|
||||
@ -608,8 +602,7 @@ impl<'a> Resolver<'a> {
|
||||
ns,
|
||||
parent_scope,
|
||||
None,
|
||||
last_import_segment,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
) {
|
||||
if use_prelude || this.is_builtin_macro(binding.res()) {
|
||||
result = Ok((binding, Flags::MISC_FROM_PRELUDE));
|
||||
@ -731,7 +724,7 @@ impl<'a> Resolver<'a> {
|
||||
ns: Namespace,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
) -> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, false, None)
|
||||
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None)
|
||||
.map_err(|(determinacy, _)| determinacy)
|
||||
}
|
||||
|
||||
@ -742,23 +735,11 @@ impl<'a> Resolver<'a> {
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
finalize: Option<Span>,
|
||||
// We are resolving a last import segment during import validation.
|
||||
last_import_segment: bool,
|
||||
// This binding should be ignored during in-module resolution, so that we don't get
|
||||
// "self-confirming" import resolutions during import validation.
|
||||
unusable_binding: Option<&'a NameBinding<'a>>,
|
||||
finalize: Option<Finalize>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
) -> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
self.resolve_ident_in_module_ext(
|
||||
module,
|
||||
ident,
|
||||
ns,
|
||||
parent_scope,
|
||||
finalize,
|
||||
last_import_segment,
|
||||
unusable_binding,
|
||||
)
|
||||
.map_err(|(determinacy, _)| determinacy)
|
||||
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, finalize, ignore_binding)
|
||||
.map_err(|(determinacy, _)| determinacy)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
@ -768,9 +749,8 @@ impl<'a> Resolver<'a> {
|
||||
mut ident: Ident,
|
||||
ns: Namespace,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
finalize: Option<Span>,
|
||||
last_import_segment: bool,
|
||||
unusable_binding: Option<&'a NameBinding<'a>>,
|
||||
finalize: Option<Finalize>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
|
||||
let tmp_parent_scope;
|
||||
let mut adjusted_parent_scope = parent_scope;
|
||||
@ -796,8 +776,7 @@ impl<'a> Resolver<'a> {
|
||||
adjusted_parent_scope,
|
||||
false,
|
||||
finalize,
|
||||
last_import_segment,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
)
|
||||
}
|
||||
|
||||
@ -808,9 +787,8 @@ impl<'a> Resolver<'a> {
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
finalize: Option<Span>,
|
||||
last_import_segment: bool,
|
||||
unusable_binding: Option<&'a NameBinding<'a>>,
|
||||
finalize: Option<Finalize>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
) -> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
self.resolve_ident_in_module_unadjusted_ext(
|
||||
module,
|
||||
@ -819,8 +797,7 @@ impl<'a> Resolver<'a> {
|
||||
parent_scope,
|
||||
false,
|
||||
finalize,
|
||||
last_import_segment,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
)
|
||||
.map_err(|(determinacy, _)| determinacy)
|
||||
}
|
||||
@ -835,9 +812,10 @@ impl<'a> Resolver<'a> {
|
||||
ns: Namespace,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
restricted_shadowing: bool,
|
||||
finalize: Option<Span>,
|
||||
last_import_segment: bool,
|
||||
unusable_binding: Option<&'a NameBinding<'a>>,
|
||||
finalize: Option<Finalize>,
|
||||
// This binding should be ignored during in-module resolution, so that we don't get
|
||||
// "self-confirming" import resolutions during import validation and checking.
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
|
||||
let module = match module {
|
||||
ModuleOrUniformRoot::Module(module) => module,
|
||||
@ -849,8 +827,7 @@ impl<'a> Resolver<'a> {
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
last_import_segment,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
);
|
||||
return binding.map_err(|determinacy| (determinacy, Weak::No));
|
||||
}
|
||||
@ -890,8 +867,7 @@ impl<'a> Resolver<'a> {
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
last_import_segment,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
);
|
||||
return binding.map_err(|determinacy| (determinacy, Weak::No));
|
||||
}
|
||||
@ -901,19 +877,15 @@ impl<'a> Resolver<'a> {
|
||||
let resolution =
|
||||
self.resolution(module, key).try_borrow_mut().map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports.
|
||||
|
||||
if let Some(path_span) = finalize {
|
||||
if let Some(Finalize { path_span, report_private, .. }) = finalize {
|
||||
// If the primary binding is unusable, search further and return the shadowed glob
|
||||
// binding if it exists. What we really want here is having two separate scopes in
|
||||
// a module - one for non-globs and one for globs, but until that's done use this
|
||||
// hack to avoid inconsistent resolution ICEs during import validation.
|
||||
let binding = [resolution.binding, resolution.shadowed_glob]
|
||||
.into_iter()
|
||||
.filter_map(|binding| match (binding, unusable_binding) {
|
||||
(Some(binding), Some(unusable_binding))
|
||||
if ptr::eq(binding, unusable_binding) =>
|
||||
{
|
||||
None
|
||||
}
|
||||
.filter_map(|binding| match (binding, ignore_binding) {
|
||||
(Some(binding), Some(ignored)) if ptr::eq(binding, ignored) => None,
|
||||
_ => binding,
|
||||
})
|
||||
.next();
|
||||
@ -922,14 +894,14 @@ impl<'a> Resolver<'a> {
|
||||
};
|
||||
|
||||
if !self.is_accessible_from(binding.vis, parent_scope.module) {
|
||||
if last_import_segment {
|
||||
return Err((Determined, Weak::No));
|
||||
} else {
|
||||
if report_private {
|
||||
self.privacy_errors.push(PrivacyError {
|
||||
ident,
|
||||
binding,
|
||||
dedup_span: path_span,
|
||||
});
|
||||
} else {
|
||||
return Err((Determined, Weak::No));
|
||||
}
|
||||
}
|
||||
|
||||
@ -960,10 +932,8 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
|
||||
let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
|
||||
if let Some(unusable_binding) = unusable_binding {
|
||||
if ptr::eq(binding, unusable_binding) {
|
||||
return Err((Determined, Weak::No));
|
||||
}
|
||||
if let Some(ignored) = ignore_binding && ptr::eq(binding, ignored) {
|
||||
return Err((Determined, Weak::No));
|
||||
}
|
||||
let usable = this.is_accessible_from(binding.vis, parent_scope.module);
|
||||
if usable { Ok(binding) } else { Err((Determined, Weak::No)) }
|
||||
@ -996,8 +966,7 @@ impl<'a> Resolver<'a> {
|
||||
ns,
|
||||
&single_import.parent_scope,
|
||||
None,
|
||||
last_import_segment,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
) {
|
||||
Err(Determined) => continue,
|
||||
Ok(binding)
|
||||
@ -1073,8 +1042,7 @@ impl<'a> Resolver<'a> {
|
||||
ns,
|
||||
adjusted_parent_scope,
|
||||
None,
|
||||
last_import_segment,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
);
|
||||
|
||||
match result {
|
||||
@ -1371,7 +1339,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,10 +1348,10 @@ impl<'a> Resolver<'a> {
|
||||
path: &[Segment],
|
||||
opt_ns: Option<Namespace>, // `None` indicates a module path in import
|
||||
parent_scope: &ParentScope<'a>,
|
||||
finalize: Finalize,
|
||||
unusable_binding: Option<&'a NameBinding<'a>>,
|
||||
finalize: Option<Finalize>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
) -> PathResult<'a> {
|
||||
self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, unusable_binding)
|
||||
self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, ignore_binding)
|
||||
}
|
||||
|
||||
crate fn resolve_path_with_ribs(
|
||||
@ -1391,13 +1359,12 @@ 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: Option<Finalize>,
|
||||
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
|
||||
unusable_binding: Option<&'a NameBinding<'a>>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
) -> PathResult<'a> {
|
||||
debug!("resolve_path(path={:?}, opt_ns={:?}, finalize={:?})", path, opt_ns, finalize_full);
|
||||
debug!("resolve_path(path={:?}, opt_ns={:?}, finalize={:?})", path, opt_ns, finalize);
|
||||
|
||||
let finalize = finalize_full.path_span();
|
||||
let mut module = None;
|
||||
let mut allow_super = true;
|
||||
let mut second_binding = None;
|
||||
@ -1497,8 +1464,7 @@ impl<'a> Resolver<'a> {
|
||||
ns,
|
||||
parent_scope,
|
||||
finalize,
|
||||
false,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
)
|
||||
} else if let Some(ribs) = ribs
|
||||
&& let Some(TypeNS | ValueNS) = opt_ns
|
||||
@ -1507,9 +1473,9 @@ impl<'a> Resolver<'a> {
|
||||
ident,
|
||||
ns,
|
||||
parent_scope,
|
||||
finalize_full,
|
||||
finalize,
|
||||
&ribs[ns],
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
) {
|
||||
// we found a locally-imported or available item/module
|
||||
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
|
||||
@ -1525,8 +1491,7 @@ impl<'a> Resolver<'a> {
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
false,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
)
|
||||
};
|
||||
FindBindingResult::Binding(binding)
|
||||
@ -1566,7 +1531,7 @@ impl<'a> Resolver<'a> {
|
||||
} else if res == Res::Err {
|
||||
return PathResult::NonModule(PartialRes::new(Res::Err));
|
||||
} else if opt_ns.is_some() && (is_last || maybe_assoc) {
|
||||
self.lint_if_path_starts_with_module(finalize_full, path, second_binding);
|
||||
self.lint_if_path_starts_with_module(finalize, path, second_binding);
|
||||
return PathResult::NonModule(PartialRes::with_unresolved_segments(
|
||||
res,
|
||||
path.len() - i - 1,
|
||||
@ -1599,7 +1564,7 @@ impl<'a> Resolver<'a> {
|
||||
opt_ns,
|
||||
parent_scope,
|
||||
ribs,
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
module,
|
||||
i,
|
||||
ident,
|
||||
@ -1609,7 +1574,7 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
self.lint_if_path_starts_with_module(finalize_full, path, second_binding);
|
||||
self.lint_if_path_starts_with_module(finalize, path, second_binding);
|
||||
|
||||
PathResult::Module(match module {
|
||||
Some(module) => module,
|
||||
|
@ -545,7 +545,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
ns,
|
||||
&import.parent_scope,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
);
|
||||
import.vis.set(orig_vis);
|
||||
@ -589,22 +588,18 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
/// consolidate multiple unresolved import errors into a single diagnostic.
|
||||
fn finalize_import(&mut self, import: &'b Import<'b>) -> Option<UnresolvedImportError> {
|
||||
let orig_vis = import.vis.replace(ty::Visibility::Invisible);
|
||||
let unusable_binding = match &import.kind {
|
||||
let ignore_binding = match &import.kind {
|
||||
ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(),
|
||||
_ => 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 = Finalize::with_root_span(import.root_id, import.span, import.root_span);
|
||||
let path_res = self.r.resolve_path(
|
||||
&import.module_path,
|
||||
None,
|
||||
&import.parent_scope,
|
||||
finalize,
|
||||
unusable_binding,
|
||||
Some(finalize),
|
||||
ignore_binding,
|
||||
);
|
||||
let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len;
|
||||
import.vis.set(orig_vis);
|
||||
@ -685,7 +680,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
// 2 segments, so the `resolve_path` above won't trigger it.
|
||||
let mut full_path = import.module_path.clone();
|
||||
full_path.push(Segment::from_ident(Ident::empty()));
|
||||
self.r.lint_if_path_starts_with_module(finalize, &full_path, None);
|
||||
self.r.lint_if_path_starts_with_module(Some(finalize), &full_path, None);
|
||||
}
|
||||
|
||||
if let ModuleOrUniformRoot::Module(module) = module {
|
||||
@ -720,8 +715,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
ident,
|
||||
ns,
|
||||
&import.parent_scope,
|
||||
Some(import.span),
|
||||
true,
|
||||
Some(Finalize { report_private: false, ..finalize }),
|
||||
target_bindings[ns].get(),
|
||||
);
|
||||
import.vis.set(orig_vis);
|
||||
@ -781,8 +775,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
ident,
|
||||
ns,
|
||||
&import.parent_scope,
|
||||
Some(import.span),
|
||||
false,
|
||||
Some(finalize),
|
||||
None,
|
||||
);
|
||||
if binding.is_ok() {
|
||||
@ -948,7 +941,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
full_path.push(Segment::from_ident(ident));
|
||||
self.r.per_ns(|this, ns| {
|
||||
if let Ok(binding) = source_bindings[ns].get() {
|
||||
this.lint_if_path_starts_with_module(finalize, &full_path, Some(binding));
|
||||
this.lint_if_path_starts_with_module(Some(finalize), &full_path, Some(binding));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1003,7 +996,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
&import.parent_scope,
|
||||
None,
|
||||
false,
|
||||
false,
|
||||
target_bindings[ns].get(),
|
||||
) {
|
||||
Ok(other_binding) => {
|
||||
|
@ -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,8 +968,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
&mut self,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
finalize: Finalize,
|
||||
unusable_binding: Option<&'a NameBinding<'a>>,
|
||||
finalize: Option<Finalize>,
|
||||
ignore_binding: Option<&'a NameBinding<'a>>,
|
||||
) -> Option<LexicalScopeBinding<'a>> {
|
||||
self.r.resolve_ident_in_lexical_scope(
|
||||
ident,
|
||||
@ -977,7 +977,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
&self.parent_scope,
|
||||
finalize,
|
||||
&self.ribs[ns],
|
||||
unusable_binding,
|
||||
ignore_binding,
|
||||
)
|
||||
}
|
||||
|
||||
@ -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",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -2044,42 +2044,27 @@ 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,
|
||||
/// Whether to report privacy errors or silently return "no resolution" for them,
|
||||
/// similarly to speculative resolution.
|
||||
report_private: bool,
|
||||
}
|
||||
|
||||
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::with_root_span(node_id, path_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, report_private: true }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -604,7 +604,6 @@ impl<'a> Resolver<'a> {
|
||||
parent_scope,
|
||||
None,
|
||||
force,
|
||||
false,
|
||||
None,
|
||||
);
|
||||
if let Err(Determinacy::Undetermined) = binding {
|
||||
@ -673,7 +672,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 => {
|
||||
@ -708,9 +707,8 @@ impl<'a> Resolver<'a> {
|
||||
ident,
|
||||
ScopeSet::Macro(kind),
|
||||
&parent_scope,
|
||||
Some(ident.span),
|
||||
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
|
||||
true,
|
||||
false,
|
||||
None,
|
||||
) {
|
||||
Ok(binding) => {
|
||||
@ -751,9 +749,8 @@ impl<'a> Resolver<'a> {
|
||||
ident,
|
||||
ScopeSet::Macro(MacroKind::Attr),
|
||||
&parent_scope,
|
||||
Some(ident.span),
|
||||
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
|
||||
true,
|
||||
false,
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user