rustc_resolve: reduce rightwards drift with let..else 👉💨

This commit is contained in:
Yotam Ofek 2025-01-20 20:35:45 +00:00
parent cf91a93d09
commit ae87d005bc
4 changed files with 389 additions and 383 deletions

View File

@ -1038,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)),
);
} }
} }
} }
@ -1362,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,
));
} }
} }
@ -1500,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,
@ -1508,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
&& !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;
} }
} }
@ -1738,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>) {
@ -2399,115 +2403,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 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"),
));
}
} }
_ => 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.

View File

@ -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);
}
} }
} }
} }

View File

@ -542,30 +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();
&& source.name == kw::SelfLower
// Silence `unresolved import` error if E0429 is already emitted
&& 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;
} }
} }
@ -607,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,
},
);
}
}
} }
} }
} }
@ -1242,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
&& binding_def_id.is_top_level_module() if !binding.vis.is_at_least(import.vis, this.tcx) {
{ reexport_error = Some((ns, binding));
crate_private_reexport = true; 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;
} }
}); });
@ -1469,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);
} }
} }
} }

View File

@ -1234,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(_) => {}
} }
} }
@ -3496,21 +3498,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]) {