diff options
Diffstat (limited to 'compiler/rustc_resolve/src')
| -rw-r--r-- | compiler/rustc_resolve/src/build_reduced_graph.rs | 201 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/check_unused.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/def_collector.rs | 64 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/diagnostics.rs | 212 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/effective_visibilities.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/errors.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/ident.rs | 49 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/imports.rs | 60 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 308 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/diagnostics.rs | 415 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/lib.rs | 61 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/macros.rs | 60 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/rustdoc.rs | 3 |
13 files changed, 941 insertions, 514 deletions
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 65901eedb21..b855ec8f920 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -16,10 +16,10 @@ use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind}; -use rustc_ast::{Block, Fn, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId}; +use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId}; use rustc_attr as attr; use rustc_data_structures::sync::Lrc; -use rustc_errors::{struct_span_err, Applicability}; +use rustc_errors::{struct_span_code_err, Applicability}; use rustc_expand::expand::AstFragment; use rustc_hir::def::{self, *}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; @@ -210,6 +210,11 @@ impl<'a, 'tcx> AsMut<Resolver<'a, 'tcx>> for BuildReducedGraphVisitor<'a, '_, 't } impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { + fn res(&self, def_id: impl Into<DefId>) -> Res { + let def_id = def_id.into(); + Res::Def(self.r.tcx.def_kind(def_id), def_id) + } + fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility { self.try_resolve_visibility(vis, true).unwrap_or_else(|err| { self.r.report_vis_error(err); @@ -231,7 +236,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { // (i.e. variants, fields, and trait items) inherits from the visibility // of the enum or trait. ModuleKind::Def(DefKind::Enum | DefKind::Trait, def_id, _) => { - self.r.visibilities[&def_id.expect_local()] + self.r.tcx.visibility(def_id).expect_local() } // Otherwise, the visibility is restricted to the nearest parent `mod` item. _ => ty::Visibility::Restricted( @@ -389,6 +394,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { id: NodeId, parent_prefix: &[Segment], nested: bool, + list_stem: bool, // The whole `use` item item: &Item, vis: ty::Visibility, @@ -399,6 +405,12 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { parent_prefix, use_tree, nested ); + // Top level use tree reuses the item's id and list stems reuse their parent + // use tree's ids, so in both cases their visibilities are already filled. + if nested && !list_stem { + self.r.feed_visibility(self.r.local_def_id(id), vis); + } + let mut prefix_iter = parent_prefix .iter() .cloned() @@ -437,8 +449,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let mut source = module_path.pop().unwrap(); let mut type_ns_only = false; - self.r.visibilities.insert(self.r.local_def_id(id), vis); - if nested { // Correctly handle `self` if source.ident.name == kw::SelfLower { @@ -514,12 +524,12 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { ident.name = crate_name; } - self.r.tcx.sess.emit_err(errors::CrateImported { span: item.span }); + self.r.dcx().emit_err(errors::CrateImported { span: item.span }); } } if ident.name == kw::Crate { - self.r.tcx.sess.span_err( + self.r.dcx().span_err( ident.span, "crate root imports need to be explicitly named: \ `use crate as name;`", @@ -552,7 +562,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { max_vis: Cell::new(None), id, }; - self.r.visibilities.insert(self.r.local_def_id(id), vis); + self.add_import(prefix, kind, use_tree.span, item, root_span, item.id, vis); } ast::UseTreeKind::Nested(ref items) => { @@ -585,7 +595,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { for &(ref tree, id) in items { self.build_reduced_graph_for_use_tree( // This particular use tree - tree, id, &prefix, true, // The whole `use` item + tree, id, &prefix, true, false, // The whole `use` item item, vis, root_span, ); } @@ -606,6 +616,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { id, &prefix, true, + true, // The whole `use` item item, ty::Visibility::Restricted( @@ -628,8 +639,10 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let vis = self.resolve_visibility(&item.vis); let local_def_id = self.r.local_def_id(item.id); let def_id = local_def_id.to_def_id(); + let def_kind = self.r.tcx.def_kind(def_id); + let res = Res::Def(def_kind, def_id); - self.r.visibilities.insert(local_def_id, vis); + self.r.feed_visibility(local_def_id, vis); match item.kind { ItemKind::Use(ref use_tree) => { @@ -639,6 +652,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { item.id, &[], false, + false, // The whole `use` item item, vis, @@ -659,7 +673,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { ItemKind::Mod(..) => { let module = self.r.new_module( Some(parent), - ModuleKind::Def(DefKind::Mod, def_id, ident.name), + ModuleKind::Def(def_kind, def_id, ident.name), expansion.to_expn_id(), item.span, parent.no_implicit_prelude @@ -672,16 +686,10 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } // These items live in the value namespace. - ItemKind::Static(box ast::StaticItem { mutability, .. }) => { - let res = Res::Def(DefKind::Static(mutability), def_id); - self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); - } - ItemKind::Const(..) => { - let res = Res::Def(DefKind::Const, def_id); + ItemKind::Const(..) | ItemKind::Delegation(..) | ItemKind::Static(..) => { self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); } ItemKind::Fn(..) => { - let res = Res::Def(DefKind::Fn, def_id); self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); // Functions introducing procedural macros reserve a slot @@ -690,15 +698,14 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } // These items live in the type namespace. - ItemKind::TyAlias(..) => { - let res = Res::Def(DefKind::TyAlias, def_id); + ItemKind::TyAlias(..) | ItemKind::TraitAlias(..) => { self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); } - ItemKind::Enum(_, _) => { + ItemKind::Enum(_, _) | ItemKind::Trait(..) => { let module = self.r.new_module( Some(parent), - ModuleKind::Def(DefKind::Enum, def_id, ident.name), + ModuleKind::Def(def_kind, def_id, ident.name), expansion.to_expn_id(), item.span, parent.no_implicit_prelude, @@ -707,15 +714,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.parent_scope.module = module; } - ItemKind::TraitAlias(..) => { - let res = Res::Def(DefKind::TraitAlias, def_id); - self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); - } - // These items live in both the type and value namespaces. ItemKind::Struct(ref vdata, _) => { // Define a name in the type namespace. - let res = Res::Def(DefKind::Struct, def_id); self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); // Record field names for error reporting. @@ -724,7 +725,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { // If this is a tuple or unit struct, define a name // in the value namespace as well. - if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(vdata) { + if let Some(ctor_node_id) = vdata.ctor_node_id() { // If the structure is marked as non_exhaustive then lower the visibility // to within the crate. let mut ctor_vis = if vis.is_public() @@ -750,10 +751,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { ret_fields.push(field_vis.to_def_id()); } let ctor_def_id = self.r.local_def_id(ctor_node_id); - let ctor_res = - Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id.to_def_id()); + let ctor_res = self.res(ctor_def_id); self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion)); - self.r.visibilities.insert(ctor_def_id, ctor_vis); + self.r.feed_visibility(ctor_def_id, ctor_vis); // We need the field visibility spans also for the constructor for E0603. self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata); @@ -764,7 +764,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } ItemKind::Union(ref vdata, _) => { - let res = Res::Def(DefKind::Union, def_id); self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); // Record field names for error reporting. @@ -772,19 +771,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.insert_field_visibilities_local(def_id, vdata); } - ItemKind::Trait(..) => { - // Add all the items within to a new module. - let module = self.r.new_module( - Some(parent), - ModuleKind::Def(DefKind::Trait, def_id, ident.name), - expansion.to_expn_id(), - item.span, - parent.no_implicit_prelude, - ); - self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); - self.parent_scope.module = module; - } - // These items do not add names to modules. ItemKind::Impl(box Impl { of_trait: Some(..), .. }) => { self.r.trait_impl_items.insert(local_def_id); @@ -810,10 +796,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let (used, module, binding) = if orig_name.is_none() && ident.name == kw::SelfLower { self.r - .tcx - .sess + .dcx() .struct_span_err(item.span, "`extern crate self;` requires renaming") - .span_suggestion( + .with_span_suggestion( item.span, "rename the `self` crate to be able to import it", "extern crate self as name;", @@ -861,7 +846,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { if expansion != LocalExpnId::ROOT && orig_name.is_some() && !entry.is_import() { let msg = "macro-expanded `extern crate` items cannot \ shadow names passed with `--extern`"; - self.r.tcx.sess.span_err(item.span, msg); + self.r.dcx().span_err(item.span, msg); // `return` is intended to discard this binding because it's an // unregistered ambiguity error which would result in a panic // caused by inconsistency `path_res` @@ -888,18 +873,17 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) { let local_def_id = self.r.local_def_id(item.id); let def_id = local_def_id.to_def_id(); - let (def_kind, ns) = match item.kind { - ForeignItemKind::Fn(..) => (DefKind::Fn, ValueNS), - ForeignItemKind::Static(_, mt, _) => (DefKind::Static(mt), ValueNS), - ForeignItemKind::TyAlias(..) => (DefKind::ForeignTy, TypeNS), - ForeignItemKind::MacCall(_) => unreachable!(), + let ns = match item.kind { + ForeignItemKind::Fn(..) => ValueNS, + ForeignItemKind::Static(..) => ValueNS, + ForeignItemKind::TyAlias(..) => TypeNS, + ForeignItemKind::MacCall(..) => unreachable!(), }; let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; let vis = self.resolve_visibility(&item.vis); - let res = Res::Def(def_kind, def_id); - self.r.define(parent, item.ident, ns, (res, vis, item.span, expansion)); - self.r.visibilities.insert(local_def_id, vis); + self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion)); + self.r.feed_visibility(local_def_id, vis); } fn build_reduced_graph_for_block(&mut self, block: &Block) { @@ -995,7 +979,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let msg = format!("`{name}` is already in scope"); let note = "macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)"; - self.r.tcx.sess.struct_span_err(span, msg).note(note).emit(); + self.r.dcx().struct_span_err(span, msg).with_note(note).emit(); } } @@ -1006,8 +990,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { for attr in &item.attrs { if attr.has_name(sym::macro_use) { if self.parent_scope.module.parent.is_some() { - struct_span_err!( - self.r.tcx.sess, + struct_span_code_err!( + self.r.dcx(), item.span, E0468, "an `extern crate` loading macros must be at the crate root" @@ -1016,14 +1000,11 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } if let ItemKind::ExternCrate(Some(orig_name)) = item.kind { if orig_name == kw::SelfLower { - self.r - .tcx - .sess - .emit_err(errors::MacroUseExternCrateSelf { span: attr.span }); + self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span: attr.span }); } } let ill_formed = |span| { - struct_span_err!(self.r.tcx.sess, span, E0466, "bad macro import").emit(); + struct_span_code_err!(self.r.dcx(), span, E0466, "bad macro import").emit(); }; match attr.meta() { Some(meta) => match meta.kind { @@ -1048,9 +1029,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - let macro_use_import = |this: &Self, span| { + let macro_use_import = |this: &Self, span, warn_private| { this.r.arenas.alloc_import(ImportData { - kind: ImportKind::MacroUse, + kind: ImportKind::MacroUse { warn_private }, root_id: item.id, parent_scope: this.parent_scope, imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), @@ -1067,11 +1048,25 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let allow_shadowing = self.parent_scope.expansion == LocalExpnId::ROOT; if let Some(span) = import_all { - let import = macro_use_import(self, span); + let import = macro_use_import(self, span, false); self.r.potentially_unused_imports.push(import); module.for_each_child(self, |this, ident, ns, binding| { if ns == MacroNS { - let imported_binding = this.r.import(binding, import); + let imported_binding = + if this.r.is_accessible_from(binding.vis, this.parent_scope.module) { + this.r.import(binding, import) + } else if !this.r.is_builtin_macro(binding.res()) + && !this.r.macro_use_prelude.contains_key(&ident.name) + { + // - `!r.is_builtin_macro(res)` excluding the built-in macros such as `Debug` or `Hash`. + // - `!r.macro_use_prelude.contains_key(name)` excluding macros defined in other extern + // crates such as `std`. + // FIXME: This branch should eventually be removed. + let import = macro_use_import(this, span, true); + this.r.import(binding, import) + } else { + return; + }; this.add_macro_use_binding(ident.name, imported_binding, span, allow_shadowing); } }); @@ -1084,7 +1079,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { &self.parent_scope, ); if let Ok(binding) = result { - let import = macro_use_import(self, ident.span); + let import = macro_use_import(self, ident.span, false); self.r.potentially_unused_imports.push(import); let imported_binding = self.r.import(binding, import); self.add_macro_use_binding( @@ -1094,8 +1089,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { allow_shadowing, ); } else { - struct_span_err!( - self.r.tcx.sess, + struct_span_code_err!( + self.r.dcx(), ident.span, E0469, "imported macro not found" @@ -1112,21 +1107,17 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { for attr in attrs { if attr.has_name(sym::macro_escape) { let msg = "`#[macro_escape]` is a deprecated synonym for `#[macro_use]`"; - let mut err = self.r.tcx.sess.struct_span_warn(attr.span, msg); + let mut err = self.r.dcx().struct_span_warn(attr.span, msg); if let ast::AttrStyle::Inner = attr.style { - err.help("try an outer attribute: `#[macro_use]`").emit(); - } else { - err.emit(); + err.help("try an outer attribute: `#[macro_use]`"); } + err.emit(); } else if !attr.has_name(sym::macro_use) { continue; } if !attr.is_word() { - self.r - .tcx - .sess - .span_err(attr.span, "arguments to `macro_use` are not allowed here"); + self.r.dcx().span_err(attr.span, "arguments to `macro_use` are not allowed here"); } return true; } @@ -1180,24 +1171,21 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; let def_id = self.r.local_def_id(item.id); - let (macro_kind, ident, span, macro_rules) = match &item.kind { - ItemKind::MacroDef(def) => { - let macro_kind = self.r.macro_map[&def_id.to_def_id()].ext.macro_kind(); - (macro_kind, item.ident, item.span, def.macro_rules) - } + let (res, ident, span, macro_rules) = match &item.kind { + ItemKind::MacroDef(def) => (self.res(def_id), item.ident, item.span, def.macro_rules), ItemKind::Fn(..) => match self.proc_macro_stub(item) { Some((macro_kind, ident, span)) => { + let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id()); let macro_data = MacroData::new(self.r.dummy_ext(macro_kind)); self.r.macro_map.insert(def_id.to_def_id(), macro_data); self.r.proc_macro_stubs.insert(def_id); - (macro_kind, ident, span, false) + (res, ident, span, false) } None => return parent_scope.macro_rules, }, _ => unreachable!(), }; - let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id()); self.r.local_macro_def_scopes.insert(def_id, parent_scope.module); if macro_rules { @@ -1233,7 +1221,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.r.check_reserved_macro_name(ident, res); self.insert_unused_macro(ident, def_id, item.id); } - self.r.visibilities.insert(def_id, vis); + self.r.feed_visibility(def_id, vis); let scope = self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding( self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding { parent_macro_rules_scope: parent_scope.macro_rules, @@ -1257,7 +1245,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.insert_unused_macro(ident, def_id, item.id); } self.r.define(module, ident, MacroNS, (res, vis, span, expansion)); - self.r.visibilities.insert(def_id, vis); + self.r.feed_visibility(def_id, vis); self.parent_scope.macro_rules } } @@ -1359,26 +1347,21 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Trait impl item visibility is inherited from its trait when not specified // explicitly. In that case we cannot determine it here in early resolve, // so we leave a hole in the visibility table to be filled later. - self.r.visibilities.insert(local_def_id, vis); + self.r.feed_visibility(local_def_id, vis); } if ctxt == AssocCtxt::Trait { - let (def_kind, ns) = match item.kind { - AssocItemKind::Const(..) => (DefKind::AssocConst, ValueNS), - AssocItemKind::Fn(box Fn { ref sig, .. }) => { - if sig.decl.has_self() { - self.r.has_self.insert(local_def_id); - } - (DefKind::AssocFn, ValueNS) - } - AssocItemKind::Type(..) => (DefKind::AssocTy, TypeNS), + let ns = match item.kind { + AssocItemKind::Const(..) + | AssocItemKind::Delegation(..) + | AssocItemKind::Fn(..) => ValueNS, + AssocItemKind::Type(..) => TypeNS, AssocItemKind::MacCall(_) => bug!(), // handled above }; let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; - let res = Res::Def(def_kind, def_id); - self.r.define(parent, item.ident, ns, (res, vis, item.span, expansion)); + self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion)); } visit::walk_assoc_item(self, item, ctxt); @@ -1438,7 +1421,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.visit_invoc(sf.id); } else { let vis = self.resolve_visibility(&sf.vis); - self.r.visibilities.insert(self.r.local_def_id(sf.id), vis); + self.r.feed_visibility(self.r.local_def_id(sf.id), vis); visit::walk_field_def(self, sf); } } @@ -1457,10 +1440,9 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Define a name in the type namespace. let def_id = self.r.local_def_id(variant.id); - let res = Res::Def(DefKind::Variant, def_id.to_def_id()); let vis = self.resolve_visibility(&variant.vis); - self.r.define(parent, ident, TypeNS, (res, vis, variant.span, expn_id)); - self.r.visibilities.insert(def_id, vis); + self.r.define(parent, ident, TypeNS, (self.res(def_id), vis, variant.span, expn_id)); + self.r.feed_visibility(def_id, vis); // If the variant is marked as non_exhaustive then lower the visibility to within the crate. let ctor_vis = @@ -1471,12 +1453,11 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { }; // Define a constructor name in the value namespace. - if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(&variant.data) { + if let Some(ctor_node_id) = variant.data.ctor_node_id() { let ctor_def_id = self.r.local_def_id(ctor_node_id); - let ctor_res = - Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id.to_def_id()); + let ctor_res = self.res(ctor_def_id); self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id)); - self.r.visibilities.insert(ctor_def_id, ctor_vis); + self.r.feed_visibility(ctor_def_id, ctor_vis); } // Record field names for error reporting. diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 3b1f957c890..fc72d76c3a7 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -20,7 +20,7 @@ // separate step to be able to collapse the adjacent spans that rustfix // will remove // -// - `check_crate` finally emits the diagnostics based on the data generated +// - `check_unused` finally emits the diagnostics based on the data generated // in the last step use crate::imports::ImportKind; @@ -290,7 +290,7 @@ impl Resolver<'_, '_> { || import.expect_vis().is_public() || import.span.is_dummy() => { - if let ImportKind::MacroUse = import.kind { + if let ImportKind::MacroUse { .. } = import.kind { if !import.span.is_dummy() { self.lint_buffer.buffer_lint( MACRO_USE_EXTERN_CRATE, @@ -315,7 +315,7 @@ impl Resolver<'_, '_> { maybe_unused_extern_crates.insert(id, import.span); } } - ImportKind::MacroUse => { + ImportKind::MacroUse { .. } => { let msg = "unused `#[macro_use]` import"; self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.root_id, import.span, msg); } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index ab5d3b368eb..b77102c085c 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -111,7 +111,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { ItemKind::TyAlias(..) => DefKind::TyAlias, ItemKind::Static(s) => DefKind::Static(s.mutability), ItemKind::Const(..) => DefKind::Const, - ItemKind::Fn(..) => DefKind::Fn, + ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn, ItemKind::MacroDef(..) => { let macro_data = self.resolver.compile_macro(i, self.resolver.tcx.sess.edition()); let macro_kind = macro_data.ext.macro_kind(); @@ -156,29 +156,33 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind { - if let Some( - CoroutineKind::Async { closure_id, .. } | CoroutineKind::Gen { closure_id, .. }, - ) = sig.header.coro_kind - { - self.visit_generics(generics); - - // For async functions, we need to create their inner defs inside of a - // closure to match their desugared representation. Besides that, - // we must mirror everything that `visit::walk_fn` below does. - self.visit_fn_header(&sig.header); - for param in &sig.decl.inputs { - self.visit_param(param); - } - self.visit_fn_ret_ty(&sig.decl.output); - // If this async fn has no body (i.e. it's an async fn signature in a trait) - // then the closure_def will never be used, and we should avoid generating a - // def-id for it. - if let Some(body) = body { - let closure_def = - self.create_def(closure_id, kw::Empty, DefKind::Closure, span); - self.with_parent(closure_def, |this| this.visit_block(body)); + match sig.header.coroutine_kind { + Some(coroutine_kind) => { + self.visit_generics(generics); + + // For async functions, we need to create their inner defs inside of a + // closure to match their desugared representation. Besides that, + // we must mirror everything that `visit::walk_fn` below does. + self.visit_fn_header(&sig.header); + for param in &sig.decl.inputs { + self.visit_param(param); + } + self.visit_fn_ret_ty(&sig.decl.output); + // If this async fn has no body (i.e. it's an async fn signature in a trait) + // then the closure_def will never be used, and we should avoid generating a + // def-id for it. + if let Some(body) = body { + let closure_def = self.create_def( + coroutine_kind.closure_id(), + kw::Empty, + DefKind::Closure, + span, + ); + self.with_parent(closure_def, |this| this.visit_block(body)); + } + return; } - return; + None => {} } } @@ -255,7 +259,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { let def_kind = match &i.kind { - AssocItemKind::Fn(..) => DefKind::AssocFn, + AssocItemKind::Fn(..) | AssocItemKind::Delegation(..) => DefKind::AssocFn, AssocItemKind::Const(..) => DefKind::AssocConst, AssocItemKind::Type(..) => DefKind::AssocTy, AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id), @@ -284,11 +288,13 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { // Async closures desugar to closures inside of closures, so // we must create two defs. let closure_def = self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span); - match closure.coro_kind { - Some( - CoroutineKind::Async { closure_id, .. } - | CoroutineKind::Gen { closure_id, .. }, - ) => self.create_def(closure_id, kw::Empty, DefKind::Closure, expr.span), + match closure.coroutine_kind { + Some(coroutine_kind) => self.create_def( + coroutine_kind.closure_id(), + kw::Empty, + DefKind::Closure, + expr.span, + ), None => closure_def, } } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 542aff69e34..66dfee6c062 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -5,8 +5,10 @@ use rustc_ast::{self as ast, Crate, ItemKind, ModKind, NodeId, Path, CRATE_NODE_ use rustc_ast::{MetaItemKind, NestedMetaItem}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{pluralize, report_ambiguity_error, struct_span_err, SuggestionStyle}; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{ + pluralize, report_ambiguity_error, struct_span_code_err, Applicability, DiagCtxt, Diagnostic, + DiagnosticBuilder, ErrorGuaranteed, MultiSpan, SuggestionStyle, +}; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS}; @@ -98,6 +100,8 @@ pub(crate) struct ImportSuggestion { pub descr: &'static str, pub path: Path, pub accessible: bool, + // false if the path traverses a foreign `#[doc(hidden)]` item. + pub doc_visible: bool, pub via_import: bool, /// An extra note that should be issued if this item is suggested pub note: Option<String>, @@ -116,6 +120,10 @@ fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span { } impl<'a, 'tcx> Resolver<'a, 'tcx> { + pub(crate) fn dcx(&self) -> &'tcx DiagCtxt { + self.tcx.dcx() + } + pub(crate) fn report_errors(&mut self, krate: &Crate) { self.report_with_use_injections(krate); @@ -145,7 +153,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { BuiltinLintDiagnostics::AmbiguousGlobImports { diag }, ); } else { - let mut err = struct_span_err!(self.tcx.sess, diag.span, E0659, "{}", &diag.msg); + let mut err = struct_span_code_err!(self.dcx(), diag.span, E0659, "{}", &diag.msg); report_ambiguity_error(&mut err, diag); err.emit(); } @@ -246,15 +254,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let msg = format!("the name `{name}` is defined multiple times"); let mut err = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) { - (true, true) => struct_span_err!(self.tcx.sess, span, E0259, "{}", msg), + (true, true) => struct_span_code_err!(self.dcx(), span, E0259, "{}", msg), (true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() { - true => struct_span_err!(self.tcx.sess, span, E0254, "{}", msg), - false => struct_span_err!(self.tcx.sess, span, E0260, "{}", msg), + true => struct_span_code_err!(self.dcx(), span, E0254, "{}", msg), + false => struct_span_code_err!(self.dcx(), span, E0260, "{}", msg), }, _ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) { - (false, false) => struct_span_err!(self.tcx.sess, span, E0428, "{}", msg), - (true, true) => struct_span_err!(self.tcx.sess, span, E0252, "{}", msg), - _ => struct_span_err!(self.tcx.sess, span, E0255, "{}", msg), + (false, false) => struct_span_code_err!(self.dcx(), span, E0428, "{}", msg), + (true, true) => struct_span_code_err!(self.dcx(), span, E0252, "{}", msg), + _ => struct_span_code_err!(self.dcx(), span, E0255, "{}", msg), }, }; @@ -277,7 +285,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { use NameBindingKind::Import; let can_suggest = |binding: NameBinding<'_>, import: self::Import<'_>| { !binding.span.is_dummy() - && !matches!(import.kind, ImportKind::MacroUse | ImportKind::MacroExport) + && !matches!(import.kind, ImportKind::MacroUse { .. } | ImportKind::MacroExport) }; let import = match (&new_binding.kind, &old_binding.kind) { // If there are two imports where one or both have attributes then prefer removing the @@ -551,7 +559,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, span: Span, resolution_error: ResolutionError<'a>, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_> { match resolution_error { ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params) => { use errs::GenericParamsFromOuterItemLabel as Label; @@ -566,7 +574,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let def_id = match outer_res { Res::SelfTyParam { .. } => { err.label = Some(Label::SelfTyParam(span)); - return self.tcx.sess.create_err(err); + return self.dcx().create_err(err); } Res::SelfTyAlias { alias_to: def_id, .. } => { err.label = Some(Label::SelfTyAlias(reduce_impl_span_to_impl_keyword( @@ -574,7 +582,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.def_span(def_id), ))); err.refer_to_type_directly = Some(span); - return self.tcx.sess.create_err(err); + return self.dcx().create_err(err); } Res::Def(DefKind::TyParam, def_id) => { err.label = Some(Label::TyParam(self.def_span(def_id))); @@ -606,14 +614,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { err.sugg = Some(errs::GenericParamsFromOuterItemSugg { span, snippet }); } - self.tcx.sess.create_err(err) + self.dcx().create_err(err) } ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => self - .tcx - .sess + .dcx() .create_err(errs::NameAlreadyUsedInParameterList { span, first_use_span, name }), ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => { - self.tcx.sess.create_err(errs::MethodNotMemberOfTrait { + self.dcx().create_err(errs::MethodNotMemberOfTrait { span, method, trait_, @@ -624,7 +631,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }) } ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => { - self.tcx.sess.create_err(errs::TypeNotMemberOfTrait { + self.dcx().create_err(errs::TypeNotMemberOfTrait { span, type_, trait_, @@ -635,7 +642,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }) } ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => { - self.tcx.sess.create_err(errs::ConstNotMemberOfTrait { + self.dcx().create_err(errs::ConstNotMemberOfTrait { span, const_, trait_, @@ -652,8 +659,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let origin_sp = origin.iter().copied().collect::<Vec<_>>(); let msp = MultiSpan::from_spans(target_sp.clone()); - let mut err = struct_span_err!( - self.tcx.sess, + let mut err = struct_span_code_err!( + self.dcx(), msp, E0408, "variable `{}` is not bound in all patterns", @@ -706,19 +713,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { err } ResolutionError::VariableBoundWithDifferentMode(variable_name, first_binding_span) => { - self.tcx.sess.create_err(errs::VariableBoundWithDifferentMode { + self.dcx().create_err(errs::VariableBoundWithDifferentMode { span, first_binding_span, variable_name, }) } ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => self - .tcx - .sess + .dcx() .create_err(errs::IdentifierBoundMoreThanOnceInParameterList { span, identifier }), ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => self - .tcx - .sess + .dcx() .create_err(errs::IdentifierBoundMoreThanOnceInSamePattern { span, identifier }), ResolutionError::UndeclaredLabel { name, suggestion } => { let ((sub_reachable, sub_reachable_suggestion), sub_unreachable) = match suggestion @@ -744,7 +749,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // No similarly-named labels exist. None => ((None, None), None), }; - self.tcx.sess.create_err(errs::UndeclaredLabel { + self.dcx().create_err(errs::UndeclaredLabel { span, name, sub_reachable, @@ -769,22 +774,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }; (Some(suggestion), Some(mpart_suggestion)) }; - self.tcx.sess.create_err(errs::SelfImportsOnlyAllowedWithin { + self.dcx().create_err(errs::SelfImportsOnlyAllowedWithin { span, suggestion, mpart_suggestion, }) } ResolutionError::SelfImportCanOnlyAppearOnceInTheList => { - self.tcx.sess.create_err(errs::SelfImportCanOnlyAppearOnceInTheList { span }) + self.dcx().create_err(errs::SelfImportCanOnlyAppearOnceInTheList { span }) } - ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => self - .tcx - .sess - .create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span }), - ResolutionError::FailedToResolve { last_segment, label, suggestion, module } => { + ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => { + self.dcx().create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span }) + } + ResolutionError::FailedToResolve { segment, label, suggestion, module } => { let mut err = - struct_span_err!(self.tcx.sess, span, E0433, "failed to resolve: {}", &label); + struct_span_code_err!(self.dcx(), span, E0433, "failed to resolve: {}", &label); err.span_label(span, label); if let Some((suggestions, msg, applicability)) = suggestion { @@ -797,15 +801,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(ModuleOrUniformRoot::Module(module)) = module && let Some(module) = module.opt_def_id() - && let Some(last_segment) = last_segment + && let Some(segment) = segment { - self.find_cfg_stripped(&mut err, &last_segment, module); + self.find_cfg_stripped(&mut err, &segment, module); } err } ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => { - self.tcx.sess.create_err(errs::CannotCaptureDynamicEnvironmentInFnItem { span }) + self.dcx().create_err(errs::CannotCaptureDynamicEnvironmentInFnItem { span }) } ResolutionError::AttemptToUseNonConstantValueInConstant(ident, suggestion, current) => { // let foo =... @@ -844,7 +848,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ), }; - self.tcx.sess.create_err(errs::AttemptToUseNonConstantValueInConstant { + self.dcx().create_err(errs::AttemptToUseNonConstantValueInConstant { span, with, with_label, @@ -858,7 +862,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { article, shadowed_binding, shadowed_binding_span, - } => self.tcx.sess.create_err(errs::BindingShadowsSomethingUnacceptable { + } => self.dcx().create_err(errs::BindingShadowsSomethingUnacceptable { span, shadowing_binding, shadowed_binding, @@ -875,14 +879,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { name, }), ResolutionError::ForwardDeclaredGenericParam => { - self.tcx.sess.create_err(errs::ForwardDeclaredGenericParam { span }) + self.dcx().create_err(errs::ForwardDeclaredGenericParam { span }) } ResolutionError::ParamInTyOfConstParam { name, param_kind: is_type } => self - .tcx - .sess + .dcx() .create_err(errs::ParamInTyOfConstParam { span, name, param_kind: is_type }), ResolutionError::ParamInNonTrivialAnonConst { name, param_kind: is_type } => { - self.tcx.sess.create_err(errs::ParamInNonTrivialAnonConst { + self.dcx().create_err(errs::ParamInNonTrivialAnonConst { span, name, param_kind: is_type, @@ -894,11 +897,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }) } ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => self - .tcx - .sess + .dcx() .create_err(errs::ParamInEnumDiscriminant { span, name, param_kind: is_type }), ResolutionError::SelfInGenericParamDefault => { - self.tcx.sess.create_err(errs::SelfInGenericParamDefault { span }) + self.dcx().create_err(errs::SelfInGenericParamDefault { span }) } ResolutionError::UnreachableLabel { name, definition_span, suggestion } => { let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) = @@ -926,7 +928,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // No similarly-named labels exist. None => ((None, None), None), }; - self.tcx.sess.create_err(errs::UnreachableLabel { + self.dcx().create_err(errs::UnreachableLabel { span, name, definition_span, @@ -942,26 +944,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { trait_item_span, trait_path, } => { - let mut err = self.tcx.sess.struct_span_err_with_code( + self.dcx().struct_span_err( span, format!( "item `{name}` is an associated {kind}, which doesn't match its trait `{trait_path}`", ), - code, - ); - err.span_label(span, "does not match trait"); - err.span_label(trait_item_span, "item in trait"); - err + ) + .with_code(code) + .with_span_label(span, "does not match trait") + .with_span_label(trait_item_span, "item in trait") } ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => self - .tcx - .sess + .dcx() .create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }), - ResolutionError::InvalidAsmSym => { - self.tcx.sess.create_err(errs::InvalidAsmSym { span }) - } - ResolutionError::LowercaseSelf => { - self.tcx.sess.create_err(errs::LowercaseSelf { span }) + ResolutionError::InvalidAsmSym => self.dcx().create_err(errs::InvalidAsmSym { span }), + ResolutionError::LowercaseSelf => self.dcx().create_err(errs::LowercaseSelf { span }), + ResolutionError::BindingInNeverPattern => { + self.dcx().create_err(errs::BindingInNeverPattern { span }) } } } @@ -972,7 +971,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ) -> ErrorGuaranteed { match vis_resolution_error { VisResolutionError::Relative2018(span, path) => { - self.tcx.sess.create_err(errs::Relative2018 { + self.dcx().create_err(errs::Relative2018 { span, path_span: path.span, // intentionally converting to String, as the text would also be used as @@ -981,26 +980,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }) } VisResolutionError::AncestorOnly(span) => { - self.tcx.sess.create_err(errs::AncestorOnly(span)) + self.dcx().create_err(errs::AncestorOnly(span)) } VisResolutionError::FailedToResolve(span, label, suggestion) => self.into_struct_error( span, - ResolutionError::FailedToResolve { - last_segment: None, - label, - suggestion, - module: None, - }, + ResolutionError::FailedToResolve { segment: None, label, suggestion, module: None }, ), VisResolutionError::ExpectedFound(span, path_str, res) => { - self.tcx.sess.create_err(errs::ExpectedFound { span, res, path_str }) + self.dcx().create_err(errs::ExpectedFound { span, res, path_str }) } VisResolutionError::Indeterminate(span) => { - self.tcx.sess.create_err(errs::Indeterminate(span)) - } - VisResolutionError::ModuleOnly(span) => { - self.tcx.sess.create_err(errs::ModuleOnly(span)) + self.dcx().create_err(errs::Indeterminate(span)) } + VisResolutionError::ModuleOnly(span) => self.dcx().create_err(errs::ModuleOnly(span)), } .emit() } @@ -1153,10 +1145,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { { let mut candidates = Vec::new(); let mut seen_modules = FxHashSet::default(); - let mut worklist = vec![(start_module, ThinVec::<ast::PathSegment>::new(), true)]; + let start_did = start_module.def_id(); + let mut worklist = vec![( + start_module, + ThinVec::<ast::PathSegment>::new(), + true, + start_did.is_local() || !self.tcx.is_doc_hidden(start_did), + )]; let mut worklist_via_import = vec![]; - while let Some((in_module, path_segments, accessible)) = match worklist.pop() { + while let Some((in_module, path_segments, accessible, doc_visible)) = match worklist.pop() { None => worklist_via_import.pop(), Some(x) => Some(x), } { @@ -1199,6 +1197,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } + let res = name_binding.res(); + let did = match res { + Res::Def(DefKind::Ctor(..), did) => this.tcx.opt_parent(did), + _ => res.opt_def_id(), + }; + let child_doc_visible = doc_visible + && (did.map_or(true, |did| did.is_local() || !this.tcx.is_doc_hidden(did))); + // collect results based on the filter function // avoid suggesting anything from the same module in which we are resolving // avoid suggesting anything with a hygienic name @@ -1207,7 +1213,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && in_module != parent_scope.module && !ident.span.normalize_to_macros_2_0().from_expansion() { - let res = name_binding.res(); if filter_fn(res) { // create the path let mut segms = if lookup_ident.span.at_least_rust_2018() { @@ -1221,10 +1226,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { segms.push(ast::PathSegment::from_ident(ident)); let path = Path { span: name_binding.span, segments: segms, tokens: None }; - let did = match res { - Res::Def(DefKind::Ctor(..), did) => this.tcx.opt_parent(did), - _ => res.opt_def_id(), - }; if child_accessible { // Remove invisible match if exists @@ -1264,6 +1265,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { descr: res.descr(), path, accessible: child_accessible, + doc_visible: child_doc_visible, note, via_import, }); @@ -1284,7 +1286,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // add the module to the lookup if seen_modules.insert(module.def_id()) { if via_import { &mut worklist_via_import } else { &mut worklist } - .push((module, path_segments, child_accessible)); + .push((module, path_segments, child_accessible, child_doc_visible)); } } } @@ -1698,8 +1700,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Print the primary message. let descr = get_descr(binding); - let mut err = - struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident); + let mut err = struct_span_code_err!( + self.dcx(), + ident.span, + E0603, + "{} `{}` is private", + descr, + ident + ); err.span_label(ident.span, format!("private {descr}")); let mut not_publicly_reexported = false; @@ -1811,9 +1819,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { next_ident = source; Some(binding) } - ImportKind::Glob { .. } | ImportKind::MacroUse | ImportKind::MacroExport => { - Some(binding) - } + ImportKind::Glob { .. } + | ImportKind::MacroUse { .. } + | ImportKind::MacroExport => Some(binding), ImportKind::ExternCrate { .. } => None, }, _ => None, @@ -2440,7 +2448,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn find_cfg_stripped( &mut self, err: &mut Diagnostic, - last_segment: &Symbol, + segment: &Symbol, module: DefId, ) { let local_items; @@ -2459,7 +2467,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }; for &StrippedCfgItem { parent_module, name, ref cfg } in symbols { - if parent_module != module || name.name != *last_segment { + if parent_module != module || name.name != *segment { continue; } @@ -2694,8 +2702,26 @@ fn show_candidates( Vec::new(); candidates.iter().for_each(|c| { - (if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings }) - .push((pprust::path_to_string(&c.path), c.descr, c.did, &c.note, c.via_import)) + if c.accessible { + // Don't suggest `#[doc(hidden)]` items from other crates + if c.doc_visible { + accessible_path_strings.push(( + pprust::path_to_string(&c.path), + c.descr, + c.did, + &c.note, + c.via_import, + )) + } + } else { + inaccessible_path_strings.push(( + pprust::path_to_string(&c.path), + c.descr, + c.did, + &c.note, + c.via_import, + )) + } }); // we want consistent results across executions, but candidates are produced @@ -2794,9 +2820,7 @@ fn show_candidates( err.help(msg); } true - } else if !matches!(mode, DiagnosticMode::Import) { - assert!(!inaccessible_path_strings.is_empty()); - + } else if !(inaccessible_path_strings.is_empty() || matches!(mode, DiagnosticMode::Import)) { let prefix = if let DiagnosticMode::Pattern = mode { "you might have meant to match on " } else { diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index a71c50dd82f..3443bbe6e11 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -186,7 +186,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { ) -> Option<Option<Visibility>> { match parent_id { ParentId::Def(def_id) => (nominal_vis != self.current_private_vis - && self.r.visibilities[&def_id] != self.current_private_vis) + && self.r.tcx.local_visibility(def_id) != self.current_private_vis) .then_some(Some(self.current_private_vis)), ParentId::Import(_) => Some(None), } @@ -222,7 +222,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { } fn update_field(&mut self, def_id: LocalDefId, parent_id: LocalDefId) { - self.update_def(def_id, self.r.visibilities[&def_id], ParentId::Def(parent_id)); + self.update_def(def_id, self.r.tcx.local_visibility(def_id), ParentId::Def(parent_id)); } } @@ -277,7 +277,8 @@ impl<'r, 'ast, 'tcx> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r, 't | ast::ItemKind::TraitAlias(..) | ast::ItemKind::MacroDef(..) | ast::ItemKind::ForeignMod(..) - | ast::ItemKind::Fn(..) => return, + | ast::ItemKind::Fn(..) + | ast::ItemKind::Delegation(..) => return, } } } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 1fdb193e571..821b1e946f3 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -486,6 +486,15 @@ pub(crate) struct LowercaseSelf { pub(crate) span: Span, } +#[derive(Debug)] +#[derive(Diagnostic)] +#[diag(resolve_binding_in_never_pattern)] +pub(crate) struct BindingInNeverPattern { + #[primary_span] + #[suggestion(code = "_", applicability = "machine-applicable", style = "short")] + pub(crate) span: Span, +} + #[derive(Diagnostic)] #[diag(resolve_trait_impl_duplicate, code = "E0201")] pub(crate) struct TraitImplDuplicate { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index a9f7002e564..7fb9db16e9c 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -377,6 +377,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ignore_binding: Option<NameBinding<'a>>, ) -> Result<NameBinding<'a>, Determinacy> { bitflags::bitflags! { + #[derive(Clone, Copy)] struct Flags: u8 { const MACRO_RULES = 1 << 0; const MODULE = 1 << 1; @@ -1201,7 +1202,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; self.report_error(span, error); - self.tcx.sess.span_delayed_bug(span, CG_BUG_STR); + self.dcx().span_delayed_bug(span, CG_BUG_STR); } return Res::Err; @@ -1380,13 +1381,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { continue; } } - return PathResult::failed( - ident.span, - false, - finalize.is_some(), - module, - || ("there are too many leading `super` keywords".to_string(), None), - ); + return PathResult::failed(ident, false, finalize.is_some(), module, || { + ("there are too many leading `super` keywords".to_string(), None) + }); } if segment_idx == 0 { if name == kw::SelfLower { @@ -1418,7 +1415,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Report special messages for path segment keywords in wrong positions. if ident.is_path_segment_keyword() && segment_idx != 0 { - return PathResult::failed(ident.span, false, finalize.is_some(), module, || { + return PathResult::failed(ident, false, finalize.is_some(), module, || { let name_str = if name == kw::PathRoot { "crate root".to_string() } else { @@ -1496,7 +1493,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { record_segment_res(self, res); } else if res == Res::ToolMod && !is_last && opt_ns.is_some() { if binding.is_import() { - self.tcx.sess.emit_err(errors::ToolModuleImported { + self.dcx().emit_err(errors::ToolModuleImported { span: ident.span, import: binding.span, }); @@ -1514,7 +1511,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { )); } else { return PathResult::failed( - ident.span, + ident, is_last, finalize.is_some(), module, @@ -1540,24 +1537,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - 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, - ) - }, - ); + return PathResult::failed(ident, 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 c2306e3ea7d..ad60caed354 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -17,7 +17,7 @@ use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult}; use rustc_ast::NodeId; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::intern::Interned; -use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan}; +use rustc_errors::{pluralize, struct_span_code_err, Applicability, MultiSpan}; use rustc_hir::def::{self, DefKind, PartialRes}; use rustc_middle::metadata::ModChild; use rustc_middle::metadata::Reexport; @@ -80,7 +80,11 @@ pub(crate) enum ImportKind<'a> { target: Ident, id: NodeId, }, - MacroUse, + MacroUse { + /// A field has been added indicating whether it should be reported as a lint, + /// addressing issue#119301. + warn_private: bool, + }, MacroExport, } @@ -127,7 +131,7 @@ impl<'a> std::fmt::Debug for ImportKind<'a> { .field("target", target) .field("id", id) .finish(), - MacroUse => f.debug_struct("MacroUse").finish(), + MacroUse { .. } => f.debug_struct("MacroUse").finish(), MacroExport => f.debug_struct("MacroExport").finish(), } } @@ -197,7 +201,7 @@ impl<'a> ImportData<'a> { ImportKind::Single { id, .. } | ImportKind::Glob { id, .. } | ImportKind::ExternCrate { id, .. } => Some(id), - ImportKind::MacroUse | ImportKind::MacroExport => None, + ImportKind::MacroUse { .. } | ImportKind::MacroExport => None, } } @@ -207,7 +211,7 @@ impl<'a> ImportData<'a> { ImportKind::Single { id, .. } => Reexport::Single(to_def_id(id)), ImportKind::Glob { id, .. } => Reexport::Glob(to_def_id(id)), ImportKind::ExternCrate { id, .. } => Reexport::ExternCrate(to_def_id(id)), - ImportKind::MacroUse => Reexport::MacroUse, + ImportKind::MacroUse { .. } => Reexport::MacroUse, ImportKind::MacroExport => Reexport::MacroExport, } } @@ -686,7 +690,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .collect::<Vec<_>>(); let msg = format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),); - let mut diag = struct_span_err!(self.tcx.sess, span, E0432, "{}", &msg); + let mut diag = struct_span_code_err!(self.dcx(), span, E0432, "{}", &msg); if let Some((_, UnresolvedImportError { note: Some(note), .. })) = errors.iter().last() { diag.note(note.clone()); @@ -826,8 +830,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } source_binding @ (Ok(..) | Err(Determined)) => { if source_binding.is_ok() { - this.tcx - .sess + this.dcx() .create_err(IsNotDirectlyImportable { span: import.span, target }) .emit(); } @@ -877,8 +880,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { span_bug!(import.span, "inconsistent resolution for an import"); } } else if self.privacy_errors.is_empty() { - self.tcx - .sess + self.dcx() .create_err(CannotDetermineImportResolution { span: import.span }) .emit(); } @@ -888,6 +890,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PathResult::Failed { is_error_from_last_segment: false, span, + segment_name, label, suggestion, module, @@ -897,7 +900,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.report_error( span, ResolutionError::FailedToResolve { - last_segment: None, + segment: Some(segment_name), label, suggestion, module, @@ -1002,7 +1005,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { UNUSED_IMPORTS, id, import.span, - msg.to_string(), + msg, BuiltinLintDiagnostics::RedundantImportVisibility { max_vis: max_vis.to_string(def_id, self.tcx), span: import.span, @@ -1063,15 +1066,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { initial_binding.res() }); let res = binding.res(); - let has_ambiguity_error = this - .ambiguity_errors - .iter() - .filter(|error| !error.warning) - .next() - .is_some(); + let has_ambiguity_error = + this.ambiguity_errors.iter().any(|error| !error.warning); if res == Res::Err || has_ambiguity_error { - this.tcx - .sess + this.dcx() .span_delayed_bug(import.span, "some error happened for an import"); return; } @@ -1080,8 +1078,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { span_bug!(import.span, "inconsistent resolution for an import"); } } else if this.privacy_errors.is_empty() { - this.tcx - .sess + this.dcx() .create_err(CannotDetermineImportResolution { span: import.span }) .emit(); } @@ -1241,25 +1238,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ); } else { if ns == TypeNS { - let mut err = if crate_private_reexport { - self.tcx.sess.create_err(CannotBeReexportedCratePublicNS { + let err = if crate_private_reexport { + self.dcx().create_err(CannotBeReexportedCratePublicNS { span: import.span, ident, }) } else { - self.tcx - .sess + self.dcx() .create_err(CannotBeReexportedPrivateNS { span: import.span, ident }) }; err.emit(); } else { let mut err = if crate_private_reexport { - self.tcx - .sess + self.dcx() .create_err(CannotBeReexportedCratePublic { span: import.span, ident }) } else { - self.tcx - .sess + self.dcx() .create_err(CannotBeReexportedPrivate { span: import.span, ident }) }; @@ -1382,12 +1376,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let ImportKind::Glob { id, is_prelude, .. } = import.kind else { unreachable!() }; let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else { - self.tcx.sess.create_err(CannotGlobImportAllCrates { span: import.span }).emit(); + self.dcx().emit_err(CannotGlobImportAllCrates { span: import.span }); return; }; if module.is_trait() { - self.tcx.sess.create_err(ItemsInTraitsAreNotImportable { span: import.span }).emit(); + self.dcx().emit_err(ItemsInTraitsAreNotImportable { span: import.span }); return; } else if module == import.parent_scope.module { return; @@ -1492,7 +1486,7 @@ fn import_kind_to_string(import_kind: &ImportKind<'_>) -> String { ImportKind::Single { source, .. } => source.to_string(), ImportKind::Glob { .. } => "*".to_string(), ImportKind::ExternCrate { .. } => "<extern crate>".to_string(), - ImportKind::MacroUse => "#[macro_use]".to_string(), + ImportKind::MacroUse { .. } => "#[macro_use]".to_string(), ImportKind::MacroExport => "#[macro_export]".to_string(), } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 07c8c036c9e..abd724a6cc2 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -16,7 +16,7 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; -use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg}; +use rustc_errors::{Applicability, DiagnosticArgValue, IntoDiagnosticArg}; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; @@ -65,6 +65,8 @@ enum IsRepeatExpr { Yes, } +struct IsNeverPattern; + /// Describes whether an `AnonConst` is a type level const arg or /// some other form of anon const (i.e. inline consts or enum discriminants) #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -394,13 +396,18 @@ pub(crate) enum PathSource<'a> { TupleStruct(Span, &'a [Span]), // `m::A::B` in `<T as m::A>::B::C`. TraitItem(Namespace), + // Paths in delegation item + Delegation, } impl<'a> PathSource<'a> { fn namespace(self) -> Namespace { match self { PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS, - PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct(..) => ValueNS, + PathSource::Expr(..) + | PathSource::Pat + | PathSource::TupleStruct(..) + | PathSource::Delegation => ValueNS, PathSource::TraitItem(ns) => ns, } } @@ -412,7 +419,7 @@ impl<'a> PathSource<'a> { | PathSource::Pat | PathSource::Struct | PathSource::TupleStruct(..) => true, - PathSource::Trait(_) | PathSource::TraitItem(..) => false, + PathSource::Trait(_) | PathSource::TraitItem(..) | PathSource::Delegation => false, } } @@ -454,6 +461,7 @@ impl<'a> PathSource<'a> { }, _ => "value", }, + PathSource::Delegation => "function", } } @@ -521,10 +529,11 @@ impl<'a> PathSource<'a> { Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true, _ => false, }, + PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)), } } - fn error_code(self, has_unexpected_resolution: bool) -> DiagnosticId { + fn error_code(self, has_unexpected_resolution: bool) -> String { use rustc_errors::error_code; match (self, has_unexpected_resolution) { (PathSource::Trait(_), true) => error_code!(E0404), @@ -533,8 +542,8 @@ impl<'a> PathSource<'a> { (PathSource::Type, false) => error_code!(E0412), (PathSource::Struct, true) => error_code!(E0574), (PathSource::Struct, false) => error_code!(E0422), - (PathSource::Expr(..), true) => error_code!(E0423), - (PathSource::Expr(..), false) => error_code!(E0425), + (PathSource::Expr(..), true) | (PathSource::Delegation, true) => error_code!(E0423), + (PathSource::Expr(..), false) | (PathSource::Delegation, false) => error_code!(E0425), (PathSource::Pat | PathSource::TupleStruct(..), true) => error_code!(E0532), (PathSource::Pat | PathSource::TupleStruct(..), false) => error_code!(E0531), (PathSource::TraitItem(..), true) => error_code!(E0575), @@ -916,8 +925,10 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, &sig.decl.output, ); - if let Some((coro_node_id, _)) = - sig.header.coro_kind.map(|coro_kind| coro_kind.return_id()) + if let Some((coro_node_id, _)) = sig + .header + .coroutine_kind + .map(|coroutine_kind| coroutine_kind.return_id()) { this.record_lifetime_params_for_impl_trait(coro_node_id); } @@ -942,8 +953,10 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, this.visit_generics(generics); let declaration = &sig.decl; - let coro_node_id = - sig.header.coro_kind.map(|coro_kind| coro_kind.return_id()); + let coro_node_id = sig + .header + .coroutine_kind + .map(|coroutine_kind| coroutine_kind.return_id()); this.with_lifetime_rib( LifetimeRibKind::AnonymousCreateParameter { @@ -1660,8 +1673,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } else { ("`'_` cannot be used here", "`'_` is a reserved lifetime name") }; - let mut diag = rustc_errors::struct_span_err!( - self.r.tcx.sess, + let mut diag = rustc_errors::struct_span_code_err!( + self.r.dcx(), lifetime.ident.span, E0637, "{}", @@ -1801,7 +1814,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { PathSource::Expr(..) | PathSource::Pat | PathSource::Struct - | PathSource::TupleStruct(..) => true, + | PathSource::TupleStruct(..) + | PathSource::Delegation => true, }; if inferred { // Do not create a parameter for patterns and expressions: type checking can infer @@ -1849,8 +1863,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } | LifetimeRibKind::AnonymousWarn(_) => { let sess = self.r.tcx.sess; - let mut err = rustc_errors::struct_span_err!( - sess, + let mut err = rustc_errors::struct_span_code_err!( + sess.dcx(), path_span, E0726, "implicit elided lifetime not allowed here" @@ -2297,11 +2311,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let report_error = |this: &Self, ns| { if this.should_report_errs() { let what = if ns == TypeNS { "type parameters" } else { "local variables" }; - this.r - .tcx - .sess - .create_err(ImportsCannotReferTo { span: ident.span, what }) - .emit(); + this.r.dcx().emit_err(ImportsCannotReferTo { span: ident.span, what }); } }; @@ -2514,6 +2524,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { visit::walk_item(self, item); } + ItemKind::Delegation(ref delegation) => { + self.resolve_delegation(delegation); + } + ItemKind::ExternCrate(..) => {} ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"), @@ -2594,13 +2608,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } if param.ident.name == kw::UnderscoreLifetime { - rustc_errors::struct_span_err!( - self.r.tcx.sess, + rustc_errors::struct_span_code_err!( + self.r.dcx(), param.ident.span, E0637, "`'_` cannot be used here" ) - .span_label(param.ident.span, "`'_` is a reserved lifetime name") + .with_span_label(param.ident.span, "`'_` is a reserved lifetime name") .emit(); // Record lifetime res, so lowering knows there is something fishy. self.record_lifetime_param(param.id, LifetimeRes::Error); @@ -2608,14 +2622,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } if param.ident.name == kw::StaticLifetime { - rustc_errors::struct_span_err!( - self.r.tcx.sess, + rustc_errors::struct_span_code_err!( + self.r.dcx(), param.ident.span, E0262, "invalid lifetime parameter name: `{}`", param.ident, ) - .span_label(param.ident.span, "'static is a reserved lifetime name") + .with_span_label(param.ident.span, "'static is a reserved lifetime name") .emit(); // Record lifetime res, so lowering knows there is something fishy. self.record_lifetime_param(param.id, LifetimeRes::Error); @@ -2790,6 +2804,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { AssocItemKind::Fn(box Fn { generics, .. }) => { walk_assoc_item(self, generics, LifetimeBinderKind::Function, item); } + AssocItemKind::Delegation(delegation) => { + self.resolve_delegation(delegation); + } AssocItemKind::Type(box TyAlias { generics, .. }) => self .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { walk_assoc_item(this, generics, LifetimeBinderKind::Item, item) @@ -3036,6 +3053,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }, ); } + AssocItemKind::Delegation(box delegation) => { + debug!("resolve_implementation AssocItemKind::Delegation"); + self.check_trait_item( + item.id, + item.ident, + &item.kind, + ValueNS, + item.span, + seen_trait_items, + |i, s, c| MethodNotMemberOfTrait(i, s, c), + ); + self.resolve_delegation(delegation); + } AssocItemKind::MacCall(_) => { panic!("unexpanded macro in resolve!") } @@ -3074,17 +3104,34 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding); debug!(?binding); } + + let feed_visibility = |this: &mut Self, def_id| { + let vis = this.r.tcx.visibility(def_id); + let vis = if vis.is_visible_locally() { + vis.expect_local() + } else { + this.r.dcx().span_delayed_bug( + span, + "error should be emitted when an unexpected trait item is used", + ); + rustc_middle::ty::Visibility::Public + }; + this.r.feed_visibility(this.r.local_def_id(id), vis); + }; + let Some(binding) = binding else { // We could not find the method: report an error. let candidate = self.find_similarly_named_assoc_item(ident.name, kind); let path = &self.current_trait_ref.as_ref().unwrap().1.path; let path_names = path_names_to_string(path); self.report_error(span, err(ident, path_names, candidate)); + feed_visibility(self, module.def_id()); return; }; let res = binding.res(); let Res::Def(def_kind, id_in_trait) = res else { bug!() }; + feed_visibility(self, id_in_trait); match seen_trait_items.entry(id_in_trait) { Entry::Occupied(entry) => { @@ -3106,7 +3153,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { match (def_kind, kind) { (DefKind::AssocTy, AssocItemKind::Type(..)) | (DefKind::AssocFn, AssocItemKind::Fn(..)) - | (DefKind::AssocConst, AssocItemKind::Const(..)) => { + | (DefKind::AssocConst, AssocItemKind::Const(..)) + | (DefKind::AssocFn, AssocItemKind::Delegation(..)) => { self.r.record_partial_res(id, PartialRes::new(res)); return; } @@ -3119,6 +3167,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { AssocItemKind::Const(..) => (rustc_errors::error_code!(E0323), "const"), AssocItemKind::Fn(..) => (rustc_errors::error_code!(E0324), "method"), AssocItemKind::Type(..) => (rustc_errors::error_code!(E0325), "type"), + AssocItemKind::Delegation(..) => (rustc_errors::error_code!(E0324), "method"), AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"), }; let trait_path = path_names_to_string(path); @@ -3142,6 +3191,32 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }) } + fn resolve_delegation(&mut self, delegation: &'ast Delegation) { + self.smart_resolve_path( + delegation.id, + &delegation.qself, + &delegation.path, + PathSource::Delegation, + ); + if let Some(qself) = &delegation.qself { + self.visit_ty(&qself.ty); + } + self.visit_path(&delegation.path, delegation.id); + if let Some(body) = &delegation.body { + // `PatBoundCtx` is not necessary in this context + let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; + + let span = delegation.path.segments.last().unwrap().ident.span; + self.fresh_binding( + Ident::new(kw::SelfLower, span), + delegation.id, + PatternSource::FnParam, + &mut bindings, + ); + self.visit_block(body); + } + } + fn resolve_params(&mut self, params: &'ast [Param]) { let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| { @@ -3173,12 +3248,31 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.resolve_pattern_top(&local.pat, PatternSource::Let); } - /// build a map from pattern identifiers to binding-info's. - /// this is done hygienically. This could arise for a macro - /// that expands into an or-pattern where one 'x' was from the - /// user and one 'x' came from the macro. - fn binding_mode_map(&mut self, pat: &Pat) -> FxIndexMap<Ident, BindingInfo> { + /// Build a map from pattern identifiers to binding-info's, and check the bindings are + /// consistent when encountering or-patterns and never patterns. + /// This is done hygienically: this could arise for a macro that expands into an or-pattern + /// where one 'x' was from the user and one 'x' came from the macro. + /// + /// A never pattern by definition indicates an unreachable case. For example, matching on + /// `Result<T, &!>` could look like: + /// ```rust + /// # #![feature(never_type)] + /// # #![feature(never_patterns)] + /// # fn bar(_x: u32) {} + /// let foo: Result<u32, &!> = Ok(0); + /// match foo { + /// Ok(x) => bar(x), + /// Err(&!), + /// } + /// ``` + /// This extends to product types: `(x, !)` is likewise unreachable. So it doesn't make sense to + /// have a binding here, and we tell the user to use `_` instead. + fn compute_and_check_binding_map( + &mut self, + pat: &Pat, + ) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> { let mut binding_map = FxIndexMap::default(); + let mut is_never_pat = false; pat.walk(&mut |pat| { match pat.kind { @@ -3190,18 +3284,27 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { PatKind::Or(ref ps) => { // Check the consistency of this or-pattern and // then add all bindings to the larger map. - for bm in self.check_consistent_bindings(ps) { - binding_map.extend(bm); + match self.compute_and_check_or_pat_binding_map(ps) { + Ok(bm) => binding_map.extend(bm), + Err(IsNeverPattern) => is_never_pat = true, } return false; } + PatKind::Never => is_never_pat = true, _ => {} } true }); - binding_map + if is_never_pat { + for (_, binding) in binding_map { + self.report_error(binding.span, ResolutionError::BindingInNeverPattern); + } + Err(IsNeverPattern) + } else { + Ok(binding_map) + } } fn is_base_res_local(&self, nid: NodeId) -> bool { @@ -3211,33 +3314,52 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ) } - /// Checks that all of the arms in an or-pattern have exactly the - /// same set of bindings, with the same binding modes for each. - fn check_consistent_bindings( + /// Compute the binding map for an or-pattern. Checks that all of the arms in the or-pattern + /// have exactly the same set of bindings, with the same binding modes for each. + /// Returns the computed binding map and a boolean indicating whether the pattern is a never + /// pattern. + /// + /// A never pattern by definition indicates an unreachable case. For example, destructuring a + /// `Result<T, &!>` could look like: + /// ```rust + /// # #![feature(never_type)] + /// # #![feature(never_patterns)] + /// # fn foo() -> Result<bool, &'static !> { Ok(true) } + /// let (Ok(x) | Err(&!)) = foo(); + /// # let _ = x; + /// ``` + /// Because the `Err(&!)` branch is never reached, it does not need to have the same bindings as + /// the other branches of the or-pattern. So we must ignore never pattern when checking the + /// bindings of an or-pattern. + /// Moreover, if all the subpatterns are never patterns (e.g. `Ok(!) | Err(!)`), then the + /// pattern as a whole counts as a never pattern (since it's definitionallly unreachable). + fn compute_and_check_or_pat_binding_map( &mut self, pats: &[P<Pat>], - ) -> Vec<FxIndexMap<Ident, BindingInfo>> { - // pats is consistent. + ) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> { let mut missing_vars = FxIndexMap::default(); let mut inconsistent_vars = FxIndexMap::default(); - // 1) Compute the binding maps of all arms. - let maps = pats.iter().map(|pat| self.binding_mode_map(pat)).collect::<Vec<_>>(); + // 1) Compute the binding maps of all arms; we must ignore never patterns here. + let not_never_pats = pats + .iter() + .filter_map(|pat| { + let binding_map = self.compute_and_check_binding_map(pat).ok()?; + Some((binding_map, pat)) + }) + .collect::<Vec<_>>(); // 2) Record any missing bindings or binding mode inconsistencies. - for (map_outer, pat_outer) in maps.iter().zip(pats.iter()) { + for (map_outer, pat_outer) in not_never_pats.iter() { // Check against all arms except for the same pattern which is always self-consistent. - let inners = maps + let inners = not_never_pats .iter() - .zip(pats.iter()) .filter(|(_, pat)| pat.id != pat_outer.id) - .flat_map(|(map, _)| map) - .map(|(key, binding)| (key.name, map_outer.get(key), binding)); - - let inners = inners.collect::<Vec<_>>(); + .flat_map(|(map, _)| map); - for (name, info, &binding_inner) in inners { - match info { + for (key, binding_inner) in inners { + let name = key.name; + match map_outer.get(key) { None => { // The inner binding is missing in the outer. let binding_error = @@ -3278,19 +3400,32 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(name, v.1)); } - // 5) Finally bubble up all the binding maps. - maps + // 5) Bubble up the final binding map. + if not_never_pats.is_empty() { + // All the patterns are never patterns, so the whole or-pattern is one too. + Err(IsNeverPattern) + } else { + let mut binding_map = FxIndexMap::default(); + for (bm, _) in not_never_pats { + binding_map.extend(bm); + } + Ok(binding_map) + } } - /// Check the consistency of the outermost or-patterns. - fn check_consistent_bindings_top(&mut self, pat: &'ast Pat) { + /// Check the consistency of bindings wrt or-patterns and never patterns. + fn check_consistent_bindings(&mut self, pat: &'ast Pat) { + let mut is_or_or_never = false; pat.walk(&mut |pat| match pat.kind { - PatKind::Or(ref ps) => { - self.check_consistent_bindings(ps); + PatKind::Or(..) | PatKind::Never => { + is_or_or_never = true; false } _ => true, - }) + }); + if is_or_or_never { + let _ = self.compute_and_check_binding_map(pat); + } } fn resolve_arm(&mut self, arm: &'ast Arm) { @@ -3319,7 +3454,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { visit::walk_pat(self, pat); self.resolve_pattern_inner(pat, pat_src, bindings); // This has to happen *after* we determine which pat_idents are variants: - self.check_consistent_bindings_top(pat); + self.check_consistent_bindings(pat); } /// Resolve bindings in a pattern. This is a helper to `resolve_pattern`. @@ -3547,7 +3682,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { Res::SelfCtor(_) => { // We resolve `Self` in pattern position as an ident sometimes during recovery, // so delay a bug instead of ICEing. - self.r.tcx.sess.span_delayed_bug( + self.r.dcx().span_delayed_bug( ident.span, "unexpected `SelfCtor` in pattern, expected identifier" ); @@ -3681,12 +3816,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node); // overwrite all properties with the parent's error message - err.message = take(&mut parent_err.message); + err.messages = take(&mut parent_err.messages); err.code = take(&mut parent_err.code); swap(&mut err.span, &mut parent_err.span); err.children = take(&mut parent_err.children); err.sort_span = parent_err.sort_span; - err.is_lint = parent_err.is_lint; + err.is_lint = parent_err.is_lint.clone(); // merge the parent's suggestions with the typo suggestions fn append_result<T, E>(res1: &mut Result<Vec<T>, E>, res2: Result<Vec<T>, E>) { @@ -3981,11 +4116,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { label, suggestion, module, + segment_name, } => { return Err(respan( span, ResolutionError::FailedToResolve { - last_segment: None, + segment: Some(segment_name), label, suggestion, module, @@ -4246,11 +4382,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }); } - ExprKind::ForLoop(ref pat, ref iter_expr, ref block, label) => { - self.visit_expr(iter_expr); + ExprKind::ForLoop { ref pat, ref iter, ref body, label, kind: _ } => { + self.visit_expr(iter); self.with_rib(ValueNS, RibKind::Normal, |this| { this.resolve_pattern_top(pat, PatternSource::For); - this.resolve_labeled_block(label, expr.id, block); + this.resolve_labeled_block(label, expr.id, body); }); } @@ -4294,7 +4430,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // // Similarly, `gen |x| ...` gets desugared to `|x| gen {...}`, so we handle that too. ExprKind::Closure(box ast::Closure { - coro_kind: Some(_), + coroutine_kind: Some(_), ref fn_decl, ref body, .. @@ -4534,13 +4670,24 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } } -struct LifetimeCountVisitor<'a, 'b, 'tcx> { +/// Walks the whole crate in DFS order, visiting each item, counting the declared number of +/// lifetime generic parameters and function parameters. +struct ItemInfoCollector<'a, 'b, 'tcx> { r: &'b mut Resolver<'a, 'tcx>, } -/// Walks the whole crate in DFS order, visiting each item, counting the declared number of -/// lifetime generic parameters. -impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> { +impl ItemInfoCollector<'_, '_, '_> { + fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) { + let def_id = self.r.local_def_id(id); + self.r.fn_parameter_counts.insert(def_id, sig.decl.inputs.len()); + + if sig.decl.has_self() { + self.r.has_self.insert(def_id); + } + } +} + +impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { fn visit_item(&mut self, item: &'ast Item) { match &item.kind { ItemKind::TyAlias(box TyAlias { ref generics, .. }) @@ -4552,6 +4699,10 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> { | ItemKind::Impl(box Impl { ref generics, .. }) | ItemKind::Trait(box Trait { ref generics, .. }) | ItemKind::TraitAlias(ref generics, _) => { + if let ItemKind::Fn(box Fn { ref sig, .. }) = &item.kind { + self.collect_fn_info(sig, item.id); + } + let def_id = self.r.local_def_id(item.id); let count = generics .params @@ -4569,14 +4720,27 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> { | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(..) | ItemKind::MacCall(..) => {} + ItemKind::Delegation(..) => { + // Delegated functions have lifetimes, their count is not necessarily zero. + // But skipping the delegation items here doesn't mean that the count will be considered zero, + // it means there will be a panic when retrieving the count, + // but for delegation items we are never actually retrieving that count in practice. + } } visit::walk_item(self, item) } + + fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) { + if let AssocItemKind::Fn(box Fn { ref sig, .. }) = &item.kind { + self.collect_fn_info(sig, item.id); + } + visit::walk_assoc_item(self, item, ctxt); + } } impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) { - visit::walk_crate(&mut LifetimeCountVisitor { r: self }, krate); + visit::walk_crate(&mut ItemInfoCollector { r: self }, krate); let mut late_resolution_visitor = LateResolutionVisitor::new(self); late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); visit::walk_crate(&mut late_resolution_visitor, krate); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index df30c185c60..abb0a7a465a 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -8,7 +8,7 @@ use crate::{PathResult, PathSource, Segment}; use rustc_hir::def::Namespace::{self, *}; use rustc_ast::ptr::P; -use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt}; +use rustc_ast::visit::{walk_ty, FnCtxt, FnKind, LifetimeCtxt, Visitor}; use rustc_ast::{ self as ast, AssocItemKind, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind, MethodCall, NodeId, Path, Ty, TyKind, DUMMY_NODE_ID, @@ -16,7 +16,7 @@ use rustc_ast::{ 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, + pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, SuggestionStyle, }; use rustc_hir as hir; @@ -424,16 +424,13 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { span: Span, source: PathSource<'_>, res: Option<Res>, - ) -> (DiagnosticBuilder<'tcx, ErrorGuaranteed>, Vec<ImportSuggestion>) { + ) -> (DiagnosticBuilder<'tcx>, 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, - base_error.msg.clone(), - code, - ); + let mut err = self.r.dcx().struct_span_err(base_error.span, base_error.msg.clone()); + err.code(code); self.suggest_at_operator_in_slice_pat_with_range(&mut err, path); self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span); @@ -520,7 +517,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { continue; }; for bound in bounds { - let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None) = bound + let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifiers::NONE) = bound else { continue; }; @@ -659,7 +656,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let typo_sugg = self .lookup_typo_candidate(path, following_seg, source.namespace(), is_expected) .to_opt_suggestion(); - if path.len() == 1 && self.self_type_is_available() { + if path.len() == 1 + && !matches!(source, PathSource::Delegation) + && self.self_type_is_available() + { if let Some(candidate) = self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call()) { @@ -1242,7 +1242,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } if let ( [ast::PathSegment { args: None, .. }], - [ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifier::None)], + [ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifiers::NONE)], ) = (&type_param_path.segments[..], &bounds[..]) { if let [ast::PathSegment { ident, args: None, .. }] = @@ -1386,7 +1386,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { | PathSource::TupleStruct(span, _) => { // We want the main underline to cover the suggested code as well for // cleaner output. - err.set_span(*span); + err.span(*span); *span } _ => span, @@ -1409,7 +1409,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { | ExprKind::Unary(..) | ExprKind::If(..) | ExprKind::While(..) - | ExprKind::ForLoop(..) + | ExprKind::ForLoop { .. } | ExprKind::Match(..), .. }), @@ -1618,7 +1618,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let field_spans = match source { // e.g. `if let Enum::TupleVariant(field1, field2) = _` PathSource::TupleStruct(_, pattern_spans) => { - err.set_primary_message( + err.primary_message( "cannot match against a tuple struct which contains private fields", ); @@ -1631,7 +1631,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { span: call_span, .. })) => { - err.set_primary_message( + err.primary_message( "cannot initialize a tuple struct which contains private fields", ); self.suggest_alternative_construction_methods( @@ -1745,12 +1745,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { // Doing analysis on local `DefId`s would cause infinite recursion. return; } + let Ok(impls) = self.r.tcx.inherent_impls(def_id) else { return }; // Look at all the associated functions without receivers in the type's // inherent impls to look for builders that return `Self` - let mut items = self - .r - .tcx - .inherent_impls(def_id) + let mut items = impls .iter() .flat_map(|i| self.r.tcx.associated_items(i).in_definition_order()) // Only assoc fn with no receivers. @@ -1758,11 +1756,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { .filter_map(|item| { // Only assoc fns that return `Self` let fn_sig = self.r.tcx.fn_sig(item.def_id).skip_binder(); - let ret_ty = fn_sig.output(); - let ret_ty = self - .r - .tcx - .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), ret_ty); + // Don't normalize the return type, because that can cause cycle errors. + let ret_ty = fn_sig.output().skip_binder(); let ty::Adt(def, _args) = ret_ty.kind() else { return None; }; @@ -1829,13 +1824,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { ) .iter() .filter_map(|candidate| candidate.did) - .filter(|did| { + .find(|did| { self.r .tcx .get_attrs(*did, sym::rustc_diagnostic_item) .any(|attr| attr.value_str() == Some(sym::Default)) - }) - .next(); + }); let Some(default_trait) = default_trait else { return; }; @@ -1880,11 +1874,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { }; fields.is_some_and(|fields| { - fields - .iter() - .filter(|vis| !self.r.is_accessible_from(**vis, self.parent_scope.module)) - .next() - .is_some() + fields.iter().any(|vis| !self.r.is_accessible_from(*vis, self.parent_scope.module)) }) } @@ -1910,6 +1900,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { (AssocItemKind::Const(..), Res::Def(DefKind::AssocConst, _)) => true, (AssocItemKind::Fn(_), Res::Def(DefKind::AssocFn, _)) => true, (AssocItemKind::Type(..), Res::Def(DefKind::AssocTy, _)) => true, + (AssocItemKind::Delegation(_), Res::Def(DefKind::AssocFn, _)) => true, _ => false, }) .map(|(key, _)| key.ident.name) @@ -1971,6 +1962,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called }, ast::AssocItemKind::Type(..) => AssocSuggestion::AssocType, + ast::AssocItemKind::Delegation(..) + if self.r.has_self.contains(&self.r.local_def_id(assoc_item.id)) => + { + AssocSuggestion::MethodWithSelf { called } + } + ast::AssocItemKind::Delegation(..) => AssocSuggestion::AssocFn { called }, ast::AssocItemKind::MacCall(_) => continue, }); } @@ -2178,7 +2175,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let (span, text) = match path.segments.first() { Some(seg) if let Some(name) = seg.ident.as_str().strip_prefix("let") => { // a special case for #117894 - let name = name.strip_prefix("_").unwrap_or(name); + let name = name.strip_prefix('_').unwrap_or(name); (ident_span, format!("let {name}")) } _ => (ident_span.shrink_to_lo(), "let ".to_string()), @@ -2199,15 +2196,20 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> { let mut result = None; let mut seen_modules = FxHashSet::default(); - let mut worklist = vec![(self.r.graph_root, ThinVec::new())]; - - while let Some((in_module, path_segments)) = worklist.pop() { + let root_did = self.r.graph_root.def_id(); + let mut worklist = vec![( + self.r.graph_root, + ThinVec::new(), + root_did.is_local() || !self.r.tcx.is_doc_hidden(root_did), + )]; + + while let Some((in_module, path_segments, doc_visible)) = worklist.pop() { // abort if the module is already found if result.is_some() { break; } - in_module.for_each_child(self.r, |_, ident, _, name_binding| { + in_module.for_each_child(self.r, |r, ident, _, name_binding| { // abort if the module is already found or if name_binding is private external if result.is_some() || !name_binding.vis.is_visible_locally() { return; @@ -2217,6 +2219,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let mut path_segments = path_segments.clone(); path_segments.push(ast::PathSegment::from_ident(ident)); let module_def_id = module.def_id(); + let doc_visible = doc_visible + && (module_def_id.is_local() || !r.tcx.is_doc_hidden(module_def_id)); if module_def_id == def_id { let path = Path { span: name_binding.span, segments: path_segments, tokens: None }; @@ -2227,6 +2231,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { descr: "module", path, accessible: true, + doc_visible, note: None, via_import: false, }, @@ -2234,7 +2239,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } else { // add the module to the lookup if seen_modules.insert(module_def_id) { - worklist.push((module, path_segments)); + worklist.push((module, path_segments, doc_visible)); } } } @@ -2562,8 +2567,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { debug!(?param.ident, ?param.ident.span, ?use_span); let elidable = matches!(use_ctxt, LifetimeCtxt::Ref); + let deletion_span = + if param.bounds.is_empty() { deletion_span() } else { None }; - let deletion_span = deletion_span(); self.r.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::SINGLE_USE_LIFETIMES, param.id, @@ -2606,25 +2612,23 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { ) { debug_assert_ne!(lifetime_ref.ident.name, kw::UnderscoreLifetime); let mut err = if let Some(outer) = outer_lifetime_ref { - let mut err = struct_span_err!( - self.r.tcx.sess, + struct_span_code_err!( + self.r.dcx(), lifetime_ref.ident.span, E0401, "can't use generic parameters from outer item", - ); - err.span_label(lifetime_ref.ident.span, "use of generic parameter from outer item"); - err.span_label(outer.span, "lifetime parameter from outer item"); - err + ) + .with_span_label(lifetime_ref.ident.span, "use of generic parameter from outer item") + .with_span_label(outer.span, "lifetime parameter from outer item") } else { - let mut err = struct_span_err!( - self.r.tcx.sess, + struct_span_code_err!( + self.r.dcx(), lifetime_ref.ident.span, E0261, "use of undeclared lifetime name `{}`", lifetime_ref.ident - ); - err.span_label(lifetime_ref.ident.span, "undeclared lifetime"); - err + ) + .with_span_label(lifetime_ref.ident.span, "undeclared lifetime") }; self.suggest_introducing_lifetime( &mut err, @@ -2726,8 +2730,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { pub(crate) fn emit_non_static_lt_in_const_param_ty_error(&self, lifetime_ref: &ast::Lifetime) { self.r - .tcx - .sess + .dcx() .create_err(errors::ParamInTyOfConstParam { span: lifetime_ref.ident.span, name: lifetime_ref.ident.name, @@ -2747,8 +2750,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { match cause { NoConstantGenericsReason::IsEnumDiscriminant => { self.r - .tcx - .sess + .dcx() .create_err(errors::ParamInEnumDiscriminant { span: lifetime_ref.ident.span, name: lifetime_ref.ident.name, @@ -2759,8 +2761,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { NoConstantGenericsReason::NonTrivialConstArg => { assert!(!self.r.tcx.features().generic_const_exprs); self.r - .tcx - .sess + .dcx() .create_err(errors::ParamInNonTrivialAnonConst { span: lifetime_ref.ident.span, name: lifetime_ref.ident.name, @@ -2785,8 +2786,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let num_lifetimes: usize = lifetime_refs.iter().map(|lt| lt.count).sum(); let spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect(); - let mut err = struct_span_err!( - self.r.tcx.sess, + let mut err = struct_span_code_err!( + self.r.dcx(), spans, E0106, "missing lifetime specifier{}", @@ -2830,6 +2831,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { .collect(); debug!(?in_scope_lifetimes); + let mut maybe_static = false; debug!(?function_param_lifetimes); if let Some((param_lifetimes, params)) = &function_param_lifetimes { let elided_len = param_lifetimes.len(); @@ -2868,10 +2870,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { if num_params == 0 { err.help( - "this function's return type contains a borrowed value, \ - but there is no value for it to be borrowed from", + "this function's return type contains a borrowed value, but there is no value \ + for it to be borrowed from", ); if in_scope_lifetimes.is_empty() { + maybe_static = true; in_scope_lifetimes = vec![( Ident::with_dummy_span(kw::StaticLifetime), (DUMMY_NODE_ID, LifetimeRes::Static), @@ -2879,11 +2882,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } } else if elided_len == 0 { err.help( - "this function's return type contains a borrowed value with \ - an elided lifetime, but the lifetime cannot be derived from \ - the arguments", + "this function's return type contains a borrowed value with an elided \ + lifetime, but the lifetime cannot be derived from the arguments", ); if in_scope_lifetimes.is_empty() { + maybe_static = true; in_scope_lifetimes = vec![( Ident::with_dummy_span(kw::StaticLifetime), (DUMMY_NODE_ID, LifetimeRes::Static), @@ -2891,13 +2894,13 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } } else if num_params == 1 { err.help(format!( - "this function's return type contains a borrowed value, \ - but the signature does not say which {m} it is borrowed from" + "this function's return type contains a borrowed value, but the signature does \ + not say which {m} it is borrowed from", )); } else { err.help(format!( - "this function's return type contains a borrowed value, \ - but the signature does not say whether it is borrowed from {m}" + "this function's return type contains a borrowed value, but the signature does \ + not say whether it is borrowed from {m}", )); } } @@ -2962,11 +2965,238 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { ); } 1 => { + let post = if maybe_static { + let owned = if let [lt] = &lifetime_refs[..] + && lt.kind != MissingLifetimeKind::Ampersand + { + ", or if you will only have owned values" + } else { + "" + }; + format!( + ", but this is uncommon unless you're returning a borrowed value from a \ + `const` or a `static`{owned}", + ) + } else { + String::new() + }; err.multipart_suggestion_verbose( - format!("consider using the `{existing_name}` lifetime"), + format!("consider using the `{existing_name}` lifetime{post}"), spans_suggs, Applicability::MaybeIncorrect, ); + if maybe_static { + // FIXME: what follows are general suggestions, but we'd want to perform some + // minimal flow analysis to provide more accurate suggestions. For example, if + // we identified that the return expression references only one argument, we + // would suggest borrowing only that argument, and we'd skip the prior + // "use `'static`" suggestion entirely. + if let [lt] = &lifetime_refs[..] + && (lt.kind == MissingLifetimeKind::Ampersand + || lt.kind == MissingLifetimeKind::Underscore) + { + let pre = if lt.kind == MissingLifetimeKind::Ampersand + && let Some((kind, _span)) = self.diagnostic_metadata.current_function + && let FnKind::Fn(_, _, sig, _, _, _) = kind + && !sig.decl.inputs.is_empty() + && let sugg = sig + .decl + .inputs + .iter() + .filter_map(|param| { + if param.ty.span.contains(lt.span) { + // We don't want to suggest `fn elision(_: &fn() -> &i32)` + // when we have `fn elision(_: fn() -> &i32)` + None + } else if let TyKind::CVarArgs = param.ty.kind { + // Don't suggest `&...` for ffi fn with varargs + None + } else if let TyKind::ImplTrait(..) = ¶m.ty.kind { + // We handle these in the next `else if` branch. + None + } else { + Some((param.ty.span.shrink_to_lo(), "&".to_string())) + } + }) + .collect::<Vec<_>>() + && !sugg.is_empty() + { + let (the, s) = if sig.decl.inputs.len() == 1 { + ("the", "") + } else { + ("one of the", "s") + }; + err.multipart_suggestion_verbose( + format!( + "instead, you are more likely to want to change {the} \ + argument{s} to be borrowed...", + ), + sugg, + Applicability::MaybeIncorrect, + ); + "...or alternatively, you might want" + } else if (lt.kind == MissingLifetimeKind::Ampersand + || lt.kind == MissingLifetimeKind::Underscore) + && let Some((kind, _span)) = self.diagnostic_metadata.current_function + && let FnKind::Fn(_, _, sig, _, _, _) = kind + && let ast::FnRetTy::Ty(ret_ty) = &sig.decl.output + && !sig.decl.inputs.is_empty() + && let arg_refs = sig + .decl + .inputs + .iter() + .filter_map(|param| match ¶m.ty.kind { + TyKind::ImplTrait(_, bounds) => Some(bounds), + _ => None, + }) + .flat_map(|bounds| bounds.into_iter()) + .collect::<Vec<_>>() + && !arg_refs.is_empty() + { + // We have a situation like + // fn g(mut x: impl Iterator<Item = &()>) -> Option<&()> + // So we look at every ref in the trait bound. If there's any, we + // suggest + // fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()> + let mut lt_finder = + LifetimeFinder { lifetime: lt.span, found: None, seen: vec![] }; + for bound in arg_refs { + if let ast::GenericBound::Trait(trait_ref, _) = bound { + lt_finder.visit_trait_ref(&trait_ref.trait_ref); + } + } + lt_finder.visit_ty(ret_ty); + let spans_suggs: Vec<_> = lt_finder + .seen + .iter() + .filter_map(|ty| match &ty.kind { + TyKind::Ref(_, mut_ty) => { + let span = ty.span.with_hi(mut_ty.ty.span.lo()); + Some((span, "&'a ".to_string())) + } + _ => None, + }) + .collect(); + self.suggest_introducing_lifetime( + err, + None, + |err, higher_ranked, span, message, intro_sugg| { + err.multipart_suggestion_verbose( + message, + std::iter::once((span, intro_sugg)) + .chain(spans_suggs.iter().cloned()) + .collect(), + Applicability::MaybeIncorrect, + ); + higher_ranked + }, + ); + "alternatively, you might want" + } else { + "instead, you are more likely to want" + }; + let mut owned_sugg = lt.kind == MissingLifetimeKind::Ampersand; + let mut sugg = vec![(lt.span, String::new())]; + if let Some((kind, _span)) = self.diagnostic_metadata.current_function + && let FnKind::Fn(_, _, sig, _, _, _) = kind + && let ast::FnRetTy::Ty(ty) = &sig.decl.output + { + let mut lt_finder = + LifetimeFinder { lifetime: lt.span, found: None, seen: vec![] }; + lt_finder.visit_ty(&ty); + + if let [Ty { span, kind: TyKind::Ref(_, mut_ty), .. }] = + <_finder.seen[..] + { + // We might have a situation like + // fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> + // but `lt.span` only points at `'_`, so to suggest `-> Option<()>` + // we need to find a more accurate span to end up with + // fn g<'a>(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> + sugg = vec![(span.with_hi(mut_ty.ty.span.lo()), String::new())]; + owned_sugg = true; + } + if let Some(ty) = lt_finder.found { + if let TyKind::Path(None, path) = &ty.kind { + // Check if the path being borrowed is likely to be owned. + let path: Vec<_> = Segment::from_path(path); + match self.resolve_path(&path, Some(TypeNS), None) { + PathResult::Module(ModuleOrUniformRoot::Module(module)) => { + match module.res() { + Some(Res::PrimTy(PrimTy::Str)) => { + // Don't suggest `-> str`, suggest `-> String`. + sugg = vec![( + lt.span.with_hi(ty.span.hi()), + "String".to_string(), + )]; + } + Some(Res::PrimTy(..)) => {} + Some(Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::ForeignTy + | DefKind::AssocTy + | DefKind::OpaqueTy + | DefKind::TyParam, + _, + )) => {} + _ => { + // Do not suggest in all other cases. + owned_sugg = false; + } + } + } + PathResult::NonModule(res) => { + match res.base_res() { + Res::PrimTy(PrimTy::Str) => { + // Don't suggest `-> str`, suggest `-> String`. + sugg = vec![( + lt.span.with_hi(ty.span.hi()), + "String".to_string(), + )]; + } + Res::PrimTy(..) => {} + Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::ForeignTy + | DefKind::AssocTy + | DefKind::OpaqueTy + | DefKind::TyParam, + _, + ) => {} + _ => { + // Do not suggest in all other cases. + owned_sugg = false; + } + } + } + _ => { + // Do not suggest in all other cases. + owned_sugg = false; + } + } + } + if let TyKind::Slice(inner_ty) = &ty.kind { + // Don't suggest `-> [T]`, suggest `-> Vec<T>`. + sugg = vec![ + (lt.span.with_hi(inner_ty.span.lo()), "Vec<".to_string()), + (ty.span.with_lo(inner_ty.span.hi()), ">".to_string()), + ]; + } + } + } + if owned_sugg { + err.multipart_suggestion_verbose( + format!("{pre} to return an owned value"), + sugg, + Applicability::MaybeIncorrect, + ); + } + } + } // Record as using the suggested resolution. let (_, (_, res)) = in_scope_lifetimes[0]; @@ -2996,7 +3226,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { fn mk_where_bound_predicate( path: &Path, poly_trait_ref: &ast::PolyTraitRef, - ty: &ast::Ty, + ty: &Ty, ) -> Option<ast::WhereBoundPredicate> { use rustc_span::DUMMY_SP; let modified_segments = { @@ -3052,7 +3282,7 @@ fn mk_where_bound_predicate( }, span: DUMMY_SP, }, - ast::TraitBoundModifier::None, + ast::TraitBoundModifiers::NONE, )], }; @@ -3061,16 +3291,34 @@ fn mk_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!( - sess, + struct_span_code_err!( + sess.dcx(), shadower.span, E0496, "lifetime name `{}` shadows a lifetime name that is already in scope", orig.name, - ); - err.span_label(orig.span, "first declared here"); - err.span_label(shadower.span, format!("lifetime `{}` already in scope", orig.name)); - err.emit(); + ) + .with_span_label(orig.span, "first declared here") + .with_span_label(shadower.span, format!("lifetime `{}` already in scope", orig.name)) + .emit(); +} + +struct LifetimeFinder<'ast> { + lifetime: Span, + found: Option<&'ast Ty>, + seen: Vec<&'ast Ty>, +} + +impl<'ast> Visitor<'ast> for LifetimeFinder<'ast> { + fn visit_ty(&mut self, t: &'ast Ty) { + if let TyKind::Ref(_, mut_ty) = &t.kind { + self.seen.push(t); + if t.span.lo() == self.lifetime.lo() { + self.found = Some(&mut_ty.ty); + } + } + walk_ty(self, t) + } } /// Shadowing involving a label is only a warning for historical reasons. @@ -3078,11 +3326,12 @@ pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: I pub(super) fn signal_label_shadowing(sess: &Session, orig: Span, shadower: Ident) { let name = shadower.name; let shadower = shadower.span; - let mut err = sess.struct_span_warn( - shadower, - format!("label name `{name}` shadows a label name that is already in scope"), - ); - err.span_label(orig, "first declared here"); - err.span_label(shadower, format!("label `{name}` already in scope")); - err.emit(); + sess.dcx() + .struct_span_warn( + shadower, + format!("label name `{name}` shadows a label name that is already in scope"), + ) + .with_span_label(orig, "first declared here") + .with_span_label(shadower, format!("label `{name}` already in scope")) + .emit(); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 70e0eb12c01..1c00f545eb8 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -37,7 +37,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{FreezeReadGuard, Lrc}; -use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind}; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; @@ -55,6 +55,7 @@ use rustc_middle::span_bug; use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt}; use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs}; use rustc_query_system::ich::StableHashingContext; +use rustc_session::lint::builtin::PRIVATE_MACRO_USE; use rustc_session::lint::LintBuffer; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -213,7 +214,7 @@ enum ResolutionError<'a> { SelfImportOnlyInImportListWithNonEmptyPrefix, /// Error E0433: failed to resolve. FailedToResolve { - last_segment: Option<Symbol>, + segment: Option<Symbol>, label: String, suggestion: Option<Suggestion>, module: Option<ModuleOrUniformRoot<'a>>, @@ -257,7 +258,7 @@ enum ResolutionError<'a> { kind: &'static str, trait_path: String, trait_item_span: Span, - code: rustc_errors::DiagnosticId, + code: String, }, /// Error E0201: multiple impl items for the same trait item. TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span }, @@ -265,6 +266,8 @@ enum ResolutionError<'a> { InvalidAsmSym, /// `self` used instead of `Self` in a generic parameter LowercaseSelf, + /// A never pattern has a binding. + BindingInNeverPattern, } enum VisResolutionError<'a> { @@ -396,12 +399,14 @@ enum PathResult<'a> { suggestion: Option<Suggestion>, is_error_from_last_segment: bool, module: Option<ModuleOrUniformRoot<'a>>, + /// The segment name of target + segment_name: Symbol, }, } impl<'a> PathResult<'a> { fn failed( - span: Span, + ident: Ident, is_error_from_last_segment: bool, finalize: bool, module: Option<ModuleOrUniformRoot<'a>>, @@ -409,7 +414,14 @@ impl<'a> PathResult<'a> { ) -> PathResult<'a> { let (label, suggestion) = if finalize { label_and_suggestion() } else { (String::new(), None) }; - PathResult::Failed { span, label, suggestion, is_error_from_last_segment, module } + PathResult::Failed { + span: ident.span, + segment_name: ident.name, + label, + suggestion, + is_error_from_last_segment, + module, + } } } @@ -704,7 +716,7 @@ struct PrivacyError<'a> { #[derive(Debug)] struct UseError<'a> { - err: DiagnosticBuilder<'a, ErrorGuaranteed>, + err: DiagnosticBuilder<'a>, /// Candidates which user could `use` to access the missing type. candidates: Vec<ImportSuggestion>, /// The `DefId` of the module to place the use-statements in. @@ -1007,8 +1019,7 @@ pub struct Resolver<'a, 'tcx> { /// Maps glob imports to the names of items actually imported. glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>, - /// Visibilities in "lowered" form, for all entities that have them. - visibilities: FxHashMap<LocalDefId, ty::Visibility>, + visibilities_for_hashing: Vec<(LocalDefId, ty::Visibility)>, used_imports: FxHashSet<NodeId>, maybe_unused_trait_imports: FxIndexSet<LocalDefId>, @@ -1085,7 +1096,7 @@ pub struct Resolver<'a, 'tcx> { next_node_id: NodeId, - node_id_to_def_id: FxHashMap<ast::NodeId, LocalDefId>, + node_id_to_def_id: NodeMap<LocalDefId>, def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>, /// Indices of unnamed struct or variant fields with unresolved attributes. @@ -1102,6 +1113,8 @@ pub struct Resolver<'a, 'tcx> { legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>, /// Amount of lifetime parameters for each item in the crate. item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>, + /// Amount of parameters for each function in the crate. + fn_parameter_counts: LocalDefIdMap<usize>, main_def: Option<MainDefinition>, trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>, @@ -1226,10 +1239,7 @@ impl<'tcx> Resolver<'_, 'tcx> { ); // FIXME: remove `def_span` body, pass in the right spans here and call `tcx.at().create_def()` - let def_id = self.tcx.untracked().definitions.write().create_def(parent, data); - - let feed = self.tcx.feed_local_def_id(def_id); - feed.def_kind(def_kind); + let def_id = self.tcx.create_def(parent, name, def_kind); // Create the definition. if expn_id != ExpnId::root() { @@ -1295,12 +1305,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut FxHashMap::default(), ); - let mut visibilities = FxHashMap::default(); - visibilities.insert(CRATE_DEF_ID, ty::Visibility::Public); - let mut def_id_to_node_id = IndexVec::default(); assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), CRATE_DEF_ID); - let mut node_id_to_def_id = FxHashMap::default(); + let mut node_id_to_def_id = NodeMap::default(); node_id_to_def_id.insert(CRATE_NODE_ID, CRATE_DEF_ID); let mut invocation_parents = FxHashMap::default(); @@ -1363,7 +1370,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ast_transform_scopes: FxHashMap::default(), glob_map: Default::default(), - visibilities, + visibilities_for_hashing: Default::default(), used_imports: FxHashSet::default(), maybe_unused_trait_imports: Default::default(), @@ -1446,10 +1453,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { doc_link_resolutions: Default::default(), doc_link_traits_in_scope: Default::default(), all_macro_rules: Default::default(), + fn_parameter_counts: Default::default(), }; let root_parent_scope = ParentScope::module(graph_root, &resolver); resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope); + resolver.feed_visibility(CRATE_DEF_ID, ty::Visibility::Public); resolver } @@ -1497,10 +1506,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Default::default() } + fn feed_visibility(&mut self, def_id: LocalDefId, vis: ty::Visibility) { + self.tcx.feed_local_def_id(def_id).visibility(vis.to_def_id()); + self.visibilities_for_hashing.push((def_id, vis)); + } + pub fn into_outputs(self) -> ResolverOutputs { let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect(); let expn_that_defined = self.expn_that_defined; - let visibilities = self.visibilities; let extern_crate_map = self.extern_crate_map; let maybe_unused_trait_imports = self.maybe_unused_trait_imports; let glob_map = self.glob_map; @@ -1517,7 +1530,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let global_ctxt = ResolverGlobalCtxt { expn_that_defined, - visibilities, + visibilities_for_hashing: self.visibilities_for_hashing, effective_visibilities, extern_crate_map, module_children: self.module_children, @@ -1544,6 +1557,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { trait_map: self.trait_map, lifetime_elision_allowed: self.lifetime_elision_allowed, lint_buffer: Steal::new(self.lint_buffer), + has_self: self.has_self, + fn_parameter_counts: self.fn_parameter_counts, }; ResolverOutputs { global_ctxt, ast_lowering } } @@ -1785,6 +1800,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } if let NameBindingKind::Import { import, binding, ref used } = used_binding.kind { + if let ImportKind::MacroUse { warn_private: true } = import.kind { + let msg = format!("macro `{ident}` is private"); + self.lint_buffer().buffer_lint(PRIVATE_MACRO_USE, import.root_id, ident.span, msg); + } // Avoid marking `extern crate` items that refer to a name from extern prelude, // but not introduce it, as used if they are accessed from lexical scope. if is_lexical_scope { @@ -2055,7 +2074,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut ret = Vec::new(); for meta in attr.meta_item_list()? { match meta.lit()?.kind { - LitKind::Int(a, _) => ret.push(a as usize), + LitKind::Int(a, _) => ret.push(a.get() as usize), _ => panic!("invalid arg index"), } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index ca225416e36..1c085ddf57b 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -15,7 +15,7 @@ use rustc_ast_pretty::pprust; use rustc_attr::StabilityLevel; use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; -use rustc_errors::{struct_span_err, Applicability}; +use rustc_errors::{struct_span_code_err, Applicability}; use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand}; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; @@ -126,18 +126,18 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools { Some(ident) => { if let Some(old_ident) = registered_tools.replace(ident) { let msg = format!("{} `{}` was already registered", "tool", ident); - tcx.sess + tcx.dcx() .struct_span_err(ident.span, msg) - .span_label(old_ident.span, "already registered here") + .with_span_label(old_ident.span, "already registered here") .emit(); } } None => { let msg = format!("`{}` only accepts identifiers", sym::register_tool); let span = nested_meta.span(); - tcx.sess + tcx.dcx() .struct_span_err(span, msg) - .span_label(span, "not an identifier") + .with_span_label(span, "not an identifier") .emit(); } } @@ -205,10 +205,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind) { if self.builtin_macros.insert(name, BuiltinMacroState::NotYetSeen(ext)).is_some() { - self.tcx - .sess - .diagnostic() - .bug(format!("built-in macro `{name}` was already registered")); + self.dcx().bug(format!("built-in macro `{name}` was already registered")); } } @@ -450,7 +447,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { PathResult::NonModule(..) | // HACK(Urgau): This shouldn't be necessary PathResult::Failed { is_error_from_last_segment: false, .. } => { - self.tcx.sess + self.dcx() .emit_err(errors::CfgAccessibleUnsure { span }); // If we get a partially resolved NonModule in one namespace, we should get the @@ -515,10 +512,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Report errors for the resolved macro. for segment in &path.segments { if let Some(args) = &segment.args { - self.tcx.sess.span_err(args.span(), "generic arguments in macro path"); + self.dcx().span_err(args.span(), "generic arguments in macro path"); } if kind == MacroKind::Attr && segment.ident.as_str().starts_with("rustc") { - self.tcx.sess.span_err( + self.dcx().span_err( segment.ident.span, "attributes starting with `rustc` are reserved for use by the `rustc` compiler", ); @@ -530,7 +527,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(def_id) = def_id.as_local() { self.unused_macros.remove(&def_id); if self.proc_macro_stubs.contains(&def_id) { - self.tcx.sess.emit_err(errors::ProcMacroSameCrate { + self.dcx().emit_err(errors::ProcMacroSameCrate { span: path.span, is_test: self.tcx.sess.is_test_crate(), }); @@ -579,10 +576,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str }); } - let mut err = self.tcx.sess.create_err(err); - err.span_label(path.span, format!("not {article} {expected}")); - - err.emit(); + self.dcx() + .create_err(err) + .with_span_label(path.span, format!("not {article} {expected}")) + .emit(); return Ok((self.dummy_ext(kind), Res::Err)); } @@ -597,13 +594,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if soft_custom_inner_attributes_gate { self.tcx.sess.parse_sess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg); } else { - feature_err( - &self.tcx.sess.parse_sess, - sym::custom_inner_attributes, - path.span, - msg, - ) - .emit(); + feature_err(&self.tcx.sess, sym::custom_inner_attributes, path.span, msg).emit(); } } @@ -710,7 +701,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Make sure compilation does not succeed if preferred macro resolution // has changed after the macro had been expanded. In theory all such // situations should be reported as errors, so this is a bug. - this.tcx.sess.span_delayed_bug(span, "inconsistent resolution for a macro"); + this.dcx().span_delayed_bug(span, "inconsistent resolution for a macro"); } } else { // It's possible that the macro was unresolved (indeterminate) and silently @@ -721,7 +712,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // even if speculative `resolve_path` returned nothing previously, so we skip this // less informative error if the privacy error is reported elsewhere. if this.privacy_errors.is_empty() { - this.tcx.sess.emit_err(CannotDetermineMacroResolution { + this.dcx().emit_err(CannotDetermineMacroResolution { span, kind: kind.descr(), path: Segment::names_to_string(path), @@ -782,7 +773,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.report_error( span, ResolutionError::FailedToResolve { - last_segment: path.last().map(|segment| segment.ident.name), + segment: path.last().map(|segment| segment.ident.name), label, suggestion, module, @@ -828,12 +819,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Err(..) => { let expected = kind.descr_expected(); - let mut err = self.tcx.sess.create_err(CannotFindIdentInThisScope { + let mut err = self.dcx().create_err(CannotFindIdentInThisScope { span: ident.span, expected, ident, }); - self.unresolved_macro_suggestions(&mut err, kind, &parent_scope, ident, krate); err.emit(); } @@ -910,7 +900,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if kind != NonMacroAttrKind::Tool && binding.map_or(true, |b| b.is_import()) { let msg = format!("cannot use {} {} through an import", kind.article(), kind.descr()); - let mut err = self.tcx.sess.struct_span_err(span, msg); + let mut err = self.dcx().struct_span_err(span, msg); if let Some(binding) = binding { err.span_note(binding.span, format!("the {} imported here", kind.descr())); } @@ -925,7 +915,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if ident.name == sym::cfg || ident.name == sym::cfg_attr { let macro_kind = self.get_macro(res).map(|macro_data| macro_data.ext.macro_kind()); if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) { - self.tcx.sess.span_err( + self.dcx().span_err( ident.span, format!("name `{ident}` is reserved in attribute namespace"), ); @@ -952,19 +942,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { rule_spans = Vec::new(); } BuiltinMacroState::AlreadySeen(span) => { - struct_span_err!( - self.tcx.sess, + struct_span_code_err!( + self.dcx(), item.span, E0773, "attempted to define built-in macro more than once" ) - .span_note(span, "previously defined here") + .with_span_note(span, "previously defined here") .emit(); } } } else { let msg = format!("cannot find a built-in macro with name `{}`", item.ident); - self.tcx.sess.span_err(item.span, msg); + self.dcx().span_err(item.span, msg); } } diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index f95c0acd750..4ff4ccf5e98 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -407,8 +407,7 @@ fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> { doc, main_body_opts(), Some(&mut broken_link_callback), - ) - .into_iter(); + ); let mut links = Vec::new(); while let Some(event) = event_iter.next() { |
