summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_resolve
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_resolve
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_resolve')
-rw-r--r--compiler/rustc_resolve/Cargo.toml4
-rw-r--r--compiler/rustc_resolve/messages.ftl12
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs2
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs26
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs112
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs3
-rw-r--r--compiler/rustc_resolve/src/ident.rs20
-rw-r--r--compiler/rustc_resolve/src/imports.rs40
-rw-r--r--compiler/rustc_resolve/src/late.rs87
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs187
-rw-r--r--compiler/rustc_resolve/src/lib.rs19
-rw-r--r--compiler/rustc_resolve/src/macros.rs62
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs4
14 files changed, 346 insertions, 234 deletions
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index 46da0aa28..ff9d6d873 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -3,9 +3,8 @@ name = "rustc_resolve"
version = "0.0.0"
edition = "2021"
-[lib]
-
[dependencies]
+# tidy-alphabetical-start
bitflags = "1.2.1"
pulldown-cmark = { version = "0.9.3", default-features = false }
rustc_arena = { path = "../rustc_arena" }
@@ -28,3 +27,4 @@ rustc_span = { path = "../rustc_span" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
thin-vec = "0.2.12"
tracing = "0.1"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 9a970f5db..272483d4a 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -130,9 +130,6 @@ resolve_generic_params_from_outer_item_ty_param = type parameter from outer item
resolve_glob_import_doesnt_reexport =
glob import doesn't reexport anything because no candidate is public enough
-resolve_help_try_using_local_generic_param =
- try using a local generic parameter instead
-
resolve_ident_bound_more_than_once_in_parameter_list =
identifier `{$identifier}` is bound more than once in this parameter list
.label = used as parameter more than once
@@ -249,9 +246,6 @@ resolve_self_in_generic_param_default =
generic parameters cannot use `Self` in their defaults
.label = `Self` in generic parameter default
-resolve_self_type_implicitly_declared_by_impl =
- `Self` type implicitly declared here, by this `impl`
-
resolve_tool_module_imported =
cannot use a tool module through an import
.note = the tool module imported here
@@ -267,12 +261,6 @@ resolve_trait_impl_mismatch =
.label = does not match trait
.label_trait_item = item in trait
-resolve_try_adding_local_generic_param_on_method =
- try adding a local generic parameter in this method instead
-
-resolve_try_using_local_generic_parameter =
- try using a local generic parameter instead
-
resolve_try_using_similarly_named_label =
try using similarly named label
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index a18109574..0407db528 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -981,7 +981,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
| DefKind::GlobalAsm
| DefKind::Closure
| DefKind::Impl { .. }
- | DefKind::Generator,
+ | DefKind::Coroutine,
_,
)
| Res::Local(..)
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 7dbbd4c34..3b1f957c8 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -59,7 +59,6 @@ struct UnusedImportCheckVisitor<'a, 'b, 'tcx> {
base_use_tree: Option<&'a ast::UseTree>,
base_id: ast::NodeId,
item_span: Span,
- base_use_is_pub: bool,
}
struct ExternCrateToLint {
@@ -146,7 +145,6 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
// because this means that they were generated in some fashion by the
// compiler and we don't need to consider them.
ast::ItemKind::Use(..) if item.span.is_dummy() => return,
- ast::ItemKind::Use(..) => self.base_use_is_pub = item.vis.kind.is_pub(),
ast::ItemKind::ExternCrate(orig_name) => {
self.extern_crate_items.push(ExternCrateToLint {
id: item.id,
@@ -173,7 +171,7 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
self.base_use_tree = Some(use_tree);
}
- if self.base_use_is_pub {
+ if self.r.effective_visibilities.is_exported(self.r.local_def_id(id)) {
self.check_import_as_underscore(use_tree, id);
return;
}
@@ -332,13 +330,12 @@ impl Resolver<'_, '_> {
base_use_tree: None,
base_id: ast::DUMMY_NODE_ID,
item_span: DUMMY_SP,
- base_use_is_pub: false,
};
visit::walk_crate(&mut visitor, krate);
for unused in visitor.unused_imports.values() {
let mut fixes = Vec::new();
- let mut spans = match calc_unused_spans(unused, unused.use_tree, unused.use_tree_id) {
+ let spans = match calc_unused_spans(unused, unused.use_tree, unused.use_tree_id) {
UnusedSpanResult::Used => continue,
UnusedSpanResult::FlatUnused(span, remove) => {
fixes.push((remove, String::new()));
@@ -356,20 +353,19 @@ impl Resolver<'_, '_> {
}
};
- let len = spans.len();
- spans.sort();
- let ms = MultiSpan::from_spans(spans.clone());
- let mut span_snippets = spans
+ let ms = MultiSpan::from_spans(spans);
+
+ let mut span_snippets = ms
+ .primary_spans()
.iter()
- .filter_map(|s| match tcx.sess.source_map().span_to_snippet(*s) {
- Ok(s) => Some(format!("`{s}`")),
- _ => None,
- })
+ .filter_map(|span| tcx.sess.source_map().span_to_snippet(*span).ok())
+ .map(|s| format!("`{s}`"))
.collect::<Vec<String>>();
span_snippets.sort();
+
let msg = format!(
"unused import{}{}",
- pluralize!(len),
+ pluralize!(ms.primary_spans().len()),
if !span_snippets.is_empty() {
format!(": {}", span_snippets.join(", "))
} else {
@@ -379,7 +375,7 @@ impl Resolver<'_, '_> {
let fix_msg = if fixes.len() == 1 && fixes[0].0 == unused.item_span {
"remove the whole `use` item"
- } else if spans.len() > 1 {
+ } else if ms.primary_spans().len() > 1 {
"remove the unused imports"
} else {
"remove the unused import"
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 356d7f365..13df7efe6 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -260,7 +260,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
Async::No => closure_def,
}
}
- ExprKind::Async(_, _) => self.create_def(expr.id, DefPathData::ClosureExpr, expr.span),
+ ExprKind::Gen(_, _, _) => self.create_def(expr.id, DefPathData::ClosureExpr, expr.span),
_ => self.parent_def,
};
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 907a6b1c4..93db6cfc4 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -25,7 +25,7 @@ use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Span, SyntaxContext};
-use thin_vec::ThinVec;
+use thin_vec::{thin_vec, ThinVec};
use crate::errors::{
AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive,
@@ -187,7 +187,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} else if let Some((span, msg, sugg, appl)) = suggestion {
err.span_suggestion_verbose(span, msg, sugg, appl);
err.emit();
- } else if let [segment] = path.as_slice() && is_call {
+ } else if let [segment] = path.as_slice()
+ && is_call
+ {
err.stash(segment.ident.span, rustc_errors::StashKey::CallIntoMethod);
} else {
err.emit();
@@ -1145,7 +1147,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
namespace: Namespace,
parent_scope: &ParentScope<'a>,
start_module: Module<'a>,
- crate_name: Ident,
+ crate_path: ThinVec<ast::PathSegment>,
filter_fn: FilterFn,
) -> Vec<ImportSuggestion>
where
@@ -1161,14 +1163,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
Some(x) => Some(x),
} {
let in_module_is_extern = !in_module.def_id().is_local();
- // We have to visit module children in deterministic order to avoid
- // instabilities in reported imports (#43552).
in_module.for_each_child(self, |this, ident, ns, name_binding| {
// avoid non-importable candidates
if !name_binding.is_importable() {
return;
}
+ if ident.name == kw::Underscore {
+ return;
+ }
+
let child_accessible =
accessible && this.is_accessible_from(name_binding.vis, parent_scope.module);
@@ -1208,12 +1212,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let res = name_binding.res();
if filter_fn(res) {
// create the path
- let mut segms = path_segments.clone();
- if lookup_ident.span.at_least_rust_2018() {
+ let mut segms = if lookup_ident.span.at_least_rust_2018() {
// crate-local absolute paths start with `crate::` in edition 2018
// FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
- segms.insert(0, ast::PathSegment::from_ident(crate_name));
- }
+ crate_path.clone()
+ } else {
+ ThinVec::new()
+ };
+ segms.append(&mut path_segments.clone());
segms.push(ast::PathSegment::from_ident(ident));
let path = Path { span: name_binding.span, segments: segms, tokens: None };
@@ -1312,18 +1318,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
where
FilterFn: Fn(Res) -> bool,
{
+ let crate_path = thin_vec![ast::PathSegment::from_ident(Ident::with_dummy_span(kw::Crate))];
let mut suggestions = self.lookup_import_candidates_from_module(
lookup_ident,
namespace,
parent_scope,
self.graph_root,
- Ident::with_dummy_span(kw::Crate),
+ crate_path,
&filter_fn,
);
if lookup_ident.span.at_least_rust_2018() {
- let extern_prelude_names = self.extern_prelude.clone();
- for (ident, _) in extern_prelude_names.into_iter() {
+ for ident in self.extern_prelude.clone().into_keys() {
if ident.span.from_expansion() {
// Idents are adjusted to the root context before being
// resolved in the extern prelude, so reporting this to the
@@ -1334,13 +1340,43 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
let crate_id = self.crate_loader(|c| c.maybe_process_path_extern(ident.name));
if let Some(crate_id) = crate_id {
- let crate_root = self.expect_module(crate_id.as_def_id());
+ let crate_def_id = crate_id.as_def_id();
+ 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.
+ // If so, we have to disambiguate the potential import suggestions by making
+ // the paths *global* (i.e., by prefixing them with `::`).
+ let needs_disambiguation =
+ self.resolutions(parent_scope.module).borrow().iter().any(
+ |(key, name_resolution)| {
+ if key.ns == TypeNS
+ && key.ident == ident
+ && let Some(binding) = name_resolution.borrow().binding
+ {
+ match binding.res() {
+ // No disambiguation needed if the identically named item we
+ // found in scope actually refers to the crate in question.
+ Res::Def(_, def_id) => def_id != crate_def_id,
+ Res::PrimTy(_) => true,
+ _ => false,
+ }
+ } else {
+ false
+ }
+ },
+ );
+ let mut crate_path = ThinVec::new();
+ if needs_disambiguation {
+ crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP));
+ }
+ crate_path.push(ast::PathSegment::from_ident(ident));
+
suggestions.extend(self.lookup_import_candidates_from_module(
lookup_ident,
namespace,
parent_scope,
crate_root,
- ident,
+ crate_path,
&filter_fn,
));
}
@@ -1505,9 +1541,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
),
);
}
+
+ let (span, sugg, post) = if let SuggestionTarget::SimilarlyNamed = suggestion.target
+ && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+ && let Some(span) = suggestion.span
+ && let Some(candidate) = suggestion.candidate.as_str().strip_prefix('_')
+ && snippet == candidate
+ {
+ // When the suggested binding change would be from `x` to `_x`, suggest changing the
+ // original binding definition instead. (#60164)
+ (span, snippet, ", consider changing it")
+ } else {
+ (span, suggestion.candidate.to_string(), "")
+ };
let msg = match suggestion.target {
SuggestionTarget::SimilarlyNamed => format!(
- "{} {} with a similar name exists",
+ "{} {} with a similar name exists{post}",
suggestion.res.article(),
suggestion.res.descr()
),
@@ -1515,7 +1564,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
format!("maybe you meant this {}", suggestion.res.descr())
}
};
- err.span_suggestion(span, msg, suggestion.candidate, Applicability::MaybeIncorrect);
+ err.span_suggestion(span, msg, sugg, Applicability::MaybeIncorrect);
true
}
@@ -1686,7 +1735,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
non_exhaustive = Some(attr.span);
} else if let Some(span) = ctor_fields_span {
err.span_label(span, "a constructor is private if any of the fields is private");
- if let Res::Def(_, d) = res && let Some(fields) = self.field_visibility_spans.get(&d) {
+ if let Res::Def(_, d) = res
+ && let Some(fields) = self.field_visibility_spans.get(&d)
+ {
err.multipart_suggestion_verbose(
format!(
"consider making the field{} publicly accessible",
@@ -1735,7 +1786,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
// Final step in the import chain, point out if the ADT is `non_exhaustive`
// which is probably why this privacy violation occurred.
- if next_binding.is_none() && let Some(span) = non_exhaustive {
+ if next_binding.is_none()
+ && let Some(span) = non_exhaustive
+ {
note_span.push_span_label(
span,
"cannot be constructed because it is `#[non_exhaustive]`",
@@ -1842,7 +1895,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope,
None,
ignore_binding,
- ).ok()
+ )
+ .ok()
} else if let Some(ribs) = ribs
&& let Some(TypeNS | ValueNS) = opt_ns
{
@@ -1866,7 +1920,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None,
false,
ignore_binding,
- ).ok()
+ )
+ .ok()
};
if let Some(binding) = binding {
let mut found = |what| {
@@ -2228,7 +2283,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// 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) {
+ if is_definitely_crate
+ && let Ok(start_snippet) = source_map.span_to_snippet(start_point)
+ {
corrections.push((
start_point,
if has_nested {
@@ -2243,7 +2300,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// 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()));
+ corrections
+ .push((source_map.end_point(after_crate_name), "};".to_string()));
}
} else {
// If the root import is module-relative, add the import separately
@@ -2526,7 +2584,7 @@ fn show_candidates(
candidates.iter().for_each(|c| {
(if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings })
- .push((path_names_to_string(&c.path), c.descr, c.did, &c.note, c.via_import))
+ .push((pprust::path_to_string(&c.path), c.descr, c.did, &c.note, c.via_import))
});
// we want consistent results across executions, but candidates are produced
@@ -2582,7 +2640,13 @@ fn show_candidates(
for candidate in &mut accessible_path_strings {
// produce an additional newline to separate the new use statement
// from the directly following item.
- let additional_newline = if let FoundUse::No = found_use && let DiagnosticMode::Normal = mode { "\n" } else { "" };
+ let additional_newline = if let FoundUse::No = found_use
+ && let DiagnosticMode::Normal = mode
+ {
+ "\n"
+ } else {
+ ""
+ };
candidate.0 =
format!("{add_use}{}{append}{trailing}{additional_newline}", &candidate.0);
}
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 46f5df5ca..4477b9672 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -147,7 +147,8 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
warn_ambiguity |= nested_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);
}
}
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 54388f80f..1a50bd5ec 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -896,7 +896,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if !restricted_shadowing && binding.expansion != LocalExpnId::ROOT {
if let NameBindingKind::Import { import, .. } = binding.kind
- && matches!(import.kind, ImportKind::MacroExport) {
+ && matches!(import.kind, ImportKind::MacroExport)
+ {
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
}
}
@@ -928,9 +929,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if !self.is_accessible_from(import_vis, parent_scope.module) {
continue;
}
- if let Some(ignored) = ignore_binding &&
- let NameBindingKind::Import { import, .. } = ignored.kind &&
- import == *single_import {
+ if let Some(ignored) = ignore_binding
+ && let NameBindingKind::Import { import, .. } = ignored.kind
+ && import == *single_import
+ {
// Ignore not just the binding itself, but if it has a shadowed_glob,
// ignore that, too, because this loop is supposed to only process
// named imports.
@@ -1081,7 +1083,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
for rib in ribs {
match rib.kind {
RibKind::Normal
- | RibKind::ClosureOrAsync
+ | RibKind::FnOrCoroutine
| RibKind::Module(..)
| RibKind::MacroDefinition(..)
| RibKind::ForwardGenericParamBan => {
@@ -1154,7 +1156,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
for rib in ribs {
let has_generic_params: HasGenericParams = match rib.kind {
RibKind::Normal
- | RibKind::ClosureOrAsync
+ | RibKind::FnOrCoroutine
| RibKind::Module(..)
| RibKind::MacroDefinition(..)
| RibKind::InlineAsmSym
@@ -1238,7 +1240,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
for rib in ribs {
let has_generic_params = match rib.kind {
RibKind::Normal
- | RibKind::ClosureOrAsync
+ | RibKind::FnOrCoroutine
| RibKind::Module(..)
| RibKind::MacroDefinition(..)
| RibKind::InlineAsmSym
@@ -1440,7 +1442,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
finalize,
ignore_binding,
)
- } else if let Some(ribs) = ribs && let Some(TypeNS | ValueNS) = opt_ns {
+ } else if let Some(ribs) = ribs
+ && let Some(TypeNS | ValueNS) = opt_ns
+ {
match self.resolve_ident_in_lexical_scope(
ident,
ns,
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index d271519a8..b34790a92 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -313,26 +313,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
(true, true) => {
// FIXME: remove `!binding.is_ambiguity()` after delete the warning ambiguity.
if !binding.is_ambiguity()
- && let NameBindingKind::Import { import: old_import, .. } = old_binding.kind
+ && let NameBindingKind::Import { import: old_import, .. } =
+ old_binding.kind
&& let NameBindingKind::Import { import, .. } = binding.kind
- && old_import == import {
+ && old_import == import
+ {
// We should replace the `old_binding` with `binding` regardless
// of whether they has same resolution or not when they are
// imported from the same glob-import statement.
resolution.binding = Some(binding);
} else if res != old_binding.res() {
let binding = if warn_ambiguity {
- this.warn_ambiguity(
- AmbiguityKind::GlobVsGlob,
- old_binding,
- binding,
- )
+ this.warn_ambiguity(AmbiguityKind::GlobVsGlob, old_binding, binding)
} else {
- this.ambiguity(
- AmbiguityKind::GlobVsGlob,
- old_binding,
- binding,
- )
+ this.ambiguity(AmbiguityKind::GlobVsGlob, old_binding, binding)
};
resolution.binding = Some(binding);
} else if !old_binding.vis.is_at_least(binding.vis, this.tcx) {
@@ -434,7 +428,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let t = f(self, resolution);
- if let Some(binding) = resolution.binding() && old_binding != Some(binding) {
+ if let Some(binding) = resolution.binding()
+ && old_binding != Some(binding)
+ {
(binding, t, warn_ambiguity || old_binding.is_some())
} else {
return t;
@@ -637,7 +633,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if binding.res() != Res::Err
&& glob_binding.res() != Res::Err
- && let NameBindingKind::Import { import: glob_import, .. } = glob_binding.kind
+ && 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)
@@ -738,11 +735,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
match &import.kind {
ImportKind::Single { source, .. } => {
if let Some(ModuleOrUniformRoot::Module(module)) = import.imported_module.get()
- && let Some(module) = module.opt_def_id()
+ && let Some(module) = module.opt_def_id()
{
self.find_cfg_stripped(&mut diag, &source.name, module)
}
- },
+ }
_ => {}
}
}
@@ -989,10 +986,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
if !is_prelude
- && let Some(max_vis) = max_vis.get()
- && !max_vis.is_at_least(import.expect_vis(), self.tcx)
+ && let Some(max_vis) = max_vis.get()
+ && !max_vis.is_at_least(import.expect_vis(), self.tcx)
{
- self.lint_buffer.buffer_lint(UNUSED_IMPORTS, id, import.span, fluent::resolve_glob_import_doesnt_reexport);
+ self.lint_buffer.buffer_lint(
+ UNUSED_IMPORTS,
+ id,
+ import.span,
+ fluent::resolve_glob_import_doesnt_reexport,
+ );
}
return None;
}
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 15ec727e4..3be962dab 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -41,9 +41,6 @@ type Res = def::Res<NodeId>;
type IdentMap<T> = FxHashMap<Ident, T>;
-/// Map from the name in a pattern to its binding mode.
-type BindingMap = IdentMap<BindingInfo>;
-
use diagnostics::{
ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime, MissingLifetimeKind,
};
@@ -180,8 +177,8 @@ pub(crate) enum RibKind<'a> {
/// upvars).
AssocItem,
- /// We passed through a closure. Disallow labels.
- ClosureOrAsync,
+ /// We passed through a function, closure or coroutine signature. Disallow labels.
+ FnOrCoroutine,
/// We passed through an item scope. Disallow upvars.
Item(HasGenericParams),
@@ -218,7 +215,7 @@ impl RibKind<'_> {
pub(crate) fn contains_params(&self) -> bool {
match self {
RibKind::Normal
- | RibKind::ClosureOrAsync
+ | RibKind::FnOrCoroutine
| RibKind::ConstantItem(..)
| RibKind::Module(_)
| RibKind::MacroDefinition(_)
@@ -234,7 +231,7 @@ impl RibKind<'_> {
RibKind::Normal | RibKind::MacroDefinition(..) => false,
RibKind::AssocItem
- | RibKind::ClosureOrAsync
+ | RibKind::FnOrCoroutine
| RibKind::Item(..)
| RibKind::ConstantItem(..)
| RibKind::Module(..)
@@ -739,7 +736,8 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
// Check whether we should interpret this as a bare trait object.
if qself.is_none()
&& let Some(partial_res) = self.r.partial_res_map.get(&ty.id)
- && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res()
+ && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) =
+ partial_res.full_res()
{
// This path is actually a bare trait object. In case of a bare `Fn`-trait
// object with anonymous lifetimes, we need this rib to correctly place the
@@ -926,9 +924,9 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
debug!("(resolving function) entering function");
// Create a value rib for the function.
- self.with_rib(ValueNS, RibKind::ClosureOrAsync, |this| {
+ self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
// Create a label rib for the function.
- this.with_label_rib(RibKind::ClosureOrAsync, |this| {
+ this.with_label_rib(RibKind::FnOrCoroutine, |this| {
match fn_kind {
FnKind::Fn(_, _, sig, _, generics, body) => {
this.visit_generics(generics);
@@ -2049,7 +2047,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
if lifetime_count != 0 {
parameter_info.push(ElisionFnParameter {
index,
- ident: if let Some(pat) = pat && let PatKind::Ident(_, ident, _) = pat.kind {
+ ident: if let Some(pat) = pat
+ && let PatKind::Ident(_, ident, _) = pat.kind
+ {
Some(ident)
} else {
None
@@ -2143,7 +2143,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
impl<'a> Visitor<'a> for SelfVisitor<'_, '_, '_> {
fn visit_ty(&mut self, ty: &'a Ty) {
trace!("SelfVisitor considering ty={:?}", ty);
- if let TyKind::Ref(lt, ref mt) = ty.kind && self.is_self_ty(&mt.ty) {
+ if let TyKind::Ref(lt, ref mt) = ty.kind
+ && self.is_self_ty(&mt.ty)
+ {
let lt_id = if let Some(lt) = lt {
lt.id
} else {
@@ -3164,8 +3166,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
/// this is done hygienically. This could arise for a macro
/// that expands into an or-pattern where one 'x' was from the
/// user and one 'x' came from the macro.
- fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
- let mut binding_map = FxHashMap::default();
+ fn binding_mode_map(&mut self, pat: &Pat) -> FxIndexMap<Ident, BindingInfo> {
+ let mut binding_map = FxIndexMap::default();
pat.walk(&mut |pat| {
match pat.kind {
@@ -3200,22 +3202,28 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
/// Checks that all of the arms in an or-pattern have exactly the
/// same set of bindings, with the same binding modes for each.
- fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) -> Vec<BindingMap> {
- let mut missing_vars = FxHashMap::default();
- let mut inconsistent_vars = FxHashMap::default();
+ fn check_consistent_bindings(
+ &mut self,
+ pats: &[P<Pat>],
+ ) -> Vec<FxIndexMap<Ident, BindingInfo>> {
+ // pats is consistent.
+ let mut missing_vars = FxIndexMap::default();
+ let mut inconsistent_vars = FxIndexMap::default();
// 1) Compute the binding maps of all arms.
let maps = pats.iter().map(|pat| self.binding_mode_map(pat)).collect::<Vec<_>>();
// 2) Record any missing bindings or binding mode inconsistencies.
- for (map_outer, pat_outer) in pats.iter().enumerate().map(|(idx, pat)| (&maps[idx], pat)) {
+ for (map_outer, pat_outer) in maps.iter().zip(pats.iter()) {
// Check against all arms except for the same pattern which is always self-consistent.
- let inners = pats
+ let inners = maps
.iter()
- .enumerate()
+ .zip(pats.iter())
.filter(|(_, pat)| pat.id != pat_outer.id)
- .flat_map(|(idx, _)| maps[idx].iter())
- .map(|(key, binding)| (key.name, map_outer.get(&key), binding));
+ .flat_map(|(map, _)| map)
+ .map(|(key, binding)| (key.name, map_outer.get(key), binding));
+
+ let inners = inners.collect::<Vec<_>>();
for (name, info, &binding_inner) in inners {
match info {
@@ -3244,10 +3252,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
}
// 3) Report all missing variables we found.
- let mut missing_vars = missing_vars.into_iter().collect::<Vec<_>>();
- missing_vars.sort_by_key(|&(sym, ref _err)| sym);
-
- for (name, mut v) in missing_vars.into_iter() {
+ for (name, mut v) in missing_vars {
if inconsistent_vars.contains_key(&name) {
v.could_be_path = false;
}
@@ -3258,10 +3263,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
}
// 4) Report all inconsistencies in binding modes we found.
- let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>();
- inconsistent_vars.sort();
for (name, v) in inconsistent_vars {
- self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1));
+ self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(name, v.1));
}
// 5) Finally bubble up all the binding maps.
@@ -3604,7 +3607,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
sugg.to_string(),
Applicability::MaybeIncorrect,
))
- } else if res.is_none() && let PathSource::Type | PathSource::Expr(_) = source {
+ } else if res.is_none()
+ && let PathSource::Type | PathSource::Expr(_) = source
+ {
this.suggest_adding_generic_parameter(path, source)
} else {
None
@@ -4006,7 +4011,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
"unnecessary qualification",
lint::BuiltinLintDiagnostics::UnusedQualifications {
removal_span: finalize.path_span.until(last_segment.ident.span),
- }
+ },
)
}
}
@@ -4059,13 +4064,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
(block.could_be_bare_literal, &block.stmts[..])
&& let ExprKind::Type(..) = expr.kind
{
- self.diagnostic_metadata.current_block_could_be_bare_struct_literal =
- Some(block.span);
+ self.diagnostic_metadata.current_block_could_be_bare_struct_literal = Some(block.span);
}
// Descend into the block.
for stmt in &block.stmts {
if let StmtKind::Item(ref item) = stmt.kind
- && let ItemKind::MacroDef(..) = item.kind {
+ && let ItemKind::MacroDef(..) = item.kind
+ {
num_macro_definition_ribs += 1;
let res = self.r.local_def_id(item.id).to_def_id();
self.ribs[ValueNS].push(Rib::new(RibKind::MacroDefinition(res)));
@@ -4282,7 +4287,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
..
}) => {
self.with_rib(ValueNS, RibKind::Normal, |this| {
- this.with_label_rib(RibKind::ClosureOrAsync, |this| {
+ this.with_label_rib(RibKind::FnOrCoroutine, |this| {
// Resolve arguments:
this.resolve_params(&fn_decl.inputs);
// No need to resolve return type --
@@ -4299,7 +4304,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
})
});
}
- // For closures, ClosureOrAsyncRibKind is added in visit_fn
+ // For closures, RibKind::FnOrCoroutine is added in visit_fn
ExprKind::Closure(box ast::Closure {
binder: ClosureBinder::For { ref generic_params, span },
..
@@ -4316,8 +4321,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
);
}
ExprKind::Closure(..) => visit::walk_expr(self, expr),
- ExprKind::Async(..) => {
- self.with_label_rib(RibKind::ClosureOrAsync, |this| visit::walk_expr(this, expr));
+ ExprKind::Gen(..) => {
+ self.with_label_rib(RibKind::FnOrCoroutine, |this| visit::walk_expr(this, expr));
}
ExprKind::Repeat(ref elem, ref ct) => {
self.visit_expr(elem);
@@ -4421,7 +4426,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
&& let Some(def_id) = res.opt_def_id()
&& !def_id.is_local()
&& self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
- && matches!(self.r.tcx.sess.opts.resolve_doc_links, ResolveDocLinks::ExportedMetadata) {
+ && matches!(
+ self.r.tcx.sess.opts.resolve_doc_links,
+ ResolveDocLinks::ExportedMetadata
+ )
+ {
// Encoding foreign def ids in proc macro crate metadata will ICE.
return None;
}
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index bc5f8a37b..fd5d6fabf 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -229,8 +229,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
i.ident.name == item_str.name
// Don't suggest if the item is in Fn signature arguments (#112590).
&& !sig.span.contains(item_span)
- })
- {
+ }) {
let sp = item_span.shrink_to_lo();
// Account for `Foo { field }` when suggesting `self.field` so we result on
@@ -241,7 +240,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
_ => None,
};
- let pre = if let Some(field) = field && field.is_shorthand {
+ let pre = if let Some(field) = field
+ && field.is_shorthand
+ {
format!("{item_ident}: ")
} else {
String::new()
@@ -254,13 +255,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
_ => matches!(
source,
- PathSource::Expr(Some(Expr { kind: ExprKind::Call(..), ..})),
+ PathSource::Expr(Some(Expr { kind: ExprKind::Call(..), .. })),
),
};
match &item.kind {
AssocItemKind::Fn(fn_)
- if (!sig.decl.has_self() || !is_call) && fn_.sig.decl.has_self() => {
+ if (!sig.decl.has_self() || !is_call) && fn_.sig.decl.has_self() =>
+ {
// Ensure that we only suggest `self.` if `self` is available,
// you can't call `fn foo(&self)` from `fn bar()` (#115992).
// We also want to mention that the method exists.
@@ -270,19 +272,16 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
));
None
}
- AssocItemKind::Fn(fn_)
- if !fn_.sig.decl.has_self() && !is_call => {
+ AssocItemKind::Fn(fn_) if !fn_.sig.decl.has_self() && !is_call => {
span_label = Some((
item.ident.span,
"an associated function by that name is available on `Self` here",
));
None
}
- AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => Some((
- sp,
- "consider using the method on `Self`",
- format!("{pre}self."),
- )),
+ AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => {
+ Some((sp, "consider using the method on `Self`", format!("{pre}self.")))
+ }
AssocItemKind::Fn(_) => Some((
sp,
"consider using the associated function on `Self`",
@@ -293,7 +292,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
"consider using the associated constant on `Self`",
format!("{pre}Self::"),
)),
- _ => None
+ _ => None,
}
} else {
None
@@ -379,8 +378,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
prefix_path: &[Segment],
following_seg: Option<&Segment>,
) -> Vec<ImportSuggestion> {
- if let Some(segment) = prefix_path.last() &&
- let Some(following_seg) = following_seg
+ if let Some(segment) = prefix_path.last()
+ && let Some(following_seg) = following_seg
{
let candidates = self.r.lookup_import_candidates(
segment.ident,
@@ -392,12 +391,16 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
candidates
.into_iter()
.filter(|candidate| {
- if let Some(def_id) = candidate.did &&
- let Some(module) = self.r.get_module(def_id) {
- Some(def_id) != self.parent_scope.module.opt_def_id() &&
- self.r.resolutions(module).borrow().iter().any(|(key, _r)| {
- key.ident.name == following_seg.ident.name
- })
+ if let Some(def_id) = candidate.did
+ && let Some(module) = self.r.get_module(def_id)
+ {
+ Some(def_id) != self.parent_scope.module.opt_def_id()
+ && self
+ .r
+ .resolutions(module)
+ .borrow()
+ .iter()
+ .any(|(key, _r)| key.ident.name == following_seg.ident.name)
} else {
false
}
@@ -747,11 +750,15 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
// Try to find in last block rib
- if let Some(rib) = &self.last_block_rib && let RibKind::Normal = rib.kind {
+ if let Some(rib) = &self.last_block_rib
+ && let RibKind::Normal = rib.kind
+ {
for (ident, &res) in &rib.bindings {
- if let Res::Local(_) = res && path.len() == 1 &&
- ident.span.eq_ctxt(path[0].ident.span) &&
- ident.name == path[0].ident.name {
+ if let Res::Local(_) = res
+ && path.len() == 1
+ && ident.span.eq_ctxt(path[0].ident.span)
+ && ident.name == path[0].ident.name
+ {
err.span_help(
ident.span,
format!("the binding `{path_str}` is available in a different scope in the same function"),
@@ -867,9 +874,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
// (could be in a different file) or introduced in the same file as the typo
// (could belong to a different crate)
if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg
- && res
- .opt_def_id()
- .is_some_and(|id| id.is_local() || is_in_same_file(span, sugg_span))
+ && res.opt_def_id().is_some_and(|id| id.is_local() || is_in_same_file(span, sugg_span))
{
err.span_label(
sugg_span,
@@ -1074,12 +1079,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
&& trait_ref.path.span == span
&& let PathSource::Trait(_) = source
&& let Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)) = res
- && let Ok(self_ty_str) =
- self.r.tcx.sess.source_map().span_to_snippet(self_ty.span)
+ && let Ok(self_ty_str) = self.r.tcx.sess.source_map().span_to_snippet(self_ty.span)
&& let Ok(trait_ref_str) =
self.r.tcx.sess.source_map().span_to_snippet(trait_ref.path.span)
{
- err.multipart_suggestion(
+ err.multipart_suggestion(
"`impl` items mention the trait being implemented first and the type it is being implemented for second",
vec![(trait_ref.path.span, self_ty_str), (self_ty.span, trait_ref_str)],
Applicability::MaybeIncorrect,
@@ -1106,12 +1110,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
source: PathSource<'_>,
span: Span,
) -> bool {
- if let PathSource::Expr(_) = source &&
- let Some(Expr {
- span: expr_span,
- kind: ExprKind::Assign(lhs, _, _),
- ..
- }) = self.diagnostic_metadata.in_if_condition {
+ if let PathSource::Expr(_) = source
+ && let Some(Expr { span: expr_span, kind: ExprKind::Assign(lhs, _, _), .. }) =
+ self.diagnostic_metadata.in_if_condition
+ {
// Icky heuristic so we don't suggest:
// `if (i + 2) = 2` => `if let (i + 2) = 2` (approximately pattern)
// `if 2 = i` => `if let 2 = i` (lhs needs to contain error span)
@@ -1240,31 +1242,32 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
let mut has_self_arg = None;
if let PathSource::Expr(Some(parent)) = source
&& let ExprKind::Call(_, args) = &parent.kind
- && !args.is_empty() {
- let mut expr_kind = &args[0].kind;
- loop {
- match expr_kind {
- ExprKind::Path(_, arg_name) if arg_name.segments.len() == 1 => {
- if arg_name.segments[0].ident.name == kw::SelfLower {
- let call_span = parent.span;
- let tail_args_span = if args.len() > 1 {
- Some(Span::new(
- args[1].span.lo(),
- args.last().unwrap().span.hi(),
- call_span.ctxt(),
- None,
- ))
- } else {
- None
- };
- has_self_arg = Some((call_span, tail_args_span));
- }
- break;
+ && !args.is_empty()
+ {
+ let mut expr_kind = &args[0].kind;
+ loop {
+ match expr_kind {
+ ExprKind::Path(_, arg_name) if arg_name.segments.len() == 1 => {
+ if arg_name.segments[0].ident.name == kw::SelfLower {
+ let call_span = parent.span;
+ let tail_args_span = if args.len() > 1 {
+ Some(Span::new(
+ args[1].span.lo(),
+ args.last().unwrap().span.hi(),
+ call_span.ctxt(),
+ None,
+ ))
+ } else {
+ None
+ };
+ has_self_arg = Some((call_span, tail_args_span));
}
- ExprKind::AddrOf(_, _, expr) => expr_kind = &expr.kind,
- _ => break,
+ break;
}
+ ExprKind::AddrOf(_, _, expr) => expr_kind = &expr.kind,
+ _ => break,
}
+ }
}
has_self_arg
}
@@ -1321,8 +1324,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
);
true
} else if kind == DefKind::Struct
- && let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
- && let Ok(snippet) = self.r.tcx.sess.source_map().span_to_snippet(lhs_source_span)
+ && let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
+ && let Ok(snippet) = self.r.tcx.sess.source_map().span_to_snippet(lhs_source_span)
{
// The LHS is a type that originates from a macro call.
// We have to add angle brackets around it.
@@ -1427,7 +1430,13 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
.map(|(idx, new)| (new, old_fields.get(idx)))
.map(|(new, old)| {
let new = new.to_ident_string();
- if let Some(Some(old)) = old && new != *old { format!("{new}: {old}") } else { new }
+ if let Some(Some(old)) = old
+ && new != *old
+ {
+ format!("{new}: {old}")
+ } else {
+ new
+ }
})
.collect::<Vec<String>>()
} else {
@@ -1561,7 +1570,26 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
err.set_primary_message(
"cannot initialize a tuple struct which contains private fields",
);
-
+ if !def_id.is_local()
+ && self
+ .r
+ .tcx
+ .inherent_impls(def_id)
+ .iter()
+ .flat_map(|impl_def_id| {
+ self.r.tcx.provided_trait_methods(*impl_def_id)
+ })
+ .any(|assoc| !assoc.fn_has_self_parameter && assoc.name == sym::new)
+ {
+ // FIXME: look for associated functions with Self return type,
+ // instead of relying only on the name and lack of self receiver.
+ err.span_suggestion_verbose(
+ span.shrink_to_hi(),
+ "you might have meant to use the `new` associated function",
+ "::new".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
// Use spans of the tuple struct definition.
self.r.field_def_ids(def_id).map(|field_ids| {
field_ids
@@ -1813,7 +1841,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
}
- if let RibKind::MacroDefinition(def) = rib.kind && def == self.r.macro_def(ctxt) {
+ if let RibKind::MacroDefinition(def) = rib.kind
+ && def == self.r.macro_def(ctxt)
+ {
// If an invocation of this macro created `ident`, give up on `ident`
// and switch to `ident`'s source from the macro definition.
ctxt.remove_mark();
@@ -1934,18 +1964,20 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
// try to give a suggestion for this pattern: `name = blah`, which is common in other languages
// suggest `let name = blah` to introduce a new binding
fn let_binding_suggestion(&mut self, err: &mut Diagnostic, ident_span: Span) -> bool {
- if let Some(Expr { kind: ExprKind::Assign(lhs, .. ), .. }) = self.diagnostic_metadata.in_assignment &&
- let ast::ExprKind::Path(None, _) = lhs.kind {
- if !ident_span.from_expansion() {
- err.span_suggestion_verbose(
- ident_span.shrink_to_lo(),
- "you might have meant to introduce a new binding",
- "let ".to_string(),
- Applicability::MaybeIncorrect,
- );
- return true;
- }
+ if let Some(Expr { kind: ExprKind::Assign(lhs, ..), .. }) =
+ self.diagnostic_metadata.in_assignment
+ && let ast::ExprKind::Path(None, _) = lhs.kind
+ {
+ if !ident_span.from_expansion() {
+ err.span_suggestion_verbose(
+ ident_span.shrink_to_lo(),
+ "you might have meant to introduce a new binding",
+ "let ".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ return true;
}
+ }
false
}
@@ -2406,7 +2438,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
continue;
}
- if !span.can_be_used_for_suggestions() && suggest_note && let Some(name) = name {
+ if !span.can_be_used_for_suggestions()
+ && suggest_note
+ && let Some(name) = name
+ {
suggest_note = false; // Avoid displaying the same help multiple times.
err.span_label(
span,
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 949c6ab5a..501747df5 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -7,6 +7,8 @@
//! Type-relative name resolution (methods, fields, associated items) happens in `rustc_hir_analysis`.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![cfg_attr(not(bootstrap), doc(rust_logo))]
+#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(extract_if)]
@@ -824,8 +826,10 @@ impl<'a> NameBindingData<'a> {
matches!(import.kind, ImportKind::ExternCrate { .. })
}
NameBindingKind::Module(module)
- if let ModuleKind::Def(DefKind::Mod, def_id, _) = module.kind
- => def_id.is_crate_root(),
+ if let ModuleKind::Def(DefKind::Mod, def_id, _) = module.kind =>
+ {
+ def_id.is_crate_root()
+ }
_ => false,
}
}
@@ -1074,8 +1078,8 @@ pub struct Resolver<'a, 'tcx> {
/// Also includes of list of each fields visibility
struct_constructors: LocalDefIdMap<(Res, ty::Visibility<DefId>, Vec<ty::Visibility<DefId>>)>,
- /// Features enabled for this crate.
- active_features: FxHashSet<Symbol>,
+ /// Features declared for this crate.
+ declared_features: FxHashSet<Symbol>,
lint_buffer: LintBuffer,
@@ -1417,12 +1421,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
multi_segment_macro_resolutions: Default::default(),
builtin_attrs: Default::default(),
containers_deriving_copy: Default::default(),
- active_features: features
- .declared_lib_features
- .iter()
- .map(|(feat, ..)| *feat)
- .chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat))
- .collect(),
+ declared_features: features.declared_features.clone(),
lint_buffer: LintBuffer::default(),
next_node_id: CRATE_NODE_ID,
node_id_to_def_id,
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 90ae08ce3..2ff6fb424 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -748,33 +748,45 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
path_res @ (PathResult::NonModule(..) | PathResult::Failed { .. }) => {
let mut suggestion = None;
- let (span, label, module) = if let PathResult::Failed { span, label, module, .. } = path_res {
- // try to suggest if it's not a macro, maybe a function
- if let PathResult::NonModule(partial_res) = self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope)
- && partial_res.unresolved_segments() == 0 {
- let sm = self.tcx.sess.source_map();
- let exclamation_span = sm.next_point(span);
- suggestion = Some((
- vec![(exclamation_span, "".to_string())],
- format!("{} is not a macro, but a {}, try to remove `!`", Segment::names_to_string(&path), partial_res.base_res().descr()),
- Applicability::MaybeIncorrect
+ let (span, label, module) =
+ if let PathResult::Failed { span, label, module, .. } = path_res {
+ // try to suggest if it's not a macro, maybe a function
+ if let PathResult::NonModule(partial_res) =
+ self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope)
+ && partial_res.unresolved_segments() == 0
+ {
+ let sm = self.tcx.sess.source_map();
+ let exclamation_span = sm.next_point(span);
+ suggestion = Some((
+ vec![(exclamation_span, "".to_string())],
+ format!(
+ "{} is not a macro, but a {}, try to remove `!`",
+ Segment::names_to_string(&path),
+ partial_res.base_res().descr()
+ ),
+ Applicability::MaybeIncorrect,
));
- }
- (span, label, module)
- } else {
- (
- path_span,
- format!(
- "partially resolved path in {} {}",
- kind.article(),
- kind.descr()
- ),
- None,
- )
- };
+ }
+ (span, label, module)
+ } else {
+ (
+ path_span,
+ format!(
+ "partially resolved path in {} {}",
+ kind.article(),
+ kind.descr()
+ ),
+ None,
+ )
+ };
self.report_error(
span,
- ResolutionError::FailedToResolve { last_segment: path.last().map(|segment| segment.ident.name), label, suggestion, module },
+ ResolutionError::FailedToResolve {
+ last_segment: path.last().map(|segment| segment.ident.name),
+ label,
+ suggestion,
+ module,
+ },
);
}
PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
@@ -854,7 +866,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let feature = stability.feature;
let is_allowed = |feature| {
- self.active_features.contains(&feature) || span.allows_unstable(feature)
+ self.declared_features.contains(&feature) || span.allows_unstable(feature)
};
let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature));
if !is_allowed(feature) && !allowed_by_implication {
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 7c41c32d0..fe4b8c7f6 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -346,7 +346,9 @@ pub fn has_primitive_or_keyword_docs(attrs: &[ast::Attribute]) -> bool {
for attr in attrs {
if attr.has_name(sym::rustc_doc_primitive) {
return true;
- } else if attr.has_name(sym::doc) && let Some(items) = attr.meta_item_list() {
+ } else if attr.has_name(sym::doc)
+ && let Some(items) = attr.meta_item_list()
+ {
for item in items {
if item.has_name(sym::keyword) {
return true;