Rollup merge of #135826 - yotamofek:resolve-cleanups4, r=petrochenkov
Misc. `rustc_resolve` cleanups
Hopefully this PR should make `rustc_resolve` a bit cleaner.
Each commit here stands on its own. I tried to only include changes that are easy to review, and are a clear improvement. (but I'll be happy to revert any changes that turn out to be more controversial than I'd thought)
Best viewed with whitespace ignored 😁 (especially [these two commits](a93616acf3..ae87d005bc
?diff=unified&w=1))
This commit is contained in:
commit
41885a4858
6 changed files with 564 additions and 608 deletions
|
@ -645,10 +645,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
||||||
let self_spans = items
|
let self_spans = items
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(use_tree, _)| {
|
.filter_map(|(use_tree, _)| {
|
||||||
if let ast::UseTreeKind::Simple(..) = use_tree.kind {
|
if let ast::UseTreeKind::Simple(..) = use_tree.kind
|
||||||
if use_tree.ident().name == kw::SelfLower {
|
&& use_tree.ident().name == kw::SelfLower
|
||||||
return Some(use_tree.span);
|
{
|
||||||
}
|
return Some(use_tree.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
|
@ -947,19 +947,19 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
||||||
let imported_binding = self.r.import(binding, import);
|
let imported_binding = self.r.import(binding, import);
|
||||||
if parent == self.r.graph_root {
|
if parent == self.r.graph_root {
|
||||||
let ident = ident.normalize_to_macros_2_0();
|
let ident = ident.normalize_to_macros_2_0();
|
||||||
if let Some(entry) = self.r.extern_prelude.get(&ident) {
|
if let Some(entry) = self.r.extern_prelude.get(&ident)
|
||||||
if expansion != LocalExpnId::ROOT && orig_name.is_some() && !entry.is_import() {
|
&& expansion != LocalExpnId::ROOT
|
||||||
self.r.dcx().emit_err(
|
&& orig_name.is_some()
|
||||||
errors::MacroExpandedExternCrateCannotShadowExternArguments {
|
&& !entry.is_import()
|
||||||
span: item.span,
|
{
|
||||||
},
|
self.r.dcx().emit_err(
|
||||||
);
|
errors::MacroExpandedExternCrateCannotShadowExternArguments { span: item.span },
|
||||||
// `return` is intended to discard this binding because it's an
|
);
|
||||||
// unregistered ambiguity error which would result in a panic
|
// `return` is intended to discard this binding because it's an
|
||||||
// caused by inconsistency `path_res`
|
// unregistered ambiguity error which would result in a panic
|
||||||
// more details: https://github.com/rust-lang/rust/pull/111761
|
// caused by inconsistency `path_res`
|
||||||
return;
|
// more details: https://github.com/rust-lang/rust/pull/111761
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
let entry = self
|
let entry = self
|
||||||
.r
|
.r
|
||||||
|
@ -1040,10 +1040,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
||||||
span: item.span,
|
span: item.span,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if let ItemKind::ExternCrate(Some(orig_name)) = item.kind {
|
if let ItemKind::ExternCrate(Some(orig_name)) = item.kind
|
||||||
if orig_name == kw::SelfLower {
|
&& orig_name == kw::SelfLower
|
||||||
self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span: attr.span });
|
{
|
||||||
}
|
self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span: attr.span });
|
||||||
}
|
}
|
||||||
let ill_formed = |span| {
|
let ill_formed = |span| {
|
||||||
self.r.dcx().emit_err(errors::BadMacroImport { span });
|
self.r.dcx().emit_err(errors::BadMacroImport { span });
|
||||||
|
@ -1179,14 +1179,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
||||||
return Some((MacroKind::Bang, item.ident, item.span));
|
return Some((MacroKind::Bang, item.ident, item.span));
|
||||||
} else if ast::attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
|
} else if ast::attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
|
||||||
return Some((MacroKind::Attr, item.ident, item.span));
|
return Some((MacroKind::Attr, item.ident, item.span));
|
||||||
} else if let Some(attr) = ast::attr::find_by_name(&item.attrs, sym::proc_macro_derive) {
|
} else if let Some(attr) = ast::attr::find_by_name(&item.attrs, sym::proc_macro_derive)
|
||||||
if let Some(meta_item_inner) =
|
&& let Some(meta_item_inner) =
|
||||||
attr.meta_item_list().and_then(|list| list.get(0).cloned())
|
attr.meta_item_list().and_then(|list| list.get(0).cloned())
|
||||||
{
|
&& let Some(ident) = meta_item_inner.ident()
|
||||||
if let Some(ident) = meta_item_inner.ident() {
|
{
|
||||||
return Some((MacroKind::Derive, ident, ident.span));
|
return Some((MacroKind::Derive, ident, ident.span));
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,10 +225,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
let (name, span) =
|
let (name, span) =
|
||||||
(ident.name, self.tcx.sess.source_map().guess_head_span(new_binding.span));
|
(ident.name, self.tcx.sess.source_map().guess_head_span(new_binding.span));
|
||||||
|
|
||||||
if let Some(s) = self.name_already_seen.get(&name) {
|
if self.name_already_seen.get(&name) == Some(&span) {
|
||||||
if s == &span {
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let old_kind = match (ns, old_binding.module()) {
|
let old_kind = match (ns, old_binding.module()) {
|
||||||
|
@ -380,20 +378,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
suggestion = Some(format!("self as {suggested_name}"))
|
suggestion = Some(format!("self as {suggested_name}"))
|
||||||
}
|
}
|
||||||
ImportKind::Single { source, .. } => {
|
ImportKind::Single { source, .. } => {
|
||||||
if let Some(pos) =
|
if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0)
|
||||||
source.span.hi().0.checked_sub(binding_span.lo().0).map(|pos| pos as usize)
|
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(binding_span)
|
||||||
|
&& pos as usize <= snippet.len()
|
||||||
{
|
{
|
||||||
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(binding_span) {
|
span = binding_span.with_lo(binding_span.lo() + BytePos(pos)).with_hi(
|
||||||
if pos <= snippet.len() {
|
binding_span.hi() - BytePos(if snippet.ends_with(';') { 1 } else { 0 }),
|
||||||
span = binding_span
|
);
|
||||||
.with_lo(binding_span.lo() + BytePos(pos as u32))
|
suggestion = Some(format!(" as {suggested_name}"));
|
||||||
.with_hi(
|
|
||||||
binding_span.hi()
|
|
||||||
- BytePos(if snippet.ends_with(';') { 1 } else { 0 }),
|
|
||||||
);
|
|
||||||
suggestion = Some(format!(" as {suggested_name}"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImportKind::ExternCrate { source, target, .. } => {
|
ImportKind::ExternCrate { source, target, .. } => {
|
||||||
|
@ -510,13 +502,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
// If the first element of our path was actually resolved to an
|
// If the first element of our path was actually resolved to an
|
||||||
// `ExternCrate` (also used for `crate::...`) then no need to issue a
|
// `ExternCrate` (also used for `crate::...`) then no need to issue a
|
||||||
// warning, this looks all good!
|
// warning, this looks all good!
|
||||||
if let Some(binding) = second_binding {
|
if let Some(binding) = second_binding
|
||||||
if let NameBindingKind::Import { import, .. } = binding.kind {
|
&& let NameBindingKind::Import { import, .. } = binding.kind
|
||||||
// Careful: we still want to rewrite paths from renamed extern crates.
|
// Careful: we still want to rewrite paths from renamed extern crates.
|
||||||
if let ImportKind::ExternCrate { source: None, .. } = import.kind {
|
&& let ImportKind::ExternCrate { source: None, .. } = import.kind
|
||||||
return;
|
{
|
||||||
}
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let diag = BuiltinLintDiag::AbsPathWithModule(root_span);
|
let diag = BuiltinLintDiag::AbsPathWithModule(root_span);
|
||||||
|
@ -1047,20 +1038,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
if filter_fn(res) {
|
if filter_fn(res) {
|
||||||
for derive in parent_scope.derives {
|
for derive in parent_scope.derives {
|
||||||
let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
|
let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
|
||||||
if let Ok((Some(ext), _)) = this.resolve_macro_path(
|
let Ok((Some(ext), _)) = this.resolve_macro_path(
|
||||||
derive,
|
derive,
|
||||||
Some(MacroKind::Derive),
|
Some(MacroKind::Derive),
|
||||||
parent_scope,
|
parent_scope,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
) {
|
) else {
|
||||||
suggestions.extend(
|
continue;
|
||||||
ext.helper_attrs
|
};
|
||||||
.iter()
|
suggestions.extend(
|
||||||
.map(|name| TypoSuggestion::typo_from_name(*name, res)),
|
ext.helper_attrs
|
||||||
);
|
.iter()
|
||||||
}
|
.map(|name| TypoSuggestion::typo_from_name(*name, res)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1215,12 +1207,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// #90113: Do not count an inaccessible reexported item as a candidate.
|
// #90113: Do not count an inaccessible reexported item as a candidate.
|
||||||
if let NameBindingKind::Import { binding, .. } = name_binding.kind {
|
if let NameBindingKind::Import { binding, .. } = name_binding.kind
|
||||||
if this.is_accessible_from(binding.vis, parent_scope.module)
|
&& this.is_accessible_from(binding.vis, parent_scope.module)
|
||||||
&& !this.is_accessible_from(name_binding.vis, parent_scope.module)
|
&& !this.is_accessible_from(name_binding.vis, parent_scope.module)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = name_binding.res();
|
let res = name_binding.res();
|
||||||
|
@ -1253,14 +1244,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
segms.push(ast::PathSegment::from_ident(ident));
|
segms.push(ast::PathSegment::from_ident(ident));
|
||||||
let path = Path { span: name_binding.span, segments: segms, tokens: None };
|
let path = Path { span: name_binding.span, segments: segms, tokens: None };
|
||||||
|
|
||||||
if child_accessible {
|
if child_accessible
|
||||||
// Remove invisible match if exists
|
// Remove invisible match if exists
|
||||||
if let Some(idx) = candidates
|
&& let Some(idx) = candidates
|
||||||
.iter()
|
.iter()
|
||||||
.position(|v: &ImportSuggestion| v.did == did && !v.accessible)
|
.position(|v: &ImportSuggestion| v.did == did && !v.accessible)
|
||||||
{
|
{
|
||||||
candidates.remove(idx);
|
candidates.remove(idx);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
|
if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
|
||||||
|
@ -1373,48 +1363,50 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
// otherwise cause duplicate suggestions.
|
// otherwise cause duplicate suggestions.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let crate_id = self.crate_loader(|c| c.maybe_process_path_extern(ident.name));
|
let Some(crate_id) = self.crate_loader(|c| c.maybe_process_path_extern(ident.name))
|
||||||
if let Some(crate_id) = crate_id {
|
else {
|
||||||
let crate_def_id = crate_id.as_def_id();
|
continue;
|
||||||
let crate_root = self.expect_module(crate_def_id);
|
};
|
||||||
|
|
||||||
// Check if there's already an item in scope with the same name as the crate.
|
let crate_def_id = crate_id.as_def_id();
|
||||||
// If so, we have to disambiguate the potential import suggestions by making
|
let crate_root = self.expect_module(crate_def_id);
|
||||||
// the paths *global* (i.e., by prefixing them with `::`).
|
|
||||||
let needs_disambiguation =
|
// Check if there's already an item in scope with the same name as the crate.
|
||||||
self.resolutions(parent_scope.module).borrow().iter().any(
|
// If so, we have to disambiguate the potential import suggestions by making
|
||||||
|(key, name_resolution)| {
|
// the paths *global* (i.e., by prefixing them with `::`).
|
||||||
if key.ns == TypeNS
|
let needs_disambiguation =
|
||||||
&& key.ident == ident
|
self.resolutions(parent_scope.module).borrow().iter().any(
|
||||||
&& let Some(binding) = name_resolution.borrow().binding
|
|(key, name_resolution)| {
|
||||||
{
|
if key.ns == TypeNS
|
||||||
match binding.res() {
|
&& key.ident == ident
|
||||||
// No disambiguation needed if the identically named item we
|
&& let Some(binding) = name_resolution.borrow().binding
|
||||||
// found in scope actually refers to the crate in question.
|
{
|
||||||
Res::Def(_, def_id) => def_id != crate_def_id,
|
match binding.res() {
|
||||||
Res::PrimTy(_) => true,
|
// No disambiguation needed if the identically named item we
|
||||||
_ => false,
|
// found in scope actually refers to the crate in question.
|
||||||
}
|
Res::Def(_, def_id) => def_id != crate_def_id,
|
||||||
} else {
|
Res::PrimTy(_) => true,
|
||||||
false
|
_ => false,
|
||||||
}
|
}
|
||||||
},
|
} else {
|
||||||
);
|
false
|
||||||
let mut crate_path = ThinVec::new();
|
}
|
||||||
if needs_disambiguation {
|
},
|
||||||
crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP));
|
);
|
||||||
}
|
let mut crate_path = ThinVec::new();
|
||||||
crate_path.push(ast::PathSegment::from_ident(ident));
|
if needs_disambiguation {
|
||||||
|
crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP));
|
||||||
suggestions.extend(self.lookup_import_candidates_from_module(
|
|
||||||
lookup_ident,
|
|
||||||
namespace,
|
|
||||||
parent_scope,
|
|
||||||
crate_root,
|
|
||||||
crate_path,
|
|
||||||
&filter_fn,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
crate_path.push(ast::PathSegment::from_ident(ident));
|
||||||
|
|
||||||
|
suggestions.extend(self.lookup_import_candidates_from_module(
|
||||||
|
lookup_ident,
|
||||||
|
namespace,
|
||||||
|
parent_scope,
|
||||||
|
crate_root,
|
||||||
|
crate_path,
|
||||||
|
&filter_fn,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1511,7 +1503,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
|
for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
|
||||||
if let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
|
let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
|
||||||
ident,
|
ident,
|
||||||
ScopeSet::All(ns),
|
ScopeSet::All(ns),
|
||||||
parent_scope,
|
parent_scope,
|
||||||
|
@ -1519,53 +1511,53 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
) {
|
) else {
|
||||||
let desc = match binding.res() {
|
continue;
|
||||||
Res::Def(DefKind::Macro(MacroKind::Bang), _) => {
|
};
|
||||||
"a function-like macro".to_string()
|
|
||||||
}
|
let desc = match binding.res() {
|
||||||
Res::Def(DefKind::Macro(MacroKind::Attr), _) | Res::NonMacroAttr(..) => {
|
Res::Def(DefKind::Macro(MacroKind::Bang), _) => "a function-like macro".to_string(),
|
||||||
format!("an attribute: `#[{ident}]`")
|
Res::Def(DefKind::Macro(MacroKind::Attr), _) | Res::NonMacroAttr(..) => {
|
||||||
}
|
format!("an attribute: `#[{ident}]`")
|
||||||
Res::Def(DefKind::Macro(MacroKind::Derive), _) => {
|
|
||||||
format!("a derive macro: `#[derive({ident})]`")
|
|
||||||
}
|
|
||||||
Res::ToolMod => {
|
|
||||||
// Don't confuse the user with tool modules.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => {
|
|
||||||
"only a trait, without a derive macro".to_string()
|
|
||||||
}
|
|
||||||
res => format!(
|
|
||||||
"{} {}, not {} {}",
|
|
||||||
res.article(),
|
|
||||||
res.descr(),
|
|
||||||
macro_kind.article(),
|
|
||||||
macro_kind.descr_expected(),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
if let crate::NameBindingKind::Import { import, .. } = binding.kind {
|
|
||||||
if !import.span.is_dummy() {
|
|
||||||
let note = errors::IdentImporterHereButItIsDesc {
|
|
||||||
span: import.span,
|
|
||||||
imported_ident: ident,
|
|
||||||
imported_ident_desc: &desc,
|
|
||||||
};
|
|
||||||
err.subdiagnostic(note);
|
|
||||||
// Silence the 'unused import' warning we might get,
|
|
||||||
// since this diagnostic already covers that import.
|
|
||||||
self.record_use(ident, binding, Used::Other);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let note = errors::IdentInScopeButItIsDesc {
|
Res::Def(DefKind::Macro(MacroKind::Derive), _) => {
|
||||||
|
format!("a derive macro: `#[derive({ident})]`")
|
||||||
|
}
|
||||||
|
Res::ToolMod => {
|
||||||
|
// Don't confuse the user with tool modules.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => {
|
||||||
|
"only a trait, without a derive macro".to_string()
|
||||||
|
}
|
||||||
|
res => format!(
|
||||||
|
"{} {}, not {} {}",
|
||||||
|
res.article(),
|
||||||
|
res.descr(),
|
||||||
|
macro_kind.article(),
|
||||||
|
macro_kind.descr_expected(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
if let crate::NameBindingKind::Import { import, .. } = binding.kind
|
||||||
|
&& !import.span.is_dummy()
|
||||||
|
{
|
||||||
|
let note = errors::IdentImporterHereButItIsDesc {
|
||||||
|
span: import.span,
|
||||||
imported_ident: ident,
|
imported_ident: ident,
|
||||||
imported_ident_desc: &desc,
|
imported_ident_desc: &desc,
|
||||||
};
|
};
|
||||||
err.subdiagnostic(note);
|
err.subdiagnostic(note);
|
||||||
|
// Silence the 'unused import' warning we might get,
|
||||||
|
// since this diagnostic already covers that import.
|
||||||
|
self.record_use(ident, binding, Used::Other);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let note = errors::IdentInScopeButItIsDesc {
|
||||||
|
imported_ident: ident,
|
||||||
|
imported_ident_desc: &desc,
|
||||||
|
};
|
||||||
|
err.subdiagnostic(note);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1749,15 +1741,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
/// If the binding refers to a tuple struct constructor with fields,
|
/// If the binding refers to a tuple struct constructor with fields,
|
||||||
/// returns the span of its fields.
|
/// returns the span of its fields.
|
||||||
fn ctor_fields_span(&self, binding: NameBinding<'_>) -> Option<Span> {
|
fn ctor_fields_span(&self, binding: NameBinding<'_>) -> Option<Span> {
|
||||||
if let NameBindingKind::Res(Res::Def(
|
let NameBindingKind::Res(Res::Def(
|
||||||
DefKind::Ctor(CtorOf::Struct, CtorKind::Fn),
|
DefKind::Ctor(CtorOf::Struct, CtorKind::Fn),
|
||||||
ctor_def_id,
|
ctor_def_id,
|
||||||
)) = binding.kind
|
)) = binding.kind
|
||||||
{
|
else {
|
||||||
let def_id = self.tcx.parent(ctor_def_id);
|
return None;
|
||||||
return self.field_idents(def_id)?.iter().map(|&f| f.span).reduce(Span::to); // None for `struct Foo()`
|
};
|
||||||
}
|
|
||||||
None
|
let def_id = self.tcx.parent(ctor_def_id);
|
||||||
|
self.field_idents(def_id)?.iter().map(|&f| f.span).reduce(Span::to) // None for `struct Foo()`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) {
|
fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) {
|
||||||
|
@ -1983,10 +1976,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
candidates.sort();
|
candidates.sort();
|
||||||
candidates.dedup();
|
candidates.dedup();
|
||||||
match find_best_match_for_name(&candidates, ident, None) {
|
find_best_match_for_name(&candidates, ident, None).filter(|sugg| *sugg != ident)
|
||||||
Some(sugg) if sugg == ident => None,
|
|
||||||
sugg => sugg,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn report_path_resolution_error(
|
pub(crate) fn report_path_resolution_error(
|
||||||
|
@ -2410,115 +2400,115 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
let binding_key = BindingKey::new(ident, MacroNS);
|
let binding_key = BindingKey::new(ident, MacroNS);
|
||||||
let resolution = resolutions.get(&binding_key)?;
|
let resolution = resolutions.get(&binding_key)?;
|
||||||
let binding = resolution.borrow().binding()?;
|
let binding = resolution.borrow().binding()?;
|
||||||
if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {
|
let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() else {
|
||||||
let module_name = crate_module.kind.name().unwrap();
|
return None;
|
||||||
let import_snippet = match import.kind {
|
};
|
||||||
ImportKind::Single { source, target, .. } if source != target => {
|
let module_name = crate_module.kind.name().unwrap();
|
||||||
format!("{source} as {target}")
|
let import_snippet = match import.kind {
|
||||||
}
|
ImportKind::Single { source, target, .. } if source != target => {
|
||||||
_ => format!("{ident}"),
|
format!("{source} as {target}")
|
||||||
};
|
|
||||||
|
|
||||||
let mut corrections: Vec<(Span, String)> = Vec::new();
|
|
||||||
if !import.is_nested() {
|
|
||||||
// Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
|
|
||||||
// intermediate segments.
|
|
||||||
corrections.push((import.span, format!("{module_name}::{import_snippet}")));
|
|
||||||
} else {
|
|
||||||
// Find the binding span (and any trailing commas and spaces).
|
|
||||||
// ie. `use a::b::{c, d, e};`
|
|
||||||
// ^^^
|
|
||||||
let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
|
|
||||||
self.tcx.sess,
|
|
||||||
import.span,
|
|
||||||
import.use_span,
|
|
||||||
);
|
|
||||||
debug!(found_closing_brace, ?binding_span);
|
|
||||||
|
|
||||||
let mut removal_span = binding_span;
|
|
||||||
if found_closing_brace {
|
|
||||||
// If the binding span ended with a closing brace, as in the below example:
|
|
||||||
// ie. `use a::b::{c, d};`
|
|
||||||
// ^
|
|
||||||
// Then expand the span of characters to remove to include the previous
|
|
||||||
// binding's trailing comma.
|
|
||||||
// ie. `use a::b::{c, d};`
|
|
||||||
// ^^^
|
|
||||||
if let Some(previous_span) =
|
|
||||||
extend_span_to_previous_binding(self.tcx.sess, binding_span)
|
|
||||||
{
|
|
||||||
debug!(?previous_span);
|
|
||||||
removal_span = removal_span.with_lo(previous_span.lo());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug!(?removal_span);
|
|
||||||
|
|
||||||
// Remove the `removal_span`.
|
|
||||||
corrections.push((removal_span, "".to_string()));
|
|
||||||
|
|
||||||
// Find the span after the crate name and if it has nested imports immediately
|
|
||||||
// after the crate name already.
|
|
||||||
// ie. `use a::b::{c, d};`
|
|
||||||
// ^^^^^^^^^
|
|
||||||
// or `use a::{b, c, d}};`
|
|
||||||
// ^^^^^^^^^^^
|
|
||||||
let (has_nested, after_crate_name) = find_span_immediately_after_crate_name(
|
|
||||||
self.tcx.sess,
|
|
||||||
module_name,
|
|
||||||
import.use_span,
|
|
||||||
);
|
|
||||||
debug!(has_nested, ?after_crate_name);
|
|
||||||
|
|
||||||
let source_map = self.tcx.sess.source_map();
|
|
||||||
|
|
||||||
// Make sure this is actually crate-relative.
|
|
||||||
let is_definitely_crate = import
|
|
||||||
.module_path
|
|
||||||
.first()
|
|
||||||
.is_some_and(|f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super);
|
|
||||||
|
|
||||||
// Add the import to the start, with a `{` if required.
|
|
||||||
let start_point = source_map.start_point(after_crate_name);
|
|
||||||
if is_definitely_crate
|
|
||||||
&& let Ok(start_snippet) = source_map.span_to_snippet(start_point)
|
|
||||||
{
|
|
||||||
corrections.push((
|
|
||||||
start_point,
|
|
||||||
if has_nested {
|
|
||||||
// In this case, `start_snippet` must equal '{'.
|
|
||||||
format!("{start_snippet}{import_snippet}, ")
|
|
||||||
} else {
|
|
||||||
// In this case, add a `{`, then the moved import, then whatever
|
|
||||||
// was there before.
|
|
||||||
format!("{{{import_snippet}, {start_snippet}")
|
|
||||||
},
|
|
||||||
));
|
|
||||||
|
|
||||||
// Add a `};` to the end if nested, matching the `{` added at the start.
|
|
||||||
if !has_nested {
|
|
||||||
corrections
|
|
||||||
.push((source_map.end_point(after_crate_name), "};".to_string()));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If the root import is module-relative, add the import separately
|
|
||||||
corrections.push((
|
|
||||||
import.use_span.shrink_to_lo(),
|
|
||||||
format!("use {module_name}::{import_snippet};\n"),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_ => format!("{ident}"),
|
||||||
|
};
|
||||||
|
|
||||||
let suggestion = Some((
|
let mut corrections: Vec<(Span, String)> = Vec::new();
|
||||||
corrections,
|
if !import.is_nested() {
|
||||||
String::from("a macro with this name exists at the root of the crate"),
|
// Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
|
||||||
Applicability::MaybeIncorrect,
|
// intermediate segments.
|
||||||
));
|
corrections.push((import.span, format!("{module_name}::{import_snippet}")));
|
||||||
Some((suggestion, Some("this could be because a macro annotated with `#[macro_export]` will be exported \
|
|
||||||
at the root of the crate instead of the module where it is defined"
|
|
||||||
.to_string())))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
// Find the binding span (and any trailing commas and spaces).
|
||||||
|
// ie. `use a::b::{c, d, e};`
|
||||||
|
// ^^^
|
||||||
|
let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
|
||||||
|
self.tcx.sess,
|
||||||
|
import.span,
|
||||||
|
import.use_span,
|
||||||
|
);
|
||||||
|
debug!(found_closing_brace, ?binding_span);
|
||||||
|
|
||||||
|
let mut removal_span = binding_span;
|
||||||
|
|
||||||
|
// If the binding span ended with a closing brace, as in the below example:
|
||||||
|
// ie. `use a::b::{c, d};`
|
||||||
|
// ^
|
||||||
|
// Then expand the span of characters to remove to include the previous
|
||||||
|
// binding's trailing comma.
|
||||||
|
// ie. `use a::b::{c, d};`
|
||||||
|
// ^^^
|
||||||
|
if found_closing_brace
|
||||||
|
&& let Some(previous_span) =
|
||||||
|
extend_span_to_previous_binding(self.tcx.sess, binding_span)
|
||||||
|
{
|
||||||
|
debug!(?previous_span);
|
||||||
|
removal_span = removal_span.with_lo(previous_span.lo());
|
||||||
|
}
|
||||||
|
debug!(?removal_span);
|
||||||
|
|
||||||
|
// Remove the `removal_span`.
|
||||||
|
corrections.push((removal_span, "".to_string()));
|
||||||
|
|
||||||
|
// Find the span after the crate name and if it has nested imports immediately
|
||||||
|
// after the crate name already.
|
||||||
|
// ie. `use a::b::{c, d};`
|
||||||
|
// ^^^^^^^^^
|
||||||
|
// or `use a::{b, c, d}};`
|
||||||
|
// ^^^^^^^^^^^
|
||||||
|
let (has_nested, after_crate_name) =
|
||||||
|
find_span_immediately_after_crate_name(self.tcx.sess, module_name, import.use_span);
|
||||||
|
debug!(has_nested, ?after_crate_name);
|
||||||
|
|
||||||
|
let source_map = self.tcx.sess.source_map();
|
||||||
|
|
||||||
|
// Make sure this is actually crate-relative.
|
||||||
|
let is_definitely_crate = import
|
||||||
|
.module_path
|
||||||
|
.first()
|
||||||
|
.is_some_and(|f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super);
|
||||||
|
|
||||||
|
// Add the import to the start, with a `{` if required.
|
||||||
|
let start_point = source_map.start_point(after_crate_name);
|
||||||
|
if is_definitely_crate
|
||||||
|
&& let Ok(start_snippet) = source_map.span_to_snippet(start_point)
|
||||||
|
{
|
||||||
|
corrections.push((
|
||||||
|
start_point,
|
||||||
|
if has_nested {
|
||||||
|
// In this case, `start_snippet` must equal '{'.
|
||||||
|
format!("{start_snippet}{import_snippet}, ")
|
||||||
|
} else {
|
||||||
|
// In this case, add a `{`, then the moved import, then whatever
|
||||||
|
// was there before.
|
||||||
|
format!("{{{import_snippet}, {start_snippet}")
|
||||||
|
},
|
||||||
|
));
|
||||||
|
|
||||||
|
// Add a `};` to the end if nested, matching the `{` added at the start.
|
||||||
|
if !has_nested {
|
||||||
|
corrections.push((source_map.end_point(after_crate_name), "};".to_string()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If the root import is module-relative, add the import separately
|
||||||
|
corrections.push((
|
||||||
|
import.use_span.shrink_to_lo(),
|
||||||
|
format!("use {module_name}::{import_snippet};\n"),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let suggestion = Some((
|
||||||
|
corrections,
|
||||||
|
String::from("a macro with this name exists at the root of the crate"),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
));
|
||||||
|
Some((
|
||||||
|
suggestion,
|
||||||
|
Some(
|
||||||
|
"this could be because a macro annotated with `#[macro_export]` will be exported \
|
||||||
|
at the root of the crate instead of the module where it is defined"
|
||||||
|
.to_string(),
|
||||||
|
),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds a cfg-ed out item inside `module` with the matching name.
|
/// Finds a cfg-ed out item inside `module` with the matching name.
|
||||||
|
@ -3042,7 +3032,6 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder {
|
||||||
self.first_legal_span = Some(inject);
|
self.first_legal_span = Some(inject);
|
||||||
}
|
}
|
||||||
self.first_use_span = search_for_any_use_in_items(&c.items);
|
self.first_use_span = search_for_any_use_in_items(&c.items);
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
visit::walk_crate(self, c);
|
visit::walk_crate(self, c);
|
||||||
}
|
}
|
||||||
|
@ -3056,7 +3045,6 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder {
|
||||||
self.first_legal_span = Some(inject);
|
self.first_legal_span = Some(inject);
|
||||||
}
|
}
|
||||||
self.first_use_span = search_for_any_use_in_items(items);
|
self.first_use_span = search_for_any_use_in_items(items);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
visit::walk_item(self, item);
|
visit::walk_item(self, item);
|
||||||
|
@ -3066,16 +3054,16 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder {
|
||||||
|
|
||||||
fn search_for_any_use_in_items(items: &[P<ast::Item>]) -> Option<Span> {
|
fn search_for_any_use_in_items(items: &[P<ast::Item>]) -> Option<Span> {
|
||||||
for item in items {
|
for item in items {
|
||||||
if let ItemKind::Use(..) = item.kind {
|
if let ItemKind::Use(..) = item.kind
|
||||||
if is_span_suitable_for_use_injection(item.span) {
|
&& is_span_suitable_for_use_injection(item.span)
|
||||||
let mut lo = item.span.lo();
|
{
|
||||||
for attr in &item.attrs {
|
let mut lo = item.span.lo();
|
||||||
if attr.span.eq_ctxt(item.span) {
|
for attr in &item.attrs {
|
||||||
lo = std::cmp::min(lo, attr.span.lo());
|
if attr.span.eq_ctxt(item.span) {
|
||||||
}
|
lo = std::cmp::min(lo, attr.span.lo());
|
||||||
}
|
}
|
||||||
return Some(Span::new(lo, lo, item.span.ctxt(), item.span.parent()));
|
|
||||||
}
|
}
|
||||||
|
return Some(Span::new(lo, lo, item.span.ctxt(), item.span.parent()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
|
@ -118,37 +118,38 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
|
||||||
let resolutions = self.r.resolutions(module);
|
let resolutions = self.r.resolutions(module);
|
||||||
|
|
||||||
for (_, name_resolution) in resolutions.borrow().iter() {
|
for (_, name_resolution) in resolutions.borrow().iter() {
|
||||||
if let Some(mut binding) = name_resolution.borrow().binding() {
|
let Some(mut binding) = name_resolution.borrow().binding() else {
|
||||||
// Set the given effective visibility level to `Level::Direct` and
|
continue;
|
||||||
// sets the rest of the `use` chain to `Level::Reexported` until
|
};
|
||||||
// we hit the actual exported item.
|
// Set the given effective visibility level to `Level::Direct` and
|
||||||
//
|
// sets the rest of the `use` chain to `Level::Reexported` until
|
||||||
// If the binding is ambiguous, put the root ambiguity binding and all reexports
|
// we hit the actual exported item.
|
||||||
// leading to it into the table. They are used by the `ambiguous_glob_reexports`
|
//
|
||||||
// lint. For all bindings added to the table this way `is_ambiguity` returns true.
|
// If the binding is ambiguous, put the root ambiguity binding and all reexports
|
||||||
let is_ambiguity =
|
// leading to it into the table. They are used by the `ambiguous_glob_reexports`
|
||||||
|binding: NameBinding<'ra>, warn: bool| binding.ambiguity.is_some() && !warn;
|
// lint. For all bindings added to the table this way `is_ambiguity` returns true.
|
||||||
let mut parent_id = ParentId::Def(module_id);
|
let is_ambiguity =
|
||||||
let mut warn_ambiguity = binding.warn_ambiguity;
|
|binding: NameBinding<'ra>, warn: bool| binding.ambiguity.is_some() && !warn;
|
||||||
while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind {
|
let mut parent_id = ParentId::Def(module_id);
|
||||||
self.update_import(binding, parent_id);
|
let mut warn_ambiguity = binding.warn_ambiguity;
|
||||||
|
while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind {
|
||||||
|
self.update_import(binding, parent_id);
|
||||||
|
|
||||||
if is_ambiguity(binding, warn_ambiguity) {
|
if is_ambiguity(binding, warn_ambiguity) {
|
||||||
// Stop at the root ambiguity, further bindings in the chain should not
|
// Stop at the root ambiguity, further bindings in the chain should not
|
||||||
// be reexported because the root ambiguity blocks any access to them.
|
// be reexported because the root ambiguity blocks any access to them.
|
||||||
// (Those further bindings are most likely not ambiguities themselves.)
|
// (Those further bindings are most likely not ambiguities themselves.)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent_id = ParentId::Import(binding);
|
parent_id = ParentId::Import(binding);
|
||||||
binding = nested_binding;
|
binding = nested_binding;
|
||||||
warn_ambiguity |= nested_binding.warn_ambiguity;
|
warn_ambiguity |= nested_binding.warn_ambiguity;
|
||||||
}
|
}
|
||||||
if !is_ambiguity(binding, warn_ambiguity)
|
if !is_ambiguity(binding, warn_ambiguity)
|
||||||
&& let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local())
|
&& let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local())
|
||||||
{
|
{
|
||||||
self.update_def(def_id, binding.vis.expect_local(), parent_id);
|
self.update_def(def_id, binding.vis.expect_local(), parent_id);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,23 +246,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
// ---- end
|
// ---- end
|
||||||
// ```
|
// ```
|
||||||
// So we have to fall back to the module's parent during lexical resolution in this case.
|
// So we have to fall back to the module's parent during lexical resolution in this case.
|
||||||
if derive_fallback_lint_id.is_some() {
|
if derive_fallback_lint_id.is_some()
|
||||||
if let Some(parent) = module.parent {
|
&& let Some(parent) = module.parent
|
||||||
// Inner module is inside the macro, parent module is outside of the macro.
|
// Inner module is inside the macro
|
||||||
if module.expansion != parent.expansion
|
&& module.expansion != parent.expansion
|
||||||
&& module.expansion.is_descendant_of(parent.expansion)
|
// Parent module is outside of the macro
|
||||||
{
|
&& module.expansion.is_descendant_of(parent.expansion)
|
||||||
// The macro is a proc macro derive
|
// The macro is a proc macro derive
|
||||||
if let Some(def_id) = module.expansion.expn_data().macro_def_id {
|
&& let Some(def_id) = module.expansion.expn_data().macro_def_id
|
||||||
let ext = &self.get_macro_by_def_id(def_id).ext;
|
{
|
||||||
if ext.builtin_name.is_none()
|
let ext = &self.get_macro_by_def_id(def_id).ext;
|
||||||
&& ext.macro_kind() == MacroKind::Derive
|
if ext.builtin_name.is_none()
|
||||||
&& parent.expansion.outer_expn_is_descendant_of(*ctxt)
|
&& ext.macro_kind() == MacroKind::Derive
|
||||||
{
|
&& parent.expansion.outer_expn_is_descendant_of(*ctxt)
|
||||||
return Some((parent, derive_fallback_lint_id));
|
{
|
||||||
}
|
return Some((parent, derive_fallback_lint_id));
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,8 +591,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
},
|
},
|
||||||
Scope::StdLibPrelude => {
|
Scope::StdLibPrelude => {
|
||||||
let mut result = Err(Determinacy::Determined);
|
let mut result = Err(Determinacy::Determined);
|
||||||
if let Some(prelude) = this.prelude {
|
if let Some(prelude) = this.prelude
|
||||||
if let Ok(binding) = this.resolve_ident_in_module_unadjusted(
|
&& let Ok(binding) = this.resolve_ident_in_module_unadjusted(
|
||||||
ModuleOrUniformRoot::Module(prelude),
|
ModuleOrUniformRoot::Module(prelude),
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
|
@ -603,14 +601,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
None,
|
None,
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
ignore_import,
|
ignore_import,
|
||||||
) {
|
)
|
||||||
if matches!(use_prelude, UsePrelude::Yes)
|
&& (matches!(use_prelude, UsePrelude::Yes)
|
||||||
|| this.is_builtin_macro(binding.res())
|
|| this.is_builtin_macro(binding.res()))
|
||||||
{
|
{
|
||||||
result = Ok((binding, Flags::MISC_FROM_PRELUDE));
|
result = Ok((binding, Flags::MISC_FROM_PRELUDE));
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
Scope::BuiltinTypes => match this.builtin_types_bindings.get(&ident.name) {
|
Scope::BuiltinTypes => match this.builtin_types_bindings.get(&ident.name) {
|
||||||
|
@ -939,10 +936,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Items and single imports are not shadowable, if we have one, then it's determined.
|
// Items and single imports are not shadowable, if we have one, then it's determined.
|
||||||
if let Some(binding) = binding {
|
if let Some(binding) = binding
|
||||||
if !binding.is_glob_import() {
|
&& !binding.is_glob_import()
|
||||||
return check_usable(self, binding);
|
{
|
||||||
}
|
return check_usable(self, binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- From now on we either have a glob resolution or no resolution. ---
|
// --- From now on we either have a glob resolution or no resolution. ---
|
||||||
|
@ -1437,13 +1434,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
for (segment_idx, &Segment { ident, id, .. }) in path.iter().enumerate() {
|
for (segment_idx, &Segment { ident, id, .. }) in path.iter().enumerate() {
|
||||||
debug!("resolve_path ident {} {:?} {:?}", segment_idx, ident, id);
|
debug!("resolve_path ident {} {:?} {:?}", segment_idx, ident, id);
|
||||||
let record_segment_res = |this: &mut Self, res| {
|
let record_segment_res = |this: &mut Self, res| {
|
||||||
if finalize.is_some() {
|
if finalize.is_some()
|
||||||
if let Some(id) = id {
|
&& let Some(id) = id
|
||||||
if !this.partial_res_map.contains_key(&id) {
|
&& !this.partial_res_map.contains_key(&id)
|
||||||
assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id");
|
{
|
||||||
this.record_partial_res(id, PartialRes::new(res));
|
assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id");
|
||||||
}
|
this.record_partial_res(id, PartialRes::new(res));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1463,13 +1459,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if let Some(self_module) = self_module {
|
if let Some(self_module) = self_module
|
||||||
if let Some(parent) = self_module.parent {
|
&& let Some(parent) = self_module.parent
|
||||||
module = Some(ModuleOrUniformRoot::Module(
|
{
|
||||||
self.resolve_self(&mut ctxt, parent),
|
module =
|
||||||
));
|
Some(ModuleOrUniformRoot::Module(self.resolve_self(&mut ctxt, parent)));
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return PathResult::failed(
|
return PathResult::failed(
|
||||||
ident,
|
ident,
|
||||||
|
@ -1644,13 +1639,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
}
|
}
|
||||||
Err(Undetermined) => return PathResult::Indeterminate,
|
Err(Undetermined) => return PathResult::Indeterminate,
|
||||||
Err(Determined) => {
|
Err(Determined) => {
|
||||||
if let Some(ModuleOrUniformRoot::Module(module)) = module {
|
if let Some(ModuleOrUniformRoot::Module(module)) = module
|
||||||
if opt_ns.is_some() && !module.is_normal() {
|
&& opt_ns.is_some()
|
||||||
return PathResult::NonModule(PartialRes::with_unresolved_segments(
|
&& !module.is_normal()
|
||||||
module.res().unwrap(),
|
{
|
||||||
path.len() - segment_idx,
|
return PathResult::NonModule(PartialRes::with_unresolved_segments(
|
||||||
));
|
module.res().unwrap(),
|
||||||
}
|
path.len() - segment_idx,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return PathResult::failed(
|
return PathResult::failed(
|
||||||
|
|
|
@ -287,12 +287,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
binding.vis
|
binding.vis
|
||||||
};
|
};
|
||||||
|
|
||||||
if let ImportKind::Glob { ref max_vis, .. } = import.kind {
|
if let ImportKind::Glob { ref max_vis, .. } = import.kind
|
||||||
if vis == import_vis
|
&& (vis == import_vis
|
||||||
|| max_vis.get().is_none_or(|max_vis| vis.is_at_least(max_vis, self.tcx))
|
|| max_vis.get().is_none_or(|max_vis| vis.is_at_least(max_vis, self.tcx)))
|
||||||
{
|
{
|
||||||
max_vis.set(Some(vis.expect_local()))
|
max_vis.set(Some(vis.expect_local()))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.arenas.alloc_name_binding(NameBindingData {
|
self.arenas.alloc_name_binding(NameBindingData {
|
||||||
|
@ -543,31 +542,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
// resolution for it so that later resolve stages won't complain.
|
// resolution for it so that later resolve stages won't complain.
|
||||||
self.import_dummy_binding(*import, is_indeterminate);
|
self.import_dummy_binding(*import, is_indeterminate);
|
||||||
|
|
||||||
if let Some(err) = unresolved_import_error {
|
let Some(err) = unresolved_import_error else { continue };
|
||||||
glob_error |= import.is_glob();
|
|
||||||
|
|
||||||
if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
|
glob_error |= import.is_glob();
|
||||||
if source.name == kw::SelfLower {
|
|
||||||
// Silence `unresolved import` error if E0429 is already emitted
|
|
||||||
if let Err(Determined) = source_bindings.value_ns.get() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if prev_root_id != NodeId::ZERO
|
if let ImportKind::Single { source, ref source_bindings, .. } = import.kind
|
||||||
&& prev_root_id != import.root_id
|
&& source.name == kw::SelfLower
|
||||||
&& !errors.is_empty()
|
// Silence `unresolved import` error if E0429 is already emitted
|
||||||
{
|
&& let Err(Determined) = source_bindings.value_ns.get()
|
||||||
// In the case of a new import line, throw a diagnostic message
|
{
|
||||||
// for the previous line.
|
continue;
|
||||||
self.throw_unresolved_import_error(errors, glob_error);
|
}
|
||||||
errors = vec![];
|
|
||||||
}
|
if prev_root_id != NodeId::ZERO && prev_root_id != import.root_id && !errors.is_empty()
|
||||||
if seen_spans.insert(err.span) {
|
{
|
||||||
errors.push((*import, err));
|
// In the case of a new import line, throw a diagnostic message
|
||||||
prev_root_id = import.root_id;
|
// for the previous line.
|
||||||
}
|
self.throw_unresolved_import_error(errors, glob_error);
|
||||||
|
errors = vec![];
|
||||||
|
}
|
||||||
|
if seen_spans.insert(err.span) {
|
||||||
|
errors.push((*import, err));
|
||||||
|
prev_root_id = import.root_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,60 +605,60 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
for (key, resolution) in self.resolutions(*module).borrow().iter() {
|
for (key, resolution) in self.resolutions(*module).borrow().iter() {
|
||||||
let resolution = resolution.borrow();
|
let resolution = resolution.borrow();
|
||||||
|
|
||||||
if let Some(binding) = resolution.binding {
|
let Some(binding) = resolution.binding else { continue };
|
||||||
if let NameBindingKind::Import { import, .. } = binding.kind
|
|
||||||
&& let Some((amb_binding, _)) = binding.ambiguity
|
if let NameBindingKind::Import { import, .. } = binding.kind
|
||||||
&& binding.res() != Res::Err
|
&& let Some((amb_binding, _)) = binding.ambiguity
|
||||||
&& exported_ambiguities.contains(&binding)
|
&& binding.res() != Res::Err
|
||||||
|
&& exported_ambiguities.contains(&binding)
|
||||||
|
{
|
||||||
|
self.lint_buffer.buffer_lint(
|
||||||
|
AMBIGUOUS_GLOB_REEXPORTS,
|
||||||
|
import.root_id,
|
||||||
|
import.root_span,
|
||||||
|
BuiltinLintDiag::AmbiguousGlobReexports {
|
||||||
|
name: key.ident.to_string(),
|
||||||
|
namespace: key.ns.descr().to_string(),
|
||||||
|
first_reexport_span: import.root_span,
|
||||||
|
duplicate_reexport_span: amb_binding.span,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(glob_binding) = resolution.shadowed_glob {
|
||||||
|
let binding_id = match binding.kind {
|
||||||
|
NameBindingKind::Res(res) => {
|
||||||
|
Some(self.def_id_to_node_id[res.def_id().expect_local()])
|
||||||
|
}
|
||||||
|
NameBindingKind::Module(module) => {
|
||||||
|
Some(self.def_id_to_node_id[module.def_id().expect_local()])
|
||||||
|
}
|
||||||
|
NameBindingKind::Import { import, .. } => import.id(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if binding.res() != Res::Err
|
||||||
|
&& glob_binding.res() != Res::Err
|
||||||
|
&& let NameBindingKind::Import { import: glob_import, .. } =
|
||||||
|
glob_binding.kind
|
||||||
|
&& let Some(binding_id) = binding_id
|
||||||
|
&& let Some(glob_import_id) = glob_import.id()
|
||||||
|
&& let glob_import_def_id = self.local_def_id(glob_import_id)
|
||||||
|
&& self.effective_visibilities.is_exported(glob_import_def_id)
|
||||||
|
&& glob_binding.vis.is_public()
|
||||||
|
&& !binding.vis.is_public()
|
||||||
{
|
{
|
||||||
self.lint_buffer.buffer_lint(
|
self.lint_buffer.buffer_lint(
|
||||||
AMBIGUOUS_GLOB_REEXPORTS,
|
HIDDEN_GLOB_REEXPORTS,
|
||||||
import.root_id,
|
binding_id,
|
||||||
import.root_span,
|
binding.span,
|
||||||
BuiltinLintDiag::AmbiguousGlobReexports {
|
BuiltinLintDiag::HiddenGlobReexports {
|
||||||
name: key.ident.to_string(),
|
name: key.ident.name.to_string(),
|
||||||
namespace: key.ns.descr().to_string(),
|
namespace: key.ns.descr().to_owned(),
|
||||||
first_reexport_span: import.root_span,
|
glob_reexport_span: glob_binding.span,
|
||||||
duplicate_reexport_span: amb_binding.span,
|
private_item_span: binding.span,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(glob_binding) = resolution.shadowed_glob {
|
|
||||||
let binding_id = match binding.kind {
|
|
||||||
NameBindingKind::Res(res) => {
|
|
||||||
Some(self.def_id_to_node_id[res.def_id().expect_local()])
|
|
||||||
}
|
|
||||||
NameBindingKind::Module(module) => {
|
|
||||||
Some(self.def_id_to_node_id[module.def_id().expect_local()])
|
|
||||||
}
|
|
||||||
NameBindingKind::Import { import, .. } => import.id(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if binding.res() != Res::Err
|
|
||||||
&& glob_binding.res() != Res::Err
|
|
||||||
&& let NameBindingKind::Import { import: glob_import, .. } =
|
|
||||||
glob_binding.kind
|
|
||||||
&& let Some(binding_id) = binding_id
|
|
||||||
&& let Some(glob_import_id) = glob_import.id()
|
|
||||||
&& let glob_import_def_id = self.local_def_id(glob_import_id)
|
|
||||||
&& self.effective_visibilities.is_exported(glob_import_def_id)
|
|
||||||
&& glob_binding.vis.is_public()
|
|
||||||
&& !binding.vis.is_public()
|
|
||||||
{
|
|
||||||
self.lint_buffer.buffer_lint(
|
|
||||||
HIDDEN_GLOB_REEXPORTS,
|
|
||||||
binding_id,
|
|
||||||
binding.span,
|
|
||||||
BuiltinLintDiag::HiddenGlobReexports {
|
|
||||||
name: key.ident.name.to_string(),
|
|
||||||
namespace: key.ns.descr().to_owned(),
|
|
||||||
glob_reexport_span: glob_binding.span,
|
|
||||||
private_item_span: binding.span,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1006,21 +1002,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
self.lint_if_path_starts_with_module(Some(finalize), &full_path, None);
|
self.lint_if_path_starts_with_module(Some(finalize), &full_path, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ModuleOrUniformRoot::Module(module) = module {
|
if let ModuleOrUniformRoot::Module(module) = module
|
||||||
if module == import.parent_scope.module {
|
&& module == import.parent_scope.module
|
||||||
// Importing a module into itself is not allowed.
|
{
|
||||||
return Some(UnresolvedImportError {
|
// Importing a module into itself is not allowed.
|
||||||
span: import.span,
|
return Some(UnresolvedImportError {
|
||||||
label: Some(String::from(
|
span: import.span,
|
||||||
"cannot glob-import a module into itself",
|
label: Some(String::from("cannot glob-import a module into itself")),
|
||||||
)),
|
note: None,
|
||||||
note: None,
|
suggestion: None,
|
||||||
suggestion: None,
|
candidates: None,
|
||||||
candidates: None,
|
segment: None,
|
||||||
segment: None,
|
module: None,
|
||||||
module: None,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if !is_prelude
|
if !is_prelude
|
||||||
&& let Some(max_vis) = max_vis.get()
|
&& let Some(max_vis) = max_vis.get()
|
||||||
|
@ -1081,18 +1075,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
// Consistency checks, analogous to `finalize_macro_resolutions`.
|
// Consistency checks, analogous to `finalize_macro_resolutions`.
|
||||||
let initial_res = source_bindings[ns].get().map(|initial_binding| {
|
let initial_res = source_bindings[ns].get().map(|initial_binding| {
|
||||||
all_ns_err = false;
|
all_ns_err = false;
|
||||||
if let Some(target_binding) = target_bindings[ns].get() {
|
if let Some(target_binding) = target_bindings[ns].get()
|
||||||
if target.name == kw::Underscore
|
&& target.name == kw::Underscore
|
||||||
&& initial_binding.is_extern_crate()
|
&& initial_binding.is_extern_crate()
|
||||||
&& !initial_binding.is_import()
|
&& !initial_binding.is_import()
|
||||||
{
|
{
|
||||||
let used = if import.module_path.is_empty() {
|
let used = if import.module_path.is_empty() {
|
||||||
Used::Scope
|
Used::Scope
|
||||||
} else {
|
} else {
|
||||||
Used::Other
|
Used::Other
|
||||||
};
|
};
|
||||||
this.record_use(ident, target_binding, used);
|
this.record_use(ident, target_binding, used);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
initial_binding.res()
|
initial_binding.res()
|
||||||
});
|
});
|
||||||
|
@ -1247,17 +1240,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
let mut any_successful_reexport = false;
|
let mut any_successful_reexport = false;
|
||||||
let mut crate_private_reexport = false;
|
let mut crate_private_reexport = false;
|
||||||
self.per_ns(|this, ns| {
|
self.per_ns(|this, ns| {
|
||||||
if let Ok(binding) = source_bindings[ns].get() {
|
let Ok(binding) = source_bindings[ns].get() else {
|
||||||
if !binding.vis.is_at_least(import.vis, this.tcx) {
|
return;
|
||||||
reexport_error = Some((ns, binding));
|
};
|
||||||
if let ty::Visibility::Restricted(binding_def_id) = binding.vis {
|
|
||||||
if binding_def_id.is_top_level_module() {
|
if !binding.vis.is_at_least(import.vis, this.tcx) {
|
||||||
crate_private_reexport = true;
|
reexport_error = Some((ns, binding));
|
||||||
}
|
if let ty::Visibility::Restricted(binding_def_id) = binding.vis
|
||||||
}
|
&& binding_def_id.is_top_level_module()
|
||||||
} else {
|
{
|
||||||
any_successful_reexport = true;
|
crate_private_reexport = true;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
any_successful_reexport = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1474,28 +1469,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
// Since import resolution is finished, globs will not define any more names.
|
// Since import resolution is finished, globs will not define any more names.
|
||||||
*module.globs.borrow_mut() = Vec::new();
|
*module.globs.borrow_mut() = Vec::new();
|
||||||
|
|
||||||
if let Some(def_id) = module.opt_def_id() {
|
let Some(def_id) = module.opt_def_id() else { return };
|
||||||
let mut children = Vec::new();
|
|
||||||
|
|
||||||
module.for_each_child(self, |this, ident, _, binding| {
|
let mut children = Vec::new();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
children.push(ModChild { ident, res, vis: binding.vis, reexport_chain });
|
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 !children.is_empty() {
|
children.push(ModChild { ident, res, vis: binding.vis, reexport_chain });
|
||||||
// Should be fine because this code is only called for local modules.
|
|
||||||
self.module_children.insert(def_id.expect_local(), children);
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if !children.is_empty() {
|
||||||
|
// Should be fine because this code is only called for local modules.
|
||||||
|
self.module_children.insert(def_id.expect_local(), children);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -468,16 +468,12 @@ impl<'a> PathSource<'a> {
|
||||||
{
|
{
|
||||||
"external crate"
|
"external crate"
|
||||||
}
|
}
|
||||||
ExprKind::Path(_, path) => {
|
ExprKind::Path(_, path)
|
||||||
let mut msg = "function";
|
if let Some(segment) = path.segments.last()
|
||||||
if let Some(segment) = path.segments.iter().last() {
|
&& let Some(c) = segment.ident.to_string().chars().next()
|
||||||
if let Some(c) = segment.ident.to_string().chars().next() {
|
&& c.is_uppercase() =>
|
||||||
if c.is_uppercase() {
|
{
|
||||||
msg = "function, tuple struct or tuple variant";
|
"function, tuple struct or tuple variant"
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
msg
|
|
||||||
}
|
}
|
||||||
_ => "function",
|
_ => "function",
|
||||||
},
|
},
|
||||||
|
@ -1182,32 +1178,27 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
|
||||||
// namespace first, and if that fails we try again in the value namespace. If
|
// namespace first, and if that fails we try again in the value namespace. If
|
||||||
// resolution in the value namespace succeeds, we have an generic const argument on
|
// resolution in the value namespace succeeds, we have an generic const argument on
|
||||||
// our hands.
|
// our hands.
|
||||||
if let TyKind::Path(None, ref path) = ty.kind {
|
if let TyKind::Path(None, ref path) = ty.kind
|
||||||
// We cannot disambiguate multi-segment paths right now as that requires type
|
// We cannot disambiguate multi-segment paths right now as that requires type
|
||||||
// checking.
|
// checking.
|
||||||
if path.is_potential_trivial_const_arg() {
|
&& path.is_potential_trivial_const_arg()
|
||||||
let mut check_ns = |ns| {
|
{
|
||||||
self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns)
|
let mut check_ns = |ns| {
|
||||||
.is_some()
|
self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns)
|
||||||
};
|
.is_some()
|
||||||
if !check_ns(TypeNS) && check_ns(ValueNS) {
|
};
|
||||||
self.resolve_anon_const_manual(
|
if !check_ns(TypeNS) && check_ns(ValueNS) {
|
||||||
true,
|
self.resolve_anon_const_manual(
|
||||||
AnonConstKind::ConstArg(IsRepeatExpr::No),
|
true,
|
||||||
|this| {
|
AnonConstKind::ConstArg(IsRepeatExpr::No),
|
||||||
this.smart_resolve_path(
|
|this| {
|
||||||
ty.id,
|
this.smart_resolve_path(ty.id, &None, path, PathSource::Expr(None));
|
||||||
&None,
|
this.visit_path(path, ty.id);
|
||||||
path,
|
},
|
||||||
PathSource::Expr(None),
|
);
|
||||||
);
|
|
||||||
this.visit_path(path, ty.id);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
self.diag_metadata.currently_processing_generic_args = prev;
|
self.diag_metadata.currently_processing_generic_args = prev;
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1243,54 +1234,56 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) {
|
fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) {
|
||||||
if let Some(ref args) = path_segment.args {
|
let Some(ref args) = path_segment.args else {
|
||||||
match &**args {
|
return;
|
||||||
GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, args),
|
};
|
||||||
GenericArgs::Parenthesized(p_args) => {
|
|
||||||
// Probe the lifetime ribs to know how to behave.
|
match &**args {
|
||||||
for rib in self.lifetime_ribs.iter().rev() {
|
GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, args),
|
||||||
match rib.kind {
|
GenericArgs::Parenthesized(p_args) => {
|
||||||
// We are inside a `PolyTraitRef`. The lifetimes are
|
// Probe the lifetime ribs to know how to behave.
|
||||||
// to be introduced in that (maybe implicit) `for<>` binder.
|
for rib in self.lifetime_ribs.iter().rev() {
|
||||||
LifetimeRibKind::Generics {
|
match rib.kind {
|
||||||
binder,
|
// We are inside a `PolyTraitRef`. The lifetimes are
|
||||||
kind: LifetimeBinderKind::PolyTrait,
|
// to be introduced in that (maybe implicit) `for<>` binder.
|
||||||
..
|
LifetimeRibKind::Generics {
|
||||||
} => {
|
binder,
|
||||||
self.with_lifetime_rib(
|
kind: LifetimeBinderKind::PolyTrait,
|
||||||
LifetimeRibKind::AnonymousCreateParameter {
|
..
|
||||||
|
} => {
|
||||||
|
self.with_lifetime_rib(
|
||||||
|
LifetimeRibKind::AnonymousCreateParameter {
|
||||||
|
binder,
|
||||||
|
report_in_path: false,
|
||||||
|
},
|
||||||
|
|this| {
|
||||||
|
this.resolve_fn_signature(
|
||||||
binder,
|
binder,
|
||||||
report_in_path: false,
|
false,
|
||||||
},
|
p_args.inputs.iter().map(|ty| (None, &**ty)),
|
||||||
|this| {
|
&p_args.output,
|
||||||
this.resolve_fn_signature(
|
)
|
||||||
binder,
|
},
|
||||||
false,
|
);
|
||||||
p_args.inputs.iter().map(|ty| (None, &**ty)),
|
break;
|
||||||
&p_args.output,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// We have nowhere to introduce generics. Code is malformed,
|
|
||||||
// so use regular lifetime resolution to avoid spurious errors.
|
|
||||||
LifetimeRibKind::Item | LifetimeRibKind::Generics { .. } => {
|
|
||||||
visit::walk_generic_args(self, args);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
LifetimeRibKind::AnonymousCreateParameter { .. }
|
|
||||||
| LifetimeRibKind::AnonymousReportError
|
|
||||||
| LifetimeRibKind::StaticIfNoLifetimeInScope { .. }
|
|
||||||
| LifetimeRibKind::Elided(_)
|
|
||||||
| LifetimeRibKind::ElisionFailure
|
|
||||||
| LifetimeRibKind::ConcreteAnonConst(_)
|
|
||||||
| LifetimeRibKind::ConstParamTy => {}
|
|
||||||
}
|
}
|
||||||
|
// We have nowhere to introduce generics. Code is malformed,
|
||||||
|
// so use regular lifetime resolution to avoid spurious errors.
|
||||||
|
LifetimeRibKind::Item | LifetimeRibKind::Generics { .. } => {
|
||||||
|
visit::walk_generic_args(self, args);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LifetimeRibKind::AnonymousCreateParameter { .. }
|
||||||
|
| LifetimeRibKind::AnonymousReportError
|
||||||
|
| LifetimeRibKind::StaticIfNoLifetimeInScope { .. }
|
||||||
|
| LifetimeRibKind::Elided(_)
|
||||||
|
| LifetimeRibKind::ElisionFailure
|
||||||
|
| LifetimeRibKind::ConcreteAnonConst(_)
|
||||||
|
| LifetimeRibKind::ConstParamTy => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GenericArgs::ParenthesizedElided(_) => {}
|
|
||||||
}
|
}
|
||||||
|
GenericArgs::ParenthesizedElided(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1735,13 +1728,8 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let normalized_ident = ident.normalize_to_macros_2_0();
|
let normalized_ident = ident.normalize_to_macros_2_0();
|
||||||
let mut outer_res = None;
|
let outer_res = lifetime_rib_iter
|
||||||
for rib in lifetime_rib_iter {
|
.find_map(|rib| rib.bindings.get_key_value(&normalized_ident).map(|(&outer, _)| outer));
|
||||||
if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) {
|
|
||||||
outer_res = Some(outer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.emit_undeclared_lifetime_error(lifetime, outer_res);
|
self.emit_undeclared_lifetime_error(lifetime, outer_res);
|
||||||
self.record_lifetime_res(lifetime.id, LifetimeRes::Error, LifetimeElisionCandidate::Named);
|
self.record_lifetime_res(lifetime.id, LifetimeRes::Error, LifetimeElisionCandidate::Named);
|
||||||
|
@ -1808,23 +1796,21 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
}
|
}
|
||||||
LifetimeRibKind::AnonymousReportError => {
|
LifetimeRibKind::AnonymousReportError => {
|
||||||
if elided {
|
if elided {
|
||||||
let mut suggestion = None;
|
let suggestion = self.lifetime_ribs[i..].iter().rev().find_map(|rib| {
|
||||||
for rib in self.lifetime_ribs[i..].iter().rev() {
|
|
||||||
if let LifetimeRibKind::Generics {
|
if let LifetimeRibKind::Generics {
|
||||||
span,
|
span,
|
||||||
kind: LifetimeBinderKind::PolyTrait | LifetimeBinderKind::WhereBound,
|
kind: LifetimeBinderKind::PolyTrait | LifetimeBinderKind::WhereBound,
|
||||||
..
|
..
|
||||||
} = &rib.kind
|
} = rib.kind
|
||||||
{
|
{
|
||||||
suggestion =
|
Some(errors::ElidedAnonymousLivetimeReportErrorSuggestion {
|
||||||
Some(errors::ElidedAnonymousLivetimeReportErrorSuggestion {
|
lo: span.shrink_to_lo(),
|
||||||
lo: span.shrink_to_lo(),
|
hi: lifetime.ident.span.shrink_to_hi(),
|
||||||
hi: lifetime.ident.span.shrink_to_hi(),
|
})
|
||||||
});
|
} else {
|
||||||
break;
|
None
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
// are we trying to use an anonymous lifetime
|
// are we trying to use an anonymous lifetime
|
||||||
// on a non GAT associated trait type?
|
// on a non GAT associated trait type?
|
||||||
if !self.in_func_body
|
if !self.in_func_body
|
||||||
|
@ -2460,12 +2446,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
for i in (0..self.label_ribs.len()).rev() {
|
for i in (0..self.label_ribs.len()).rev() {
|
||||||
let rib = &self.label_ribs[i];
|
let rib = &self.label_ribs[i];
|
||||||
|
|
||||||
if let RibKind::MacroDefinition(def) = rib.kind {
|
if let RibKind::MacroDefinition(def) = rib.kind
|
||||||
// If an invocation of this macro created `ident`, give up on `ident`
|
// If an invocation of this macro created `ident`, give up on `ident`
|
||||||
// and switch to `ident`'s source from the macro definition.
|
// and switch to `ident`'s source from the macro definition.
|
||||||
if def == self.r.macro_def(label.span.ctxt()) {
|
&& def == self.r.macro_def(label.span.ctxt())
|
||||||
label.span.remove_mark();
|
{
|
||||||
}
|
label.span.remove_mark();
|
||||||
}
|
}
|
||||||
|
|
||||||
let ident = label.normalize_to_macro_rules();
|
let ident = label.normalize_to_macro_rules();
|
||||||
|
@ -2493,14 +2479,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
/// Determine whether or not a label from the `rib_index`th label rib is reachable.
|
/// Determine whether or not a label from the `rib_index`th label rib is reachable.
|
||||||
fn is_label_valid_from_rib(&self, rib_index: usize) -> bool {
|
fn is_label_valid_from_rib(&self, rib_index: usize) -> bool {
|
||||||
let ribs = &self.label_ribs[rib_index + 1..];
|
let ribs = &self.label_ribs[rib_index + 1..];
|
||||||
|
ribs.iter().all(|rib| !rib.kind.is_label_barrier())
|
||||||
for rib in ribs {
|
|
||||||
if rib.kind.is_label_barrier() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) {
|
fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) {
|
||||||
|
@ -3505,21 +3484,20 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
self.visit_ty(&qself.ty);
|
self.visit_ty(&qself.ty);
|
||||||
}
|
}
|
||||||
self.visit_path(&delegation.path, delegation.id);
|
self.visit_path(&delegation.path, delegation.id);
|
||||||
if let Some(body) = &delegation.body {
|
let Some(body) = &delegation.body else { return };
|
||||||
self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
|
self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
|
||||||
// `PatBoundCtx` is not necessary in this context
|
// `PatBoundCtx` is not necessary in this context
|
||||||
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
|
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
|
||||||
|
|
||||||
let span = delegation.path.segments.last().unwrap().ident.span;
|
let span = delegation.path.segments.last().unwrap().ident.span;
|
||||||
this.fresh_binding(
|
this.fresh_binding(
|
||||||
Ident::new(kw::SelfLower, span),
|
Ident::new(kw::SelfLower, span),
|
||||||
delegation.id,
|
delegation.id,
|
||||||
PatternSource::FnParam,
|
PatternSource::FnParam,
|
||||||
&mut bindings,
|
&mut bindings,
|
||||||
);
|
);
|
||||||
this.visit_block(body);
|
this.visit_block(body);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_params(&mut self, params: &'ast [Param]) {
|
fn resolve_params(&mut self, params: &'ast [Param]) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue