summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_resolve
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /compiler/rustc_resolve
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_resolve')
-rw-r--r--compiler/rustc_resolve/messages.ftl56
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs33
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs269
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs20
-rw-r--r--compiler/rustc_resolve/src/errors.rs145
-rw-r--r--compiler/rustc_resolve/src/ident.rs274
-rw-r--r--compiler/rustc_resolve/src/imports.rs382
-rw-r--r--compiler/rustc_resolve/src/late.rs55
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs227
-rw-r--r--compiler/rustc_resolve/src/lib.rs240
-rw-r--r--compiler/rustc_resolve/src/macros.rs41
11 files changed, 1146 insertions, 596 deletions
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 539b88aa9..f98918cba 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -5,6 +5,9 @@ resolve_add_as_non_derive =
add as non-Derive macro
`#[{$macro_path}]`
+resolve_added_macro_use =
+ have you added the `#[macro_use]` on the module/import?
+
resolve_ampersand_used_without_explicit_lifetime_name =
`&` without an explicit lifetime name cannot be used here
.note = explicit lifetime name needed here
@@ -41,13 +44,44 @@ resolve_binding_shadows_something_unacceptable =
resolve_binding_shadows_something_unacceptable_suggestion =
try specify the pattern arguments
+resolve_cannot_be_reexported_crate_public =
+ `{$ident}` is only public within the crate, and cannot be re-exported outside
+
+resolve_cannot_be_reexported_private =
+ `{$ident}` is private, and cannot be re-exported
+
resolve_cannot_capture_dynamic_environment_in_fn_item =
can't capture dynamic environment in a fn item
.help = use the `|| {"{"} ... {"}"}` closure form instead
+resolve_cannot_determine_import_resolution =
+ cannot determine resolution for the import
+ .note = import resolution is stuck, try simplifying other imports
+
+resolve_cannot_find_ident_in_this_scope =
+ cannot find {$expected} `{$ident}` in this scope
+
+resolve_cannot_glob_import_possible_crates =
+ cannot glob-import all possible crates
+
resolve_cannot_use_self_type_here =
can't use `Self` here
+resolve_change_import_binding =
+ you can use `as` to change the binding name of the import
+
+resolve_consider_adding_a_derive =
+ consider adding a derive
+
+resolve_consider_adding_macro_export =
+ consider adding a `#[macro_export]` to the macro in the imported module
+
+resolve_consider_declaring_with_pub =
+ consider declaring type or module `{$ident}` with `pub`
+
+resolve_consider_marking_as_pub =
+ consider marking `{$ident}` as `pub` in the imported module
+
resolve_const_not_member_of_trait =
const `{$const_}` is not a member of trait `{$trait_}`
.label = not a member of trait `{$trait_}`
@@ -74,6 +108,9 @@ resolve_expected_found =
expected module, found {$res} `{$path_str}`
.label = not a module
+resolve_explicit_unsafe_traits =
+ unsafe traits like `{$ident}` should be implemented explicitly
+
resolve_forward_declared_generic_param =
generic parameters with a default cannot use forward declared identifiers
.label = defaulted generic parameters cannot be forward declared
@@ -83,6 +120,9 @@ resolve_generic_params_from_outer_function =
.label = use of generic parameter from outer function
.suggestion = try using a local generic parameter instead
+resolve_glob_import_doesnt_reexport =
+ glob import doesn't reexport anything because no candidate is public enough
+
resolve_help_try_using_local_generic_param =
try using a local generic parameter instead
@@ -96,6 +136,9 @@ resolve_ident_bound_more_than_once_in_same_pattern =
resolve_imported_crate = `$crate` may not be imported
+resolve_imports_cannot_refer_to =
+ imports cannot refer to {$what}
+
resolve_indeterminate =
cannot determine resolution for the visibility
@@ -104,6 +147,13 @@ resolve_invalid_asm_sym =
.label = is a local variable
.help = `sym` operands must refer to either a function or a static
+resolve_is_not_directly_importable =
+ `{$target}` is not directly importable
+ .label = cannot be imported directly
+
+resolve_items_in_traits_are_not_importable =
+ items in traits are not importable
+
resolve_label_with_similar_name_reachable =
a label with a similar name is reachable
@@ -158,6 +208,12 @@ resolve_parent_module_reset_for_binding =
resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it
.help = you can define integration tests in a directory named `tests`
+resolve_reexport_of_crate_public =
+ re-export of crate public `{$ident}`
+
+resolve_reexport_of_private =
+ re-export of private `{$ident}`
+
resolve_relative_2018 =
relative paths are not supported in visibilities in 2018 edition or later
.suggestion = try
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 727777333..e6ceedddf 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -6,10 +6,10 @@
//! Imports are also considered items and placed into modules here, but not resolved yet.
use crate::def_collector::collect_definitions;
-use crate::imports::{Import, ImportKind};
+use crate::imports::{ImportData, ImportKind};
use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
use crate::Namespace::{self, MacroNS, TypeNS, ValueNS};
-use crate::{errors, BindingKey, MacroData};
+use crate::{errors, BindingKey, MacroData, NameBindingData};
use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot};
use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError};
use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError};
@@ -31,15 +31,14 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
use std::cell::Cell;
-use std::ptr;
type Res = def::Res<NodeId>;
impl<'a, Id: Into<DefId>> ToNameBinding<'a>
for (Module<'a>, ty::Visibility<Id>, Span, LocalExpnId)
{
- fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
- arenas.alloc_name_binding(NameBinding {
+ fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> {
+ arenas.alloc_name_binding(NameBindingData {
kind: NameBindingKind::Module(self.0),
ambiguity: None,
vis: self.1.to_def_id(),
@@ -50,8 +49,8 @@ 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 {
+ fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> {
+ arenas.alloc_name_binding(NameBindingData {
kind: NameBindingKind::Res(self.0),
ambiguity: None,
vis: self.1.to_def_id(),
@@ -71,7 +70,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let binding = def.to_name_binding(self.arenas);
let key = self.new_disambiguated_key(ident, ns);
if let Err(old_binding) = self.try_define(parent, key, binding) {
- self.report_conflict(parent, ident, ns, old_binding, &binding);
+ self.report_conflict(parent, ident, ns, old_binding, binding);
}
}
@@ -142,8 +141,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
Some(def_id) => self.macro_def_scope(def_id),
None => expn_id
.as_local()
- .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id))
- .unwrap_or(&self.graph_root),
+ .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id).copied())
+ .unwrap_or(self.graph_root),
}
}
@@ -354,7 +353,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
vis: ty::Visibility,
) {
let current_module = self.parent_scope.module;
- let import = self.r.arenas.alloc_import(Import {
+ let import = self.r.arenas.alloc_import(ImportData {
kind,
parent_scope: self.parent_scope,
module_path,
@@ -378,7 +377,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
if !type_ns_only || ns == TypeNS {
let key = BindingKey::new(target, ns);
let mut resolution = this.resolution(current_module, key).borrow_mut();
- resolution.add_single_import(import);
+ resolution.single_imports.insert(import);
}
});
}
@@ -848,7 +847,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
(used, Some(ModuleOrUniformRoot::Module(module)), binding)
})
.unwrap_or((true, None, self.r.dummy_binding));
- let import = self.r.arenas.alloc_import(Import {
+ let import = self.r.arenas.alloc_import(ImportData {
kind: ImportKind::ExternCrate { source: orig_name, target: ident, id: item.id },
root_id: item.id,
parent_scope: self.parent_scope,
@@ -864,7 +863,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
});
self.r.potentially_unused_imports.push(import);
let imported_binding = self.r.import(binding, import);
- if ptr::eq(parent, self.r.graph_root) {
+ if parent == self.r.graph_root {
if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
if expansion != LocalExpnId::ROOT
&& orig_name.is_some()
@@ -996,7 +995,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
fn add_macro_use_binding(
&mut self,
name: Symbol,
- binding: &'a NameBinding<'a>,
+ binding: NameBinding<'a>,
span: Span,
allow_shadowing: bool,
) {
@@ -1058,7 +1057,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
}
let macro_use_import = |this: &Self, span| {
- this.r.arenas.alloc_import(Import {
+ this.r.arenas.alloc_import(ImportData {
kind: ImportKind::MacroUse,
root_id: item.id,
parent_scope: this.parent_scope,
@@ -1228,7 +1227,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
self.r.set_binding_parent_module(binding, parent_scope.module);
self.r.all_macro_rules.insert(ident.name, res);
if is_macro_export {
- let import = self.r.arenas.alloc_import(Import {
+ let import = self.r.arenas.alloc_import(ImportData {
kind: ImportKind::MacroExport,
root_id: item.id,
parent_scope: self.parent_scope,
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 8c6ac822a..d3dcdfa42 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1,8 +1,8 @@
-use std::ptr;
-
+use rustc_ast::expand::StrippedCfgItem;
use rustc_ast::ptr::P;
use rustc_ast::visit::{self, Visitor};
use rustc_ast::{self as ast, Crate, ItemKind, ModKind, NodeId, Path, CRATE_NODE_ID};
+use rustc_ast::{MetaItemKind, NestedMetaItem};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{
@@ -28,6 +28,10 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Span, SyntaxContext};
use thin_vec::ThinVec;
+use crate::errors::{
+ AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive,
+ ExplicitUnsafeTraits,
+};
use crate::imports::{Import, ImportKind};
use crate::late::{PatternSource, Rib};
use crate::path_names_to_string;
@@ -97,6 +101,7 @@ pub(crate) struct ImportSuggestion {
pub descr: &'static str,
pub path: Path,
pub accessible: bool,
+ pub via_import: bool,
/// An extra note that should be issued if this item is suggested
pub note: Option<String>,
}
@@ -134,9 +139,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
let mut reported_spans = FxHashSet::default();
- for error in &self.privacy_errors {
+ for error in std::mem::take(&mut self.privacy_errors) {
if reported_spans.insert(error.dedup_span) {
- self.report_privacy_error(error);
+ self.report_privacy_error(&error);
}
}
}
@@ -175,13 +180,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
- pub(crate) fn report_conflict<'b>(
+ pub(crate) fn report_conflict(
&mut self,
parent: Module<'_>,
ident: Ident,
ns: Namespace,
- new_binding: &NameBinding<'b>,
- old_binding: &NameBinding<'b>,
+ new_binding: NameBinding<'a>,
+ old_binding: NameBinding<'a>,
) {
// Error on the second of two conflicting names
if old_binding.span.lo() > new_binding.span.lo() {
@@ -255,7 +260,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// See https://github.com/rust-lang/rust/issues/32354
use NameBindingKind::Import;
- let can_suggest = |binding: &NameBinding<'_>, import: &self::Import<'_>| {
+ let can_suggest = |binding: NameBinding<'_>, import: self::Import<'_>| {
!binding.span.is_dummy()
&& !matches!(import.kind, ImportKind::MacroUse | ImportKind::MacroExport)
};
@@ -265,22 +270,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
(Import { import: new, .. }, Import { import: old, .. })
if {
(new.has_attributes || old.has_attributes)
- && can_suggest(old_binding, old)
- && can_suggest(new_binding, new)
+ && can_suggest(old_binding, *old)
+ && can_suggest(new_binding, *new)
} =>
{
if old.has_attributes {
- Some((new, new_binding.span, true))
+ Some((*new, new_binding.span, true))
} else {
- Some((old, old_binding.span, true))
+ Some((*old, old_binding.span, true))
}
}
// Otherwise prioritize the new binding.
- (Import { import, .. }, other) if can_suggest(new_binding, import) => {
- Some((import, new_binding.span, other.is_import()))
+ (Import { import, .. }, other) if can_suggest(new_binding, *import) => {
+ Some((*import, new_binding.span, other.is_import()))
}
- (other, Import { import, .. }) if can_suggest(old_binding, import) => {
- Some((import, old_binding.span, other.is_import()))
+ (other, Import { import, .. }) if can_suggest(old_binding, *import) => {
+ Some((*import, old_binding.span, other.is_import()))
}
_ => None,
};
@@ -334,7 +339,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&self,
err: &mut Diagnostic,
name: Symbol,
- import: &Import<'_>,
+ import: Import<'_>,
binding_span: Span,
) {
let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
@@ -374,16 +379,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
_ => unreachable!(),
}
- let rename_msg = "you can use `as` to change the binding name of the import";
if let Some(suggestion) = suggestion {
- err.span_suggestion(
- binding_span,
- rename_msg,
- suggestion,
- Applicability::MaybeIncorrect,
- );
+ err.subdiagnostic(ChangeImportBindingSuggestion { span: binding_span, suggestion });
} else {
- err.span_label(binding_span, rename_msg);
+ err.subdiagnostic(ChangeImportBinding { span: binding_span });
}
}
@@ -412,7 +411,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
fn add_suggestion_for_duplicate_nested_use(
&self,
err: &mut Diagnostic,
- import: &Import<'_>,
+ import: Import<'_>,
binding_span: Span,
) {
assert!(import.is_nested());
@@ -454,7 +453,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&mut self,
finalize: Option<Finalize>,
path: &[Segment],
- second_binding: Option<&NameBinding<'_>>,
+ second_binding: Option<NameBinding<'_>>,
) {
let Some(Finalize { node_id, root_span, .. }) = finalize else {
return;
@@ -776,7 +775,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
.tcx
.sess
.create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span }),
- ResolutionError::FailedToResolve { label, suggestion } => {
+ ResolutionError::FailedToResolve { last_segment, label, suggestion, module } => {
let mut err =
struct_span_err!(self.tcx.sess, span, E0433, "failed to resolve: {}", &label);
err.span_label(span, label);
@@ -789,6 +788,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
err.multipart_suggestion(msg, suggestions, applicability);
}
+ if let Some(ModuleOrUniformRoot::Module(module)) = module
+ && let Some(module) = module.opt_def_id()
+ && let Some(last_segment) = last_segment
+ {
+ self.find_cfg_stripped(&mut err, &last_segment, module);
+ }
+
err
}
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
@@ -971,9 +977,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
VisResolutionError::AncestorOnly(span) => {
self.tcx.sess.create_err(errs::AncestorOnly(span))
}
- VisResolutionError::FailedToResolve(span, label, suggestion) => {
- self.into_struct_error(span, ResolutionError::FailedToResolve { label, suggestion })
- }
+ VisResolutionError::FailedToResolve(span, label, suggestion) => self.into_struct_error(
+ span,
+ ResolutionError::FailedToResolve {
+ last_segment: None,
+ label,
+ suggestion,
+ module: None,
+ },
+ ),
VisResolutionError::ExpectedFound(span, path_str, res) => {
self.tcx.sess.create_err(errs::ExpectedFound { span, res, path_str })
}
@@ -1184,7 +1196,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// avoid suggesting anything with a hygienic name
if ident.name == lookup_ident.name
&& ns == namespace
- && !ptr::eq(in_module, parent_scope.module)
+ && in_module != parent_scope.module
&& !ident.span.normalize_to_macros_2_0().from_expansion()
{
let res = name_binding.res();
@@ -1243,6 +1255,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
path,
accessible: child_accessible,
note,
+ via_import,
});
}
}
@@ -1337,6 +1350,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
macro_kind: MacroKind,
parent_scope: &ParentScope<'a>,
ident: Ident,
+ krate: &Crate,
) {
let is_expected = &|res: Res| res.macro_kind() == Some(macro_kind);
let suggestion = self.early_lookup_typo_candidate(
@@ -1349,25 +1363,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let import_suggestions =
self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
+ let (span, found_use) = match parent_scope.module.nearest_parent_mod().as_local() {
+ Some(def_id) => UsePlacementFinder::check(krate, self.def_id_to_node_id[def_id]),
+ None => (None, FoundUse::No),
+ };
show_candidates(
self.tcx,
err,
- None,
+ span,
&import_suggestions,
Instead::No,
- FoundUse::Yes,
+ found_use,
DiagnosticMode::Normal,
vec![],
"",
);
if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
- let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident);
- err.span_note(ident.span, msg);
+ err.subdiagnostic(ExplicitUnsafeTraits { span: ident.span, ident });
return;
}
if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
- err.help("have you added the `#[macro_use]` on the module/import?");
+ err.subdiagnostic(AddedMacroUse);
return;
}
if ident.name == kw::Default
@@ -1376,19 +1393,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let span = self.def_span(def_id);
let source_map = self.tcx.sess.source_map();
let head_span = source_map.guess_head_span(span);
- if let Ok(head) = source_map.span_to_snippet(head_span) {
- err.span_suggestion(head_span, "consider adding a derive", format!("#[derive(Default)]\n{head}"), Applicability::MaybeIncorrect);
- } else {
- err.span_help(
- head_span,
- "consider adding `#[derive(Default)]` to this enum",
- );
- }
+ err.subdiagnostic(ConsiderAddingADerive {
+ span: head_span.shrink_to_lo(),
+ suggestion: format!("#[derive(Default)]\n")
+ });
}
for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
if let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
ident,
- ScopeSet::All(ns, false),
+ ScopeSet::All(ns),
&parent_scope,
None,
false,
@@ -1500,7 +1513,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
true
}
- fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
+ fn binding_description(&self, b: NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
let res = b.res();
if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) {
// These already contain the "built-in" prefix or look bad with it.
@@ -1540,7 +1553,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
err.span_label(ident.span, "ambiguous name");
err.note(format!("ambiguous because of {}", kind.descr()));
- let mut could_refer_to = |b: &NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
+ let mut could_refer_to = |b: NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude);
let note_msg = format!("`{ident}` could{also} refer to {what}");
@@ -1580,7 +1593,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// 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> {
+ fn ctor_fields_span(&self, binding: NameBinding<'_>) -> Option<Span> {
if let NameBindingKind::Res(Res::Def(
DefKind::Ctor(CtorOf::Struct, CtorKind::Fn),
ctor_def_id,
@@ -1596,8 +1609,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None
}
- fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
- let PrivacyError { ident, binding, .. } = *privacy_error;
+ fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'a>) {
+ let PrivacyError { ident, binding, outermost_res, parent_scope, dedup_span } =
+ *privacy_error;
let res = binding.res();
let ctor_fields_span = self.ctor_fields_span(binding);
@@ -1606,7 +1620,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
let import_descr = nonimport_descr.clone() + " import";
let get_descr =
- |b: &NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
+ |b: NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
// Print the primary message.
let descr = get_descr(binding);
@@ -1614,6 +1628,33 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident);
err.span_label(ident.span, format!("private {}", descr));
+ if let Some((this_res, outer_ident)) = outermost_res {
+ let import_suggestions = self.lookup_import_candidates(
+ outer_ident,
+ this_res.ns().unwrap_or(Namespace::TypeNS),
+ &parent_scope,
+ &|res: Res| res == this_res,
+ );
+ let point_to_def = !show_candidates(
+ self.tcx,
+ &mut err,
+ Some(dedup_span.until(outer_ident.span.shrink_to_hi())),
+ &import_suggestions,
+ Instead::Yes,
+ FoundUse::Yes,
+ DiagnosticMode::Import,
+ vec![],
+ "",
+ );
+ // If we suggest importing a public re-export, don't point at the definition.
+ if point_to_def && ident.span != outer_ident.span {
+ err.span_label(
+ outer_ident.span,
+ format!("{} `{outer_ident}` is not publicly re-exported", this_res.descr()),
+ );
+ }
+ }
+
let mut non_exhaustive = None;
// If an ADT is foreign and marked as `non_exhaustive`, then that's
// probably why we have the privacy error.
@@ -1659,7 +1700,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
_ => None,
};
- let first = ptr::eq(binding, first_binding);
+ let first = binding == first_binding;
let msg = format!(
"{and_refers_to}the {item} `{name}`{which} is defined here{dots}",
and_refers_to = if first { "" } else { "...and refers to " },
@@ -1689,7 +1730,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
pub(crate) fn find_similarly_named_module_or_crate(
&mut self,
ident: Symbol,
- current_module: &Module<'a>,
+ current_module: Module<'a>,
) -> Option<Symbol> {
let mut candidates = self
.extern_prelude
@@ -1699,7 +1740,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
self.module_map
.iter()
.filter(|(_, module)| {
- current_module.is_ancestor_of(module) && !ptr::eq(current_module, *module)
+ current_module.is_ancestor_of(**module) && current_module != **module
})
.flat_map(|(_, module)| module.kind.name()),
)
@@ -1719,12 +1760,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
opt_ns: Option<Namespace>, // `None` indicates a module path in import
parent_scope: &ParentScope<'a>,
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
- ignore_binding: Option<&'a NameBinding<'a>>,
+ ignore_binding: Option<NameBinding<'a>>,
module: Option<ModuleOrUniformRoot<'a>>,
- i: usize,
+ failed_segment_idx: usize,
ident: Ident,
) -> (String, Option<Suggestion>) {
- let is_last = i == path.len() - 1;
+ let is_last = failed_segment_idx == path.len() - 1;
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
let module_res = match module {
Some(ModuleOrUniformRoot::Module(module)) => module.res(),
@@ -1758,8 +1799,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} else {
(format!("could not find `{ident}` in the crate root"), None)
}
- } else if i > 0 {
- let parent = path[i - 1].ident.name;
+ } else if failed_segment_idx > 0 {
+ let parent = path[failed_segment_idx - 1].ident.name;
let parent = match parent {
// ::foo is mounted at the crate root for 2015, and is the extern
// prelude for 2018+
@@ -1798,10 +1839,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
_ => None,
}
} else {
- let scopes = ScopeSet::All(ns_to_try, opt_ns.is_none());
self.early_resolve_ident_in_lexical_scope(
ident,
- scopes,
+ ScopeSet::All(ns_to_try),
parent_scope,
None,
false,
@@ -1903,7 +1943,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
suggestion = suggestion.or_else(|| {
- self.find_similarly_named_module_or_crate(ident.name, &parent_scope.module).map(
+ self.find_similarly_named_module_or_crate(ident.name, parent_scope.module).map(
|sugg| {
(
vec![(ident.span, sugg.to_string())],
@@ -2072,7 +2112,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// ```
pub(crate) fn check_for_module_export_macro(
&mut self,
- import: &'a Import<'a>,
+ import: Import<'a>,
module: ModuleOrUniformRoot<'a>,
ident: Ident,
) -> Option<(Option<Suggestion>, Option<String>)> {
@@ -2084,9 +2124,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
crate_module = parent;
}
- if ModuleOrUniformRoot::same_def(ModuleOrUniformRoot::Module(crate_module), module) {
- // Don't make a suggestion if the import was already from the root of the
- // crate.
+ if module == ModuleOrUniformRoot::Module(crate_module) {
+ // Don't make a suggestion if the import was already from the root of the crate.
return None;
}
@@ -2207,6 +2246,44 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None
}
}
+
+ /// Finds a cfg-ed out item inside `module` with the matching name.
+ pub(crate) fn find_cfg_stripped(
+ &mut self,
+ err: &mut Diagnostic,
+ last_segment: &Symbol,
+ module: DefId,
+ ) {
+ let local_items;
+ let symbols = if module.is_local() {
+ local_items = self
+ .stripped_cfg_items
+ .iter()
+ .filter_map(|item| {
+ let parent_module = self.opt_local_def_id(item.parent_module)?.to_def_id();
+ Some(StrippedCfgItem { parent_module, name: item.name, cfg: item.cfg.clone() })
+ })
+ .collect::<Vec<_>>();
+ local_items.as_slice()
+ } else {
+ self.tcx.stripped_cfg_items(module.krate)
+ };
+
+ for &StrippedCfgItem { parent_module, name, ref cfg } in symbols {
+ if parent_module != module || name.name != *last_segment {
+ continue;
+ }
+
+ err.span_note(name.span, "found an item that was configured out");
+
+ if let MetaItemKind::List(nested) = &cfg.kind
+ && let NestedMetaItem::MetaItem(meta_item) = &nested[0]
+ && let MetaItemKind::NameValue(feature_name) = &meta_item.kind
+ {
+ err.note(format!("the item is gated behind the `{}` feature", feature_name.symbol));
+ }
+ }
+ }
}
/// Given a `binding_span` of a binding within a use statement:
@@ -2404,7 +2481,8 @@ pub(crate) fn import_candidates(
/// When an entity with a given name is not available in scope, we search for
/// entities with that name in all crates. This method allows outputting the
-/// results of this search in a programmer-friendly way
+/// results of this search in a programmer-friendly way. If any entities are
+/// found and suggested, returns `true`, otherwise returns `false`.
fn show_candidates(
tcx: TyCtxt<'_>,
err: &mut Diagnostic,
@@ -2416,19 +2494,19 @@ fn show_candidates(
mode: DiagnosticMode,
path: Vec<Segment>,
append: &str,
-) {
+) -> bool {
if candidates.is_empty() {
- return;
+ return false;
}
- let mut accessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> =
+ let mut accessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>, bool)> =
Vec::new();
- let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> =
+ let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>, bool)> =
Vec::new();
candidates.iter().for_each(|c| {
(if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings })
- .push((path_names_to_string(&c.path), c.descr, c.did, &c.note))
+ .push((path_names_to_string(&c.path), c.descr, c.did, &c.note, c.via_import))
});
// we want consistent results across executions, but candidates are produced
@@ -2436,26 +2514,31 @@ fn show_candidates(
for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
path_strings.sort_by(|a, b| a.0.cmp(&b.0));
let core_path_strings =
- path_strings.drain_filter(|p| p.0.starts_with("core::")).collect::<Vec<_>>();
+ path_strings.extract_if(|p| p.0.starts_with("core::")).collect::<Vec<_>>();
path_strings.extend(core_path_strings);
path_strings.dedup_by(|a, b| a.0 == b.0);
}
if !accessible_path_strings.is_empty() {
- let (determiner, kind, name) = if accessible_path_strings.len() == 1 {
- ("this", accessible_path_strings[0].1, format!(" `{}`", accessible_path_strings[0].0))
- } else {
- ("one of these", "items", String::new())
- };
+ let (determiner, kind, name, through) =
+ if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] {
+ (
+ "this",
+ *descr,
+ format!(" `{name}`"),
+ if *via_import { " through its public re-export" } else { "" },
+ )
+ } else {
+ ("one of these", "items", String::new(), "")
+ };
let instead = if let Instead::Yes = instead { " instead" } else { "" };
let mut msg = if let DiagnosticMode::Pattern = mode {
format!(
- "if you meant to match on {}{}{}, use the full path in the pattern",
- kind, instead, name
+ "if you meant to match on {kind}{instead}{name}, use the full path in the pattern",
)
} else {
- format!("consider importing {} {}{}", determiner, kind, instead)
+ format!("consider importing {determiner} {kind}{through}{instead}")
};
for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
@@ -2471,7 +2554,7 @@ fn show_candidates(
accessible_path_strings.into_iter().map(|a| a.0),
Applicability::MaybeIncorrect,
);
- return;
+ return true;
}
DiagnosticMode::Import => ("", ""),
DiagnosticMode::Normal => ("use ", ";\n"),
@@ -2512,6 +2595,7 @@ fn show_candidates(
err.help(msg);
}
+ true
} else if !matches!(mode, DiagnosticMode::Import) {
assert!(!inaccessible_path_strings.is_empty());
@@ -2520,13 +2604,9 @@ fn show_candidates(
} else {
""
};
- if inaccessible_path_strings.len() == 1 {
- let (name, descr, def_id, note) = &inaccessible_path_strings[0];
+ if let [(name, descr, def_id, note, _)] = &inaccessible_path_strings[..] {
let msg = format!(
- "{}{} `{}`{} exists but is inaccessible",
- prefix,
- descr,
- name,
+ "{prefix}{descr} `{name}`{} exists but is inaccessible",
if let DiagnosticMode::Pattern = mode { ", which" } else { "" }
);
@@ -2540,14 +2620,14 @@ fn show_candidates(
err.note(msg);
}
if let Some(note) = (*note).as_deref() {
- err.note(note);
+ err.note(note.to_string());
}
} else {
- let (_, descr_first, _, _) = &inaccessible_path_strings[0];
+ let (_, descr_first, _, _, _) = &inaccessible_path_strings[0];
let descr = if inaccessible_path_strings
.iter()
.skip(1)
- .all(|(_, descr, _, _)| descr == descr_first)
+ .all(|(_, descr, _, _, _)| descr == descr_first)
{
descr_first
} else {
@@ -2560,7 +2640,7 @@ fn show_candidates(
let mut has_colon = false;
let mut spans = Vec::new();
- for (name, _, def_id, _) in &inaccessible_path_strings {
+ for (name, _, def_id, _, _) in &inaccessible_path_strings {
if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
let span = tcx.source_span(local_def_id);
let span = tcx.sess.source_map().guess_head_span(span);
@@ -2586,6 +2666,9 @@ fn show_candidates(
err.span_note(multi_span, msg);
}
+ true
+ } else {
+ false
}
}
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 7393bdb38..eb210532f 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -5,7 +5,6 @@ use rustc_ast::visit::Visitor;
use rustc_ast::Crate;
use rustc_ast::EnumDef;
use rustc_data_structures::fx::FxHashSet;
-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;
@@ -13,12 +12,10 @@ use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility};
use rustc_middle::ty::Visibility;
use std::mem;
-type ImportId<'a> = Interned<'a, NameBinding<'a>>;
-
#[derive(Clone, Copy)]
enum ParentId<'a> {
Def(LocalDefId),
- Import(ImportId<'a>),
+ Import(NameBinding<'a>),
}
impl ParentId<'_> {
@@ -36,7 +33,7 @@ pub(crate) struct EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
/// 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>>,
+ import_effective_visibilities: EffectiveVisibilities<NameBinding<'a>>,
// It's possible to recalculate this at any point, but it's relatively expensive.
current_private_vis: Visibility,
changed: bool,
@@ -47,7 +44,7 @@ impl Resolver<'_, '_> {
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 {
+ fn private_vis_import(&mut self, binding: NameBinding<'_>) -> Visibility {
let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() };
Visibility::Restricted(
import
@@ -75,13 +72,13 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
pub(crate) fn compute_effective_visibilities<'c>(
r: &'r mut Resolver<'a, 'tcx>,
krate: &'c Crate,
- ) -> FxHashSet<Interned<'a, NameBinding<'a>>> {
+ ) -> FxHashSet<NameBinding<'a>> {
let mut visitor = EffectiveVisibilitiesVisitor {
r,
def_effective_visibilities: Default::default(),
import_effective_visibilities: Default::default(),
current_private_vis: Visibility::Restricted(CRATE_DEF_ID),
- changed: false,
+ changed: true,
};
visitor.def_effective_visibilities.update_root();
@@ -133,8 +130,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
// lint. For all bindings added to the table this way `is_ambiguity` returns true.
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);
+ self.update_import(binding, parent_id);
if binding.ambiguity.is_some() {
// Stop at the root ambiguity, further bindings in the chain should not
@@ -143,7 +139,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
break;
}
- parent_id = ParentId::Import(binding_id);
+ parent_id = ParentId::Import(binding);
binding = nested_binding;
}
@@ -192,7 +188,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
}
}
- fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) {
+ fn update_import(&mut self, binding: NameBinding<'a>, parent_id: ParentId<'a>) {
let nominal_vis = binding.vis.expect_local();
let Some(cheap_private_vis) = self.may_update(nominal_vis, parent_id) else { return };
let inherited_eff_vis = self.effective_vis_or_private(parent_id);
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 2ab55f126..e4b89c658 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -330,6 +330,7 @@ pub(crate) struct ParamInTyOfConstParam {
pub(crate) param_kind: Option<ParamKindInTyOfConstParam>,
}
+#[derive(Debug)]
#[derive(Subdiagnostic)]
pub(crate) enum ParamKindInTyOfConstParam {
#[note(resolve_type_param_in_ty_of_const_param)]
@@ -365,6 +366,7 @@ pub(crate) struct ParamInNonTrivialAnonConst {
#[help(resolve_param_in_non_trivial_anon_const_help)]
pub(crate) struct ParamInNonTrivialAnonConstHelp;
+#[derive(Debug)]
#[derive(Subdiagnostic)]
pub(crate) enum ParamKindInNonTrivialAnonConst {
#[note(resolve_type_param_in_non_trivial_anon_const)]
@@ -562,6 +564,7 @@ pub(crate) struct CfgAccessibleUnsure {
pub(crate) span: Span,
}
+#[derive(Debug)]
#[derive(Diagnostic)]
#[diag(resolve_param_in_enum_discriminant)]
pub(crate) struct ParamInEnumDiscriminant {
@@ -573,6 +576,7 @@ pub(crate) struct ParamInEnumDiscriminant {
pub(crate) param_kind: ParamKindInEnumDiscriminant,
}
+#[derive(Debug)]
#[derive(Subdiagnostic)]
pub(crate) enum ParamKindInEnumDiscriminant {
#[note(resolve_type_param_in_enum_discriminant)]
@@ -582,3 +586,144 @@ pub(crate) enum ParamKindInEnumDiscriminant {
#[note(resolve_lifetime_param_in_enum_discriminant)]
Lifetime,
}
+
+#[derive(Subdiagnostic)]
+#[label(resolve_change_import_binding)]
+pub(crate) struct ChangeImportBinding {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ resolve_change_import_binding,
+ code = "{suggestion}",
+ applicability = "maybe-incorrect"
+)]
+pub(crate) struct ChangeImportBindingSuggestion {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) suggestion: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_imports_cannot_refer_to)]
+pub(crate) struct ImportsCannotReferTo<'a> {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) what: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_cannot_find_ident_in_this_scope)]
+pub(crate) struct CannotFindIdentInThisScope<'a> {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) expected: &'a str,
+ pub(crate) ident: Ident,
+}
+
+#[derive(Subdiagnostic)]
+#[note(resolve_explicit_unsafe_traits)]
+pub(crate) struct ExplicitUnsafeTraits {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) ident: Ident,
+}
+
+#[derive(Subdiagnostic)]
+#[help(resolve_added_macro_use)]
+pub(crate) struct AddedMacroUse;
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ resolve_consider_adding_a_derive,
+ code = "{suggestion}",
+ applicability = "maybe-incorrect"
+)]
+pub(crate) struct ConsiderAddingADerive {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) suggestion: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_cannot_determine_import_resolution)]
+pub(crate) struct CannotDetermineImportResolution {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_cannot_be_reexported_private, code = "E0364")]
+pub(crate) struct CannotBeReexportedPrivate {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) ident: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_cannot_be_reexported_crate_public, code = "E0364")]
+pub(crate) struct CannotBeReexportedCratePublic {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) ident: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_cannot_be_reexported_private, code = "E0365")]
+#[note(resolve_consider_declaring_with_pub)]
+pub(crate) struct CannotBeReexportedPrivateNS {
+ #[primary_span]
+ #[label(resolve_reexport_of_private)]
+ pub(crate) span: Span,
+ pub(crate) ident: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_cannot_be_reexported_crate_public, code = "E0365")]
+#[note(resolve_consider_declaring_with_pub)]
+pub(crate) struct CannotBeReexportedCratePublicNS {
+ #[primary_span]
+ #[label(resolve_reexport_of_crate_public)]
+ pub(crate) span: Span,
+ pub(crate) ident: Ident,
+}
+
+#[derive(Subdiagnostic)]
+#[help(resolve_consider_adding_macro_export)]
+pub(crate) struct ConsiderAddingMacroExport {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[note(resolve_consider_marking_as_pub)]
+pub(crate) struct ConsiderMarkingAsPub {
+ #[primary_span]
+ pub(crate) span: Span,
+ pub(crate) ident: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_cannot_glob_import_possible_crates)]
+pub(crate) struct CannotGlobImportAllCrates {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_items_in_traits_are_not_importable)]
+pub(crate) struct ItemsInTraitsAreNotImportable {
+ #[primary_span]
+ pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_is_not_directly_importable, code = "E0253")]
+pub(crate) struct IsNotDirectlyImportable {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) target: Ident,
+}
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 945c7ce3a..520fab1f0 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -11,8 +11,6 @@ use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContex
use rustc_span::symbol::{kw, Ident};
use rustc_span::{Span, DUMMY_SP};
-use std::ptr;
-
use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
use crate::late::{
ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind,
@@ -20,7 +18,7 @@ use crate::late::{
use crate::macros::{sub_namespace_match, MacroRulesScope};
use crate::BindingKey;
use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize};
-use crate::{Import, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot};
+use crate::{ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot};
use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res};
use crate::{ResolutionError, Resolver, Scope, ScopeSet, Segment, ToNameBinding, Weak};
@@ -88,7 +86,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let rust_2015 = ctxt.edition().is_rust_2015();
let (ns, macro_kind, is_absolute_path) = match scope_set {
- ScopeSet::All(ns, _) => (ns, None, false),
+ ScopeSet::All(ns) => (ns, None, false),
ScopeSet::AbsolutePath(ns) => (ns, None, true),
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false),
ScopeSet::Late(ns, ..) => (ns, None, false),
@@ -284,7 +282,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
ribs: &[Rib<'a>],
- ignore_binding: Option<&'a NameBinding<'a>>,
+ ignore_binding: Option<NameBinding<'a>>,
) -> Option<LexicalScopeBinding<'a>> {
assert!(ns == TypeNS || ns == ValueNS);
let orig_ident = ident;
@@ -370,7 +368,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// expansion and import resolution (perhaps they can be merged in the future).
/// The function is used for resolving initial segments of macro paths (e.g., `foo` in
/// `foo::bar!();` or `foo!();`) and also for import paths on 2018 edition.
- #[instrument(level = "debug", skip(self, scope_set))]
+ #[instrument(level = "debug", skip(self))]
pub(crate) fn early_resolve_ident_in_lexical_scope(
&mut self,
orig_ident: Ident,
@@ -378,8 +376,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
force: bool,
- ignore_binding: Option<&'a NameBinding<'a>>,
- ) -> Result<&'a NameBinding<'a>, Determinacy> {
+ ignore_binding: Option<NameBinding<'a>>,
+ ) -> Result<NameBinding<'a>, Determinacy> {
bitflags::bitflags! {
struct Flags: u8 {
const MACRO_RULES = 1 << 0;
@@ -397,11 +395,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
return Err(Determinacy::Determined);
}
- let (ns, macro_kind, is_import) = match scope_set {
- ScopeSet::All(ns, is_import) => (ns, None, is_import),
- ScopeSet::AbsolutePath(ns) => (ns, None, false),
- ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false),
- ScopeSet::Late(ns, ..) => (ns, None, false),
+ let (ns, macro_kind) = match scope_set {
+ ScopeSet::All(ns) => (ns, None),
+ ScopeSet::AbsolutePath(ns) => (ns, None),
+ ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
+ ScopeSet::Late(ns, ..) => (ns, None),
};
// This is *the* result, resolution from the scope closest to the resolved identifier.
@@ -415,7 +413,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// }
// So we have to save the innermost solution and continue searching in outer scopes
// to detect potential ambiguities.
- let mut innermost_result: Option<(&NameBinding<'_>, Flags)> = None;
+ let mut innermost_result: Option<(NameBinding<'_>, Flags)> = None;
let mut determinacy = Determinacy::Determined;
// Go through all the scopes and try to resolve the name.
@@ -538,7 +536,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
),
);
}
- let misc_flags = if ptr::eq(module, this.graph_root) {
+ let misc_flags = if module == this.graph_root {
Flags::MISC_SUGGEST_CRATE
} else if module.is_normal() {
Flags::MISC_SUGGEST_SELF
@@ -631,9 +629,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let derive_helper_compat =
Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat);
- let ambiguity_error_kind = if is_import {
- Some(AmbiguityKind::Import)
- } else if is_builtin(innermost_res) || is_builtin(res) {
+ let ambiguity_error_kind = if is_builtin(innermost_res)
+ || is_builtin(res)
+ {
Some(AmbiguityKind::BuiltinAttr)
} else if innermost_res == derive_helper_compat
|| res == derive_helper_compat && innermost_res != derive_helper
@@ -717,7 +715,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ident: Ident,
ns: Namespace,
parent_scope: &ParentScope<'a>,
- ) -> Result<&'a NameBinding<'a>, Determinacy> {
+ ) -> Result<NameBinding<'a>, Determinacy> {
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None)
.map_err(|(determinacy, _)| determinacy)
}
@@ -730,8 +728,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ns: Namespace,
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
- ignore_binding: Option<&'a NameBinding<'a>>,
- ) -> Result<&'a NameBinding<'a>, Determinacy> {
+ ignore_binding: Option<NameBinding<'a>>,
+ ) -> Result<NameBinding<'a>, Determinacy> {
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, finalize, ignore_binding)
.map_err(|(determinacy, _)| determinacy)
}
@@ -744,8 +742,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ns: Namespace,
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
- ignore_binding: Option<&'a NameBinding<'a>>,
- ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
+ ignore_binding: Option<NameBinding<'a>>,
+ ) -> Result<NameBinding<'a>, (Determinacy, Weak)> {
let tmp_parent_scope;
let mut adjusted_parent_scope = parent_scope;
match module {
@@ -782,8 +780,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ns: Namespace,
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
- ignore_binding: Option<&'a NameBinding<'a>>,
- ) -> Result<&'a NameBinding<'a>, Determinacy> {
+ ignore_binding: Option<NameBinding<'a>>,
+ ) -> Result<NameBinding<'a>, Determinacy> {
self.resolve_ident_in_module_unadjusted_ext(
module,
ident,
@@ -809,8 +807,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
finalize: Option<Finalize>,
// This binding should be ignored during in-module resolution, so that we don't get
// "self-confirming" import resolutions during import validation and checking.
- ignore_binding: Option<&'a NameBinding<'a>>,
- ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
+ ignore_binding: Option<NameBinding<'a>>,
+ ) -> Result<NameBinding<'a>, (Determinacy, Weak)> {
let module = match module {
ModuleOrUniformRoot::Module(module) => module,
ModuleOrUniformRoot::CrateRootAndExternPrelude => {
@@ -853,10 +851,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
- let scopes = ScopeSet::All(ns, true);
let binding = self.early_resolve_ident_in_lexical_scope(
ident,
- scopes,
+ ScopeSet::All(ns),
parent_scope,
finalize,
finalize.is_some(),
@@ -874,13 +871,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// binding if it exists. What we really want here is having two separate scopes in
// a module - one for non-globs and one for globs, but until that's done use this
// hack to avoid inconsistent resolution ICEs during import validation.
- let binding =
- [resolution.binding, resolution.shadowed_glob].into_iter().find_map(|binding| {
- match (binding, ignore_binding) {
- (Some(binding), Some(ignored)) if ptr::eq(binding, ignored) => None,
- _ => binding,
- }
- });
+ let binding = [resolution.binding, resolution.shadowed_glob]
+ .into_iter()
+ .find_map(|binding| if binding == ignore_binding { None } else { binding });
if let Some(Finalize { path_span, report_private, .. }) = finalize {
let Some(binding) = binding else {
@@ -893,6 +886,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ident,
binding,
dedup_span: path_span,
+ outermost_res: None,
+ parent_scope: *parent_scope,
});
} else {
return Err((Determined, Weak::No));
@@ -916,11 +911,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
if !restricted_shadowing && binding.expansion != LocalExpnId::ROOT {
- if let NameBindingKind::Import {
- import: Import { kind: ImportKind::MacroExport, .. },
- ..
- } = binding.kind
- {
+ if let NameBindingKind::Import { import, .. } = binding.kind
+ && matches!(import.kind, ImportKind::MacroExport) {
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
}
}
@@ -929,7 +921,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
return Ok(binding);
}
- let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
+ let check_usable = |this: &mut Self, binding: NameBinding<'a>| {
let usable = this.is_accessible_from(binding.vis, parent_scope.module);
if usable { Ok(binding) } else { Err((Determined, Weak::No)) }
};
@@ -954,7 +946,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
if let Some(ignored) = ignore_binding &&
let NameBindingKind::Import { import, .. } = ignored.kind &&
- ptr::eq(import, &**single_import) {
+ import == *single_import {
// Ignore not just the binding itself, but if it has a shadowed_glob,
// ignore that, too, because this loop is supposed to only process
// named imports.
@@ -1351,7 +1343,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
opt_ns: Option<Namespace>, // `None` indicates a module path in import
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
- ignore_binding: Option<&'a NameBinding<'a>>,
+ ignore_binding: Option<NameBinding<'a>>,
) -> PathResult<'a> {
self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, ignore_binding)
}
@@ -1363,22 +1355,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
- ignore_binding: Option<&'a NameBinding<'a>>,
+ ignore_binding: Option<NameBinding<'a>>,
) -> PathResult<'a> {
- debug!(
- "resolve_path(path={:?}, opt_ns={:?}, finalize={:?}) path_len: {}",
- path,
- opt_ns,
- finalize,
- path.len()
- );
-
let mut module = None;
let mut allow_super = true;
let mut second_binding = None;
- for (i, &Segment { ident, id, .. }) in path.iter().enumerate() {
- debug!("resolve_path ident {} {:?} {:?}", i, ident, id);
+ // We'll provide more context to the privacy errors later, up to `len`.
+ let privacy_errors_len = self.privacy_errors.len();
+
+ for (segment_idx, &Segment { ident, id, .. }) in path.iter().enumerate() {
+ debug!("resolve_path ident {} {:?} {:?}", segment_idx, ident, id);
let record_segment_res = |this: &mut Self, res| {
if finalize.is_some() {
if let Some(id) = id {
@@ -1390,7 +1377,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
};
- let is_last = i + 1 == path.len();
+ let is_last = segment_idx + 1 == path.len();
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
let name = ident.name;
@@ -1399,7 +1386,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if ns == TypeNS {
if allow_super && name == kw::Super {
let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();
- let self_module = match i {
+ let self_module = match segment_idx {
0 => Some(self.resolve_self(&mut ctxt, parent_scope.module)),
_ => match module {
Some(ModuleOrUniformRoot::Module(module)) => Some(module),
@@ -1414,11 +1401,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
continue;
}
}
- return PathResult::failed(ident.span, false, finalize.is_some(), || {
- ("there are too many leading `super` keywords".to_string(), None)
- });
+ return PathResult::failed(
+ ident.span,
+ false,
+ finalize.is_some(),
+ module,
+ || ("there are too many leading `super` keywords".to_string(), None),
+ );
}
- if i == 0 {
+ if segment_idx == 0 {
if name == kw::SelfLower {
let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();
module = Some(ModuleOrUniformRoot::Module(
@@ -1447,14 +1438,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
// Report special messages for path segment keywords in wrong positions.
- if ident.is_path_segment_keyword() && i != 0 {
- return PathResult::failed(ident.span, false, finalize.is_some(), || {
+ if ident.is_path_segment_keyword() && segment_idx != 0 {
+ return PathResult::failed(ident.span, false, finalize.is_some(), module, || {
let name_str = if name == kw::PathRoot {
"crate root".to_string()
} else {
format!("`{}`", name)
};
- let label = if i == 1 && path[0].ident.name == kw::PathRoot {
+ let label = if segment_idx == 1 && path[0].ident.name == kw::PathRoot {
format!("global paths cannot start with {}", name_str)
} else {
format!("{} in paths can only be used in start position", name_str)
@@ -1463,66 +1454,61 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
});
}
- enum FindBindingResult<'a> {
- Binding(Result<&'a NameBinding<'a>, Determinacy>),
- Res(Res),
- }
- let find_binding_in_ns = |this: &mut Self, ns| {
- let binding = if let Some(module) = module {
- this.resolve_ident_in_module(
- module,
- ident,
- ns,
- parent_scope,
- finalize,
- ignore_binding,
- )
- } else if let Some(ribs) = ribs
- && let Some(TypeNS | ValueNS) = opt_ns
- {
- match this.resolve_ident_in_lexical_scope(
- ident,
- ns,
- parent_scope,
- finalize,
- &ribs[ns],
- ignore_binding,
- ) {
- // we found a locally-imported or available item/module
- Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
- // we found a local variable or type param
- Some(LexicalScopeBinding::Res(res)) => return FindBindingResult::Res(res),
- _ => Err(Determinacy::determined(finalize.is_some())),
+ let binding = if let Some(module) = module {
+ self.resolve_ident_in_module(
+ module,
+ ident,
+ ns,
+ parent_scope,
+ finalize,
+ ignore_binding,
+ )
+ } else if let Some(ribs) = ribs && let Some(TypeNS | ValueNS) = opt_ns {
+ match self.resolve_ident_in_lexical_scope(
+ ident,
+ ns,
+ parent_scope,
+ finalize,
+ &ribs[ns],
+ ignore_binding,
+ ) {
+ // we found a locally-imported or available item/module
+ Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
+ // we found a local variable or type param
+ Some(LexicalScopeBinding::Res(res)) => {
+ record_segment_res(self, res);
+ return PathResult::NonModule(PartialRes::with_unresolved_segments(
+ res,
+ path.len() - 1,
+ ));
}
- } else {
- let scopes = ScopeSet::All(ns, opt_ns.is_none());
- this.early_resolve_ident_in_lexical_scope(
- ident,
- scopes,
- parent_scope,
- finalize,
- finalize.is_some(),
- ignore_binding,
- )
- };
- FindBindingResult::Binding(binding)
- };
- let binding = match find_binding_in_ns(self, ns) {
- FindBindingResult::Res(res) => {
- record_segment_res(self, res);
- return PathResult::NonModule(PartialRes::with_unresolved_segments(
- res,
- path.len() - 1,
- ));
+ _ => Err(Determinacy::determined(finalize.is_some())),
}
- FindBindingResult::Binding(binding) => binding,
+ } else {
+ self.early_resolve_ident_in_lexical_scope(
+ ident,
+ ScopeSet::All(ns),
+ parent_scope,
+ finalize,
+ finalize.is_some(),
+ ignore_binding,
+ )
};
+
match binding {
Ok(binding) => {
- if i == 1 {
+ if segment_idx == 1 {
second_binding = Some(binding);
}
let res = binding.res();
+
+ // Mark every privacy error in this path with the res to the last element. This allows us
+ // to detect the item the user cares about and either find an alternative import, or tell
+ // the user it is not accessible.
+ for error in &mut self.privacy_errors[privacy_errors_len..] {
+ error.outermost_res = Some((res, ident));
+ }
+
let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res);
if let Some(next_module) = binding.module() {
module = Some(ModuleOrUniformRoot::Module(next_module));
@@ -1543,17 +1529,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
record_segment_res(self, res);
return PathResult::NonModule(PartialRes::with_unresolved_segments(
res,
- path.len() - i - 1,
+ path.len() - segment_idx - 1,
));
} else {
- return PathResult::failed(ident.span, is_last, finalize.is_some(), || {
- let label = format!(
- "`{ident}` is {} {}, not a module",
- res.article(),
- res.descr()
- );
- (label, None)
- });
+ return PathResult::failed(
+ ident.span,
+ is_last,
+ finalize.is_some(),
+ module,
+ || {
+ let label = format!(
+ "`{ident}` is {} {}, not a module",
+ res.article(),
+ res.descr()
+ );
+ (label, None)
+ },
+ );
}
}
Err(Undetermined) => return PathResult::Indeterminate,
@@ -1562,23 +1554,29 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if opt_ns.is_some() && !module.is_normal() {
return PathResult::NonModule(PartialRes::with_unresolved_segments(
module.res().unwrap(),
- path.len() - i,
+ path.len() - segment_idx,
));
}
}
- return PathResult::failed(ident.span, is_last, finalize.is_some(), || {
- self.report_path_resolution_error(
- path,
- opt_ns,
- parent_scope,
- ribs,
- ignore_binding,
- module,
- i,
- ident,
- )
- });
+ return PathResult::failed(
+ ident.span,
+ is_last,
+ finalize.is_some(),
+ module,
+ || {
+ self.report_path_resolution_error(
+ path,
+ opt_ns,
+ parent_scope,
+ ribs,
+ ignore_binding,
+ module,
+ segment_idx,
+ ident,
+ )
+ },
+ );
}
}
}
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 7c4c05d4b..d37fe783b 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -1,15 +1,18 @@
//! A bunch of methods and structures more or less related to resolving imports.
use crate::diagnostics::{import_candidates, DiagnosticMode, Suggestion};
+use crate::errors::{
+ CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
+ CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates,
+ ConsiderAddingMacroExport, ConsiderMarkingAsPub, IsNotDirectlyImportable,
+ ItemsInTraitsAreNotImportable,
+};
use crate::Determinacy::{self, *};
-use crate::Namespace::*;
+use crate::{fluent_generated as fluent, Namespace::*};
use crate::{module_to_string, names_to_string, ImportSuggestion};
-use crate::{
- AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, ModuleKind, ResolutionError,
- Resolver, Segment,
-};
+use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment};
use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet};
-use crate::{NameBinding, NameBindingKind, PathResult};
+use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult};
use rustc_ast::NodeId;
use rustc_data_structures::fx::FxHashSet;
@@ -21,7 +24,8 @@ use rustc_middle::metadata::Reexport;
use rustc_middle::span_bug;
use rustc_middle::ty;
use rustc_session::lint::builtin::{
- AMBIGUOUS_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS,
+ AMBIGUOUS_GLOB_REEXPORTS, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE,
+ UNUSED_IMPORTS,
};
use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_span::edit_distance::find_best_match_for_name;
@@ -31,7 +35,7 @@ use rustc_span::Span;
use smallvec::SmallVec;
use std::cell::Cell;
-use std::{mem, ptr};
+use std::mem;
type Res = def::Res<NodeId>;
@@ -44,9 +48,9 @@ pub(crate) enum ImportKind<'a> {
/// `target` in `use prefix::source as target`.
target: Ident,
/// Bindings to which `source` refers to.
- source_bindings: PerNS<Cell<Result<&'a NameBinding<'a>, Determinacy>>>,
+ source_bindings: PerNS<Cell<Result<NameBinding<'a>, Determinacy>>>,
/// Bindings introduced by `target`.
- target_bindings: PerNS<Cell<Option<&'a NameBinding<'a>>>>,
+ target_bindings: PerNS<Cell<Option<NameBinding<'a>>>>,
/// `true` for `...::{self [as target]}` imports, `false` otherwise.
type_ns_only: bool,
/// Did this import result from a nested import? ie. `use foo::{bar, baz};`
@@ -131,7 +135,7 @@ impl<'a> std::fmt::Debug for ImportKind<'a> {
/// One import.
#[derive(Debug, Clone)]
-pub(crate) struct Import<'a> {
+pub(crate) struct ImportData<'a> {
pub kind: ImportKind<'a>,
/// Node ID of the "root" use item -- this is always the same as `ImportKind`'s `id`
@@ -168,7 +172,11 @@ pub(crate) struct Import<'a> {
pub used: Cell<bool>,
}
-impl<'a> Import<'a> {
+/// All imports are unique and allocated on a same arena,
+/// so we can use referential equality to compare them.
+pub(crate) type Import<'a> = Interned<'a, ImportData<'a>>;
+
+impl<'a> ImportData<'a> {
pub(crate) fn is_glob(&self) -> bool {
matches!(self.kind, ImportKind::Glob { .. })
}
@@ -210,15 +218,15 @@ impl<'a> Import<'a> {
pub(crate) struct NameResolution<'a> {
/// Single imports that may define the name in the namespace.
/// Imports are arena-allocated, so it's ok to use pointers as keys.
- pub single_imports: FxHashSet<Interned<'a, Import<'a>>>,
+ pub single_imports: FxHashSet<Import<'a>>,
/// The least shadowable known binding for this name, or None if there are no known bindings.
- pub binding: Option<&'a NameBinding<'a>>,
- pub shadowed_glob: Option<&'a NameBinding<'a>>,
+ pub binding: Option<NameBinding<'a>>,
+ pub shadowed_glob: Option<NameBinding<'a>>,
}
impl<'a> NameResolution<'a> {
/// 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>> {
+ pub(crate) fn binding(&self) -> Option<NameBinding<'a>> {
self.binding.and_then(|binding| {
if !binding.is_glob_import() || self.single_imports.is_empty() {
Some(binding)
@@ -227,10 +235,6 @@ impl<'a> NameResolution<'a> {
}
})
}
-
- pub(crate) fn add_single_import(&mut self, import: &'a Import<'a>) {
- self.single_imports.insert(Interned::new_unchecked(import));
- }
}
/// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved
@@ -246,15 +250,12 @@ struct UnresolvedImportError {
// Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;`
// are permitted for backward-compatibility under a deprecation lint.
-fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBinding<'_>) -> bool {
+fn pub_use_of_private_extern_crate_hack(import: Import<'_>, binding: NameBinding<'_>) -> bool {
match (&import.kind, &binding.kind) {
- (
- ImportKind::Single { .. },
- NameBindingKind::Import {
- import: Import { kind: ImportKind::ExternCrate { .. }, .. },
- ..
- },
- ) => import.expect_vis().is_public(),
+ (ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. }) => {
+ matches!(binding_import.kind, ImportKind::ExternCrate { .. })
+ && import.expect_vis().is_public()
+ }
_ => false,
}
}
@@ -262,11 +263,7 @@ fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBindi
impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// 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>,
- import: &'a Import<'a>,
- ) -> &'a NameBinding<'a> {
+ pub(crate) fn import(&self, binding: NameBinding<'a>, import: Import<'a>) -> NameBinding<'a> {
let import_vis = import.expect_vis().to_def_id();
let vis = if binding.vis.is_at_least(import_vis, self.tcx)
|| pub_use_of_private_extern_crate_hack(import, binding)
@@ -284,7 +281,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
- self.arenas.alloc_name_binding(NameBinding {
+ self.arenas.alloc_name_binding(NameBindingData {
kind: NameBindingKind::Import { binding, import, used: Cell::new(false) },
ambiguity: None,
span: import.span,
@@ -298,8 +295,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&mut self,
module: Module<'a>,
key: BindingKey,
- binding: &'a NameBinding<'a>,
- ) -> Result<(), &'a NameBinding<'a>> {
+ binding: NameBinding<'a>,
+ ) -> Result<(), NameBinding<'a>> {
let res = binding.res();
self.check_reserved_macro_name(key.ident, res);
self.set_binding_parent_module(binding, module);
@@ -337,7 +334,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} else {
resolution.binding = Some(nonglob_binding);
}
- resolution.shadowed_glob = Some(glob_binding);
+
+ if let Some(old_binding) = resolution.shadowed_glob {
+ assert!(old_binding.is_glob_import());
+ if glob_binding.res() != old_binding.res() {
+ resolution.shadowed_glob = Some(this.ambiguity(
+ AmbiguityKind::GlobVsGlob,
+ old_binding,
+ glob_binding,
+ ));
+ } else if !old_binding.vis.is_at_least(binding.vis, this.tcx) {
+ resolution.shadowed_glob = Some(glob_binding);
+ }
+ } else {
+ resolution.shadowed_glob = Some(glob_binding);
+ }
}
(false, false) => {
return Err(old_binding);
@@ -354,12 +365,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
fn ambiguity(
&self,
kind: AmbiguityKind,
- primary_binding: &'a NameBinding<'a>,
- secondary_binding: &'a NameBinding<'a>,
- ) -> &'a NameBinding<'a> {
- self.arenas.alloc_name_binding(NameBinding {
+ primary_binding: NameBinding<'a>,
+ secondary_binding: NameBinding<'a>,
+ ) -> NameBinding<'a> {
+ self.arenas.alloc_name_binding(NameBindingData {
ambiguity: Some((secondary_binding, kind)),
- ..primary_binding.clone()
+ ..(*primary_binding).clone()
})
}
@@ -377,13 +388,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let t = f(self, resolution);
- match resolution.binding() {
- _ if old_binding.is_some() => return t,
- None => return t,
- Some(binding) => match old_binding {
- Some(old_binding) if ptr::eq(old_binding, binding) => return t,
- _ => (binding, t),
- },
+ if old_binding.is_none() && let Some(binding) = resolution.binding() {
+ (binding, t)
+ } else {
+ return t;
}
};
@@ -396,7 +404,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None => continue,
};
if self.is_accessible_from(binding.vis, scope) {
- let imported_binding = self.import(binding, import);
+ let imported_binding = self.import(binding, *import);
let key = BindingKey { ident, ..key };
let _ = self.try_define(import.parent_scope.module, key, imported_binding);
}
@@ -407,7 +415,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// Define a dummy resolution containing a `Res::Err` as a placeholder for a failed
// or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics.
- fn import_dummy_binding(&mut self, import: &'a Import<'a>, is_indeterminate: bool) {
+ fn import_dummy_binding(&mut self, import: Import<'a>, is_indeterminate: bool) {
if let ImportKind::Single { target, ref target_bindings, .. } = import.kind {
if !(is_indeterminate || target_bindings.iter().all(|binding| binding.get().is_none()))
{
@@ -445,7 +453,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
prev_indeterminate_count = indeterminate_count;
indeterminate_count = 0;
for import in mem::take(&mut self.indeterminate_imports) {
- let import_indeterminate_count = self.resolve_import(&import);
+ let import_indeterminate_count = self.resolve_import(import);
indeterminate_count += import_indeterminate_count;
match import_indeterminate_count {
0 => self.determined_imports.push(import),
@@ -457,7 +465,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
pub(crate) fn finalize_imports(&mut self) {
for module in self.arenas.local_modules().iter() {
- self.finalize_resolutions_in(module);
+ self.finalize_resolutions_in(*module);
}
let mut seen_spans = FxHashSet::default();
@@ -526,35 +534,75 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
- pub(crate) fn check_reexport_ambiguities(
+ pub(crate) fn check_hidden_glob_reexports(
&mut self,
- exported_ambiguities: FxHashSet<Interned<'a, NameBinding<'a>>>,
+ exported_ambiguities: FxHashSet<NameBinding<'a>>,
) {
for module in self.arenas.local_modules().iter() {
- module.for_each_child(self, |this, ident, ns, binding| {
- if let NameBindingKind::Import { import, .. } = binding.kind
- && let Some((amb_binding, _)) = binding.ambiguity
- && binding.res() != Res::Err
- && exported_ambiguities.contains(&Interned::new_unchecked(binding))
- {
- this.lint_buffer.buffer_lint_with_diagnostic(
- AMBIGUOUS_GLOB_REEXPORTS,
- import.root_id,
- import.root_span,
- "ambiguous glob re-exports",
- BuiltinLintDiagnostics::AmbiguousGlobReexports {
- name: ident.to_string(),
- namespace: ns.descr().to_string(),
- first_reexport_span: import.root_span,
- duplicate_reexport_span: amb_binding.span,
- },
- );
+ for (key, resolution) in self.resolutions(*module).borrow().iter() {
+ let resolution = resolution.borrow();
+
+ if let Some(binding) = resolution.binding {
+ if let NameBindingKind::Import { import, .. } = binding.kind
+ && let Some((amb_binding, _)) = binding.ambiguity
+ && binding.res() != Res::Err
+ && exported_ambiguities.contains(&binding)
+ {
+ self.lint_buffer.buffer_lint_with_diagnostic(
+ AMBIGUOUS_GLOB_REEXPORTS,
+ import.root_id,
+ import.root_span,
+ "ambiguous glob re-exports",
+ BuiltinLintDiagnostics::AmbiguousGlobReexports {
+ name: key.ident.to_string(),
+ namespace: key.ns.descr().to_string(),
+ first_reexport_span: import.root_span,
+ duplicate_reexport_span: amb_binding.span,
+ },
+ );
+ }
+
+ if let Some(glob_binding) = resolution.shadowed_glob {
+ let binding_id = match binding.kind {
+ NameBindingKind::Res(res) => {
+ Some(self.def_id_to_node_id[res.def_id().expect_local()])
+ }
+ NameBindingKind::Module(module) => {
+ Some(self.def_id_to_node_id[module.def_id().expect_local()])
+ }
+ NameBindingKind::Import { import, .. } => import.id(),
+ };
+
+ if binding.res() != Res::Err
+ && glob_binding.res() != Res::Err
+ && let NameBindingKind::Import { import: glob_import, .. } = glob_binding.kind
+ && let Some(binding_id) = binding_id
+ && let Some(glob_import_id) = glob_import.id()
+ && let glob_import_def_id = self.local_def_id(glob_import_id)
+ && self.effective_visibilities.is_exported(glob_import_def_id)
+ && glob_binding.vis.is_public()
+ && !binding.vis.is_public()
+ {
+ self.lint_buffer.buffer_lint_with_diagnostic(
+ HIDDEN_GLOB_REEXPORTS,
+ binding_id,
+ binding.span,
+ "private item shadows public glob re-export",
+ BuiltinLintDiagnostics::HiddenGlobReexports {
+ name: key.ident.name.to_string(),
+ namespace: key.ns.descr().to_owned(),
+ glob_reexport_span: glob_binding.span,
+ private_item_span: binding.span,
+ },
+ );
+ }
+ }
}
- });
+ }
}
}
- fn throw_unresolved_import_error(&self, errors: Vec<(&Import<'_>, UnresolvedImportError)>) {
+ fn throw_unresolved_import_error(&mut self, errors: Vec<(Import<'_>, UnresolvedImportError)>) {
if errors.is_empty() {
return;
}
@@ -624,6 +672,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
_ => {}
}
}
+
+ match &import.kind {
+ ImportKind::Single { source, .. } => {
+ if let Some(ModuleOrUniformRoot::Module(module)) = import.imported_module.get()
+ && let Some(module) = module.opt_def_id()
+ {
+ self.find_cfg_stripped(&mut diag, &source.name, module)
+ }
+ },
+ _ => {}
+ }
}
diag.emit();
@@ -635,7 +694,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
///
/// Meanwhile, if resolve successful, the resolved bindings are written
/// into the module.
- fn resolve_import(&mut self, import: &'a Import<'a>) -> usize {
+ fn resolve_import(&mut self, import: Import<'a>) -> usize {
debug!(
"(resolving import for module) resolving import `{}::...` in `{}`",
Segment::names_to_string(&import.module_path),
@@ -708,14 +767,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
source_binding @ (Ok(..) | Err(Determined)) => {
if source_binding.is_ok() {
- let msg = format!("`{}` is not directly importable", target);
- struct_span_err!(this.tcx.sess, import.span, E0253, "{}", &msg)
- .span_label(import.span, "cannot be imported directly")
+ this.tcx
+ .sess
+ .create_err(IsNotDirectlyImportable { span: import.span, target })
.emit();
}
let key = BindingKey::new(target, ns);
this.update_resolution(parent, key, |_, resolution| {
- resolution.single_imports.remove(&Interned::new_unchecked(import));
+ resolution.single_imports.remove(&import);
});
}
}
@@ -729,7 +788,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
///
/// Optionally returns an unresolved import error. This error is buffered and used to
/// consolidate multiple unresolved import errors into a single diagnostic.
- fn finalize_import(&mut self, import: &'a Import<'a>) -> Option<UnresolvedImportError> {
+ fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportError> {
let orig_vis = import.vis.take();
let ignore_binding = match &import.kind {
ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(),
@@ -737,6 +796,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
};
let prev_ambiguity_errors_len = self.ambiguity_errors.len();
let finalize = Finalize::with_root_span(import.root_id, import.span, import.root_span);
+
+ // We'll provide more context to the privacy errors later, up to `len`.
+ let privacy_errors_len = self.privacy_errors.len();
+
let path_res = self.resolve_path(
&import.module_path,
None,
@@ -751,25 +814,46 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
PathResult::Module(module) => {
// Consistency checks, analogous to `finalize_macro_resolutions`.
if let Some(initial_module) = import.imported_module.get() {
- if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity {
+ if module != initial_module && no_ambiguity {
span_bug!(import.span, "inconsistent resolution for an import");
}
} else if self.privacy_errors.is_empty() {
- let msg = "cannot determine resolution for the import";
- let msg_note = "import resolution is stuck, try simplifying other imports";
- self.tcx.sess.struct_span_err(import.span, msg).note(msg_note).emit();
+ self.tcx
+ .sess
+ .create_err(CannotDetermineImportResolution { span: import.span })
+ .emit();
}
module
}
- PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => {
+ PathResult::Failed {
+ is_error_from_last_segment: false,
+ span,
+ label,
+ suggestion,
+ module,
+ } => {
if no_ambiguity {
assert!(import.imported_module.get().is_none());
- self.report_error(span, ResolutionError::FailedToResolve { label, suggestion });
+ self.report_error(
+ span,
+ ResolutionError::FailedToResolve {
+ last_segment: None,
+ label,
+ suggestion,
+ module,
+ },
+ );
}
return None;
}
- PathResult::Failed { is_error_from_last_segment: true, span, label, suggestion } => {
+ PathResult::Failed {
+ is_error_from_last_segment: true,
+ span,
+ label,
+ suggestion,
+ ..
+ } => {
if no_ambiguity {
assert!(import.imported_module.get().is_none());
let err = match self.make_path_suggestion(
@@ -800,8 +884,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
return None;
}
- PathResult::NonModule(_) => {
- if no_ambiguity {
+ PathResult::NonModule(partial_res) => {
+ if no_ambiguity && partial_res.full_res() != Some(Res::Err) {
+ // Check if there are no ambiguities and the result is not dummy.
assert!(import.imported_module.get().is_none());
}
// The error was already reported earlier.
@@ -831,7 +916,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
if let ModuleOrUniformRoot::Module(module) = module {
- if ptr::eq(module, import.parent_scope.module) {
+ if module == import.parent_scope.module {
// Importing a module into itself is not allowed.
return Some(UnresolvedImportError {
span: import.span,
@@ -848,14 +933,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&& let Some(max_vis) = max_vis.get()
&& !max_vis.is_at_least(import.expect_vis(), self.tcx)
{
- let msg = "glob import doesn't reexport anything because no candidate is public enough";
- self.lint_buffer.buffer_lint(UNUSED_IMPORTS, id, import.span, msg);
+ self.lint_buffer.buffer_lint(UNUSED_IMPORTS, id, import.span, fluent::resolve_glob_import_doesnt_reexport);
}
return None;
}
_ => unreachable!(),
};
+ if self.privacy_errors.len() != privacy_errors_len {
+ // Get the Res for the last element, so that we can point to alternative ways of
+ // importing it if available.
+ let mut path = import.module_path.clone();
+ path.push(Segment::from_ident(ident));
+ if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
+ self.resolve_path(&path, None, &import.parent_scope, Some(finalize), ignore_binding)
+ {
+ let res = module.res().map(|r| (r, ident));
+ for error in &mut self.privacy_errors[privacy_errors_len..] {
+ error.outermost_res = res;
+ }
+ }
+ }
+
let mut all_ns_err = true;
self.per_ns(|this, ns| {
if !type_ns_only || ns == TypeNS {
@@ -873,7 +972,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
match binding {
Ok(binding) => {
// Consistency checks, analogous to `finalize_macro_resolutions`.
- let initial_binding = source_bindings[ns].get().map(|initial_binding| {
+ let initial_res = 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
@@ -887,29 +986,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
);
}
}
- initial_binding
+ initial_binding.res()
});
let res = binding.res();
- if let Ok(initial_binding) = initial_binding {
- let initial_res = initial_binding.res();
+ if let Ok(initial_res) = initial_res {
if res != initial_res && this.ambiguity_errors.is_empty() {
- this.ambiguity_errors.push(AmbiguityError {
- kind: AmbiguityKind::Import,
- ident,
- b1: initial_binding,
- b2: binding,
- misc1: AmbiguityErrorMisc::None,
- misc2: AmbiguityErrorMisc::None,
- });
+ span_bug!(import.span, "inconsistent resolution for an import");
}
} else if res != Res::Err
&& this.ambiguity_errors.is_empty()
&& this.privacy_errors.is_empty()
{
- let msg = "cannot determine resolution for the import";
- let msg_note =
- "import resolution is stuck, try simplifying other imports";
- this.tcx.sess.struct_span_err(import.span, msg).note(msg_note).emit();
+ this.tcx
+ .sess
+ .create_err(CannotDetermineImportResolution { span: import.span })
+ .emit();
}
}
Err(..) => {
@@ -1067,46 +1158,43 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
msg,
);
} else {
- let error_msg = if crate_private_reexport {
- format!(
- "`{}` is only public within the crate, and cannot be re-exported outside",
- ident
- )
- } else {
- format!("`{}` is private, and cannot be re-exported", ident)
- };
-
if ns == TypeNS {
- let label_msg = if crate_private_reexport {
- format!("re-export of crate public `{}`", ident)
+ let mut err = if crate_private_reexport {
+ self.tcx.sess.create_err(CannotBeReexportedCratePublicNS {
+ span: import.span,
+ ident,
+ })
} else {
- format!("re-export of private `{}`", ident)
+ self.tcx
+ .sess
+ .create_err(CannotBeReexportedPrivateNS { span: import.span, ident })
};
-
- struct_span_err!(self.tcx.sess, import.span, E0365, "{}", error_msg)
- .span_label(import.span, label_msg)
- .note(format!("consider declaring type or module `{}` with `pub`", ident))
- .emit();
+ err.emit();
} else {
- let mut err =
- struct_span_err!(self.tcx.sess, import.span, E0364, "{error_msg}");
+ let mut err = if crate_private_reexport {
+ self.tcx
+ .sess
+ .create_err(CannotBeReexportedCratePublic { span: import.span, ident })
+ } else {
+ self.tcx
+ .sess
+ .create_err(CannotBeReexportedPrivate { span: import.span, ident })
+ };
+
match binding.kind {
NameBindingKind::Res(Res::Def(DefKind::Macro(_), def_id))
// exclude decl_macro
if self.get_macro_by_def_id(def_id).macro_rules =>
{
- err.span_help(
- binding.span,
- "consider adding a `#[macro_export]` to the macro in the imported module",
- );
+ err.subdiagnostic(ConsiderAddingMacroExport {
+ span: binding.span,
+ });
}
_ => {
- err.span_note(
- import.span,
- format!(
- "consider marking `{ident}` as `pub` in the imported module"
- ),
- );
+ err.subdiagnostic(ConsiderMarkingAsPub {
+ span: import.span,
+ ident,
+ });
}
}
err.emit();
@@ -1144,9 +1232,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
fn check_for_redundant_imports(
&mut self,
ident: Ident,
- import: &'a Import<'a>,
- source_bindings: &PerNS<Cell<Result<&'a NameBinding<'a>, Determinacy>>>,
- target_bindings: &PerNS<Cell<Option<&'a NameBinding<'a>>>>,
+ import: Import<'a>,
+ source_bindings: &PerNS<Cell<Result<NameBinding<'a>, Determinacy>>>,
+ target_bindings: &PerNS<Cell<Option<NameBinding<'a>>>>,
target: Ident,
) {
// This function is only called for single imports.
@@ -1175,7 +1263,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
match this.early_resolve_ident_in_lexical_scope(
target,
- ScopeSet::All(ns, false),
+ ScopeSet::All(ns),
&import.parent_scope,
None,
false,
@@ -1207,19 +1295,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
- fn resolve_glob_import(&mut self, import: &'a Import<'a>) {
+ fn resolve_glob_import(&mut self, import: Import<'a>) {
// 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.tcx.sess.span_err(import.span, "cannot glob-import all possible crates");
+ self.tcx.sess.create_err(CannotGlobImportAllCrates {
+ span: import.span,
+ }).emit();
return;
};
if module.is_trait() {
- self.tcx.sess.span_err(import.span, "items in traits are not importable");
+ self.tcx.sess.create_err(ItemsInTraitsAreNotImportable { span: import.span }).emit();
return;
- } else if ptr::eq(module, import.parent_scope.module) {
+ } else if module == import.parent_scope.module {
return;
} else if is_prelude {
self.prelude = Some(module);
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index e06119076..90cb312ed 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -6,6 +6,7 @@
//! If you wonder why there's no `early.rs`, that's because it's split into three files -
//! `build_reduced_graph.rs`, `macros.rs` and `imports.rs`.
+use crate::errors::ImportsCannotReferTo;
use crate::BindingKey;
use crate::{path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding};
use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
@@ -1283,7 +1284,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
ident: Ident,
ns: Namespace,
finalize: Option<Finalize>,
- ignore_binding: Option<&'a NameBinding<'a>>,
+ ignore_binding: Option<NameBinding<'a>>,
) -> Option<LexicalScopeBinding<'a>> {
self.r.resolve_ident_in_lexical_scope(
ident,
@@ -1631,9 +1632,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
..
} = &rib.kind
{
- diag.span_help(
- *span,
- "consider introducing a higher-ranked lifetime here with `for<'a>`",
+ diag.multipart_suggestion(
+ "consider introducing a higher-ranked lifetime here",
+ vec![
+ (span.shrink_to_lo(), "for<'a> ".into()),
+ (lifetime.ident.span.shrink_to_hi(), "'a ".into()),
+ ],
+ Applicability::MachineApplicable,
);
break;
}
@@ -2244,12 +2249,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
_ => &[TypeNS],
};
let report_error = |this: &Self, ns| {
- let what = if ns == TypeNS { "type parameters" } else { "local variables" };
if this.should_report_errs() {
+ let what = if ns == TypeNS { "type parameters" } else { "local variables" };
this.r
.tcx
.sess
- .span_err(ident.span, format!("imports cannot refer to {}", what));
+ .create_err(ImportsCannotReferTo { span: ident.span, what })
+ .emit();
}
};
@@ -2966,7 +2972,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'a>,
{
// If there is a TraitRef in scope for an impl, then the method must be in the trait.
- let Some((module, _)) = &self.current_trait_ref else { return; };
+ let Some((module, _)) = self.current_trait_ref else { return; };
ident.span.normalize_to_macros_2_0_and_adjust(module.expansion);
let key = BindingKey::new(ident, ns);
let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
@@ -3497,7 +3503,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
let report_errors = |this: &mut Self, res: Option<Res>| {
if this.should_report_errs() {
let (err, candidates) =
- this.smart_resolve_report_errors(path, path_span, source, res);
+ this.smart_resolve_report_errors(path, path, path_span, source, res);
let def_id = this.parent_scope.module.nearest_parent_mod();
let instead = res.is_some();
@@ -3524,7 +3530,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
None
};
- this.r.use_injections.push(UseError {
+ let ue = UseError {
err,
candidates,
def_id,
@@ -3532,7 +3538,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
suggestion,
path: path.into(),
is_call: source.is_call(),
- });
+ };
+
+ this.r.use_injections.push(ue);
}
PartialRes::new(Res::Err)
@@ -3552,8 +3560,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
_ => return Some(parent_err),
};
- let (mut err, candidates) =
- this.smart_resolve_report_errors(prefix_path, path_span, PathSource::Type, None);
+ let (mut err, candidates) = this.smart_resolve_report_errors(
+ prefix_path,
+ path,
+ path_span,
+ PathSource::Type,
+ None,
+ );
// There are two different error messages user might receive at
// this point:
@@ -3866,8 +3879,22 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
PartialRes::new(module.res().unwrap())
}
- PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => {
- return Err(respan(span, ResolutionError::FailedToResolve { label, suggestion }));
+ PathResult::Failed {
+ is_error_from_last_segment: false,
+ span,
+ label,
+ suggestion,
+ module,
+ } => {
+ return Err(respan(
+ span,
+ ResolutionError::FailedToResolve {
+ last_segment: None,
+ label,
+ suggestion,
+ module,
+ },
+ ));
}
PathResult::Module(..) | PathResult::Failed { .. } => return Ok(None),
PathResult::Indeterminate => bug!("indeterminate path result in resolve_qpath"),
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index df6582580..c0e3f1aaf 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -4,20 +4,20 @@ use crate::late::{LifetimeBinderKind, LifetimeRes, LifetimeRibKind, LifetimeUseS
use crate::{errors, path_names_to_string};
use crate::{Module, ModuleKind, ModuleOrUniformRoot};
use crate::{PathResult, PathSource, Segment};
+use rustc_hir::def::Namespace::{self, *};
use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt};
use rustc_ast::{
self as ast, AssocItemKind, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind,
MethodCall, NodeId, Path, Ty, TyKind, DUMMY_NODE_ID,
};
-use rustc_ast_pretty::pprust::path_segment_to_string;
+use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
MultiSpan,
};
use rustc_hir as hir;
-use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::PrimTy;
@@ -29,6 +29,7 @@ use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
+use std::borrow::Cow;
use std::iter;
use std::ops::Deref;
@@ -148,6 +149,7 @@ struct BaseError {
span_label: Option<(Span, &'static str)>,
could_be_expr: bool,
suggestion: Option<(Span, &'static str, String)>,
+ module: Option<DefId>,
}
#[derive(Debug)]
@@ -209,19 +211,24 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
_ => false,
},
suggestion: None,
+ module: None,
}
} else {
let item_span = path.last().unwrap().ident.span;
- let (mod_prefix, mod_str, suggestion) = if path.len() == 1 {
+ let (mod_prefix, mod_str, module, suggestion) = if path.len() == 1 {
debug!(?self.diagnostic_metadata.current_impl_items);
debug!(?self.diagnostic_metadata.current_function);
let suggestion = if self.current_trait_ref.is_none()
&& let Some((fn_kind, _)) = self.diagnostic_metadata.current_function
&& let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt()
+ && let FnKind::Fn(_, _, sig, ..) = fn_kind
&& let Some(items) = self.diagnostic_metadata.current_impl_items
&& let Some(item) = items.iter().find(|i| {
if let AssocItemKind::Fn(..) | AssocItemKind::Const(..) = &i.kind
&& i.ident.name == item_str.name
+ // don't suggest if the item is in Fn signature arguments
+ // issue #112590
+ && !sig.span.contains(item_span)
{
debug!(?item_str.name);
return true
@@ -246,26 +253,37 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
} else {
None
};
- (String::new(), "this scope".to_string(), suggestion)
+ (String::new(), "this scope".to_string(), None, suggestion)
} else if path.len() == 2 && path[0].ident.name == kw::PathRoot {
if self.r.tcx.sess.edition() > Edition::Edition2015 {
// In edition 2018 onwards, the `::foo` syntax may only pull from the extern prelude
// which overrides all other expectations of item type
expected = "crate";
- (String::new(), "the list of imported crates".to_string(), None)
+ (String::new(), "the list of imported crates".to_string(), None, None)
} else {
- (String::new(), "the crate root".to_string(), None)
+ (
+ String::new(),
+ "the crate root".to_string(),
+ Some(CRATE_DEF_ID.to_def_id()),
+ None,
+ )
}
} else if path.len() == 2 && path[0].ident.name == kw::Crate {
- (String::new(), "the crate root".to_string(), None)
+ (String::new(), "the crate root".to_string(), Some(CRATE_DEF_ID.to_def_id()), None)
} else {
let mod_path = &path[..path.len() - 1];
- let mod_prefix = match self.resolve_path(mod_path, Some(TypeNS), None) {
+ let mod_res = self.resolve_path(mod_path, Some(TypeNS), None);
+ let mod_prefix = match mod_res {
PathResult::Module(ModuleOrUniformRoot::Module(module)) => module.res(),
_ => None,
- }
- .map_or_else(String::new, |res| format!("{} ", res.descr()));
- (mod_prefix, format!("`{}`", Segment::names_to_string(mod_path)), None)
+ };
+
+ let module_did = mod_prefix.as_ref().and_then(Res::mod_def_id);
+
+ let mod_prefix =
+ mod_prefix.map_or_else(String::new, |res| (format!("{} ", res.descr())));
+
+ (mod_prefix, format!("`{}`", Segment::names_to_string(mod_path)), module_did, None)
};
let (fallback_label, suggestion) = if path_str == "async"
@@ -299,21 +317,68 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
span_label: None,
could_be_expr: false,
suggestion,
+ module,
}
}
}
+ /// Try to suggest for a module path that cannot be resolved.
+ /// Such as `fmt::Debug` where `fmt` is not resolved without importing,
+ /// here we search with `lookup_import_candidates` for a module named `fmt`
+ /// with `TypeNS` as namespace.
+ ///
+ /// We need a separate function here because we won't suggest for a path with single segment
+ /// and we won't change `SourcePath` api `is_expected` to match `Type` with `DefKind::Mod`
+ pub(crate) fn smart_resolve_partial_mod_path_errors(
+ &mut self,
+ prefix_path: &[Segment],
+ path: &[Segment],
+ ) -> Vec<ImportSuggestion> {
+ let next_seg = if path.len() >= prefix_path.len() + 1 && prefix_path.len() == 1 {
+ path.get(prefix_path.len())
+ } else {
+ None
+ };
+ if let Some(segment) = prefix_path.last() &&
+ let Some(next_seg) = next_seg {
+ let candidates = self.r.lookup_import_candidates(
+ segment.ident,
+ Namespace::TypeNS,
+ &self.parent_scope,
+ &|res: Res| matches!(res, Res::Def(DefKind::Mod, _)),
+ );
+ // double check next seg is valid
+ candidates
+ .into_iter()
+ .filter(|candidate| {
+ if let Some(def_id) = candidate.did &&
+ let Some(module) = self.r.get_module(def_id) {
+ self.r.resolutions(module).borrow().iter().any(|(key, _r)| {
+ key.ident.name == next_seg.ident.name
+ })
+ } else {
+ false
+ }
+ })
+ .collect::<Vec<_>>()
+ } else {
+ Vec::new()
+ }
+ }
+
/// Handles error reporting for `smart_resolve_path_fragment` function.
/// Creates base error and amends it with one short label and possibly some longer helps/notes.
pub(crate) fn smart_resolve_report_errors(
&mut self,
path: &[Segment],
+ full_path: &[Segment],
span: Span,
source: PathSource<'_>,
res: Option<Res>,
) -> (DiagnosticBuilder<'tcx, ErrorGuaranteed>, Vec<ImportSuggestion>) {
debug!(?res, ?source);
let base_error = self.make_base_error(path, span, source, res);
+
let code = source.error_code(res.is_some());
let mut err = self.r.tcx.sess.struct_span_err_with_code(
base_error.span,
@@ -348,7 +413,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
let (found, candidates) =
- self.try_lookup_name_relaxed(&mut err, source, path, span, res, &base_error);
+ self.try_lookup_name_relaxed(&mut err, source, path, full_path, span, res, &base_error);
if found {
return (err, candidates);
}
@@ -365,6 +430,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
self.err_code_special_cases(&mut err, source, path, span);
+ if let Some(module) = base_error.module {
+ self.r.find_cfg_stripped(&mut err, &path.last().unwrap().ident.name, module);
+ }
+
(err, candidates)
}
@@ -450,6 +519,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
err: &mut Diagnostic,
source: PathSource<'_>,
path: &[Segment],
+ full_path: &[Segment],
span: Span,
res: Option<Res>,
base_error: &BaseError,
@@ -476,7 +546,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
// Try to filter out intrinsics candidates, as long as we have
// some other candidates to suggest.
let intrinsic_candidates: Vec<_> = candidates
- .drain_filter(|sugg| {
+ .extract_if(|sugg| {
let path = path_names_to_string(&sugg.path);
path.starts_with("core::intrinsics::") || path.starts_with("std::intrinsics::")
})
@@ -619,6 +689,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
}
+ if candidates.is_empty() {
+ candidates = self.smart_resolve_partial_mod_path_errors(path, full_path);
+ }
+
return (false, candidates);
}
@@ -1030,7 +1104,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
};
// Confirm that the target is an associated type.
- let (ty, position, path) = if let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind {
+ let (ty, _, 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;
@@ -1059,7 +1133,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
return false;
}
if let (
- [ast::PathSegment { ident: constrain_ident, args: None, .. }],
+ [ast::PathSegment { args: None, .. }],
[ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifier::None)],
) = (&type_param_path.segments[..], &bounds[..])
{
@@ -1067,29 +1141,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
&poly_trait_ref.trait_ref.path.segments[..]
{
if ident.span == span {
+ let Some(new_where_bound_predicate) = mk_where_bound_predicate(path, poly_trait_ref, ty) else { return false; };
err.span_suggestion_verbose(
*where_span,
format!("constrain the associated type to `{}`", ident),
- format!(
- "{}: {}<{} = {}>",
- self.r
- .tcx
- .sess
- .source_map()
- .span_to_snippet(ty.span) // Account for `<&'a T as Foo>::Bar`.
- .unwrap_or_else(|_| constrain_ident.to_string()),
- path.segments[..position]
- .iter()
- .map(|segment| path_segment_to_string(segment))
- .collect::<Vec<_>>()
- .join("::"),
- path.segments[position..]
- .iter()
- .map(|segment| path_segment_to_string(segment))
- .collect::<Vec<_>>()
- .join("::"),
- ident,
- ),
+ where_bound_predicate_to_string(&new_where_bound_predicate),
Applicability::MaybeIncorrect,
);
}
@@ -1248,7 +1304,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}),
) if followed_by_brace => {
if let Some(sp) = closing_brace {
- err.span_label(span, fallback_label);
+ err.span_label(span, fallback_label.to_string());
err.multipart_suggestion(
"surround the struct literal with parentheses",
vec![
@@ -1320,7 +1376,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
);
}
_ => {
- err.span_label(span, fallback_label);
+ err.span_label(span, fallback_label.to_string());
}
}
};
@@ -1333,7 +1389,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}))
| PathSource::Struct,
) => {
- err.span_label(span, fallback_label);
+ err.span_label(span, fallback_label.to_string());
err.span_suggestion_verbose(
span.shrink_to_hi(),
"use `!` to invoke the macro",
@@ -1345,7 +1401,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
}
(Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => {
- err.span_label(span, fallback_label);
+ err.span_label(span, fallback_label.to_string());
}
(Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => {
err.span_label(span, "type aliases cannot be used as traits");
@@ -1513,7 +1569,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
);
}
(Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }, _) if ns == ValueNS => {
- err.span_label(span, fallback_label);
+ err.span_label(span, fallback_label.to_string());
err.note("can't use `Self` as a constructor, you must use the implemented struct");
}
(Res::Def(DefKind::TyAlias | DefKind::AssocTy, _), _) if ns == ValueNS => {
@@ -1537,7 +1593,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
return None;
}
- let resolutions = self.r.resolutions(module);
+ let resolutions = self.r.resolutions(*module);
let targets = resolutions
.borrow()
.iter()
@@ -1829,6 +1885,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
path,
accessible: true,
note: None,
+ via_import: false,
},
));
} else {
@@ -2180,10 +2237,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
None => {
debug!(?param.ident, ?param.ident.span);
let deletion_span = deletion_span();
- // the give lifetime originates from expanded code so we won't be able to remove it #104432
- let lifetime_only_in_expanded_code =
- deletion_span.map(|sp| sp.in_derive_expansion()).unwrap_or(true);
- if !lifetime_only_in_expanded_code {
+
+ // if the lifetime originates from expanded code, we won't be able to remove it #104432
+ if deletion_span.is_some_and(|sp| !sp.in_derive_expansion()) {
self.r.lint_buffer.buffer_lint_with_diagnostic(
lint::builtin::UNUSED_LIFETIMES,
param.id,
@@ -2243,7 +2299,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
&self,
err: &mut Diagnostic,
name: Option<&str>,
- suggest: impl Fn(&mut Diagnostic, bool, Span, &str, String) -> bool,
+ suggest: impl Fn(&mut Diagnostic, bool, Span, Cow<'static, str>, String) -> bool,
) {
let mut suggest_note = true;
for rib in self.lifetime_ribs.iter().rev() {
@@ -2288,22 +2344,23 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
(span, sugg)
};
if higher_ranked {
- let message = format!(
+ let message = Cow::from(format!(
"consider making the {} lifetime-generic with a new `{}` lifetime",
kind.descr(),
name.unwrap_or("'a"),
- );
- should_continue = suggest(err, true, span, &message, sugg);
+ ));
+ should_continue = suggest(err, true, span, message, sugg);
err.note_once(
"for more information on higher-ranked polymorphism, visit \
https://doc.rust-lang.org/nomicon/hrtb.html",
);
} else if let Some(name) = name {
- let message = format!("consider introducing lifetime `{}` here", name);
- should_continue = suggest(err, false, span, &message, sugg);
+ let message =
+ Cow::from(format!("consider introducing lifetime `{}` here", name));
+ should_continue = suggest(err, false, span, message, sugg);
} else {
- let message = "consider introducing a named lifetime parameter";
- should_continue = suggest(err, false, span, &message, sugg);
+ let message = Cow::from("consider introducing a named lifetime parameter");
+ should_continue = suggest(err, false, span, message, sugg);
}
}
LifetimeRibKind::Item => break,
@@ -2584,6 +2641,70 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
}
+fn mk_where_bound_predicate(
+ path: &Path,
+ poly_trait_ref: &ast::PolyTraitRef,
+ ty: &ast::Ty,
+) -> Option<ast::WhereBoundPredicate> {
+ use rustc_span::DUMMY_SP;
+ let modified_segments = {
+ let mut segments = path.segments.clone();
+ let [preceding @ .., second_last, last] = segments.as_mut_slice() else { return None; };
+ let mut segments = ThinVec::from(preceding);
+
+ let added_constraint = ast::AngleBracketedArg::Constraint(ast::AssocConstraint {
+ id: DUMMY_NODE_ID,
+ ident: last.ident,
+ gen_args: None,
+ kind: ast::AssocConstraintKind::Equality {
+ term: ast::Term::Ty(ast::ptr::P(ast::Ty {
+ kind: ast::TyKind::Path(None, poly_trait_ref.trait_ref.path.clone()),
+ id: DUMMY_NODE_ID,
+ span: DUMMY_SP,
+ tokens: None,
+ })),
+ },
+ span: DUMMY_SP,
+ });
+
+ match second_last.args.as_deref_mut() {
+ Some(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { args, .. })) => {
+ args.push(added_constraint);
+ }
+ Some(_) => return None,
+ None => {
+ second_last.args =
+ Some(ast::ptr::P(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs {
+ args: ThinVec::from([added_constraint]),
+ span: DUMMY_SP,
+ })));
+ }
+ }
+
+ segments.push(second_last.clone());
+ segments
+ };
+
+ let new_where_bound_predicate = ast::WhereBoundPredicate {
+ span: DUMMY_SP,
+ bound_generic_params: ThinVec::new(),
+ bounded_ty: ast::ptr::P(ty.clone()),
+ bounds: vec![ast::GenericBound::Trait(
+ ast::PolyTraitRef {
+ bound_generic_params: ThinVec::new(),
+ trait_ref: ast::TraitRef {
+ path: ast::Path { segments: modified_segments, span: DUMMY_SP, tokens: None },
+ ref_id: DUMMY_NODE_ID,
+ },
+ span: DUMMY_SP,
+ },
+ ast::TraitBoundModifier::None,
+ )],
+ };
+
+ Some(new_where_bound_predicate)
+}
+
/// Report lifetime/lifetime shadowing as an error.
pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
let mut err = struct_span_err!(
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 3d2bd8429..da3d86a47 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -9,11 +9,12 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(assert_matches)]
#![feature(box_patterns)]
-#![feature(drain_filter)]
+#![feature(extract_if)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(never_type)]
+#![feature(rustc_attrs)]
#![recursion_limit = "256"]
#![allow(rustdoc::private_intra_doc_links)]
#![allow(rustc::potential_query_instability)]
@@ -25,6 +26,7 @@ use errors::{
ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst, ParamKindInTyOfConstParam,
};
use rustc_arena::{DroplessArena, TypedArena};
+use rustc_ast::expand::StrippedCfgItem;
use rustc_ast::node_id::NodeMap;
use rustc_ast::{self as ast, attr, NodeId, CRATE_NODE_ID};
use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path};
@@ -60,10 +62,10 @@ use rustc_span::{Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
use std::cell::{Cell, RefCell};
use std::collections::BTreeSet;
-use std::{fmt, ptr};
+use std::fmt;
use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
-use imports::{Import, ImportKind, NameResolution};
+use imports::{Import, ImportData, ImportKind, NameResolution};
use late::{HasGenericParams, PathSource, PatternSource};
use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
@@ -127,10 +129,10 @@ enum Scope<'a> {
/// with different restrictions when looking up the resolution.
/// This enum is currently used only for early resolution (imports and macros),
/// but not for late resolution yet.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
enum ScopeSet<'a> {
/// All scopes with the given namespace.
- All(Namespace, /*is_import*/ bool),
+ All(Namespace),
/// Crate root, then extern prelude (used for mixed 2015-2018 mode in macros).
AbsolutePath(Namespace),
/// All scopes with macro namespace and the given macro kind restriction.
@@ -171,6 +173,7 @@ enum ImplTraitContext {
Universal(LocalDefId),
}
+#[derive(Debug)]
struct BindingError {
name: Symbol,
origin: BTreeSet<Span>,
@@ -178,6 +181,7 @@ struct BindingError {
could_be_path: bool,
}
+#[derive(Debug)]
enum ResolutionError<'a> {
/// Error E0401: can't use type or const parameters from outer function.
GenericParamsFromOuterFunction(Res, HasGenericParams),
@@ -207,7 +211,12 @@ enum ResolutionError<'a> {
/// Error E0431: `self` import can only appear in an import list with a non-empty prefix.
SelfImportOnlyInImportListWithNonEmptyPrefix,
/// Error E0433: failed to resolve.
- FailedToResolve { label: String, suggestion: Option<Suggestion> },
+ FailedToResolve {
+ last_segment: Option<Symbol>,
+ label: String,
+ suggestion: Option<Suggestion>,
+ module: Option<ModuleOrUniformRoot<'a>>,
+ },
/// Error E0434: can't capture dynamic environment in a fn item.
CannotCaptureDynamicEnvironmentInFnItem,
/// Error E0435: attempt to use a non-constant value in a constant.
@@ -344,7 +353,7 @@ impl<'a> From<&'a ast::PathSegment> for Segment {
/// forward.
#[derive(Debug)]
enum LexicalScopeBinding<'a> {
- Item(&'a NameBinding<'a>),
+ Item(NameBinding<'a>),
Res(Res),
}
@@ -357,7 +366,7 @@ impl<'a> LexicalScopeBinding<'a> {
}
}
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
enum ModuleOrUniformRoot<'a> {
/// Regular module.
Module(Module<'a>),
@@ -375,23 +384,6 @@ enum ModuleOrUniformRoot<'a> {
CurrentScope,
}
-impl ModuleOrUniformRoot<'_> {
- fn same_def(lhs: Self, rhs: Self) -> bool {
- match (lhs, rhs) {
- (ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) => {
- ptr::eq(lhs, rhs)
- }
- (
- ModuleOrUniformRoot::CrateRootAndExternPrelude,
- ModuleOrUniformRoot::CrateRootAndExternPrelude,
- )
- | (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude)
- | (ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true,
- _ => false,
- }
- }
-}
-
#[derive(Debug)]
enum PathResult<'a> {
Module(ModuleOrUniformRoot<'a>),
@@ -402,6 +394,7 @@ enum PathResult<'a> {
label: String,
suggestion: Option<Suggestion>,
is_error_from_last_segment: bool,
+ module: Option<ModuleOrUniformRoot<'a>>,
},
}
@@ -410,11 +403,12 @@ impl<'a> PathResult<'a> {
span: Span,
is_error_from_last_segment: bool,
finalize: bool,
+ module: Option<ModuleOrUniformRoot<'a>>,
label_and_suggestion: impl FnOnce() -> (String, Option<Suggestion>),
) -> PathResult<'a> {
let (label, suggestion) =
if finalize { label_and_suggestion() } else { (String::new(), None) };
- PathResult::Failed { span, label, suggestion, is_error_from_last_segment }
+ PathResult::Failed { span, label, suggestion, is_error_from_last_segment, module }
}
}
@@ -508,11 +502,11 @@ struct ModuleData<'a> {
/// Whether `#[no_implicit_prelude]` is active.
no_implicit_prelude: bool,
- glob_importers: RefCell<Vec<&'a Import<'a>>>,
- globs: RefCell<Vec<&'a Import<'a>>>,
+ glob_importers: RefCell<Vec<Import<'a>>>,
+ globs: RefCell<Vec<Import<'a>>>,
/// Used to memoize the traits in this module for faster searches through all traits in scope.
- traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>,
+ traits: RefCell<Option<Box<[(Ident, NameBinding<'a>)]>>>,
/// Span of the module itself. Used for error reporting.
span: Span,
@@ -520,7 +514,11 @@ struct ModuleData<'a> {
expansion: ExpnId,
}
-type Module<'a> = &'a ModuleData<'a>;
+/// All modules are unique and allocated on a same arena,
+/// so we can use referential equality to compare them.
+#[derive(Clone, Copy, PartialEq)]
+#[rustc_pass_by_value]
+struct Module<'a>(Interned<'a, ModuleData<'a>>);
impl<'a> ModuleData<'a> {
fn new(
@@ -548,11 +546,13 @@ impl<'a> ModuleData<'a> {
expansion,
}
}
+}
- fn for_each_child<'tcx, R, F>(&'a self, resolver: &mut R, mut f: F)
+impl<'a> Module<'a> {
+ fn for_each_child<'tcx, R, F>(self, resolver: &mut R, mut f: F)
where
R: AsMut<Resolver<'a, 'tcx>>,
- F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>),
+ F: FnMut(&mut R, Ident, Namespace, NameBinding<'a>),
{
for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
if let Some(binding) = name_resolution.borrow().binding {
@@ -562,7 +562,7 @@ impl<'a> ModuleData<'a> {
}
/// This modifies `self` in place. The traits will be stored in `self.traits`.
- fn ensure_traits<'tcx, R>(&'a self, resolver: &mut R)
+ fn ensure_traits<'tcx, R>(self, resolver: &mut R)
where
R: AsMut<Resolver<'a, 'tcx>>,
{
@@ -581,7 +581,7 @@ impl<'a> ModuleData<'a> {
}
}
- fn res(&self) -> Option<Res> {
+ fn res(self) -> Option<Res> {
match self.kind {
ModuleKind::Def(kind, def_id, _) => Some(Res::Def(kind, def_id)),
_ => None,
@@ -589,11 +589,11 @@ impl<'a> ModuleData<'a> {
}
// Public for rustdoc.
- fn def_id(&self) -> DefId {
+ fn def_id(self) -> DefId {
self.opt_def_id().expect("`ModuleData::def_id` is called on a block module")
}
- fn opt_def_id(&self) -> Option<DefId> {
+ fn opt_def_id(self) -> Option<DefId> {
match self.kind {
ModuleKind::Def(_, def_id, _) => Some(def_id),
_ => None,
@@ -601,15 +601,15 @@ impl<'a> ModuleData<'a> {
}
// `self` resolves to the first module ancestor that `is_normal`.
- fn is_normal(&self) -> bool {
+ fn is_normal(self) -> bool {
matches!(self.kind, ModuleKind::Def(DefKind::Mod, _, _))
}
- fn is_trait(&self) -> bool {
+ fn is_trait(self) -> bool {
matches!(self.kind, ModuleKind::Def(DefKind::Trait, _, _))
}
- fn nearest_item_scope(&'a self) -> Module<'a> {
+ fn nearest_item_scope(self) -> Module<'a> {
match self.kind {
ModuleKind::Def(DefKind::Enum | DefKind::Trait, ..) => {
self.parent.expect("enum or trait module without a parent")
@@ -620,15 +620,15 @@ impl<'a> ModuleData<'a> {
/// The [`DefId`] of the nearest `mod` item ancestor (which may be this module).
/// This may be the crate root.
- fn nearest_parent_mod(&self) -> DefId {
+ fn nearest_parent_mod(self) -> DefId {
match self.kind {
ModuleKind::Def(DefKind::Mod, def_id, _) => def_id,
_ => self.parent.expect("non-root module without parent").nearest_parent_mod(),
}
}
- fn is_ancestor_of(&self, mut other: &Self) -> bool {
- while !ptr::eq(self, other) {
+ fn is_ancestor_of(self, mut other: Self) -> bool {
+ while self != other {
if let Some(parent) = other.parent {
other = parent;
} else {
@@ -639,7 +639,15 @@ impl<'a> ModuleData<'a> {
}
}
-impl<'a> fmt::Debug for ModuleData<'a> {
+impl<'a> std::ops::Deref for Module<'a> {
+ type Target = ModuleData<'a>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<'a> fmt::Debug for Module<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.res())
}
@@ -647,20 +655,24 @@ impl<'a> fmt::Debug for ModuleData<'a> {
/// Records a possibly-private value, type, or module definition.
#[derive(Clone, Debug)]
-struct NameBinding<'a> {
+struct NameBindingData<'a> {
kind: NameBindingKind<'a>,
- ambiguity: Option<(&'a NameBinding<'a>, AmbiguityKind)>,
+ ambiguity: Option<(NameBinding<'a>, AmbiguityKind)>,
expansion: LocalExpnId,
span: Span,
vis: ty::Visibility<DefId>,
}
+/// All name bindings are unique and allocated on a same arena,
+/// so we can use referential equality to compare them.
+type NameBinding<'a> = Interned<'a, NameBindingData<'a>>;
+
trait ToNameBinding<'a> {
- fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a>;
+ fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a>;
}
-impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> {
- fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
+impl<'a> ToNameBinding<'a> for NameBinding<'a> {
+ fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> NameBinding<'a> {
self
}
}
@@ -669,7 +681,7 @@ impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> {
enum NameBindingKind<'a> {
Res(Res),
Module(Module<'a>),
- Import { binding: &'a NameBinding<'a>, import: &'a Import<'a>, used: Cell<bool> },
+ Import { binding: NameBinding<'a>, import: Import<'a>, used: Cell<bool> },
}
impl<'a> NameBindingKind<'a> {
@@ -679,12 +691,16 @@ impl<'a> NameBindingKind<'a> {
}
}
+#[derive(Debug)]
struct PrivacyError<'a> {
ident: Ident,
- binding: &'a NameBinding<'a>,
+ binding: NameBinding<'a>,
dedup_span: Span,
+ outermost_res: Option<(Res, Ident)>,
+ parent_scope: ParentScope<'a>,
}
+#[derive(Debug)]
struct UseError<'a> {
err: DiagnosticBuilder<'a, ErrorGuaranteed>,
/// Candidates which user could `use` to access the missing type.
@@ -704,7 +720,6 @@ struct UseError<'a> {
#[derive(Clone, Copy, PartialEq, Debug)]
enum AmbiguityKind {
- Import,
BuiltinAttr,
DeriveHelper,
MacroRulesVsModularized,
@@ -717,7 +732,6 @@ enum AmbiguityKind {
impl AmbiguityKind {
fn descr(self) -> &'static str {
match self {
- AmbiguityKind::Import => "multiple potential import sources",
AmbiguityKind::BuiltinAttr => "a name conflict with a builtin attribute",
AmbiguityKind::DeriveHelper => "a name conflict with a derive helper attribute",
AmbiguityKind::MacroRulesVsModularized => {
@@ -749,13 +763,13 @@ enum AmbiguityErrorMisc {
struct AmbiguityError<'a> {
kind: AmbiguityKind,
ident: Ident,
- b1: &'a NameBinding<'a>,
- b2: &'a NameBinding<'a>,
+ b1: NameBinding<'a>,
+ b2: NameBinding<'a>,
misc1: AmbiguityErrorMisc,
misc2: AmbiguityErrorMisc,
}
-impl<'a> NameBinding<'a> {
+impl<'a> NameBindingData<'a> {
fn module(&self) -> Option<Module<'a>> {
match self.kind {
NameBindingKind::Module(module) => Some(module),
@@ -793,14 +807,12 @@ impl<'a> NameBinding<'a> {
fn is_extern_crate(&self) -> bool {
match self.kind {
- NameBindingKind::Import {
- import: &Import { kind: ImportKind::ExternCrate { .. }, .. },
- ..
- } => true,
- NameBindingKind::Module(&ModuleData {
- kind: ModuleKind::Def(DefKind::Mod, def_id, _),
- ..
- }) => def_id.is_crate_root(),
+ NameBindingKind::Import { import, .. } => {
+ matches!(import.kind, ImportKind::ExternCrate { .. })
+ }
+ NameBindingKind::Module(module)
+ if let ModuleKind::Def(DefKind::Mod, def_id, _) = module.kind
+ => def_id.is_crate_root(),
_ => false,
}
}
@@ -843,7 +855,7 @@ impl<'a> NameBinding<'a> {
fn may_appear_after(
&self,
invoc_parent_expansion: LocalExpnId,
- binding: &NameBinding<'_>,
+ binding: NameBinding<'_>,
) -> bool {
// self > max(invoc, binding) => !(self <= invoc || self <= binding)
// Expansions are partially ordered, so "may appear after" is an inversion of
@@ -860,7 +872,7 @@ impl<'a> NameBinding<'a> {
#[derive(Default, Clone)]
struct ExternPreludeEntry<'a> {
- extern_crate_item: Option<&'a NameBinding<'a>>,
+ extern_crate_item: Option<NameBinding<'a>>,
introduced_by_item: bool,
}
@@ -905,10 +917,10 @@ pub struct Resolver<'a, 'tcx> {
field_visibility_spans: FxHashMap<DefId, Vec<Span>>,
/// All imports known to succeed or fail.
- determined_imports: Vec<&'a Import<'a>>,
+ determined_imports: Vec<Import<'a>>,
/// All non-determined imports.
- indeterminate_imports: Vec<&'a Import<'a>>,
+ indeterminate_imports: Vec<Import<'a>>,
// Spans for local variables found during pattern resolution.
// Used for suggestions during error reporting.
@@ -950,7 +962,7 @@ pub struct Resolver<'a, 'tcx> {
/// language items.
empty_module: Module<'a>,
module_map: FxHashMap<DefId, Module<'a>>,
- binding_parent_modules: FxHashMap<Interned<'a, NameBinding<'a>>, Module<'a>>,
+ binding_parent_modules: FxHashMap<NameBinding<'a>, Module<'a>>,
underscore_disambiguator: u32,
@@ -972,7 +984,7 @@ pub struct Resolver<'a, 'tcx> {
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
arenas: &'a ResolverArenas<'a>,
- dummy_binding: &'a NameBinding<'a>,
+ dummy_binding: NameBinding<'a>,
used_extern_options: FxHashSet<Symbol>,
macro_names: FxHashSet<Ident>,
@@ -981,7 +993,7 @@ pub struct Resolver<'a, 'tcx> {
/// the surface (`macro` items in libcore), but are actually attributes or derives.
builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>,
registered_tools: &'tcx RegisteredTools,
- macro_use_prelude: FxHashMap<Symbol, &'a NameBinding<'a>>,
+ macro_use_prelude: FxHashMap<Symbol, NameBinding<'a>>,
macro_map: FxHashMap<DefId, MacroData>,
dummy_ext_bang: Lrc<SyntaxExtension>,
dummy_ext_derive: Lrc<SyntaxExtension>,
@@ -993,7 +1005,7 @@ pub struct Resolver<'a, 'tcx> {
proc_macro_stubs: FxHashSet<LocalDefId>,
/// Traces collected during macro resolution and validated when it's complete.
single_segment_macro_resolutions:
- Vec<(Ident, MacroKind, ParentScope<'a>, Option<&'a NameBinding<'a>>)>,
+ Vec<(Ident, MacroKind, ParentScope<'a>, Option<NameBinding<'a>>)>,
multi_segment_macro_resolutions:
Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'a>, Option<Res>)>,
builtin_attrs: Vec<(Ident, ParentScope<'a>)>,
@@ -1018,7 +1030,7 @@ pub struct Resolver<'a, 'tcx> {
/// Avoid duplicated errors for "name already defined".
name_already_seen: FxHashMap<Symbol, Span>,
- potentially_unused_imports: Vec<&'a Import<'a>>,
+ potentially_unused_imports: Vec<Import<'a>>,
/// Table for mapping struct IDs into struct constructor IDs,
/// it's not used during normal resolution, only for better error reporting.
@@ -1059,6 +1071,9 @@ pub struct Resolver<'a, 'tcx> {
/// Whether lifetime elision was successful.
lifetime_elision_allowed: FxHashSet<NodeId>,
+ /// Names of items that were stripped out via cfg with their corresponding cfg meta item.
+ stripped_cfg_items: Vec<StrippedCfgItem<NodeId>>,
+
effective_visibilities: EffectiveVisibilities,
doc_link_resolutions: FxHashMap<LocalDefId, DocLinkResMap>,
doc_link_traits_in_scope: FxHashMap<LocalDefId, Vec<DefId>>,
@@ -1070,7 +1085,7 @@ pub struct Resolver<'a, 'tcx> {
pub struct ResolverArenas<'a> {
modules: TypedArena<ModuleData<'a>>,
local_modules: RefCell<Vec<Module<'a>>>,
- imports: TypedArena<Import<'a>>,
+ imports: TypedArena<ImportData<'a>>,
name_resolutions: TypedArena<RefCell<NameResolution<'a>>>,
ast_paths: TypedArena<ast::Path>,
dropless: DroplessArena,
@@ -1086,8 +1101,13 @@ impl<'a> ResolverArenas<'a> {
no_implicit_prelude: bool,
module_map: &mut FxHashMap<DefId, Module<'a>>,
) -> Module<'a> {
- let module =
- self.modules.alloc(ModuleData::new(parent, kind, expn_id, span, no_implicit_prelude));
+ let module = Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new(
+ parent,
+ kind,
+ expn_id,
+ span,
+ no_implicit_prelude,
+ ))));
let def_id = module.opt_def_id();
if def_id.map_or(true, |def_id| def_id.is_local()) {
self.local_modules.borrow_mut().push(module);
@@ -1100,11 +1120,11 @@ impl<'a> ResolverArenas<'a> {
fn local_modules(&'a self) -> std::cell::Ref<'a, Vec<Module<'a>>> {
self.local_modules.borrow()
}
- fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> {
- self.dropless.alloc(name_binding)
+ fn alloc_name_binding(&'a self, name_binding: NameBindingData<'a>) -> NameBinding<'a> {
+ Interned::new_unchecked(self.dropless.alloc(name_binding))
}
- fn alloc_import(&'a self, import: Import<'a>) -> &'a Import<'_> {
- self.imports.alloc(import)
+ fn alloc_import(&'a self, import: ImportData<'a>) -> Import<'a> {
+ Interned::new_unchecked(self.imports.alloc(import))
}
fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
self.name_resolutions.alloc(Default::default())
@@ -1299,7 +1319,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
macro_expanded_macro_export_errors: BTreeSet::new(),
arenas,
- dummy_binding: arenas.alloc_name_binding(NameBinding {
+ dummy_binding: arenas.alloc_name_binding(NameBindingData {
kind: NameBindingKind::Res(Res::Err),
ambiguity: None,
expansion: LocalExpnId::ROOT,
@@ -1353,6 +1373,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
proc_macros: Default::default(),
confused_type_with_std_module: Default::default(),
lifetime_elision_allowed: Default::default(),
+ stripped_cfg_items: Default::default(),
effective_visibilities: Default::default(),
doc_link_resolutions: Default::default(),
doc_link_traits_in_scope: Default::default(),
@@ -1410,6 +1431,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let main_def = self.main_def;
let confused_type_with_std_module = self.confused_type_with_std_module;
let effective_visibilities = self.effective_visibilities;
+
+ self.tcx.feed_local_crate().stripped_cfg_items(self.tcx.arena.alloc_from_iter(
+ self.stripped_cfg_items.into_iter().filter_map(|item| {
+ let parent_module = self.node_id_to_def_id.get(&item.parent_module)?.to_def_id();
+ Some(StrippedCfgItem { parent_module, name: item.name, cfg: item.cfg })
+ }),
+ ));
+
let global_ctxt = ResolverGlobalCtxt {
expn_that_defined,
visibilities,
@@ -1496,10 +1525,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let exported_ambiguities = self.tcx.sess.time("compute_effective_visibilities", || {
EffectiveVisibilitiesVisitor::compute_effective_visibilities(self, krate)
});
- self.tcx.sess.time("check_reexport_ambiguities", || {
- self.check_reexport_ambiguities(exported_ambiguities)
+ self.tcx.sess.time("check_hidden_glob_reexports", || {
+ self.check_hidden_glob_reexports(exported_ambiguities)
});
- self.tcx.sess.time("finalize_macro_resolutions", || self.finalize_macro_resolutions());
+ self.tcx
+ .sess
+ .time("finalize_macro_resolutions", || self.finalize_macro_resolutions(krate));
self.tcx.sess.time("late_resolve_crate", || self.late_resolve_crate(krate));
self.tcx.sess.time("resolve_main", || self.resolve_main());
self.tcx.sess.time("resolve_check_unused", || self.check_unused(krate));
@@ -1529,7 +1560,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
- self.visit_scopes(ScopeSet::All(TypeNS, false), parent_scope, ctxt, |this, scope, _, _| {
+ self.visit_scopes(ScopeSet::All(TypeNS), parent_scope, ctxt, |this, scope, _, _| {
match scope {
Scope::Module(module, _) => {
this.traits_in_module(module, assoc_item, &mut found_traits);
@@ -1598,7 +1629,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
self.maybe_unused_trait_imports.insert(def_id);
import_ids.push(def_id);
}
- self.add_to_glob_map(&import, trait_name);
+ self.add_to_glob_map(*import, trait_name);
kind = &binding.kind;
}
import_ids
@@ -1620,7 +1651,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
module.populate_on_access.set(false);
self.build_reduced_graph_external(module);
}
- &module.lazy_resolutions
+ &module.0.0.lazy_resolutions
}
fn resolution(
@@ -1653,12 +1684,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
false
}
- fn record_use(
- &mut self,
- ident: Ident,
- used_binding: &'a NameBinding<'a>,
- is_lexical_scope: bool,
- ) {
+ fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'a>, is_lexical_scope: bool) {
if let Some((b2, kind)) = used_binding.ambiguity {
let ambiguity_error = AmbiguityError {
kind,
@@ -1678,10 +1704,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// but not introduce it, as used if they are accessed from lexical scope.
if is_lexical_scope {
if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
- if let Some(crate_item) = entry.extern_crate_item {
- if ptr::eq(used_binding, crate_item) && !entry.introduced_by_item {
- return;
- }
+ if !entry.introduced_by_item && entry.extern_crate_item == Some(used_binding) {
+ return;
}
}
}
@@ -1690,13 +1714,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if let Some(id) = import.id() {
self.used_imports.insert(id);
}
- self.add_to_glob_map(&import, ident);
+ self.add_to_glob_map(import, ident);
self.record_use(ident, binding, false);
}
}
#[inline]
- fn add_to_glob_map(&mut self, import: &Import<'_>, ident: Ident) {
+ fn add_to_glob_map(&mut self, import: Import<'_>, ident: Ident) {
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);
@@ -1805,11 +1829,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
vis.is_accessible_from(module.nearest_parent_mod(), self.tcx)
}
- fn set_binding_parent_module(&mut self, binding: &'a NameBinding<'a>, module: Module<'a>) {
- if let Some(old_module) =
- self.binding_parent_modules.insert(Interned::new_unchecked(binding), module)
- {
- if !ptr::eq(module, old_module) {
+ fn set_binding_parent_module(&mut self, binding: NameBinding<'a>, module: Module<'a>) {
+ if let Some(old_module) = self.binding_parent_modules.insert(binding, module) {
+ if module != old_module {
span_bug!(binding.span, "parent module is reset for binding");
}
}
@@ -1817,25 +1839,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
fn disambiguate_macro_rules_vs_modularized(
&self,
- macro_rules: &'a NameBinding<'a>,
- modularized: &'a NameBinding<'a>,
+ macro_rules: NameBinding<'a>,
+ modularized: NameBinding<'a>,
) -> bool {
// Some non-controversial subset of ambiguities "modularized macro name" vs "macro_rules"
// is disambiguated to mitigate regressions from macro modularization.
// Scoping for `macro_rules` behaves like scoping for `let` at module level, in general.
match (
- self.binding_parent_modules.get(&Interned::new_unchecked(macro_rules)),
- self.binding_parent_modules.get(&Interned::new_unchecked(modularized)),
+ self.binding_parent_modules.get(&macro_rules),
+ self.binding_parent_modules.get(&modularized),
) {
(Some(macro_rules), Some(modularized)) => {
macro_rules.nearest_parent_mod() == modularized.nearest_parent_mod()
- && modularized.is_ancestor_of(macro_rules)
+ && modularized.is_ancestor_of(*macro_rules)
}
_ => false,
}
}
- fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option<&'a NameBinding<'a>> {
+ fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option<NameBinding<'a>> {
if ident.is_path_segment_keyword() {
// Make sure `self`, `super` etc produce an error when passed to here.
return None;
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index df5c16a93..d16b7902f 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -1,12 +1,15 @@
//! A bunch of methods and structures more or less related to resolving macros and
//! interface provided by `Resolver` to macro expander.
-use crate::errors::{self, AddAsNonDerive, MacroExpectedFound, RemoveSurroundingDerive};
+use crate::errors::{
+ self, AddAsNonDerive, CannotFindIdentInThisScope, MacroExpectedFound, RemoveSurroundingDerive,
+};
use crate::Namespace::*;
use crate::{BuiltinMacroState, Determinacy};
use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment};
-use rustc_ast::{self as ast, attr, Inline, ItemKind, ModKind, NodeId};
+use rustc_ast::expand::StrippedCfgItem;
+use rustc_ast::{self as ast, attr, Crate, Inline, ItemKind, ModKind, NodeId};
use rustc_ast_pretty::pprust;
use rustc_attr::StabilityLevel;
use rustc_data_structures::intern::Interned;
@@ -39,7 +42,7 @@ type Res = def::Res<NodeId>;
/// Not modularized, can shadow previous `macro_rules` bindings, etc.
#[derive(Debug)]
pub(crate) struct MacroRulesBinding<'a> {
- pub(crate) binding: &'a NameBinding<'a>,
+ pub(crate) binding: NameBinding<'a>,
/// `macro_rules` scope into which the `macro_rules` item was planted.
pub(crate) parent_macro_rules_scope: MacroRulesScopeRef<'a>,
pub(crate) ident: Ident,
@@ -465,6 +468,10 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
self.proc_macros.push(id)
}
+ fn append_stripped_cfg_item(&mut self, parent_node: NodeId, name: Ident, cfg: ast::MetaItem) {
+ self.stripped_cfg_items.push(StrippedCfgItem { parent_module: parent_node, name, cfg });
+ }
+
fn registered_tools(&self) -> &RegisteredTools {
&self.registered_tools
}
@@ -638,7 +645,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span);
res
} else {
- let scope_set = kind.map_or(ScopeSet::All(MacroNS, false), ScopeSet::Macro);
+ let scope_set = kind.map_or(ScopeSet::All(MacroNS), ScopeSet::Macro);
let binding = self.early_resolve_ident_in_lexical_scope(
path[0].ident,
scope_set,
@@ -669,7 +676,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
res.map(|res| (self.get_macro(res).map(|macro_data| macro_data.ext), res))
}
- pub(crate) fn finalize_macro_resolutions(&mut self) {
+ pub(crate) fn finalize_macro_resolutions(&mut self, krate: &Crate) {
let check_consistency = |this: &mut Self,
path: &[Segment],
span,
@@ -721,7 +728,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
path_res @ (PathResult::NonModule(..) | PathResult::Failed { .. }) => {
let mut suggestion = None;
- let (span, label) = if let PathResult::Failed { span, label, .. } = path_res {
+ let (span, label, module) = if let PathResult::Failed { span, label, module, .. } = path_res {
// try to suggest if it's not a macro, maybe a function
if let PathResult::NonModule(partial_res) = self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope)
&& partial_res.unresolved_segments() == 0 {
@@ -733,7 +740,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
Applicability::MaybeIncorrect
));
}
- (span, label)
+ (span, label, module)
} else {
(
path_span,
@@ -742,11 +749,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
kind.article(),
kind.descr()
),
+ None,
)
};
self.report_error(
span,
- ResolutionError::FailedToResolve { label, suggestion },
+ ResolutionError::FailedToResolve { last_segment: path.last().map(|segment| segment.ident.name), label, suggestion, module },
);
}
PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
@@ -787,9 +795,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
Err(..) => {
let expected = kind.descr_expected();
- let msg = format!("cannot find {} `{}` in this scope", expected, ident);
- let mut err = self.tcx.sess.struct_span_err(ident.span, msg);
- self.unresolved_macro_suggestions(&mut err, kind, &parent_scope, ident);
+
+ let mut err = self.tcx.sess.create_err(CannotFindIdentInThisScope {
+ span: ident.span,
+ expected,
+ ident,
+ });
+
+ self.unresolved_macro_suggestions(&mut err, kind, &parent_scope, ident, krate);
err.emit();
}
}
@@ -827,7 +840,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if !is_allowed(feature) && !allowed_by_implication {
let lint_buffer = &mut self.lint_buffer;
let soft_handler =
- |lint, span, msg: &_| lint_buffer.buffer_lint(lint, node_id, span, msg);
+ |lint, span, msg: String| lint_buffer.buffer_lint(lint, node_id, span, msg);
stability::report_unstable(
self.tcx.sess,
feature,
@@ -846,7 +859,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let (message, lint) = stability::deprecation_message_and_lint(depr, "macro", &path);
stability::early_report_deprecation(
&mut self.lint_buffer,
- &message,
+ message,
depr.suggestion,
lint,
span,
@@ -857,7 +870,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
fn prohibit_imported_non_macro_attrs(
&self,
- binding: Option<&'a NameBinding<'a>>,
+ binding: Option<NameBinding<'a>>,
res: Option<Res>,
span: Span,
) {