summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_resolve/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_resolve/src')
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs125
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs8
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs29
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs649
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs227
-rw-r--r--compiler/rustc_resolve/src/errors.rs474
-rw-r--r--compiler/rustc_resolve/src/ident.rs8
-rw-r--r--compiler/rustc_resolve/src/imports.rs220
-rw-r--r--compiler/rustc_resolve/src/late.rs163
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs186
-rw-r--r--compiler/rustc_resolve/src/lib.rs72
-rw-r--r--compiler/rustc_resolve/src/macros.rs2
12 files changed, 1315 insertions, 848 deletions
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index a17793ecd..9c90d67aa 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -30,7 +30,7 @@ use rustc_middle::metadata::ModChild;
use rustc_middle::ty::{self, DefIdTree};
use rustc_session::cstore::CrateStore;
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
-use rustc_span::source_map::{respan, Spanned};
+use rustc_span::source_map::respan;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
@@ -56,21 +56,7 @@ impl<'a, Id: Into<DefId>> ToNameBinding<'a>
impl<'a, Id: Into<DefId>> ToNameBinding<'a> for (Res, ty::Visibility<Id>, Span, LocalExpnId) {
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
arenas.alloc_name_binding(NameBinding {
- kind: NameBindingKind::Res(self.0, false),
- ambiguity: None,
- vis: self.1.to_def_id(),
- span: self.2,
- expansion: self.3,
- })
- }
-}
-
-struct IsMacroExport;
-
-impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, LocalExpnId, IsMacroExport) {
- fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
- arenas.alloc_name_binding(NameBinding {
- kind: NameBindingKind::Res(self.0, true),
+ kind: NameBindingKind::Res(self.0),
ambiguity: None,
vis: self.1.to_def_id(),
span: self.2,
@@ -218,7 +204,9 @@ impl<'a> Resolver<'a> {
}
pub(crate) fn build_reduced_graph_external(&mut self, module: Module<'a>) {
- for child in self.cstore().module_children_untracked(module.def_id(), self.session) {
+ for child in
+ Vec::from_iter(self.cstore().module_children_untracked(module.def_id(), self.session))
+ {
let parent_scope = ParentScope::module(module, self);
BuildReducedGraphVisitor { r: self, parent_scope }
.build_reduced_graph_for_external_crate_res(child);
@@ -343,10 +331,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
.iter()
.map(|field| respan(field.span, field.ident.map_or(kw::Empty, |ident| ident.name)))
.collect();
- self.insert_field_names(def_id, field_names);
+ self.r.field_names.insert(def_id, field_names);
}
- fn insert_field_names(&mut self, def_id: DefId, field_names: Vec<Spanned<Symbol>>) {
+ fn insert_field_names_extern(&mut self, def_id: DefId) {
+ let field_names =
+ self.r.cstore().struct_field_names_untracked(def_id, self.r.session).collect();
self.r.field_names.insert(def_id, field_names);
}
@@ -364,7 +354,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
module_path: Vec<Segment>,
kind: ImportKind<'a>,
span: Span,
- id: NodeId,
item: &ast::Item,
root_span: Span,
root_id: NodeId,
@@ -377,7 +366,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
module_path,
imported_module: Cell::new(None),
span,
- id,
use_span: item.span,
use_span_with_attributes: item.span_with_attributes(),
has_attributes: !item.attrs.is_empty(),
@@ -457,19 +445,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
prefix.is_empty() || prefix.len() == 1 && prefix[0].ident.name == kw::PathRoot
};
match use_tree.kind {
- ast::UseTreeKind::Simple(rename, id1, id2) => {
+ ast::UseTreeKind::Simple(rename) => {
let mut ident = use_tree.ident();
let mut module_path = prefix;
let mut source = module_path.pop().unwrap();
let mut type_ns_only = false;
self.r.visibilities.insert(self.r.local_def_id(id), vis);
- if id1 != ast::DUMMY_NODE_ID {
- self.r.visibilities.insert(self.r.local_def_id(id1), vis);
- }
- if id2 != ast::DUMMY_NODE_ID {
- self.r.visibilities.insert(self.r.local_def_id(id2), vis);
- }
if nested {
// Correctly handle `self`
@@ -485,9 +467,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
}
// Replace `use foo::{ self };` with `use foo;`
+ let self_span = source.ident.span;
source = module_path.pop().unwrap();
if rename.is_none() {
- ident = source.ident;
+ // Keep the span of `self`, but the name of `foo`
+ ident = Ident { name: source.ident.name, span: self_span };
}
}
} else {
@@ -574,27 +558,19 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
},
type_ns_only,
nested,
- additional_ids: (id1, id2),
+ id,
};
- self.add_import(
- module_path,
- kind,
- use_tree.span,
- id,
- item,
- root_span,
- item.id,
- vis,
- );
+ self.add_import(module_path, kind, use_tree.span, item, root_span, item.id, vis);
}
ast::UseTreeKind::Glob => {
let kind = ImportKind::Glob {
is_prelude: self.r.session.contains_name(&item.attrs, sym::prelude_import),
max_vis: Cell::new(None),
+ id,
};
self.r.visibilities.insert(self.r.local_def_id(id), vis);
- self.add_import(prefix, kind, use_tree.span, id, item, root_span, item.id, vis);
+ self.add_import(prefix, kind, use_tree.span, item, root_span, item.id, vis);
}
ast::UseTreeKind::Nested(ref items) => {
// Ensure there is at most one `self` in the list
@@ -638,11 +614,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
let new_span = prefix[prefix.len() - 1].ident.span;
let tree = ast::UseTree {
prefix: ast::Path::from_ident(Ident::new(kw::SelfLower, new_span)),
- kind: ast::UseTreeKind::Simple(
- Some(Ident::new(kw::Underscore, new_span)),
- ast::DUMMY_NODE_ID,
- ast::DUMMY_NODE_ID,
- ),
+ kind: ast::UseTreeKind::Simple(Some(Ident::new(kw::Underscore, new_span))),
span: use_tree.span,
};
self.build_reduced_graph_for_use_tree(
@@ -768,7 +740,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
// If this is a tuple or unit struct, define a name
// in the value namespace as well.
- if let Some(ctor_node_id) = vdata.ctor_id() {
+ if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(vdata) {
// If the structure is marked as non_exhaustive then lower the visibility
// to within the crate.
let mut ctor_vis = if vis.is_public()
@@ -794,10 +766,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
ret_fields.push(field_vis.to_def_id());
}
let ctor_def_id = self.r.local_def_id(ctor_node_id);
- let ctor_res = Res::Def(
- DefKind::Ctor(CtorOf::Struct, CtorKind::from_ast(vdata)),
- ctor_def_id.to_def_id(),
- );
+ let ctor_res =
+ Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id.to_def_id());
self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion));
self.r.visibilities.insert(ctor_def_id, ctor_vis);
@@ -881,9 +851,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
})
.unwrap_or((true, None, self.r.dummy_binding));
let import = self.r.arenas.alloc_import(Import {
- kind: ImportKind::ExternCrate { source: orig_name, target: ident },
+ kind: ImportKind::ExternCrate { source: orig_name, target: ident, id: item.id },
root_id: item.id,
- id: item.id,
parent_scope: self.parent_scope,
imported_module: Cell::new(module),
has_attributes: !item.attrs.is_empty(),
@@ -1019,10 +988,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
let cstore = self.r.cstore();
match res {
Res::Def(DefKind::Struct, def_id) => {
- let field_names =
- cstore.struct_field_names_untracked(def_id, self.r.session).collect();
- let ctor = cstore.ctor_def_id_and_kind_untracked(def_id);
- if let Some((ctor_def_id, ctor_kind)) = ctor {
+ if let Some((ctor_kind, ctor_def_id)) = cstore.ctor_untracked(def_id) {
let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
let ctor_vis = cstore.visibility_untracked(ctor_def_id);
let field_visibilities =
@@ -1031,13 +997,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
.struct_constructors
.insert(def_id, (ctor_res, ctor_vis, field_visibilities));
}
- self.insert_field_names(def_id, field_names);
- }
- Res::Def(DefKind::Union, def_id) => {
- let field_names =
- cstore.struct_field_names_untracked(def_id, self.r.session).collect();
- self.insert_field_names(def_id, field_names);
+ self.insert_field_names_extern(def_id)
}
+ Res::Def(DefKind::Union, def_id) => self.insert_field_names_extern(def_id),
Res::Def(DefKind::AssocFn, def_id) => {
if cstore.fn_has_self_parameter_untracked(def_id, self.r.session) {
self.r.has_self.insert(def_id);
@@ -1118,7 +1080,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
this.r.arenas.alloc_import(Import {
kind: ImportKind::MacroUse,
root_id: item.id,
- id: item.id,
parent_scope: this.parent_scope,
imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
use_span_with_attributes: item.span_with_attributes(),
@@ -1278,8 +1239,22 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
let binding = (res, vis, span, expansion).to_name_binding(self.r.arenas);
self.r.set_binding_parent_module(binding, parent_scope.module);
if is_macro_export {
- let module = self.r.graph_root;
- self.r.define(module, ident, MacroNS, (res, vis, span, expansion, IsMacroExport));
+ let import = self.r.arenas.alloc_import(Import {
+ kind: ImportKind::MacroExport,
+ root_id: item.id,
+ parent_scope: self.parent_scope,
+ imported_module: Cell::new(None),
+ has_attributes: false,
+ use_span_with_attributes: span,
+ use_span: span,
+ root_span: span,
+ span: span,
+ module_path: Vec::new(),
+ vis: Cell::new(Some(vis)),
+ used: Cell::new(true),
+ });
+ let import_binding = self.r.import(binding, import);
+ self.r.define(self.r.graph_root, ident, MacroNS, import_binding);
} else {
self.r.check_reserved_macro_name(ident, res);
self.insert_unused_macro(ident, def_id, item.id, &rule_spans);
@@ -1526,20 +1501,16 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
};
// Define a constructor name in the value namespace.
- // Braced variants, unlike structs, generate unusable names in
- // value namespace, they are reserved for possible future use.
- // It's ok to use the variant's id as a ctor id since an
- // error will be reported on any use of such resolution anyway.
- let ctor_node_id = variant.data.ctor_id().unwrap_or(variant.id);
- let ctor_def_id = self.r.local_def_id(ctor_node_id);
- let ctor_kind = CtorKind::from_ast(&variant.data);
- let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id.to_def_id());
- self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));
- if ctor_def_id != def_id {
+ if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(&variant.data) {
+ let ctor_def_id = self.r.local_def_id(ctor_node_id);
+ let ctor_res =
+ Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id.to_def_id());
+ self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));
self.r.visibilities.insert(ctor_def_id, ctor_vis);
}
+
// Record field names for error reporting.
- self.insert_field_names_local(ctor_def_id.to_def_id(), &variant.data);
+ self.insert_field_names_local(def_id.to_def_id(), &variant.data);
visit::walk_variant(self, variant);
}
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 01c3801f2..32fb5e182 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -234,7 +234,7 @@ impl Resolver<'_> {
if !import.span.is_dummy() {
self.lint_buffer.buffer_lint(
MACRO_USE_EXTERN_CRATE,
- import.id,
+ import.root_id,
import.span,
"deprecated `#[macro_use]` attribute used to \
import macros should be replaced at use sites \
@@ -244,13 +244,13 @@ impl Resolver<'_> {
}
}
}
- ImportKind::ExternCrate { .. } => {
- let def_id = self.local_def_id(import.id);
+ ImportKind::ExternCrate { id, .. } => {
+ let def_id = self.local_def_id(id);
self.maybe_unused_extern_crates.push((def_id, import.span));
}
ImportKind::MacroUse => {
let msg = "unused `#[macro_use]` import";
- self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg);
+ self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.root_id, import.span, msg);
}
_ => {}
}
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index d36e0f61d..2764a6c28 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -118,8 +118,8 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
match i.kind {
ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
// If this is a unit or tuple-like struct, register the constructor.
- if let Some(ctor_hir_id) = struct_def.ctor_id() {
- this.create_def(ctor_hir_id, DefPathData::Ctor, i.span);
+ if let Some(ctor_node_id) = struct_def.ctor_node_id() {
+ this.create_def(ctor_node_id, DefPathData::Ctor, i.span);
}
}
_ => {}
@@ -131,12 +131,9 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind {
- if let Async::Yes { closure_id, return_impl_trait_id, .. } = sig.header.asyncness {
+ if let Async::Yes { closure_id, .. } = sig.header.asyncness {
self.visit_generics(generics);
- let return_impl_trait_id =
- self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span);
-
// For async functions, we need to create their inner defs inside of a
// closure to match their desugared representation. Besides that,
// we must mirror everything that `visit::walk_fn` below does.
@@ -144,9 +141,7 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
for param in &sig.decl.inputs {
self.visit_param(param);
}
- self.with_parent(return_impl_trait_id, |this| {
- this.visit_fn_ret_ty(&sig.decl.output)
- });
+ self.visit_fn_ret_ty(&sig.decl.output);
// If this async fn has no body (i.e. it's an async fn signature in a trait)
// then the closure_def will never be used, and we should avoid generating a
// def-id for it.
@@ -163,14 +158,6 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
self.create_def(id, DefPathData::Use, use_tree.span);
- match use_tree.kind {
- UseTreeKind::Simple(_, id1, id2) => {
- self.create_def(id1, DefPathData::Use, use_tree.prefix.span);
- self.create_def(id2, DefPathData::Use, use_tree.prefix.span);
- }
- UseTreeKind::Glob => (),
- UseTreeKind::Nested(..) => {}
- }
visit::walk_use_tree(self, use_tree, id);
}
@@ -196,8 +183,8 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
}
let def = self.create_def(v.id, DefPathData::TypeNs(v.ident.name), v.span);
self.with_parent(def, |this| {
- if let Some(ctor_hir_id) = v.data.ctor_id() {
- this.create_def(ctor_hir_id, DefPathData::Ctor, v.span);
+ if let Some(ctor_node_id) = v.data.ctor_node_id() {
+ this.create_def(ctor_node_id, DefPathData::Ctor, v.span);
}
visit::walk_variant(this, v)
});
@@ -262,11 +249,11 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
fn visit_expr(&mut self, expr: &'a Expr) {
let parent_def = match expr.kind {
ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id),
- ExprKind::Closure(_, _, asyncness, ..) => {
+ ExprKind::Closure(ref closure) => {
// Async closures desugar to closures inside of closures, so
// we must create two defs.
let closure_def = self.create_def(expr.id, DefPathData::ClosureExpr, expr.span);
- match asyncness {
+ match closure.asyncness {
Async::Yes { closure_id, .. } => {
self.create_def(closure_id, DefPathData::ClosureExpr, expr.span)
}
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 5d868ebec..e392df6c5 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -25,7 +25,9 @@ use rustc_span::lev_distance::find_best_match_for_name;
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 crate::errors as errs;
use crate::imports::{Import, ImportKind, ImportResolver};
use crate::late::{PatternSource, Rib};
use crate::path_names_to_string;
@@ -58,16 +60,32 @@ pub(crate) enum SuggestionTarget {
#[derive(Debug)]
pub(crate) struct TypoSuggestion {
pub candidate: Symbol,
+ /// The source location where the name is defined; None if the name is not defined
+ /// in source e.g. primitives
+ pub span: Option<Span>,
pub res: Res,
pub target: SuggestionTarget,
}
impl TypoSuggestion {
- pub(crate) fn typo_from_res(candidate: Symbol, res: Res) -> TypoSuggestion {
- Self { candidate, res, target: SuggestionTarget::SimilarlyNamed }
+ pub(crate) fn typo_from_ident(ident: Ident, res: Res) -> TypoSuggestion {
+ Self {
+ candidate: ident.name,
+ span: Some(ident.span),
+ res,
+ target: SuggestionTarget::SimilarlyNamed,
+ }
+ }
+ pub(crate) fn typo_from_name(candidate: Symbol, res: Res) -> TypoSuggestion {
+ Self { candidate, span: None, res, target: SuggestionTarget::SimilarlyNamed }
}
- pub(crate) fn single_item_from_res(candidate: Symbol, res: Res) -> TypoSuggestion {
- Self { candidate, res, target: SuggestionTarget::SingleItem }
+ pub(crate) fn single_item_from_ident(ident: Ident, res: Res) -> TypoSuggestion {
+ Self {
+ candidate: ident.name,
+ span: Some(ident.span),
+ res,
+ target: SuggestionTarget::SingleItem,
+ }
}
}
@@ -174,12 +192,12 @@ impl<'a> Resolver<'a> {
ModuleKind::Block => "block",
};
- let old_noun = match old_binding.is_import() {
+ let old_noun = match old_binding.is_import_user_facing() {
true => "import",
false => "definition",
};
- let new_participle = match new_binding.is_import() {
+ let new_participle = match new_binding.is_import_user_facing() {
true => "imported",
false => "defined",
};
@@ -210,7 +228,7 @@ impl<'a> Resolver<'a> {
true => struct_span_err!(self.session, span, E0254, "{}", msg),
false => struct_span_err!(self.session, span, E0260, "{}", msg),
},
- _ => match (old_binding.is_import(), new_binding.is_import()) {
+ _ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) {
(false, false) => struct_span_err!(self.session, span, E0428, "{}", msg),
(true, true) => struct_span_err!(self.session, span, E0252, "{}", msg),
_ => struct_span_err!(self.session, span, E0255, "{}", msg),
@@ -225,21 +243,27 @@ impl<'a> Resolver<'a> {
));
err.span_label(span, format!("`{}` re{} here", name, new_participle));
- err.span_label(
- self.session.source_map().guess_head_span(old_binding.span),
- format!("previous {} of the {} `{}` here", old_noun, old_kind, name),
- );
+ if !old_binding.span.is_dummy() && old_binding.span != span {
+ err.span_label(
+ self.session.source_map().guess_head_span(old_binding.span),
+ format!("previous {} of the {} `{}` here", old_noun, old_kind, name),
+ );
+ }
// See https://github.com/rust-lang/rust/issues/32354
use NameBindingKind::Import;
+ let can_suggest = |binding: &NameBinding<'_>, import: &self::Import<'_>| {
+ !binding.span.is_dummy()
+ && !matches!(import.kind, ImportKind::MacroUse | ImportKind::MacroExport)
+ };
let import = match (&new_binding.kind, &old_binding.kind) {
// If there are two imports where one or both have attributes then prefer removing the
// import without attributes.
(Import { import: new, .. }, Import { import: old, .. })
if {
- !new_binding.span.is_dummy()
- && !old_binding.span.is_dummy()
- && (new.has_attributes || old.has_attributes)
+ (new.has_attributes || old.has_attributes)
+ && can_suggest(old_binding, old)
+ && can_suggest(new_binding, new)
} =>
{
if old.has_attributes {
@@ -249,10 +273,10 @@ impl<'a> Resolver<'a> {
}
}
// Otherwise prioritize the new binding.
- (Import { import, .. }, other) if !new_binding.span.is_dummy() => {
+ (Import { import, .. }, other) if can_suggest(new_binding, import) => {
Some((import, new_binding.span, other.is_import()))
}
- (other, Import { import, .. }) if !old_binding.span.is_dummy() => {
+ (other, Import { import, .. }) if can_suggest(old_binding, import) => {
Some((import, old_binding.span, other.is_import()))
}
_ => None,
@@ -337,7 +361,7 @@ impl<'a> Resolver<'a> {
}
}
}
- ImportKind::ExternCrate { source, target } => {
+ ImportKind::ExternCrate { source, target, .. } => {
suggestion = Some(format!(
"extern crate {} as {};",
source.unwrap_or(target.name),
@@ -490,7 +514,7 @@ impl<'a> Resolver<'a> {
if let Some(binding) = resolution.borrow().binding {
let res = binding.res();
if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == key.ident.span.ctxt()) {
- names.push(TypoSuggestion::typo_from_res(key.ident.name, res));
+ names.push(TypoSuggestion::typo_from_ident(key.ident, res));
}
}
}
@@ -575,78 +599,41 @@ impl<'a> Resolver<'a> {
err
}
- ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => {
- let mut err = struct_span_err!(
- self.session,
- span,
- E0403,
- "the name `{}` is already used for a generic \
- parameter in this item's generic parameters",
- name,
- );
- err.span_label(span, "already used");
- err.span_label(first_use_span, format!("first use of `{}`", name));
- err
- }
+ ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => self
+ .session
+ .create_err(errs::NameAlreadyUsedInParameterList { span, first_use_span, name }),
ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => {
- let mut err = struct_span_err!(
- self.session,
+ self.session.create_err(errs::MethodNotMemberOfTrait {
span,
- E0407,
- "method `{}` is not a member of trait `{}`",
method,
- trait_
- );
- err.span_label(span, format!("not a member of trait `{}`", trait_));
- if let Some(candidate) = candidate {
- err.span_suggestion(
- method.span,
- "there is an associated function with a similar name",
- candidate.to_ident_string(),
- Applicability::MaybeIncorrect,
- );
- }
- err
+ trait_,
+ sub: candidate.map(|c| errs::AssociatedFnWithSimilarNameExists {
+ span: method.span,
+ candidate: c,
+ }),
+ })
}
ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => {
- let mut err = struct_span_err!(
- self.session,
+ self.session.create_err(errs::TypeNotMemberOfTrait {
span,
- E0437,
- "type `{}` is not a member of trait `{}`",
type_,
- trait_
- );
- err.span_label(span, format!("not a member of trait `{}`", trait_));
- if let Some(candidate) = candidate {
- err.span_suggestion(
- type_.span,
- "there is an associated type with a similar name",
- candidate.to_ident_string(),
- Applicability::MaybeIncorrect,
- );
- }
- err
+ trait_,
+ sub: candidate.map(|c| errs::AssociatedTypeWithSimilarNameExists {
+ span: type_.span,
+ candidate: c,
+ }),
+ })
}
ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => {
- let mut err = struct_span_err!(
- self.session,
+ self.session.create_err(errs::ConstNotMemberOfTrait {
span,
- E0438,
- "const `{}` is not a member of trait `{}`",
const_,
- trait_
- );
- err.span_label(span, format!("not a member of trait `{}`", trait_));
- if let Some(candidate) = candidate {
- err.span_suggestion(
- const_.span,
- "there is an associated constant with a similar name",
- candidate.to_ident_string(),
- Applicability::MaybeIncorrect,
- );
- }
- err
+ trait_,
+ sub: candidate.map(|c| errs::AssociatedConstWithSimilarNameExists {
+ span: const_.span,
+ candidate: c,
+ }),
+ })
}
ResolutionError::VariableNotBoundInPattern(binding_error, parent_scope) => {
let BindingError { name, target, origin, could_be_path } = binding_error;
@@ -708,128 +695,78 @@ impl<'a> Resolver<'a> {
err
}
ResolutionError::VariableBoundWithDifferentMode(variable_name, first_binding_span) => {
- let mut err = struct_span_err!(
- self.session,
- span,
- E0409,
- "variable `{}` is bound inconsistently across alternatives separated by `|`",
- variable_name
- );
- err.span_label(span, "bound in different ways");
- err.span_label(first_binding_span, "first binding");
- err
- }
- ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
- let mut err = struct_span_err!(
- self.session,
- span,
- E0415,
- "identifier `{}` is bound more than once in this parameter list",
- identifier
- );
- err.span_label(span, "used as parameter more than once");
- err
- }
- ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
- let mut err = struct_span_err!(
- self.session,
+ self.session.create_err(errs::VariableBoundWithDifferentMode {
span,
- E0416,
- "identifier `{}` is bound more than once in the same pattern",
- identifier
- );
- err.span_label(span, "used in a pattern more than once");
- err
- }
+ first_binding_span,
+ variable_name,
+ })
+ }
+ ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => self
+ .session
+ .create_err(errs::IdentifierBoundMoreThanOnceInParameterList { span, identifier }),
+ ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => self
+ .session
+ .create_err(errs::IdentifierBoundMoreThanOnceInSamePattern { span, identifier }),
ResolutionError::UndeclaredLabel { name, suggestion } => {
- let mut err = struct_span_err!(
- self.session,
- span,
- E0426,
- "use of undeclared label `{}`",
- name
- );
-
- err.span_label(span, format!("undeclared label `{}`", name));
-
- match suggestion {
+ let ((sub_reachable, sub_reachable_suggestion), sub_unreachable) = match suggestion
+ {
// A reachable label with a similar name exists.
- Some((ident, true)) => {
- err.span_label(ident.span, "a label with a similar name is reachable");
- err.span_suggestion(
- span,
- "try using similarly named label",
- ident.name,
- Applicability::MaybeIncorrect,
- );
- }
+ Some((ident, true)) => (
+ (
+ Some(errs::LabelWithSimilarNameReachable(ident.span)),
+ Some(errs::TryUsingSimilarlyNamedLabel {
+ span,
+ ident_name: ident.name,
+ }),
+ ),
+ None,
+ ),
// An unreachable label with a similar name exists.
- Some((ident, false)) => {
- err.span_label(
- ident.span,
- "a label with a similar name exists but is unreachable",
- );
- }
+ Some((ident, false)) => (
+ (None, None),
+ Some(errs::UnreachableLabelWithSimilarNameExists {
+ ident_span: ident.span,
+ }),
+ ),
// No similarly-named labels exist.
- None => (),
- }
-
- err
+ None => ((None, None), None),
+ };
+ self.session.create_err(errs::UndeclaredLabel {
+ span,
+ name,
+ sub_reachable,
+ sub_reachable_suggestion,
+ sub_unreachable,
+ })
}
ResolutionError::SelfImportsOnlyAllowedWithin { root, span_with_rename } => {
- let mut err = struct_span_err!(
- self.session,
- span,
- E0429,
- "{}",
- "`self` imports are only allowed within a { } list"
- );
-
// None of the suggestions below would help with a case like `use self`.
- if !root {
+ let (suggestion, mpart_suggestion) = if root {
+ (None, None)
+ } else {
// use foo::bar::self -> foo::bar
// use foo::bar::self as abc -> foo::bar as abc
- err.span_suggestion(
- span,
- "consider importing the module directly",
- "",
- Applicability::MachineApplicable,
- );
+ let suggestion = errs::SelfImportsOnlyAllowedWithinSuggestion { span };
// use foo::bar::self -> foo::bar::{self}
// use foo::bar::self as abc -> foo::bar::{self as abc}
- let braces = vec![
- (span_with_rename.shrink_to_lo(), "{".to_string()),
- (span_with_rename.shrink_to_hi(), "}".to_string()),
- ];
- err.multipart_suggestion(
- "alternatively, use the multi-path `use` syntax to import `self`",
- braces,
- Applicability::MachineApplicable,
- );
- }
- err
+ let mpart_suggestion = errs::SelfImportsOnlyAllowedWithinMultipartSuggestion {
+ multipart_start: span_with_rename.shrink_to_lo(),
+ multipart_end: span_with_rename.shrink_to_hi(),
+ };
+ (Some(suggestion), Some(mpart_suggestion))
+ };
+ self.session.create_err(errs::SelfImportsOnlyAllowedWithin {
+ span,
+ suggestion,
+ mpart_suggestion,
+ })
}
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
- let mut err = struct_span_err!(
- self.session,
- span,
- E0430,
- "`self` import can only appear once in an import list"
- );
- err.span_label(span, "can only appear once in an import list");
- err
+ self.session.create_err(errs::SelfImportCanOnlyAppearOnceInTheList { span })
}
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
- let mut err = struct_span_err!(
- self.session,
- span,
- E0431,
- "`self` import can only appear in an import list with \
- a non-empty prefix"
- );
- err.span_label(span, "can only appear in an import list with a non-empty prefix");
- err
+ self.session.create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span })
}
ResolutionError::FailedToResolve { label, suggestion } => {
let mut err =
@@ -847,23 +784,9 @@ impl<'a> Resolver<'a> {
err
}
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
- let mut err = struct_span_err!(
- self.session,
- span,
- E0434,
- "{}",
- "can't capture dynamic environment in a fn item"
- );
- err.help("use the `|| { ... }` closure form instead");
- err
+ self.session.create_err(errs::CannotCaptureDynamicEnvironmentInFnItem { span })
}
- ResolutionError::AttemptToUseNonConstantValueInConstant(ident, sugg, current) => {
- let mut err = struct_span_err!(
- self.session,
- span,
- E0435,
- "attempt to use a non-constant value in a constant"
- );
+ ResolutionError::AttemptToUseNonConstantValueInConstant(ident, suggestion, current) => {
// let foo =...
// ^^^ given this Span
// ------- get this Span to have an applicable suggestion
@@ -877,23 +800,34 @@ impl<'a> Resolver<'a> {
.source_map()
.span_extend_to_prev_str(ident.span, current, true, false);
- match sp {
+ let ((with, with_label), without) = match sp {
Some(sp) if !self.session.source_map().is_multiline(sp) => {
let sp = sp.with_lo(BytePos(sp.lo().0 - (current.len() as u32)));
- err.span_suggestion(
- sp,
- &format!("consider using `{}` instead of `{}`", sugg, current),
- format!("{} {}", sugg, ident),
- Applicability::MaybeIncorrect,
- );
- err.span_label(span, "non-constant value");
- }
- _ => {
- err.span_label(ident.span, &format!("this would need to be a `{}`", sugg));
+ (
+ (Some(errs::AttemptToUseNonConstantValueInConstantWithSuggestion {
+ span: sp,
+ ident,
+ suggestion,
+ current,
+ }), Some(errs::AttemptToUseNonConstantValueInConstantLabelWithSuggestion {span})),
+ None,
+ )
}
- }
+ _ => (
+ (None, None),
+ Some(errs::AttemptToUseNonConstantValueInConstantWithoutSuggestion {
+ ident_span: ident.span,
+ suggestion,
+ }),
+ ),
+ };
- err
+ self.session.create_err(errs::AttemptToUseNonConstantValueInConstant {
+ span,
+ with,
+ with_label,
+ without,
+ })
}
ResolutionError::BindingShadowsSomethingUnacceptable {
shadowing_binding,
@@ -902,135 +836,80 @@ impl<'a> Resolver<'a> {
article,
shadowed_binding,
shadowed_binding_span,
- } => {
- let shadowed_binding_descr = shadowed_binding.descr();
- let mut err = struct_span_err!(
- self.session,
- span,
- E0530,
- "{}s cannot shadow {}s",
- shadowing_binding.descr(),
- shadowed_binding_descr,
- );
- err.span_label(
- span,
- format!("cannot be named the same as {} {}", article, shadowed_binding_descr),
- );
- match (shadowing_binding, shadowed_binding) {
+ } => self.session.create_err(errs::BindingShadowsSomethingUnacceptable {
+ span,
+ shadowing_binding,
+ shadowed_binding,
+ article,
+ sub_suggestion: match (shadowing_binding, shadowed_binding) {
(
PatternSource::Match,
Res::Def(DefKind::Ctor(CtorOf::Variant | CtorOf::Struct, CtorKind::Fn), _),
- ) => {
- err.span_suggestion(
- span,
- "try specify the pattern arguments",
- format!("{}(..)", name),
- Applicability::Unspecified,
- );
- }
- _ => (),
- }
- let msg =
- format!("the {} `{}` is {} here", shadowed_binding_descr, name, participle);
- err.span_label(shadowed_binding_span, msg);
- err
- }
+ ) => Some(errs::BindingShadowsSomethingUnacceptableSuggestion { span, name }),
+ _ => None,
+ },
+ shadowed_binding_span,
+ participle,
+ name,
+ }),
ResolutionError::ForwardDeclaredGenericParam => {
- let mut err = struct_span_err!(
- self.session,
- span,
- E0128,
- "generic parameters with a default cannot use \
- forward declared identifiers"
- );
- err.span_label(span, "defaulted generic parameters cannot be forward declared");
- err
+ self.session.create_err(errs::ForwardDeclaredGenericParam { span })
}
ResolutionError::ParamInTyOfConstParam(name) => {
- let mut err = struct_span_err!(
- self.session,
- span,
- E0770,
- "the type of const parameters must not depend on other generic parameters"
- );
- err.span_label(
- span,
- format!("the type must not depend on the parameter `{}`", name),
- );
- err
+ self.session.create_err(errs::ParamInTyOfConstParam { span, name })
}
ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => {
- let mut err = self.session.struct_span_err(
+ self.session.create_err(errs::ParamInNonTrivialAnonConst {
span,
- "generic parameters may not be used in const operations",
- );
- err.span_label(span, &format!("cannot perform const operation using `{}`", name));
-
- if is_type {
- err.note("type parameters may not be used in const expressions");
- } else {
- err.help(&format!(
- "const parameters may only be used as standalone arguments, i.e. `{}`",
- name
- ));
- }
-
- if self.session.is_nightly_build() {
- err.help(
- "use `#![feature(generic_const_exprs)]` to allow generic const expressions",
- );
- }
-
- err
+ name,
+ sub_is_type: if is_type {
+ errs::ParamInNonTrivialAnonConstIsType::AType
+ } else {
+ errs::ParamInNonTrivialAnonConstIsType::NotAType { name }
+ },
+ help: self
+ .session
+ .is_nightly_build()
+ .then_some(errs::ParamInNonTrivialAnonConstHelp),
+ })
}
ResolutionError::SelfInGenericParamDefault => {
- let mut err = struct_span_err!(
- self.session,
- span,
- E0735,
- "generic parameters cannot use `Self` in their defaults"
- );
- err.span_label(span, "`Self` in generic parameter default");
- err
+ self.session.create_err(errs::SelfInGenericParamDefault { span })
}
ResolutionError::UnreachableLabel { name, definition_span, suggestion } => {
- let mut err = struct_span_err!(
- self.session,
+ let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) =
+ match suggestion {
+ // A reachable label with a similar name exists.
+ Some((ident, true)) => (
+ (
+ Some(errs::UnreachableLabelSubLabel { ident_span: ident.span }),
+ Some(errs::UnreachableLabelSubSuggestion {
+ span,
+ // intentionally taking 'ident.name' instead of 'ident' itself, as this
+ // could be used in suggestion context
+ ident_name: ident.name,
+ }),
+ ),
+ None,
+ ),
+ // An unreachable label with a similar name exists.
+ Some((ident, false)) => (
+ (None, None),
+ Some(errs::UnreachableLabelSubLabelUnreachable {
+ ident_span: ident.span,
+ }),
+ ),
+ // No similarly-named labels exist.
+ None => ((None, None), None),
+ };
+ self.session.create_err(errs::UnreachableLabel {
span,
- E0767,
- "use of unreachable label `{}`",
name,
- );
-
- err.span_label(definition_span, "unreachable label defined here");
- err.span_label(span, format!("unreachable label `{}`", name));
- err.note(
- "labels are unreachable through functions, closures, async blocks and modules",
- );
-
- match suggestion {
- // A reachable label with a similar name exists.
- Some((ident, true)) => {
- err.span_label(ident.span, "a label with a similar name is reachable");
- err.span_suggestion(
- span,
- "try using similarly named label",
- ident.name,
- Applicability::MaybeIncorrect,
- );
- }
- // An unreachable label with a similar name exists.
- Some((ident, false)) => {
- err.span_label(
- ident.span,
- "a label with a similar name exists but is also unreachable",
- );
- }
- // No similarly-named labels exist.
- None => (),
- }
-
- err
+ definition_span,
+ sub_suggestion,
+ sub_suggestion_label,
+ sub_unreachable_label,
+ })
}
ResolutionError::TraitImplMismatch {
name,
@@ -1051,25 +930,10 @@ impl<'a> Resolver<'a> {
err.span_label(trait_item_span, "item in trait");
err
}
- ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => {
- let mut err = struct_span_err!(
- self.session,
- span,
- E0201,
- "duplicate definitions with name `{}`:",
- name,
- );
- err.span_label(old_span, "previous definition here");
- err.span_label(trait_item_span, "item in trait");
- err.span_label(span, "duplicate definition");
- err
- }
- ResolutionError::InvalidAsmSym => {
- let mut err = self.session.struct_span_err(span, "invalid `sym` operand");
- err.span_label(span, "is a local variable");
- err.help("`sym` operands must refer to either a function or a static");
- err
- }
+ ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => self
+ .session
+ .create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }),
+ ResolutionError::InvalidAsmSym => self.session.create_err(errs::InvalidAsmSym { span }),
}
}
@@ -1079,48 +943,27 @@ impl<'a> Resolver<'a> {
) -> ErrorGuaranteed {
match vis_resolution_error {
VisResolutionError::Relative2018(span, path) => {
- let mut err = self.session.struct_span_err(
+ self.session.create_err(errs::Relative2018 {
span,
- "relative paths are not supported in visibilities in 2018 edition or later",
- );
- err.span_suggestion(
- path.span,
- "try",
- format!("crate::{}", pprust::path_to_string(&path)),
- Applicability::MaybeIncorrect,
- );
- err
+ path_span: path.span,
+ // intentionally converting to String, as the text would also be used as
+ // in suggestion context
+ path_str: pprust::path_to_string(&path),
+ })
+ }
+ VisResolutionError::AncestorOnly(span) => {
+ self.session.create_err(errs::AncestorOnly(span))
}
- VisResolutionError::AncestorOnly(span) => struct_span_err!(
- self.session,
- span,
- E0742,
- "visibilities can only be restricted to ancestor modules"
- ),
VisResolutionError::FailedToResolve(span, label, suggestion) => {
self.into_struct_error(span, ResolutionError::FailedToResolve { label, suggestion })
}
VisResolutionError::ExpectedFound(span, path_str, res) => {
- let mut err = struct_span_err!(
- self.session,
- span,
- E0577,
- "expected module, found {} `{}`",
- res.descr(),
- path_str
- );
- err.span_label(span, "not a module");
- err
+ self.session.create_err(errs::ExpectedFound { span, res, path_str })
}
- VisResolutionError::Indeterminate(span) => struct_span_err!(
- self.session,
- span,
- E0578,
- "cannot determine resolution for the visibility"
- ),
- VisResolutionError::ModuleOnly(span) => {
- self.session.struct_span_err(span, "visibility must resolve to a module")
+ VisResolutionError::Indeterminate(span) => {
+ self.session.create_err(errs::Indeterminate(span))
}
+ VisResolutionError::ModuleOnly(span) => self.session.create_err(errs::ModuleOnly(span)),
}
.emit()
}
@@ -1145,7 +988,7 @@ impl<'a> Resolver<'a> {
.get(&expn_id)
.into_iter()
.flatten()
- .map(|ident| TypoSuggestion::typo_from_res(ident.name, res)),
+ .map(|ident| TypoSuggestion::typo_from_ident(*ident, res)),
);
}
}
@@ -1164,7 +1007,7 @@ impl<'a> Resolver<'a> {
suggestions.extend(
ext.helper_attrs
.iter()
- .map(|name| TypoSuggestion::typo_from_res(*name, res)),
+ .map(|name| TypoSuggestion::typo_from_name(*name, res)),
);
}
}
@@ -1174,8 +1017,8 @@ impl<'a> Resolver<'a> {
if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope.get() {
let res = macro_rules_binding.binding.res();
if filter_fn(res) {
- suggestions.push(TypoSuggestion::typo_from_res(
- macro_rules_binding.ident.name,
+ suggestions.push(TypoSuggestion::typo_from_ident(
+ macro_rules_binding.ident,
res,
))
}
@@ -1193,7 +1036,7 @@ impl<'a> Resolver<'a> {
suggestions.extend(this.macro_use_prelude.iter().filter_map(
|(name, binding)| {
let res = binding.res();
- filter_fn(res).then_some(TypoSuggestion::typo_from_res(*name, res))
+ filter_fn(res).then_some(TypoSuggestion::typo_from_name(*name, res))
},
));
}
@@ -1203,14 +1046,14 @@ impl<'a> Resolver<'a> {
suggestions.extend(
BUILTIN_ATTRIBUTES
.iter()
- .map(|attr| TypoSuggestion::typo_from_res(attr.name, res)),
+ .map(|attr| TypoSuggestion::typo_from_name(attr.name, res)),
);
}
}
Scope::ExternPrelude => {
suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
- filter_fn(res).then_some(TypoSuggestion::typo_from_res(ident.name, res))
+ filter_fn(res).then_some(TypoSuggestion::typo_from_ident(*ident, res))
}));
}
Scope::ToolPrelude => {
@@ -1218,7 +1061,7 @@ impl<'a> Resolver<'a> {
suggestions.extend(
this.registered_tools
.iter()
- .map(|ident| TypoSuggestion::typo_from_res(ident.name, res)),
+ .map(|ident| TypoSuggestion::typo_from_ident(*ident, res)),
);
}
Scope::StdLibPrelude => {
@@ -1235,7 +1078,8 @@ impl<'a> Resolver<'a> {
Scope::BuiltinTypes => {
suggestions.extend(PrimTy::ALL.iter().filter_map(|prim_ty| {
let res = Res::PrimTy(*prim_ty);
- filter_fn(res).then_some(TypoSuggestion::typo_from_res(prim_ty.name(), res))
+ filter_fn(res)
+ .then_some(TypoSuggestion::typo_from_name(prim_ty.name(), res))
}))
}
}
@@ -1272,7 +1116,7 @@ impl<'a> Resolver<'a> {
{
let mut candidates = Vec::new();
let mut seen_modules = FxHashSet::default();
- let mut worklist = vec![(start_module, Vec::<ast::PathSegment>::new(), true)];
+ let mut worklist = vec![(start_module, ThinVec::<ast::PathSegment>::new(), true)];
let mut worklist_via_import = vec![];
while let Some((in_module, path_segments, accessible)) = match worklist.pop() {
@@ -1666,7 +1510,7 @@ impl<'a> Resolver<'a> {
let a = if built_in.is_empty() { res.article() } else { "a" };
format!("{a}{built_in} {thing}{from}", thing = res.descr())
} else {
- let introduced = if b.is_import() { "imported" } else { "defined" };
+ let introduced = if b.is_import_user_facing() { "imported" } else { "defined" };
format!("the {thing} {introduced} here", thing = res.descr())
}
}
@@ -1725,10 +1569,10 @@ impl<'a> Resolver<'a> {
/// If the binding refers to a tuple struct constructor with fields,
/// returns the span of its fields.
fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option<Span> {
- if let NameBindingKind::Res(
- Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id),
- _,
- ) = binding.kind
+ if let NameBindingKind::Res(Res::Def(
+ DefKind::Ctor(CtorOf::Struct, CtorKind::Fn),
+ ctor_def_id,
+ )) = binding.kind
{
let def_id = self.parent(ctor_def_id);
let fields = self.field_names.get(&def_id)?;
@@ -1772,7 +1616,9 @@ impl<'a> Resolver<'a> {
next_ident = source;
Some(binding)
}
- ImportKind::Glob { .. } | ImportKind::MacroUse => Some(binding),
+ ImportKind::Glob { .. } | ImportKind::MacroUse | ImportKind::MacroExport => {
+ Some(binding)
+ }
ImportKind::ExternCrate { .. } => None,
},
_ => None,
@@ -1994,13 +1840,16 @@ impl<'a> Resolver<'a> {
(format!("use of undeclared type `{}`", ident), suggestion)
} else {
- let suggestion = if ident.name == sym::alloc {
- Some((
+ let mut suggestion = None;
+ if ident.name == sym::alloc {
+ suggestion = Some((
vec![],
String::from("add `extern crate alloc` to use the `alloc` crate"),
Applicability::MaybeIncorrect,
))
- } else {
+ }
+
+ suggestion = suggestion.or_else(|| {
self.find_similarly_named_module_or_crate(ident.name, &parent_scope.module).map(
|sugg| {
(
@@ -2010,7 +1859,7 @@ impl<'a> Resolver<'a> {
)
},
)
- };
+ });
(format!("use of undeclared crate or module `{}`", ident), suggestion)
}
}
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index c40669ac9..85399385d 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -1,41 +1,120 @@
-use crate::{ImportKind, NameBindingKind, Resolver};
+use crate::{NameBinding, NameBindingKind, Resolver, ResolverTree};
use rustc_ast::ast;
use rustc_ast::visit;
use rustc_ast::visit::Visitor;
use rustc_ast::Crate;
use rustc_ast::EnumDef;
+use rustc_data_structures::intern::Interned;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::def_id::CRATE_DEF_ID;
-use rustc_middle::middle::privacy::Level;
+use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility};
+use rustc_middle::middle::privacy::{IntoDefIdTree, Level};
use rustc_middle::ty::{DefIdTree, Visibility};
+use std::mem;
+
+type ImportId<'a> = Interned<'a, NameBinding<'a>>;
+
+#[derive(Clone, Copy)]
+enum ParentId<'a> {
+ Def(LocalDefId),
+ Import(ImportId<'a>),
+}
+
+impl ParentId<'_> {
+ fn level(self) -> Level {
+ match self {
+ ParentId::Def(_) => Level::Direct,
+ ParentId::Import(_) => Level::Reexported,
+ }
+ }
+}
pub struct EffectiveVisibilitiesVisitor<'r, 'a> {
r: &'r mut Resolver<'a>,
+ def_effective_visibilities: EffectiveVisibilities,
+ /// While walking import chains we need to track effective visibilities per-binding, and def id
+ /// keys in `Resolver::effective_visibilities` are not enough for that, because multiple
+ /// bindings can correspond to a single def id in imports. So we keep a separate table.
+ import_effective_visibilities: EffectiveVisibilities<ImportId<'a>>,
+ // It's possible to recalculate this at any point, but it's relatively expensive.
+ current_private_vis: Visibility,
changed: bool,
}
+impl Resolver<'_> {
+ fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId {
+ self.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local()
+ }
+
+ fn private_vis_import(&mut self, binding: ImportId<'_>) -> Visibility {
+ let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() };
+ Visibility::Restricted(
+ import
+ .id()
+ .map(|id| self.nearest_normal_mod(self.local_def_id(id)))
+ .unwrap_or(CRATE_DEF_ID),
+ )
+ }
+
+ fn private_vis_def(&mut self, def_id: LocalDefId) -> Visibility {
+ // For mod items `nearest_normal_mod` returns its argument, but we actually need its parent.
+ let normal_mod_id = self.nearest_normal_mod(def_id);
+ if normal_mod_id == def_id {
+ self.opt_local_parent(def_id).map_or(Visibility::Public, Visibility::Restricted)
+ } else {
+ Visibility::Restricted(normal_mod_id)
+ }
+ }
+}
+
+impl<'a, 'b> IntoDefIdTree for &'b mut Resolver<'a> {
+ type Tree = &'b Resolver<'a>;
+ fn tree(self) -> Self::Tree {
+ self
+ }
+}
+
impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
/// Fills the `Resolver::effective_visibilities` table with public & exported items
/// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we
/// need access to a TyCtxt for that.
pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) {
- let mut visitor = EffectiveVisibilitiesVisitor { r, changed: false };
-
- visitor.update(CRATE_DEF_ID, Visibility::Public, CRATE_DEF_ID, Level::Direct);
+ let mut visitor = EffectiveVisibilitiesVisitor {
+ r,
+ def_effective_visibilities: Default::default(),
+ import_effective_visibilities: Default::default(),
+ current_private_vis: Visibility::Public,
+ changed: false,
+ };
+
+ visitor.update(CRATE_DEF_ID, CRATE_DEF_ID);
+ visitor.current_private_vis = Visibility::Restricted(CRATE_DEF_ID);
visitor.set_bindings_effective_visibilities(CRATE_DEF_ID);
while visitor.changed {
- visitor.reset();
+ visitor.changed = false;
visit::walk_crate(&mut visitor, krate);
}
+ visitor.r.effective_visibilities = visitor.def_effective_visibilities;
+
+ // Update visibilities for import def ids. These are not used during the
+ // `EffectiveVisibilitiesVisitor` pass, because we have more detailed binding-based
+ // information, but are used by later passes. Effective visibility of an import def id
+ // is the maximum value among visibilities of bindings corresponding to that def id.
+ for (binding, eff_vis) in visitor.import_effective_visibilities.iter() {
+ let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() };
+ if let Some(node_id) = import.id() {
+ r.effective_visibilities.update_eff_vis(
+ r.local_def_id(node_id),
+ eff_vis,
+ ResolverTree(&r.definitions, &r.crate_loader),
+ )
+ }
+ }
info!("resolve::effective_visibilities: {:#?}", r.effective_visibilities);
}
- fn reset(&mut self) {
- self.changed = false;
- }
-
/// Update effective visibilities of bindings in the given module,
/// including their whole reexport chains.
fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) {
@@ -48,73 +127,68 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
// Set the given effective visibility level to `Level::Direct` and
// sets the rest of the `use` chain to `Level::Reexported` until
// we hit the actual exported item.
+ let mut parent_id = ParentId::Def(module_id);
+ while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind {
+ let binding_id = ImportId::new_unchecked(binding);
+ self.update_import(binding_id, parent_id);
- // FIXME: tag and is_public() condition should be removed, but assertions occur.
- let tag = if binding.is_import() { Level::Reexported } else { Level::Direct };
- if binding.vis.is_public() {
- let mut prev_parent_id = module_id;
- let mut level = Level::Direct;
- while let NameBindingKind::Import { binding: nested_binding, import, .. } =
- binding.kind
- {
- let mut update = |node_id| self.update(
- self.r.local_def_id(node_id),
- binding.vis.expect_local(),
- prev_parent_id,
- level,
- );
- // In theory all the import IDs have individual visibilities and effective
- // visibilities, but in practice these IDs go straigth to HIR where all
- // their few uses assume that their (effective) visibility applies to the
- // whole syntactic `use` item. So we update them all to the maximum value
- // among the potential individual effective visibilities. Maybe HIR for
- // imports shouldn't use three IDs at all.
- update(import.id);
- if let ImportKind::Single { additional_ids, .. } = import.kind {
- update(additional_ids.0);
- update(additional_ids.1);
- }
-
- level = Level::Reexported;
- prev_parent_id = self.r.local_def_id(import.id);
- binding = nested_binding;
- }
+ parent_id = ParentId::Import(binding_id);
+ binding = nested_binding;
}
if let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) {
- self.update(def_id, binding.vis.expect_local(), module_id, tag);
+ self.update_def(def_id, binding.vis.expect_local(), parent_id);
}
}
}
}
- fn update(
- &mut self,
- def_id: LocalDefId,
- nominal_vis: Visibility,
- parent_id: LocalDefId,
- tag: Level,
- ) {
- let module_id = self
- .r
- .get_nearest_non_block_module(def_id.to_def_id())
- .nearest_parent_mod()
- .expect_local();
- if nominal_vis == Visibility::Restricted(module_id)
- || self.r.visibilities[&parent_id] == Visibility::Restricted(module_id)
- {
- return;
+ fn cheap_private_vis(&self, parent_id: ParentId<'_>) -> Option<Visibility> {
+ matches!(parent_id, ParentId::Def(_)).then_some(self.current_private_vis)
+ }
+
+ fn effective_vis_or_private(&mut self, parent_id: ParentId<'a>) -> EffectiveVisibility {
+ // Private nodes are only added to the table for caching, they could be added or removed at
+ // any moment without consequences, so we don't set `changed` to true when adding them.
+ *match parent_id {
+ ParentId::Def(def_id) => self
+ .def_effective_visibilities
+ .effective_vis_or_private(def_id, || self.r.private_vis_def(def_id)),
+ ParentId::Import(binding) => self
+ .import_effective_visibilities
+ .effective_vis_or_private(binding, || self.r.private_vis_import(binding)),
}
- let mut effective_visibilities = std::mem::take(&mut self.r.effective_visibilities);
- self.changed |= effective_visibilities.update(
+ }
+
+ fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) {
+ let nominal_vis = binding.vis.expect_local();
+ let private_vis = self.cheap_private_vis(parent_id);
+ let inherited_eff_vis = self.effective_vis_or_private(parent_id);
+ self.changed |= self.import_effective_visibilities.update(
+ binding,
+ nominal_vis,
+ |r| (private_vis.unwrap_or_else(|| r.private_vis_import(binding)), r),
+ inherited_eff_vis,
+ parent_id.level(),
+ &mut *self.r,
+ );
+ }
+
+ fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) {
+ let private_vis = self.cheap_private_vis(parent_id);
+ let inherited_eff_vis = self.effective_vis_or_private(parent_id);
+ self.changed |= self.def_effective_visibilities.update(
def_id,
nominal_vis,
- || Visibility::Restricted(module_id),
- parent_id,
- tag,
- &*self.r,
+ |r| (private_vis.unwrap_or_else(|| r.private_vis_def(def_id)), r),
+ inherited_eff_vis,
+ parent_id.level(),
+ &mut *self.r,
);
- self.r.effective_visibilities = effective_visibilities;
+ }
+
+ fn update(&mut self, def_id: LocalDefId, parent_id: LocalDefId) {
+ self.update_def(def_id, self.r.visibilities[&def_id], ParentId::Def(parent_id));
}
}
@@ -132,22 +206,12 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> {
"ast::ItemKind::MacCall encountered, this should not anymore appear at this stage"
),
- // Foreign modules inherit level from parents.
- ast::ItemKind::ForeignMod(..) => {
- let parent_id = self.r.local_parent(def_id);
- self.update(def_id, Visibility::Public, parent_id, Level::Direct);
- }
-
- // Only exported `macro_rules!` items are public, but they always are
- ast::ItemKind::MacroDef(ref macro_def) if macro_def.macro_rules => {
- let parent_id = self.r.local_parent(def_id);
- let vis = self.r.visibilities[&def_id];
- self.update(def_id, vis, parent_id, Level::Direct);
- }
-
ast::ItemKind::Mod(..) => {
+ let prev_private_vis =
+ mem::replace(&mut self.current_private_vis, Visibility::Restricted(def_id));
self.set_bindings_effective_visibilities(def_id);
visit::walk_item(self, item);
+ self.current_private_vis = prev_private_vis;
}
ast::ItemKind::Enum(EnumDef { ref variants }, _) => {
@@ -155,18 +219,14 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> {
for variant in variants {
let variant_def_id = self.r.local_def_id(variant.id);
for field in variant.data.fields() {
- let field_def_id = self.r.local_def_id(field.id);
- let vis = self.r.visibilities[&field_def_id];
- self.update(field_def_id, vis, variant_def_id, Level::Direct);
+ self.update(self.r.local_def_id(field.id), variant_def_id);
}
}
}
ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => {
for field in def.fields() {
- let field_def_id = self.r.local_def_id(field.id);
- let vis = self.r.visibilities[&field_def_id];
- self.update(field_def_id, vis, def_id, Level::Direct);
+ self.update(self.r.local_def_id(field.id), def_id);
}
}
@@ -182,6 +242,7 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> {
| ast::ItemKind::TyAlias(..)
| ast::ItemKind::TraitAlias(..)
| ast::ItemKind::MacroDef(..)
+ | ast::ItemKind::ForeignMod(..)
| ast::ItemKind::Fn(..) => return,
}
}
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
new file mode 100644
index 000000000..2c4427746
--- /dev/null
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -0,0 +1,474 @@
+use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_span::{
+ symbol::{Ident, Symbol},
+ Span,
+};
+
+use crate::{late::PatternSource, Res};
+
+#[derive(Diagnostic)]
+#[diag(resolve_parent_module_reset_for_binding, code = "E0637")]
+pub(crate) struct ParentModuleResetForBinding;
+
+#[derive(Diagnostic)]
+#[diag(resolve_ampersand_used_without_explicit_lifetime_name, code = "E0637")]
+#[note]
+pub(crate) struct AmpersandUsedWithoutExplicitLifetimeName(#[primary_span] pub(crate) Span);
+
+#[derive(Diagnostic)]
+#[diag(resolve_underscore_lifetime_name_cannot_be_used_here, code = "E0637")]
+#[note]
+pub(crate) struct UnderscoreLifetimeNameCannotBeUsedHere(#[primary_span] pub(crate) Span);
+
+#[derive(Diagnostic)]
+#[diag(resolve_crate_may_not_be_imported)]
+pub(crate) struct CrateMayNotBeImprted(#[primary_span] pub(crate) Span);
+
+#[derive(Diagnostic)]
+#[diag(resolve_crate_root_imports_must_be_named_explicitly)]
+pub(crate) struct CrateRootNamesMustBeNamedExplicitly(#[primary_span] pub(crate) Span);
+
+#[derive(Diagnostic)]
+#[diag(resolve_crate_root_imports_must_be_named_explicitly)]
+pub(crate) struct ResolutionError(#[primary_span] pub(crate) Span);
+
+#[derive(Diagnostic)]
+#[diag(resolve_name_is_already_used_as_generic_parameter, code = "E0403")]
+pub(crate) struct NameAlreadyUsedInParameterList {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ #[label(first_use_of_name)]
+ pub(crate) first_use_span: Span,
+ pub(crate) name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_method_not_member_of_trait, code = "E0407")]
+pub(crate) struct MethodNotMemberOfTrait {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) method: Ident,
+ pub(crate) trait_: String,
+ #[subdiagnostic]
+ pub(crate) sub: Option<AssociatedFnWithSimilarNameExists>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ resolve_associated_fn_with_similar_name_exists,
+ code = "{candidate}",
+ applicability = "maybe-incorrect"
+)]
+pub(crate) struct AssociatedFnWithSimilarNameExists {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) candidate: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_type_not_member_of_trait, code = "E0437")]
+pub(crate) struct TypeNotMemberOfTrait {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) type_: Ident,
+ pub(crate) trait_: String,
+ #[subdiagnostic]
+ pub(crate) sub: Option<AssociatedTypeWithSimilarNameExists>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ resolve_associated_type_with_similar_name_exists,
+ code = "{candidate}",
+ applicability = "maybe-incorrect"
+)]
+pub(crate) struct AssociatedTypeWithSimilarNameExists {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) candidate: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_const_not_member_of_trait, code = "E0438")]
+pub(crate) struct ConstNotMemberOfTrait {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) const_: Ident,
+ pub(crate) trait_: String,
+ #[subdiagnostic]
+ pub(crate) sub: Option<AssociatedConstWithSimilarNameExists>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ resolve_associated_const_with_similar_name_exists,
+ code = "{candidate}",
+ applicability = "maybe-incorrect"
+)]
+pub(crate) struct AssociatedConstWithSimilarNameExists {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) candidate: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_variable_bound_with_different_mode, code = "E0409")]
+pub(crate) struct VariableBoundWithDifferentMode {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ #[label(first_binding_span)]
+ pub(crate) first_binding_span: Span,
+ pub(crate) variable_name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_ident_bound_more_than_once_in_parameter_list, code = "E0415")]
+pub(crate) struct IdentifierBoundMoreThanOnceInParameterList {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) identifier: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_ident_bound_more_than_once_in_same_pattern, code = "E0416")]
+pub(crate) struct IdentifierBoundMoreThanOnceInSamePattern {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) identifier: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_undeclared_label, code = "E0426")]
+pub(crate) struct UndeclaredLabel {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) name: Symbol,
+ #[subdiagnostic]
+ pub(crate) sub_reachable: Option<LabelWithSimilarNameReachable>,
+ #[subdiagnostic]
+ pub(crate) sub_reachable_suggestion: Option<TryUsingSimilarlyNamedLabel>,
+ #[subdiagnostic]
+ pub(crate) sub_unreachable: Option<UnreachableLabelWithSimilarNameExists>,
+}
+
+#[derive(Subdiagnostic)]
+#[label(resolve_label_with_similar_name_reachable)]
+pub(crate) struct LabelWithSimilarNameReachable(#[primary_span] pub(crate) Span);
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ resolve_try_using_similarly_named_label,
+ code = "{ident_name}",
+ applicability = "maybe-incorrect"
+)]
+pub(crate) struct TryUsingSimilarlyNamedLabel {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) ident_name: Symbol,
+}
+
+#[derive(Subdiagnostic)]
+#[label(resolve_unreachable_label_with_similar_name_exists)]
+pub(crate) struct UnreachableLabelWithSimilarNameExists {
+ #[primary_span]
+ pub(crate) ident_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_self_import_can_only_appear_once_in_the_list, code = "E0430")]
+pub(crate) struct SelfImportCanOnlyAppearOnceInTheList {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_self_import_only_in_import_list_with_non_empty_prefix, code = "E0431")]
+pub(crate) struct SelfImportOnlyInImportListWithNonEmptyPrefix {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_cannot_capture_dynamic_environment_in_fn_item, code = "E0434")]
+#[help]
+pub(crate) struct CannotCaptureDynamicEnvironmentInFnItem {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_attempt_to_use_non_constant_value_in_constant, code = "E0435")]
+pub(crate) struct AttemptToUseNonConstantValueInConstant<'a> {
+ #[primary_span]
+ pub(crate) span: Span,
+ #[subdiagnostic]
+ pub(crate) with: Option<AttemptToUseNonConstantValueInConstantWithSuggestion<'a>>,
+ #[subdiagnostic]
+ pub(crate) with_label: Option<AttemptToUseNonConstantValueInConstantLabelWithSuggestion>,
+ #[subdiagnostic]
+ pub(crate) without: Option<AttemptToUseNonConstantValueInConstantWithoutSuggestion<'a>>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion,
+ code = "{suggestion} {ident}",
+ applicability = "maybe-incorrect"
+)]
+pub(crate) struct AttemptToUseNonConstantValueInConstantWithSuggestion<'a> {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) ident: Ident,
+ pub(crate) suggestion: &'a str,
+ pub(crate) current: &'a str,
+}
+
+#[derive(Subdiagnostic)]
+#[label(resolve_attempt_to_use_non_constant_value_in_constant_label_with_suggestion)]
+pub(crate) struct AttemptToUseNonConstantValueInConstantLabelWithSuggestion {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[label(resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion)]
+pub(crate) struct AttemptToUseNonConstantValueInConstantWithoutSuggestion<'a> {
+ #[primary_span]
+ pub(crate) ident_span: Span,
+ pub(crate) suggestion: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_self_imports_only_allowed_within, code = "E0429")]
+pub(crate) struct SelfImportsOnlyAllowedWithin {
+ #[primary_span]
+ pub(crate) span: Span,
+ #[subdiagnostic]
+ pub(crate) suggestion: Option<SelfImportsOnlyAllowedWithinSuggestion>,
+ #[subdiagnostic]
+ pub(crate) mpart_suggestion: Option<SelfImportsOnlyAllowedWithinMultipartSuggestion>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ resolve_self_imports_only_allowed_within_suggestion,
+ code = "",
+ applicability = "machine-applicable"
+)]
+pub(crate) struct SelfImportsOnlyAllowedWithinSuggestion {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+ resolve_self_imports_only_allowed_within_multipart_suggestion,
+ applicability = "machine-applicable"
+)]
+pub(crate) struct SelfImportsOnlyAllowedWithinMultipartSuggestion {
+ #[suggestion_part(code = "{{")]
+ pub(crate) multipart_start: Span,
+ #[suggestion_part(code = "}}")]
+ pub(crate) multipart_end: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_binding_shadows_something_unacceptable, code = "E0530")]
+pub(crate) struct BindingShadowsSomethingUnacceptable<'a> {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) shadowing_binding: PatternSource,
+ pub(crate) shadowed_binding: Res,
+ pub(crate) article: &'a str,
+ #[subdiagnostic]
+ pub(crate) sub_suggestion: Option<BindingShadowsSomethingUnacceptableSuggestion>,
+ #[label(label_shadowed_binding)]
+ pub(crate) shadowed_binding_span: Span,
+ pub(crate) participle: &'a str,
+ pub(crate) name: Symbol,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ resolve_binding_shadows_something_unacceptable_suggestion,
+ code = "{name}(..)",
+ applicability = "unspecified"
+)]
+pub(crate) struct BindingShadowsSomethingUnacceptableSuggestion {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_forward_declared_generic_param, code = "E0128")]
+pub(crate) struct ForwardDeclaredGenericParam {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_param_in_ty_of_const_param, code = "E0770")]
+pub(crate) struct ParamInTyOfConstParam {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_self_in_generic_param_default, code = "E0735")]
+pub(crate) struct SelfInGenericParamDefault {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_param_in_non_trivial_anon_const)]
+pub(crate) struct ParamInNonTrivialAnonConst {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) name: Symbol,
+ #[subdiagnostic]
+ pub(crate) sub_is_type: ParamInNonTrivialAnonConstIsType,
+ #[subdiagnostic]
+ pub(crate) help: Option<ParamInNonTrivialAnonConstHelp>,
+}
+
+#[derive(Subdiagnostic)]
+#[help(resolve_param_in_non_trivial_anon_const_help)]
+pub(crate) struct ParamInNonTrivialAnonConstHelp;
+
+#[derive(Subdiagnostic)]
+pub(crate) enum ParamInNonTrivialAnonConstIsType {
+ #[note(resolve_param_in_non_trivial_anon_const_sub_type)]
+ AType,
+ #[help(resolve_param_in_non_trivial_anon_const_sub_non_type)]
+ NotAType { name: Symbol },
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_unreachable_label, code = "E0767")]
+#[note]
+pub(crate) struct UnreachableLabel {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) name: Symbol,
+ #[label(label_definition_span)]
+ pub(crate) definition_span: Span,
+ #[subdiagnostic]
+ pub(crate) sub_suggestion: Option<UnreachableLabelSubSuggestion>,
+ #[subdiagnostic]
+ pub(crate) sub_suggestion_label: Option<UnreachableLabelSubLabel>,
+ #[subdiagnostic]
+ pub(crate) sub_unreachable_label: Option<UnreachableLabelSubLabelUnreachable>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ resolve_unreachable_label_suggestion_use_similarly_named,
+ code = "{ident_name}",
+ applicability = "maybe-incorrect"
+)]
+pub(crate) struct UnreachableLabelSubSuggestion {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) ident_name: Symbol,
+}
+
+#[derive(Subdiagnostic)]
+#[label(resolve_unreachable_label_similar_name_reachable)]
+pub(crate) struct UnreachableLabelSubLabel {
+ #[primary_span]
+ pub(crate) ident_span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[label(resolve_unreachable_label_similar_name_unreachable)]
+pub(crate) struct UnreachableLabelSubLabelUnreachable {
+ #[primary_span]
+ pub(crate) ident_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_trait_impl_mismatch, code = "{code}")]
+pub(crate) struct TraitImplMismatch {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) name: Symbol,
+ pub(crate) kind: String,
+ #[label(label_trait_item)]
+ pub(crate) trait_item_span: Span,
+ pub(crate) trait_path: String,
+ pub(crate) code: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_invalid_asm_sym)]
+#[help]
+pub(crate) struct InvalidAsmSym {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_trait_impl_duplicate, code = "E0201")]
+pub(crate) struct TraitImplDuplicate {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ #[label(old_span_label)]
+ pub(crate) old_span: Span,
+ #[label(trait_item_span)]
+ pub(crate) trait_item_span: Span,
+ pub(crate) name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_relative_2018)]
+pub(crate) struct Relative2018 {
+ #[primary_span]
+ pub(crate) span: Span,
+ #[suggestion(code = "crate::{path_str}", applicability = "maybe-incorrect")]
+ pub(crate) path_span: Span,
+ pub(crate) path_str: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_ancestor_only, code = "E0742")]
+pub(crate) struct AncestorOnly(#[primary_span] pub(crate) Span);
+
+#[derive(Diagnostic)]
+#[diag(resolve_expected_found, code = "E0577")]
+pub(crate) struct ExpectedFound {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) res: Res,
+ pub(crate) path_str: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_indeterminate, code = "E0578")]
+pub(crate) struct Indeterminate(#[primary_span] pub(crate) Span);
+
+#[derive(Diagnostic)]
+#[diag(resolve_module_only)]
+pub(crate) struct ModuleOnly(#[primary_span] pub(crate) Span);
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index e0542d547..759818856 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -19,7 +19,7 @@ use crate::late::{
};
use crate::macros::{sub_namespace_match, MacroRulesScope};
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize};
-use crate::{ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot};
+use crate::{Import, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot};
use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res};
use crate::{ResolutionError, Resolver, Scope, ScopeSet, Segment, ToNameBinding, Weak};
@@ -915,7 +915,11 @@ impl<'a> Resolver<'a> {
}
if !restricted_shadowing && binding.expansion != LocalExpnId::ROOT {
- if let NameBindingKind::Res(_, true) = binding.kind {
+ if let NameBindingKind::Import {
+ import: Import { kind: ImportKind::MacroExport, .. },
+ ..
+ } = binding.kind
+ {
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
}
}
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index f2cc50c19..b100a8c17 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -4,7 +4,10 @@ use crate::diagnostics::{import_candidates, Suggestion};
use crate::Determinacy::{self, *};
use crate::Namespace::*;
use crate::{module_to_string, names_to_string, ImportSuggestion};
-use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment};
+use crate::{
+ AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, ModuleKind, ResolutionError,
+ Resolver, Segment,
+};
use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet};
use crate::{NameBinding, NameBindingKind, PathResult};
@@ -44,20 +47,33 @@ pub enum ImportKind<'a> {
type_ns_only: bool,
/// Did this import result from a nested import? ie. `use foo::{bar, baz};`
nested: bool,
- /// Additional `NodeId`s allocated to a `ast::UseTree` for automatically generated `use` statement
- /// (eg. implicit struct constructors)
- additional_ids: (NodeId, NodeId),
+ /// The ID of the `UseTree` that imported this `Import`.
+ ///
+ /// In the case where the `Import` was expanded from a "nested" use tree,
+ /// this id is the ID of the leaf tree. For example:
+ ///
+ /// ```ignore (pacify the merciless tidy)
+ /// use foo::bar::{a, b}
+ /// ```
+ ///
+ /// If this is the import for `foo::bar::a`, we would have the ID of the `UseTree`
+ /// for `a` in this field.
+ id: NodeId,
},
Glob {
is_prelude: bool,
- max_vis: Cell<Option<ty::Visibility>>, // The visibility of the greatest re-export.
- // n.b. `max_vis` is only used in `finalize_import` to check for re-export errors.
+ // The visibility of the greatest re-export.
+ // n.b. `max_vis` is only used in `finalize_import` to check for re-export errors.
+ max_vis: Cell<Option<ty::Visibility>>,
+ id: NodeId,
},
ExternCrate {
source: Option<Symbol>,
target: Ident,
+ id: NodeId,
},
MacroUse,
+ MacroExport,
}
/// Manually implement `Debug` for `ImportKind` because the `source/target_bindings`
@@ -71,7 +87,7 @@ impl<'a> std::fmt::Debug for ImportKind<'a> {
ref target,
ref type_ns_only,
ref nested,
- ref additional_ids,
+ ref id,
// Ignore the following to avoid an infinite loop while printing.
source_bindings: _,
target_bindings: _,
@@ -81,19 +97,22 @@ impl<'a> std::fmt::Debug for ImportKind<'a> {
.field("target", target)
.field("type_ns_only", type_ns_only)
.field("nested", nested)
- .field("additional_ids", additional_ids)
+ .field("id", id)
.finish_non_exhaustive(),
- Glob { ref is_prelude, ref max_vis } => f
+ Glob { ref is_prelude, ref max_vis, ref id } => f
.debug_struct("Glob")
.field("is_prelude", is_prelude)
.field("max_vis", max_vis)
+ .field("id", id)
.finish(),
- ExternCrate { ref source, ref target } => f
+ ExternCrate { ref source, ref target, ref id } => f
.debug_struct("ExternCrate")
.field("source", source)
.field("target", target)
+ .field("id", id)
.finish(),
MacroUse => f.debug_struct("MacroUse").finish(),
+ MacroExport => f.debug_struct("MacroExport").finish(),
}
}
}
@@ -103,24 +122,15 @@ impl<'a> std::fmt::Debug for ImportKind<'a> {
pub(crate) struct Import<'a> {
pub kind: ImportKind<'a>,
- /// The ID of the `extern crate`, `UseTree` etc that imported this `Import`.
- ///
- /// In the case where the `Import` was expanded from a "nested" use tree,
- /// this id is the ID of the leaf tree. For example:
- ///
- /// ```ignore (pacify the merciless tidy)
+ /// Node ID of the "root" use item -- this is always the same as `ImportKind`'s `id`
+ /// (if it exists) except in the case of "nested" use trees, in which case
+ /// it will be the ID of the root use tree. e.g., in the example
+ /// ```ignore (incomplete code)
/// use foo::bar::{a, b}
/// ```
- ///
- /// If this is the import for `foo::bar::a`, we would have the ID of the `UseTree`
- /// for `a` in this field.
- pub id: NodeId,
-
- /// The `id` of the "root" use-kind -- this is always the same as
- /// `id` except in the case of "nested" use trees, in which case
- /// it will be the `id` of the root use tree. e.g., in the example
- /// from `id`, this would be the ID of the `use foo::bar`
- /// `UseTree` node.
+ /// this would be the ID of the `use foo::bar` `UseTree` node.
+ /// In case of imports without their own node ID it's the closest node that can be used,
+ /// for example, for reporting lints.
pub root_id: NodeId,
/// Span of the entire use statement.
@@ -161,6 +171,15 @@ impl<'a> Import<'a> {
pub(crate) fn expect_vis(&self) -> ty::Visibility {
self.vis.get().expect("encountered cleared import visibility")
}
+
+ pub(crate) fn id(&self) -> Option<NodeId> {
+ match self.kind {
+ ImportKind::Single { id, .. }
+ | ImportKind::Glob { id, .. }
+ | ImportKind::ExternCrate { id, .. } => Some(id),
+ ImportKind::MacroUse | ImportKind::MacroExport => None,
+ }
+ }
}
/// Records information about the resolution of a name in a namespace of a module.
@@ -175,7 +194,7 @@ pub(crate) struct NameResolution<'a> {
}
impl<'a> NameResolution<'a> {
- // Returns the binding for the name if it is known or None if it not known.
+ /// Returns the binding for the name if it is known or None if it not known.
pub(crate) fn binding(&self) -> Option<&'a NameBinding<'a>> {
self.binding.and_then(|binding| {
if !binding.is_glob_import() || self.single_imports.is_empty() {
@@ -207,8 +226,8 @@ fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBindi
}
impl<'a> Resolver<'a> {
- // Given a binding and an import that resolves to it,
- // return the corresponding binding defined by the import.
+ /// Given a binding and an import that resolves to it,
+ /// return the corresponding binding defined by the import.
pub(crate) fn import(
&self,
binding: &'a NameBinding<'a>,
@@ -240,7 +259,7 @@ impl<'a> Resolver<'a> {
})
}
- // Define the name or return the existing binding if there is a collision.
+ /// Define the name or return the existing binding if there is a collision.
pub(crate) fn try_define(
&mut self,
module: Module<'a>,
@@ -368,7 +387,9 @@ impl<'a> Resolver<'a> {
self.record_use(target, dummy_binding, false);
} else if import.imported_module.get().is_none() {
import.used.set(true);
- self.used_imports.insert(import.id);
+ if let Some(id) = import.id() {
+ self.used_imports.insert(id);
+ }
}
}
}
@@ -450,7 +471,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
{
// In the case of a new import line, throw a diagnostic message
// for the previous line.
- self.throw_unresolved_import_error(errors, None);
+ self.throw_unresolved_import_error(errors);
errors = vec![];
}
if seen_spans.insert(err.span) {
@@ -482,29 +503,21 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
if !errors.is_empty() {
- self.throw_unresolved_import_error(errors, None);
+ self.throw_unresolved_import_error(errors);
}
}
- fn throw_unresolved_import_error(
- &self,
- errors: Vec<(String, UnresolvedImportError)>,
- span: Option<MultiSpan>,
- ) {
+ fn throw_unresolved_import_error(&self, errors: Vec<(String, UnresolvedImportError)>) {
+ if errors.is_empty() {
+ return;
+ }
+
/// Upper limit on the number of `span_label` messages.
const MAX_LABEL_COUNT: usize = 10;
- let (span, msg) = if errors.is_empty() {
- (span.unwrap(), "unresolved import".to_string())
- } else {
- let span = MultiSpan::from_spans(errors.iter().map(|(_, err)| err.span).collect());
-
- let paths = errors.iter().map(|(path, _)| format!("`{}`", path)).collect::<Vec<_>>();
-
- let msg = format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),);
-
- (span, msg)
- };
+ let span = MultiSpan::from_spans(errors.iter().map(|(_, err)| err.span).collect());
+ let paths = errors.iter().map(|(path, _)| format!("`{}`", path)).collect::<Vec<_>>();
+ let msg = format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),);
let mut diag = struct_span_err!(self.r.session, span, E0432, "{}", &msg);
@@ -718,47 +731,51 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
PathResult::Indeterminate => unreachable!(),
};
- let (ident, target, source_bindings, target_bindings, type_ns_only) = match import.kind {
- ImportKind::Single {
- source,
- target,
- ref source_bindings,
- ref target_bindings,
- type_ns_only,
- ..
- } => (source, target, source_bindings, target_bindings, type_ns_only),
- ImportKind::Glob { is_prelude, ref max_vis } => {
- if import.module_path.len() <= 1 {
- // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
- // 2 segments, so the `resolve_path` above won't trigger it.
- let mut full_path = import.module_path.clone();
- full_path.push(Segment::from_ident(Ident::empty()));
- self.r.lint_if_path_starts_with_module(Some(finalize), &full_path, None);
- }
+ let (ident, target, source_bindings, target_bindings, type_ns_only, import_id) =
+ match import.kind {
+ ImportKind::Single {
+ source,
+ target,
+ ref source_bindings,
+ ref target_bindings,
+ type_ns_only,
+ id,
+ ..
+ } => (source, target, source_bindings, target_bindings, type_ns_only, id),
+ ImportKind::Glob { is_prelude, ref max_vis, id } => {
+ if import.module_path.len() <= 1 {
+ // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
+ // 2 segments, so the `resolve_path` above won't trigger it.
+ let mut full_path = import.module_path.clone();
+ full_path.push(Segment::from_ident(Ident::empty()));
+ self.r.lint_if_path_starts_with_module(Some(finalize), &full_path, None);
+ }
- if let ModuleOrUniformRoot::Module(module) = module {
- if ptr::eq(module, import.parent_scope.module) {
- // Importing a module into itself is not allowed.
- return Some(UnresolvedImportError {
- span: import.span,
- label: Some(String::from("cannot glob-import a module into itself")),
- note: None,
- suggestion: None,
- candidate: None,
- });
+ if let ModuleOrUniformRoot::Module(module) = module {
+ if ptr::eq(module, import.parent_scope.module) {
+ // Importing a module into itself is not allowed.
+ return Some(UnresolvedImportError {
+ span: import.span,
+ label: Some(String::from(
+ "cannot glob-import a module into itself",
+ )),
+ note: None,
+ suggestion: None,
+ candidate: None,
+ });
+ }
}
- }
- if !is_prelude
+ if !is_prelude
&& let Some(max_vis) = max_vis.get()
&& !max_vis.is_at_least(import.expect_vis(), &*self.r)
{
let msg = "glob import doesn't reexport anything because no candidate is public enough";
- self.r.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg);
+ self.r.lint_buffer.buffer_lint(UNUSED_IMPORTS, id, import.span, msg);
}
- return None;
- }
- _ => unreachable!(),
- };
+ return None;
+ }
+ _ => unreachable!(),
+ };
let mut all_ns_err = true;
self.r.per_ns(|this, ns| {
@@ -777,7 +794,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
match binding {
Ok(binding) => {
// Consistency checks, analogous to `finalize_macro_resolutions`.
- let initial_res = source_bindings[ns].get().map(|initial_binding| {
+ let initial_binding = source_bindings[ns].get().map(|initial_binding| {
all_ns_err = false;
if let Some(target_binding) = target_bindings[ns].get() {
if target.name == kw::Underscore
@@ -791,12 +808,20 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
);
}
}
- initial_binding.res()
+ initial_binding
});
let res = binding.res();
- if let Ok(initial_res) = initial_res {
+ if let Ok(initial_binding) = initial_binding {
+ let initial_res = initial_binding.res();
if res != initial_res && this.ambiguity_errors.is_empty() {
- span_bug!(import.span, "inconsistent resolution for an import");
+ this.ambiguity_errors.push(AmbiguityError {
+ kind: AmbiguityKind::Import,
+ ident,
+ b1: initial_binding,
+ b2: binding,
+ misc1: AmbiguityErrorMisc::None,
+ misc2: AmbiguityErrorMisc::None,
+ });
}
} else if res != Res::Err
&& this.ambiguity_errors.is_empty()
@@ -858,7 +883,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
match binding.kind {
// Never suggest the name that has binding error
// i.e., the name that cannot be previously resolved
- NameBindingKind::Res(Res::Err, _) => None,
+ NameBindingKind::Res(Res::Err) => None,
_ => Some(i.name),
}
}
@@ -960,7 +985,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
);
self.r.lint_buffer.buffer_lint(
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
- import.id,
+ import_id,
import.span,
&msg,
);
@@ -989,7 +1014,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let mut err =
struct_span_err!(self.r.session, import.span, E0364, "{error_msg}");
match binding.kind {
- NameBindingKind::Res(Res::Def(DefKind::Macro(_), def_id), _)
+ NameBindingKind::Res(Res::Def(DefKind::Macro(_), def_id))
// exclude decl_macro
if self.r.get_macro_by_def_id(def_id).macro_rules =>
{
@@ -1029,7 +1054,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
// purposes it's good enough to just favor one over the other.
self.r.per_ns(|this, ns| {
if let Ok(binding) = source_bindings[ns].get() {
- this.import_res_map.entry(import.id).or_default()[ns] = Some(binding.res());
+ this.import_res_map.entry(import_id).or_default()[ns] = Some(binding.res());
}
});
@@ -1047,6 +1072,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
target_bindings: &PerNS<Cell<Option<&'b NameBinding<'b>>>>,
target: Ident,
) {
+ // This function is only called for single imports.
+ let ImportKind::Single { id, .. } = import.kind else { unreachable!() };
+
// Skip if the import was produced by a macro.
if import.parent_scope.expansion != LocalExpnId::ROOT {
return;
@@ -1094,7 +1122,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
redundant_spans.dedup();
self.r.lint_buffer.buffer_lint_with_diagnostic(
UNUSED_IMPORTS,
- import.id,
+ id,
import.span,
&format!("the item `{}` is imported redundantly", ident),
BuiltinLintDiagnostics::RedundantImport(redundant_spans, ident),
@@ -1103,6 +1131,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
fn resolve_glob_import(&mut self, import: &'b Import<'b>) {
+ // This function is only called for glob imports.
+ let ImportKind::Glob { id, is_prelude, .. } = import.kind else { unreachable!() };
+
let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else {
self.r.session.span_err(import.span, "cannot glob-import all possible crates");
return;
@@ -1113,7 +1144,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
return;
} else if ptr::eq(module, import.parent_scope.module) {
return;
- } else if let ImportKind::Glob { is_prelude: true, .. } = import.kind {
+ } else if is_prelude {
self.r.prelude = Some(module);
return;
}
@@ -1145,7 +1176,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
// Record the destination of this import
- self.r.record_partial_res(import.id, PartialRes::new(module.res().unwrap()));
+ self.r.record_partial_res(id, PartialRes::new(module.res().unwrap()));
}
// Miscellaneous post-processing, including recording re-exports,
@@ -1204,5 +1235,6 @@ fn import_kind_to_string(import_kind: &ImportKind<'_>) -> String {
ImportKind::Glob { .. } => "*".to_string(),
ImportKind::ExternCrate { .. } => "<extern crate>".to_string(),
ImportKind::MacroUse => "#[macro_use]".to_string(),
+ ImportKind::MacroExport => "#[macro_export]".to_string(),
}
}
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 00eb768ad..cf3e59460 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -16,7 +16,7 @@ use rustc_ast::ptr::P;
use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
use rustc_ast::*;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
-use rustc_errors::DiagnosticId;
+use rustc_errors::{DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg};
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
@@ -31,8 +31,9 @@ use smallvec::{smallvec, SmallVec};
use rustc_span::source_map::{respan, Spanned};
use std::assert_matches::debug_assert_matches;
+use std::borrow::Cow;
use std::collections::{hash_map::Entry, BTreeSet};
-use std::mem::{replace, take};
+use std::mem::{replace, swap, take};
mod diagnostics;
@@ -78,6 +79,12 @@ impl PatternSource {
}
}
+impl IntoDiagnosticArg for PatternSource {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Borrowed(self.descr()))
+ }
+}
+
/// Denotes whether the context for the set of already bound bindings is a `Product`
/// or `Or` context. This is used in e.g., `fresh_binding` and `resolve_pattern_inner`.
/// See those functions for more information.
@@ -527,6 +534,7 @@ struct DiagnosticMetadata<'ast> {
/// Used to detect possible new binding written without `let` and to provide structured suggestion.
in_assignment: Option<&'ast Expr>,
+ is_assign_rhs: bool,
/// If we are currently in a trait object definition. Used to point at the bounds when
/// encountering a struct or enum.
@@ -647,7 +655,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
}
TyKind::Path(ref qself, ref path) => {
self.diagnostic_metadata.current_type_path = Some(ty);
- self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
+ self.smart_resolve_path(ty.id, &qself, path, PathSource::Type);
// Check whether we should interpret this as a bare trait object.
if qself.is_none()
@@ -748,7 +756,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
this.visit_generic_params(&tref.bound_generic_params, false);
this.smart_resolve_path(
tref.trait_ref.ref_id,
- None,
+ &None,
&tref.trait_ref.path,
PathSource::Trait(AliasPossibility::Maybe),
);
@@ -977,7 +985,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|this| {
this.smart_resolve_path(
ty.id,
- qself.as_ref(),
+ qself,
path,
PathSource::Expr(None),
);
@@ -1137,12 +1145,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
self.with_rib(ValueNS, InlineAsmSymRibKind, |this| {
this.with_rib(TypeNS, InlineAsmSymRibKind, |this| {
this.with_label_rib(InlineAsmSymRibKind, |this| {
- this.smart_resolve_path(
- sym.id,
- sym.qself.as_ref(),
- &sym.path,
- PathSource::Expr(None),
- );
+ this.smart_resolve_path(sym.id, &sym.qself, &sym.path, PathSource::Expr(None));
visit::walk_inline_asm_sym(this, sym);
});
})
@@ -1835,6 +1838,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let outer_failures = take(&mut self.diagnostic_metadata.current_elision_failures);
let output_rib = if let Ok(res) = elision_lifetime.as_ref() {
+ self.r.lifetime_elision_allowed.insert(fn_id);
LifetimeRibKind::Elided(*res)
} else {
LifetimeRibKind::ElisionFailure
@@ -1923,7 +1927,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// We have a single lifetime => success.
elision_lifetime = Elision::Param(res)
} else {
- // We have have multiple lifetimes => error.
+ // We have multiple lifetimes => error.
elision_lifetime = Elision::Err;
}
}
@@ -2356,8 +2360,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
if let GenericParamKind::Lifetime = param.kind {
// Record lifetime res, so lowering knows there is something fishy.
self.record_lifetime_param(param.id, LifetimeRes::Error);
- continue;
}
+ continue;
}
Entry::Vacant(entry) => {
entry.insert(param.ident.span);
@@ -2570,7 +2574,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.diagnostic_metadata.currently_processing_impl_trait =
Some((trait_ref.clone(), self_type.clone()));
let res = self.smart_resolve_path_fragment(
- None,
+ &None,
&path,
PathSource::Trait(AliasPossibility::No),
Finalize::new(trait_ref.ref_id, trait_ref.path.span),
@@ -3093,7 +3097,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
PatKind::TupleStruct(ref qself, ref path, ref sub_patterns) => {
self.smart_resolve_path(
pat.id,
- qself.as_ref(),
+ qself,
path,
PathSource::TupleStruct(
pat.span,
@@ -3102,10 +3106,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
);
}
PatKind::Path(ref qself, ref path) => {
- self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Pat);
+ self.smart_resolve_path(pat.id, qself, path, PathSource::Pat);
}
PatKind::Struct(ref qself, ref path, ..) => {
- self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Struct);
+ self.smart_resolve_path(pat.id, qself, path, PathSource::Struct);
}
PatKind::Or(ref ps) => {
// Add a new set of bindings to the stack. `Or` here records that when a
@@ -3298,7 +3302,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
fn smart_resolve_path(
&mut self,
id: NodeId,
- qself: Option<&QSelf>,
+ qself: &Option<P<QSelf>>,
path: &Path,
source: PathSource<'ast>,
) {
@@ -3312,7 +3316,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
fn smart_resolve_path_fragment(
&mut self,
- qself: Option<&QSelf>,
+ qself: &Option<P<QSelf>>,
path: &[Segment],
source: PathSource<'ast>,
finalize: Finalize,
@@ -3361,18 +3365,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// Before we start looking for candidates, we have to get our hands
// on the type user is trying to perform invocation on; basically:
// we're transforming `HashMap::new` into just `HashMap`.
- let path = match path.split_last() {
+ let prefix_path = match path.split_last() {
Some((_, path)) if !path.is_empty() => path,
_ => return Some(parent_err),
};
let (mut err, candidates) =
- this.smart_resolve_report_errors(path, path_span, PathSource::Type, None);
-
- if candidates.is_empty() {
- err.cancel();
- return Some(parent_err);
- }
+ this.smart_resolve_report_errors(prefix_path, path_span, PathSource::Type, None);
// There are two different error messages user might receive at
// this point:
@@ -3383,37 +3382,74 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// latter one - for paths in expression-position.
//
// Thus (since we're in expression-position at this point), not to
- // confuse the user, we want to keep the *message* from E0432 (so
+ // confuse the user, we want to keep the *message* from E0433 (so
// `parent_err`), but we want *hints* from E0412 (so `err`).
//
// And that's what happens below - we're just mixing both messages
// into a single one.
let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node);
+ // overwrite all properties with the parent's error message
err.message = take(&mut parent_err.message);
err.code = take(&mut parent_err.code);
+ swap(&mut err.span, &mut parent_err.span);
err.children = take(&mut parent_err.children);
+ err.sort_span = parent_err.sort_span;
+ err.is_lint = parent_err.is_lint;
+
+ // merge the parent's suggestions with the typo suggestions
+ fn append_result<T, E>(res1: &mut Result<Vec<T>, E>, res2: Result<Vec<T>, E>) {
+ match res1 {
+ Ok(vec1) => match res2 {
+ Ok(mut vec2) => vec1.append(&mut vec2),
+ Err(e) => *res1 = Err(e),
+ },
+ Err(_) => (),
+ };
+ }
+ append_result(&mut err.suggestions, parent_err.suggestions.clone());
parent_err.cancel();
let def_id = this.parent_scope.module.nearest_parent_mod();
if this.should_report_errs() {
- this.r.use_injections.push(UseError {
- err,
- candidates,
- def_id,
- instead: false,
- suggestion: None,
- path: path.into(),
- is_call: source.is_call(),
- });
+ if candidates.is_empty() {
+ if path.len() == 2 && prefix_path.len() == 1 {
+ // Delay to check whether methond name is an associated function or not
+ // ```
+ // let foo = Foo {};
+ // foo::bar(); // possibly suggest to foo.bar();
+ //```
+ err.stash(
+ prefix_path[0].ident.span,
+ rustc_errors::StashKey::CallAssocMethod,
+ );
+ } else {
+ // When there is no suggested imports, we can just emit the error
+ // and suggestions immediately. Note that we bypass the usually error
+ // reporting routine (ie via `self.r.report_error`) because we need
+ // to post-process the `ResolutionError` above.
+ err.emit();
+ }
+ } else {
+ // If there are suggested imports, the error reporting is delayed
+ this.r.use_injections.push(UseError {
+ err,
+ candidates,
+ def_id,
+ instead: false,
+ suggestion: None,
+ path: prefix_path.into(),
+ is_call: source.is_call(),
+ });
+ }
} else {
err.cancel();
}
// We don't return `Some(parent_err)` here, because the error will
- // be already printed as part of the `use` injections
+ // be already printed either immediately or as part of the `use` injections
None
};
@@ -3513,7 +3549,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// Resolve in alternative namespaces if resolution in the primary namespace fails.
fn resolve_qpath_anywhere(
&mut self,
- qself: Option<&QSelf>,
+ qself: &Option<P<QSelf>>,
path: &[Segment],
primary_ns: Namespace,
span: Span,
@@ -3557,7 +3593,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
/// Handles paths that may refer to associated items.
fn resolve_qpath(
&mut self,
- qself: Option<&QSelf>,
+ qself: &Option<P<QSelf>>,
path: &[Segment],
ns: Namespace,
finalize: Finalize,
@@ -3587,7 +3623,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// but with `qself` set to `None`.
let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
let partial_res = self.smart_resolve_path_fragment(
- None,
+ &None,
&path[..=qself.position],
PathSource::TraitItem(ns),
Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span),
@@ -3770,12 +3806,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// Next, resolve the node.
match expr.kind {
ExprKind::Path(ref qself, ref path) => {
- self.smart_resolve_path(expr.id, qself.as_ref(), path, PathSource::Expr(parent));
+ self.smart_resolve_path(expr.id, qself, path, PathSource::Expr(parent));
visit::walk_expr(self, expr);
}
ExprKind::Struct(ref se) => {
- self.smart_resolve_path(expr.id, se.qself.as_ref(), &se.path, PathSource::Struct);
+ self.smart_resolve_path(expr.id, &se.qself, &se.path, PathSource::Struct);
visit::walk_expr(self, expr);
}
@@ -3818,7 +3854,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
}
}
- ExprKind::Loop(ref block, label) => self.resolve_labeled_block(label, expr.id, &block),
+ ExprKind::Loop(ref block, label, _) => {
+ self.resolve_labeled_block(label, expr.id, &block)
+ }
ExprKind::While(ref cond, ref block, label) => {
self.with_resolved_label(label, expr.id, |this| {
@@ -3845,12 +3883,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ExprKind::Field(ref subexpression, _) => {
self.resolve_expr(subexpression, Some(expr));
}
- ExprKind::MethodCall(ref segment, ref receiver, ref arguments, _) => {
+ ExprKind::MethodCall(box MethodCall { ref seg, ref receiver, ref args, .. }) => {
self.resolve_expr(receiver, Some(expr));
- for argument in arguments {
- self.resolve_expr(argument, None);
+ for arg in args {
+ self.resolve_expr(arg, None);
}
- self.visit_path_segment(segment);
+ self.visit_path_segment(seg);
}
ExprKind::Call(ref callee, ref arguments) => {
@@ -3889,10 +3927,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
visit::walk_expr(self, expr);
self.diagnostic_metadata.current_type_ascription.pop();
}
- // `async |x| ...` gets desugared to `|x| future_from_generator(|| ...)`, so we need to
+ // `async |x| ...` gets desugared to `|x| async {...}`, so we need to
// resolve the arguments within the proper scopes so that usages of them inside the
// closure are detected as upvars rather than normal closure arg usages.
- ExprKind::Closure(_, _, Async::Yes { .. }, _, ref fn_decl, ref body, _span) => {
+ ExprKind::Closure(box ast::Closure {
+ asyncness: Async::Yes { .. },
+ ref fn_decl,
+ ref body,
+ ..
+ }) => {
self.with_rib(ValueNS, NormalRibKind, |this| {
this.with_label_rib(ClosureOrAsyncRibKind, |this| {
// Resolve arguments:
@@ -3912,7 +3955,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
});
}
// For closures, ClosureOrAsyncRibKind is added in visit_fn
- ExprKind::Closure(ClosureBinder::For { ref generic_params, span }, ..) => {
+ ExprKind::Closure(box ast::Closure {
+ binder: ClosureBinder::For { ref generic_params, span },
+ ..
+ }) => {
self.with_generic_param_rib(
&generic_params,
NormalRibKind,
@@ -3943,10 +3989,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.resolve_expr(elem, Some(expr));
self.visit_expr(idx);
}
- ExprKind::Assign(..) => {
- let old = self.diagnostic_metadata.in_assignment.replace(expr);
- visit::walk_expr(self, expr);
- self.diagnostic_metadata.in_assignment = old;
+ ExprKind::Assign(ref lhs, ref rhs, _) => {
+ if !self.diagnostic_metadata.is_assign_rhs {
+ self.diagnostic_metadata.in_assignment = Some(expr);
+ }
+ self.visit_expr(lhs);
+ self.diagnostic_metadata.is_assign_rhs = true;
+ self.diagnostic_metadata.in_assignment = None;
+ self.visit_expr(rhs);
+ self.diagnostic_metadata.is_assign_rhs = false;
}
_ => {
visit::walk_expr(self, expr);
@@ -3964,9 +4015,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let traits = self.traits_in_scope(ident, ValueNS);
self.r.trait_map.insert(expr.id, traits);
}
- ExprKind::MethodCall(ref segment, ..) => {
+ ExprKind::MethodCall(ref call) => {
debug!("(recording candidate traits for expr) recording traits for {}", expr.id);
- let traits = self.traits_in_scope(segment.ident, ValueNS);
+ let traits = self.traits_in_scope(call.seg.ident, ValueNS);
self.r.trait_map.insert(expr.id, traits);
}
_ => {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 850f023b1..df59a350e 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -8,7 +8,7 @@ use crate::{PathResult, PathSource, Segment};
use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt};
use rustc_ast::{
self as ast, AssocItemKind, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind,
- NodeId, Path, Ty, TyKind, DUMMY_NODE_ID,
+ MethodCall, NodeId, Path, Ty, TyKind, DUMMY_NODE_ID,
};
use rustc_ast_pretty::pprust::path_segment_to_string;
use rustc_data_structures::fx::FxHashSet;
@@ -21,6 +21,7 @@ use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::PrimTy;
+use rustc_middle::ty::DefIdTree;
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_session::Session;
@@ -33,6 +34,8 @@ use rustc_span::{BytePos, Span};
use std::iter;
use std::ops::Deref;
+use thin_vec::ThinVec;
+
type Res = def::Res<ast::NodeId>;
/// A field or associated item from self type suggested in case of resolution failure.
@@ -78,7 +81,7 @@ fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, Str
let path_len = suggestion.path.segments.len();
let enum_path = ast::Path {
span: suggestion.path.span,
- segments: suggestion.path.segments[0..path_len - 1].to_vec(),
+ segments: suggestion.path.segments[0..path_len - 1].iter().cloned().collect(),
tokens: None,
};
let enum_path_string = path_names_to_string(&enum_path);
@@ -150,7 +153,7 @@ struct BaseError {
#[derive(Debug)]
enum TypoCandidate {
Typo(TypoSuggestion),
- Shadowed(Res),
+ Shadowed(Res, Option<Span>),
None,
}
@@ -158,7 +161,7 @@ impl TypoCandidate {
fn to_opt_suggestion(self) -> Option<TypoSuggestion> {
match self {
TypoCandidate::Typo(sugg) => Some(sugg),
- TypoCandidate::Shadowed(_) | TypoCandidate::None => None,
+ TypoCandidate::Shadowed(_, _) | TypoCandidate::None => None,
}
}
}
@@ -219,26 +222,26 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let (mod_prefix, mod_str, suggestion) = if path.len() == 1 {
debug!(?self.diagnostic_metadata.current_impl_items);
debug!(?self.diagnostic_metadata.current_function);
- let suggestion = if let Some(items) = self.diagnostic_metadata.current_impl_items
+ let suggestion = if self.current_trait_ref.is_none()
&& let Some((fn_kind, _)) = self.diagnostic_metadata.current_function
- && self.current_trait_ref.is_none()
&& let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt()
+ && let Some(items) = self.diagnostic_metadata.current_impl_items
&& let Some(item) = items.iter().find(|i| {
- if let AssocItemKind::Fn(fn_) = &i.kind
- && !fn_.sig.decl.has_self()
- && i.ident.name == item_str.name
+ if let AssocItemKind::Fn(_) = &i.kind && i.ident.name == item_str.name
{
debug!(?item_str.name);
- debug!(?fn_.sig.decl.inputs);
return true
}
false
})
+ && let AssocItemKind::Fn(fn_) = &item.kind
{
+ debug!(?fn_);
+ let self_sugg = if fn_.sig.decl.has_self() { "self." } else { "Self::" };
Some((
- item_span,
+ item_span.shrink_to_lo(),
"consider using the associated function",
- format!("Self::{}", item.ident)
+ self_sugg.to_string()
))
} else {
None
@@ -279,6 +282,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
"you may want to use a bool value instead",
format!("{}", item_typo),
))
+ // FIXME(vincenzopalazzo): make the check smarter,
+ // and maybe expand with levenshtein distance checks
+ } else if item_str.as_str() == "printf" {
+ Some((
+ item_span,
+ "you may have meant to use the `print` macro",
+ "print!".to_owned(),
+ ))
} else {
suggestion
};
@@ -322,7 +333,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
self.suggest_bare_struct_literal(&mut err);
- self.suggest_pattern_match_with_let(&mut err, source, span);
+
+ if self.suggest_pattern_match_with_let(&mut err, source, span) {
+ // Fallback label.
+ err.span_label(base_error.span, &base_error.fallback_label);
+ return (err, Vec::new());
+ }
self.suggest_self_or_self_ref(&mut err, path, span);
self.detect_assoct_type_constraint_meant_as_path(&mut err, &base_error);
@@ -341,7 +357,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
if !self.type_ascription_suggestion(&mut err, base_error.span) {
let mut fallback =
self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error);
+
+ // if we have suggested using pattern matching, then don't add needless suggestions
+ // for typos.
fallback |= self.suggest_typo(&mut err, source, path, span, &base_error);
+
if fallback {
// Fallback label.
err.span_label(base_error.span, &base_error.fallback_label);
@@ -387,11 +407,13 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
fn suggest_self_or_self_ref(&mut self, err: &mut Diagnostic, path: &[Segment], span: Span) {
- let is_assoc_fn = self.self_type_is_available();
+ if !self.self_type_is_available() {
+ return;
+ }
let Some(path_last_segment) = path.last() else { return };
let item_str = path_last_segment.ident;
// Emit help message for fake-self from other languages (e.g., `this` in Javascript).
- if ["this", "my"].contains(&item_str.as_str()) && is_assoc_fn {
+ if ["this", "my"].contains(&item_str.as_str()) {
err.span_suggestion_short(
span,
"you might have meant to use `self` here instead",
@@ -428,7 +450,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
fn try_lookup_name_relaxed(
&mut self,
- err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
+ err: &mut Diagnostic,
source: PathSource<'_>,
path: &[Segment],
span: Span,
@@ -442,7 +464,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _));
let path_str = Segment::names_to_string(path);
let ident_span = path.last().map_or(span, |ident| ident.ident.span);
-
let mut candidates = self
.r
.lookup_import_candidates(ident, ns, &self.parent_scope, is_expected)
@@ -488,7 +509,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
.contains(span)
{
// Already reported this issue on the lhs of the type ascription.
- err.delay_as_bug();
+ err.downgrade_to_delayed_bug();
return (true, candidates);
}
}
@@ -607,7 +628,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
fn suggest_trait_and_bounds(
&mut self,
- err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
+ err: &mut Diagnostic,
source: PathSource<'_>,
res: Option<Res>,
span: Span,
@@ -682,7 +703,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
fn suggest_typo(
&mut self,
- err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
+ err: &mut Diagnostic,
source: PathSource<'_>,
path: &[Segment],
span: Span,
@@ -691,9 +712,20 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let is_expected = &|res| source.is_expected(res);
let ident_span = path.last().map_or(span, |ident| ident.ident.span);
let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected);
- if let TypoCandidate::Shadowed(res) = typo_sugg
- && let Some(id) = res.opt_def_id()
- && let Some(sugg_span) = self.r.opt_span(id)
+ let is_in_same_file = &|sp1, sp2| {
+ let source_map = self.r.session.source_map();
+ let file1 = source_map.span_to_filename(sp1);
+ let file2 = source_map.span_to_filename(sp2);
+ file1 == file2
+ };
+ // print 'you might have meant' if the candidate is (1) is a shadowed name with
+ // accessible definition and (2) either defined in the same crate as the typo
+ // (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()
+ .map_or(false, |id| id.is_local() || is_in_same_file(span, sugg_span))
{
err.span_label(
sugg_span,
@@ -730,7 +762,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
fn err_code_special_cases(
&mut self,
- err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
+ err: &mut Diagnostic,
source: PathSource<'_>,
path: &[Segment],
span: Span,
@@ -784,19 +816,18 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
return false;
}
err.code(rustc_errors::error_code!(E0411));
- err.span_label(
- span,
- "`Self` is only available in impls, traits, and type definitions".to_string(),
- );
+ err.span_label(span, "`Self` is only available in impls, traits, and type definitions");
if let Some(item_kind) = self.diagnostic_metadata.current_item {
- err.span_label(
- item_kind.ident.span,
- format!(
- "`Self` not allowed in {} {}",
- item_kind.kind.article(),
- item_kind.kind.descr()
- ),
- );
+ if !item_kind.ident.span.is_dummy() {
+ err.span_label(
+ item_kind.ident.span,
+ format!(
+ "`Self` not allowed in {} {}",
+ item_kind.kind.article(),
+ item_kind.kind.descr()
+ ),
+ );
+ }
}
true
}
@@ -929,7 +960,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
err: &mut Diagnostic,
source: PathSource<'_>,
span: Span,
- ) {
+ ) -> bool {
if let PathSource::Expr(_) = source &&
let Some(Expr {
span: expr_span,
@@ -946,8 +977,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
"let ",
Applicability::MaybeIncorrect,
);
+ return true;
}
}
+ false
}
fn get_single_associated_item(
@@ -973,10 +1006,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
.collect();
if targets.len() == 1 {
let target = targets[0];
- return Some(TypoSuggestion::single_item_from_res(
- target.0.ident.name,
- target.1,
- ));
+ return Some(TypoSuggestion::single_item_from_ident(target.0.ident, target.1));
}
}
}
@@ -1003,11 +1033,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
};
// Confirm that the target is an associated type.
- let (ty, position, path) = if let ast::TyKind::Path(
- Some(ast::QSelf { ty, position, .. }),
- path,
- ) = &bounded_ty.kind
- {
+ let (ty, position, path) = if let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind {
// use this to verify that ident is a type param.
let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else {
return false;
@@ -1018,7 +1044,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
) {
return false;
}
- (ty, position, path)
+ (&qself.ty, qself.position, path)
} else {
return false;
};
@@ -1054,12 +1080,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
.source_map()
.span_to_snippet(ty.span) // Account for `<&'a T as Foo>::Bar`.
.unwrap_or_else(|_| constrain_ident.to_string()),
- path.segments[..*position]
+ path.segments[..position]
.iter()
.map(|segment| path_segment_to_string(segment))
.collect::<Vec<_>>()
.join("::"),
- path.segments[*position..]
+ path.segments[position..]
.iter()
.map(|segment| path_segment_to_string(segment))
.collect::<Vec<_>>()
@@ -1151,7 +1177,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let (lhs_span, rhs_span) = match &expr.kind {
ExprKind::Field(base, ident) => (base.span, ident.span),
- ExprKind::MethodCall(_, receiver, _, span) => (receiver.span, *span),
+ ExprKind::MethodCall(box MethodCall { receiver, span, .. }) => {
+ (receiver.span, *span)
+ }
_ => return false,
};
@@ -1423,13 +1451,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
err.span_label(span, "constructor is not visible here due to private fields");
}
- (
- Res::Def(
- DefKind::Union | DefKind::Variant | DefKind::Ctor(_, CtorKind::Fictive),
- def_id,
- ),
- _,
- ) if ns == ValueNS => {
+ (Res::Def(DefKind::Union | DefKind::Variant, def_id), _) if ns == ValueNS => {
bad_struct_syntax_suggestion(def_id);
}
(Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id), _) if ns == ValueNS => {
@@ -1449,7 +1471,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
_ => return false,
}
}
- (Res::Def(DefKind::Ctor(_, CtorKind::Fn), def_id), _) if ns == ValueNS => {
+ (Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_def_id), _) if ns == ValueNS => {
+ let def_id = self.r.parent(ctor_def_id);
if let Some(span) = self.def_span(def_id) {
err.span_label(span, &format!("`{}` defined here", path_str));
}
@@ -1526,7 +1549,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
_ => None,
}
}
-
// Fields are generally expected in the same contexts as locals.
if filter_fn(Res::Local(ast::DUMMY_NODE_ID)) {
if let Some(node_id) =
@@ -1618,7 +1640,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
// Locals and type parameters
for (ident, &res) in &rib.bindings {
if filter_fn(res) && ident.span.ctxt() == rib_ctxt {
- names.push(TypoSuggestion::typo_from_res(ident.name, res));
+ names.push(TypoSuggestion::typo_from_ident(*ident, res));
}
}
@@ -1647,9 +1669,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
Res::Def(DefKind::Mod, crate_id.as_def_id());
if filter_fn(crate_mod) {
- Some(TypoSuggestion::typo_from_res(
- ident.name, crate_mod,
- ))
+ Some(TypoSuggestion::typo_from_ident(*ident, crate_mod))
} else {
None
}
@@ -1668,7 +1688,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
// Add primitive types to the mix
if filter_fn(Res::PrimTy(PrimTy::Bool)) {
names.extend(PrimTy::ALL.iter().map(|prim_ty| {
- TypoSuggestion::typo_from_res(prim_ty.name(), Res::PrimTy(*prim_ty))
+ TypoSuggestion::typo_from_name(prim_ty.name(), Res::PrimTy(*prim_ty))
}))
}
} else {
@@ -1695,7 +1715,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
return TypoCandidate::None;
};
if found == name {
- TypoCandidate::Shadowed(sugg.res)
+ TypoCandidate::Shadowed(sugg.res, sugg.span)
} else {
TypoCandidate::Typo(sugg)
}
@@ -1796,35 +1816,28 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
false
}
- fn let_binding_suggestion(&self, err: &mut Diagnostic, ident_span: Span) -> bool {
- // try to give a suggestion for this pattern: `name = 1`, which is common in other languages
- let mut added_suggestion = false;
- if let Some(Expr { kind: ExprKind::Assign(lhs, _rhs, _), .. }) = self.diagnostic_metadata.in_assignment &&
+ // 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 {
- let sm = self.r.session.source_map();
- let line_span = sm.span_extend_to_line(ident_span);
- let ident_name = sm.span_to_snippet(ident_span).unwrap();
- // HACK(chenyukang): make sure ident_name is at the starting of the line to protect against macros
- if sm
- .span_to_snippet(line_span)
- .map_or(false, |s| s.trim().starts_with(&ident_name))
- {
+ 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,
);
- added_suggestion = true;
+ return true;
}
}
- added_suggestion
+ false
}
fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> {
let mut result = None;
let mut seen_modules = FxHashSet::default();
- let mut worklist = vec![(self.r.graph_root, Vec::new())];
+ let mut worklist = vec![(self.r.graph_root, ThinVec::new())];
while let Some((in_module, path_segments)) = worklist.pop() {
// abort if the module is already found
@@ -1927,7 +1940,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
err.span_suggestions(
span,
&msg,
- suggestable_variants.into_iter(),
+ suggestable_variants,
Applicability::MaybeIncorrect,
);
}
@@ -1950,11 +1963,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
));
}
} else {
- let needs_placeholder = |def_id: DefId, kind: CtorKind| {
+ let needs_placeholder = |ctor_def_id: DefId, kind: CtorKind| {
+ let def_id = self.r.parent(ctor_def_id);
let has_no_fields = self.r.field_names.get(&def_id).map_or(false, |f| f.is_empty());
match kind {
CtorKind::Const => false,
- CtorKind::Fn | CtorKind::Fictive if has_no_fields => false,
+ CtorKind::Fn if has_no_fields => false,
_ => true,
}
};
@@ -1966,7 +1980,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
.map(|(variant, kind)| match kind {
CtorKind::Const => variant,
CtorKind::Fn => format!("({}())", variant),
- CtorKind::Fictive => format!("({} {{}})", variant),
})
.collect::<Vec<_>>();
let no_suggestable_variant = suggestable_variants.is_empty();
@@ -1981,7 +1994,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
err.span_suggestions(
span,
msg,
- suggestable_variants.into_iter(),
+ suggestable_variants,
Applicability::MaybeIncorrect,
);
}
@@ -1992,7 +2005,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
.map(|(variant, _, kind)| (path_names_to_string(variant), kind))
.filter_map(|(variant, kind)| match kind {
CtorKind::Fn => Some(format!("({}(/* fields */))", variant)),
- CtorKind::Fictive => Some(format!("({} {{ /* fields */ }})", variant)),
_ => None,
})
.collect::<Vec<_>>();
@@ -2011,7 +2023,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
err.span_suggestions(
span,
msg,
- suggestable_variants_with_placeholders.into_iter(),
+ suggestable_variants_with_placeholders,
Applicability::HasPlaceholders,
);
}
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 8aebb7da1..a0fa61c45 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -73,6 +73,7 @@ mod check_unused;
mod def_collector;
mod diagnostics;
mod effective_visibilities;
+mod errors;
mod ident;
mod imports;
mod late;
@@ -646,7 +647,7 @@ impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> {
#[derive(Clone, Debug)]
enum NameBindingKind<'a> {
- Res(Res, /* is_macro_export */ bool),
+ Res(Res),
Module(Module<'a>),
Import { binding: &'a NameBinding<'a>, import: &'a Import<'a>, used: Cell<bool> },
}
@@ -745,7 +746,7 @@ impl<'a> NameBinding<'a> {
fn res(&self) -> Res {
match self.kind {
- NameBindingKind::Res(res, _) => res,
+ NameBindingKind::Res(res) => res,
NameBindingKind::Module(module) => module.res().unwrap(),
NameBindingKind::Import { binding, .. } => binding.res(),
}
@@ -762,10 +763,10 @@ impl<'a> NameBinding<'a> {
fn is_possibly_imported_variant(&self) -> bool {
match self.kind {
NameBindingKind::Import { binding, .. } => binding.is_possibly_imported_variant(),
- NameBindingKind::Res(
- Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..), _),
+ NameBindingKind::Res(Res::Def(
+ DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..),
_,
- ) => true,
+ )) => true,
NameBindingKind::Res(..) | NameBindingKind::Module(..) => false,
}
}
@@ -788,6 +789,13 @@ impl<'a> NameBinding<'a> {
matches!(self.kind, NameBindingKind::Import { .. })
}
+ /// The binding introduced by `#[macro_export] macro_rules` is a public import, but it might
+ /// not be perceived as such by users, so treat it as a non-import in some diagnostics.
+ fn is_import_user_facing(&self) -> bool {
+ matches!(self.kind, NameBindingKind::Import { import, .. }
+ if !matches!(import.kind, ImportKind::MacroExport))
+ }
+
fn is_glob_import(&self) -> bool {
match self.kind {
NameBindingKind::Import { import, .. } => import.is_glob(),
@@ -1030,6 +1038,8 @@ pub struct Resolver<'a> {
/// they are declared in the static array generated by proc_macro_harness.
proc_macros: Vec<NodeId>,
confused_type_with_std_module: FxHashMap<Span, Span>,
+ /// Whether lifetime elision was successful.
+ lifetime_elision_allowed: FxHashSet<NodeId>,
effective_visibilities: EffectiveVisibilities,
}
@@ -1101,17 +1111,30 @@ impl<'a> AsMut<Resolver<'a>> for Resolver<'a> {
}
}
-impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
+/// A minimal subset of resolver that can implemenent `DefIdTree`, sometimes
+/// required to satisfy borrow checker by avoiding borrowing the whole resolver.
+#[derive(Clone, Copy)]
+struct ResolverTree<'a, 'b>(&'a Definitions, &'a CrateLoader<'b>);
+
+impl DefIdTree for ResolverTree<'_, '_> {
#[inline]
fn opt_parent(self, id: DefId) -> Option<DefId> {
+ let ResolverTree(definitions, crate_loader) = self;
match id.as_local() {
- Some(id) => self.definitions.def_key(id).parent,
- None => self.cstore().def_key(id).parent,
+ Some(id) => definitions.def_key(id).parent,
+ None => crate_loader.cstore().def_key(id).parent,
}
.map(|index| DefId { index, ..id })
}
}
+impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
+ #[inline]
+ fn opt_parent(self, id: DefId) -> Option<DefId> {
+ ResolverTree(&self.definitions, &self.crate_loader).opt_parent(id)
+ }
+}
+
impl Resolver<'_> {
fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
self.node_id_to_def_id.get(&node).copied()
@@ -1175,7 +1198,7 @@ impl<'a> Resolver<'a> {
pub fn new(
session: &'a Session,
krate: &Crate,
- crate_name: &str,
+ crate_name: Symbol,
metadata_loader: Box<MetadataLoaderDyn>,
arenas: &'a ResolverArenas<'a>,
) -> Resolver<'a> {
@@ -1283,7 +1306,7 @@ impl<'a> Resolver<'a> {
arenas,
dummy_binding: arenas.alloc_name_binding(NameBinding {
- kind: NameBindingKind::Res(Res::Err, false),
+ kind: NameBindingKind::Res(Res::Err),
ambiguity: None,
expansion: LocalExpnId::ROOT,
span: DUMMY_SP,
@@ -1335,6 +1358,7 @@ impl<'a> Resolver<'a> {
trait_impls: Default::default(),
proc_macros: Default::default(),
confused_type_with_std_module: Default::default(),
+ lifetime_elision_allowed: Default::default(),
effective_visibilities: Default::default(),
};
@@ -1429,6 +1453,7 @@ impl<'a> Resolver<'a> {
def_id_to_node_id: self.def_id_to_node_id,
trait_map: self.trait_map,
builtin_macro_kinds: self.builtin_macro_kinds,
+ lifetime_elision_allowed: self.lifetime_elision_allowed,
};
ResolverOutputs { definitions, global_ctxt, ast_lowering }
}
@@ -1472,6 +1497,7 @@ impl<'a> Resolver<'a> {
def_id_to_node_id: self.def_id_to_node_id.clone(),
trait_map: self.trait_map.clone(),
builtin_macro_kinds: self.builtin_macro_kinds.clone(),
+ lifetime_elision_allowed: self.lifetime_elision_allowed.clone(),
};
ResolverOutputs { definitions, global_ctxt, ast_lowering }
}
@@ -1613,10 +1639,12 @@ impl<'a> Resolver<'a> {
) -> SmallVec<[LocalDefId; 1]> {
let mut import_ids = smallvec![];
while let NameBindingKind::Import { import, binding, .. } = kind {
- let id = self.local_def_id(import.id);
- self.maybe_unused_trait_imports.insert(id);
+ if let Some(node_id) = import.id() {
+ let def_id = self.local_def_id(node_id);
+ self.maybe_unused_trait_imports.insert(def_id);
+ import_ids.push(def_id);
+ }
self.add_to_glob_map(&import, trait_name);
- import_ids.push(id);
kind = &binding.kind;
}
import_ids
@@ -1683,7 +1711,9 @@ impl<'a> Resolver<'a> {
}
used.set(true);
import.used.set(true);
- self.used_imports.insert(import.id);
+ if let Some(id) = import.id() {
+ self.used_imports.insert(id);
+ }
self.add_to_glob_map(&import, ident);
self.record_use(ident, binding, false);
}
@@ -1691,8 +1721,8 @@ impl<'a> Resolver<'a> {
#[inline]
fn add_to_glob_map(&mut self, import: &Import<'_>, ident: Ident) {
- if import.is_glob() {
- let def_id = self.local_def_id(import.id);
+ if let ImportKind::Glob { id, .. } = import.kind {
+ let def_id = self.local_def_id(id);
self.glob_map.entry(def_id).or_default().insert(ident.name);
}
}
@@ -1897,7 +1927,7 @@ impl<'a> Resolver<'a> {
if let Some(def_id) = def_id.as_local() {
self.reexport_map.get(&def_id).cloned().unwrap_or_default()
} else {
- self.cstore().module_children_untracked(def_id, self.session)
+ self.cstore().module_children_untracked(def_id, self.session).collect()
}
}
@@ -1961,7 +1991,7 @@ impl<'a> Resolver<'a> {
.find(|a| a.has_name(sym::rustc_legacy_const_generics))?;
let mut ret = Vec::new();
for meta in attr.meta_item_list()? {
- match meta.literal()?.kind {
+ match meta.lit()?.kind {
LitKind::Int(a, _) => ret.push(a as usize),
_ => panic!("invalid arg index"),
}
@@ -1999,11 +2029,7 @@ impl<'a> Resolver<'a> {
// Items that go to reexport table encoded to metadata and visible through it to other crates.
fn is_reexport(&self, binding: &NameBinding<'a>) -> Option<def::Res<!>> {
- // FIXME: Consider changing the binding inserted by `#[macro_export] macro_rules`
- // into the crate root to actual `NameBindingKind::Import`.
- if binding.is_import()
- || matches!(binding.kind, NameBindingKind::Res(_, _is_macro_export @ true))
- {
+ if binding.is_import() {
let res = binding.res().expect_non_local();
// Ambiguous imports are treated as errors at this point and are
// not exposed to other crates (see #36837 for more details).
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 9526296f9..8c7972f8e 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -356,7 +356,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
has_derive_copy: false,
});
let parent_scope = self.invocation_parent_scopes[&expn_id];
- for (i, (path, _, opt_ext)) in entry.resolutions.iter_mut().enumerate() {
+ for (i, (path, _, opt_ext, _)) in entry.resolutions.iter_mut().enumerate() {
if opt_ext.is_none() {
*opt_ext = Some(
match self.resolve_macro_path(