diff options
Diffstat (limited to 'compiler/rustc_resolve/src')
| -rw-r--r-- | compiler/rustc_resolve/src/build_reduced_graph.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/check_unused.rs | 140 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/def_collector.rs | 26 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/diagnostics.rs | 29 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/diagnostics/tests.rs | 40 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/effective_visibilities.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/errors.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/ident.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/imports.rs | 45 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 98 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/diagnostics.rs | 121 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/lib.rs | 64 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/macros.rs | 87 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/rustdoc.rs | 26 |
14 files changed, 372 insertions, 345 deletions
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 1b6387acf71..689109b2840 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -32,6 +32,8 @@ use rustc_span::Span; use std::cell::Cell; +use tracing::debug; + type Res = def::Res<NodeId>; impl<'a, Id: Into<DefId>> ToNameBinding<'a> @@ -560,7 +562,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.add_import(prefix, kind, use_tree.span, item, root_span, item.id, vis); } - ast::UseTreeKind::Nested(ref items) => { + ast::UseTreeKind::Nested { ref items, .. } => { // Ensure there is at most one `self` in the list let self_spans = items .iter() @@ -825,7 +827,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {} - ItemKind::MacroDef(..) | ItemKind::MacCall(_) => unreachable!(), + ItemKind::MacroDef(..) | ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => { + unreachable!() + } } } @@ -1304,11 +1308,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { visit::walk_item(self, item); macro_rules_scope } - ItemKind::MacCall(..) => { - let macro_rules_scope = self.visit_invoc_in_module(item.id); - visit::walk_item(self, item); - macro_rules_scope - } + ItemKind::MacCall(..) => self.visit_invoc_in_module(item.id), _ => { let orig_macro_rules_scope = self.parent_scope.macro_rules; self.build_reduced_graph_for_item(item); @@ -1339,7 +1339,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } self.build_reduced_graph_for_foreign_item(foreign_item); - visit::walk_foreign_item(self, foreign_item); + visit::walk_item(self, foreign_item); } fn visit_block(&mut self, block: &'b Block) { @@ -1385,7 +1385,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { | AssocItemKind::Delegation(..) | AssocItemKind::Fn(..) => ValueNS, AssocItemKind::Type(..) => TypeNS, - AssocItemKind::MacCall(_) => bug!(), // handled above + AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => bug!(), // handled above }; let parent = self.parent_scope.module; diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index f6004fed828..fc3669fecc2 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -32,7 +32,7 @@ use rustc_ast as ast; use rustc_ast::visit::{self, Visitor}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{pluralize, MultiSpan}; +use rustc_errors::MultiSpan; use rustc_hir::def::{DefKind, Res}; use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES}; use rustc_session::lint::builtin::{UNUSED_IMPORTS, UNUSED_QUALIFICATIONS}; @@ -128,7 +128,7 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { self.unused_import(self.base_id).add(id); } } - ast::UseTreeKind::Nested(ref items) => self.check_imports_as_underscore(items), + ast::UseTreeKind::Nested { ref items, .. } => self.check_imports_as_underscore(items), _ => {} } } @@ -151,11 +151,10 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { // We do this in any edition. if warn_if_unused { if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) { - self.r.lint_buffer.buffer_lint_with_diagnostic( + self.r.lint_buffer.buffer_lint( UNUSED_EXTERN_CRATES, extern_crate.id, span, - "unused extern crate", BuiltinLintDiag::UnusedExternCrate { removal_span: extern_crate.span_with_attributes, }, @@ -204,11 +203,10 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { .span .find_ancestor_inside(extern_crate.span) .unwrap_or(extern_crate.ident.span); - self.r.lint_buffer.buffer_lint_with_diagnostic( + self.r.lint_buffer.buffer_lint( UNUSED_EXTERN_CRATES, extern_crate.id, extern_crate.span, - "`extern crate` is not idiomatic in the new edition", BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span }, ); } @@ -254,7 +252,7 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { return; } - if let ast::UseTreeKind::Nested(ref items) = use_tree.kind { + if let ast::UseTreeKind::Nested { ref items, .. } = use_tree.kind { if items.is_empty() { self.unused_import(self.base_id).add(id); } @@ -268,9 +266,8 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { enum UnusedSpanResult { Used, - FlatUnused(Span, Span), - NestedFullUnused(Vec<Span>, Span), - NestedPartialUnused(Vec<Span>, Vec<Span>), + Unused { spans: Vec<Span>, remove: Span }, + PartialUnused { spans: Vec<Span>, remove: Vec<Span> }, } fn calc_unused_spans( @@ -288,36 +285,33 @@ fn calc_unused_spans( match use_tree.kind { ast::UseTreeKind::Simple(..) | ast::UseTreeKind::Glob => { if unused_import.unused.contains(&use_tree_id) { - UnusedSpanResult::FlatUnused(use_tree.span, full_span) + UnusedSpanResult::Unused { spans: vec![use_tree.span], remove: full_span } } else { UnusedSpanResult::Used } } - ast::UseTreeKind::Nested(ref nested) => { + ast::UseTreeKind::Nested { items: ref nested, span: tree_span } => { if nested.is_empty() { - return UnusedSpanResult::FlatUnused(use_tree.span, full_span); + return UnusedSpanResult::Unused { spans: vec![use_tree.span], remove: full_span }; } let mut unused_spans = Vec::new(); let mut to_remove = Vec::new(); - let mut all_nested_unused = true; + let mut used_children = 0; + let mut contains_self = false; let mut previous_unused = false; for (pos, (use_tree, use_tree_id)) in nested.iter().enumerate() { let remove = match calc_unused_spans(unused_import, use_tree, *use_tree_id) { UnusedSpanResult::Used => { - all_nested_unused = false; + used_children += 1; None } - UnusedSpanResult::FlatUnused(span, remove) => { - unused_spans.push(span); - Some(remove) - } - UnusedSpanResult::NestedFullUnused(mut spans, remove) => { + UnusedSpanResult::Unused { mut spans, remove } => { unused_spans.append(&mut spans); Some(remove) } - UnusedSpanResult::NestedPartialUnused(mut spans, mut to_remove_extra) => { - all_nested_unused = false; + UnusedSpanResult::PartialUnused { mut spans, remove: mut to_remove_extra } => { + used_children += 1; unused_spans.append(&mut spans); to_remove.append(&mut to_remove_extra); None @@ -326,7 +320,7 @@ fn calc_unused_spans( if let Some(remove) = remove { let remove_span = if nested.len() == 1 { remove - } else if pos == nested.len() - 1 || !all_nested_unused { + } else if pos == nested.len() - 1 || used_children > 0 { // Delete everything from the end of the last import, to delete the // previous comma nested[pos - 1].0.span.shrink_to_hi().to(use_tree.span) @@ -344,14 +338,38 @@ fn calc_unused_spans( to_remove.push(remove_span); } } + contains_self |= use_tree.prefix == kw::SelfLower + && matches!(use_tree.kind, ast::UseTreeKind::Simple(None)); previous_unused = remove.is_some(); } if unused_spans.is_empty() { UnusedSpanResult::Used - } else if all_nested_unused { - UnusedSpanResult::NestedFullUnused(unused_spans, full_span) + } else if used_children == 0 { + UnusedSpanResult::Unused { spans: unused_spans, remove: full_span } } else { - UnusedSpanResult::NestedPartialUnused(unused_spans, to_remove) + // If there is only one remaining child that is used, the braces around the use + // tree are not needed anymore. In that case, we determine the span of the left + // brace and the right brace, and tell rustfix to remove them as well. + // + // This means that `use a::{B, C};` will be turned into `use a::B;` rather than + // `use a::{B};`, removing a rustfmt roundtrip. + // + // Note that we cannot remove the braces if the only item inside the use tree is + // `self`: `use foo::{self};` is valid Rust syntax, while `use foo::self;` errors + // out. We also cannot turn `use foo::{self}` into `use foo`, as the former doesn't + // import types with the same name as the module. + if used_children == 1 && !contains_self { + // Left brace, from the start of the nested group to the first item. + to_remove.push( + tree_span.shrink_to_lo().to(nested.first().unwrap().0.span.shrink_to_lo()), + ); + // Right brace, from the end of the last item to the end of the nested group. + to_remove.push( + nested.last().unwrap().0.span.shrink_to_hi().to(tree_span.shrink_to_hi()), + ); + } + + UnusedSpanResult::PartialUnused { spans: unused_spans, remove: to_remove } } } } @@ -374,10 +392,7 @@ impl Resolver<'_, '_> { MACRO_USE_EXTERN_CRATE, import.root_id, import.span, - "deprecated `#[macro_use]` attribute used to \ - import macros should be replaced at use sites \ - with a `use` item to import the macro \ - instead", + BuiltinLintDiag::MacroUseDeprecated, ); } } @@ -394,8 +409,12 @@ impl Resolver<'_, '_> { } } ImportKind::MacroUse { .. } => { - let msg = "unused `#[macro_use]` import"; - self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.root_id, import.span, msg); + self.lint_buffer.buffer_lint( + UNUSED_IMPORTS, + import.root_id, + import.span, + BuiltinLintDiag::UnusedMacroUse, + ); } _ => {} } @@ -414,24 +433,12 @@ impl Resolver<'_, '_> { visitor.report_unused_extern_crate_items(maybe_unused_extern_crates); for unused in visitor.unused_imports.values() { - let mut fixes = Vec::new(); - let spans = match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) { - UnusedSpanResult::Used => continue, - UnusedSpanResult::FlatUnused(span, remove) => { - fixes.push((remove, String::new())); - vec![span] - } - UnusedSpanResult::NestedFullUnused(spans, remove) => { - fixes.push((remove, String::new())); - spans - } - UnusedSpanResult::NestedPartialUnused(spans, remove) => { - for fix in &remove { - fixes.push((*fix, String::new())); - } - spans - } - }; + let (spans, remove_spans) = + match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) { + UnusedSpanResult::Used => continue, + UnusedSpanResult::Unused { spans, remove } => (spans, vec![remove]), + UnusedSpanResult::PartialUnused { spans, remove } => (spans, remove), + }; let ms = MultiSpan::from_spans(spans); @@ -443,23 +450,8 @@ impl Resolver<'_, '_> { .collect::<Vec<String>>(); span_snippets.sort(); - let msg = format!( - "unused import{}{}", - pluralize!(ms.primary_spans().len()), - if !span_snippets.is_empty() { - format!(": {}", span_snippets.join(", ")) - } else { - String::new() - } - ); - - let fix_msg = if fixes.len() == 1 && fixes[0].0 == unused.item_span { - "remove the whole `use` item" - } else if ms.primary_spans().len() > 1 { - "remove the unused imports" - } else { - "remove the unused import" - }; + let remove_whole_use = remove_spans.len() == 1 && remove_spans[0] == unused.item_span; + let num_to_remove = ms.primary_spans().len(); // If we are in the `--test` mode, suppress a help that adds the `#[cfg(test)]` // attribute; however, if not, suggest adding the attribute. There is no way to @@ -485,12 +477,17 @@ impl Resolver<'_, '_> { } }; - visitor.r.lint_buffer.buffer_lint_with_diagnostic( + visitor.r.lint_buffer.buffer_lint( UNUSED_IMPORTS, unused.use_tree_id, ms, - msg, - BuiltinLintDiag::UnusedImports(fix_msg.into(), fixes, test_module_span), + BuiltinLintDiag::UnusedImports { + remove_whole_use, + num_to_remove, + remove_spans, + test_module_span, + span_snippets, + }, ); } @@ -536,11 +533,10 @@ impl Resolver<'_, '_> { continue; } - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( UNUSED_QUALIFICATIONS, unn_qua.node_id, unn_qua.path_span, - "unnecessary qualification", BuiltinLintDiag::UnusedQualifications { removal_span: unn_qua.removal_span }, ); } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index bef95aca0d1..cad10571afe 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -7,6 +7,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_span::hygiene::LocalExpnId; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; +use tracing::debug; pub(crate) fn collect_definitions( resolver: &mut Resolver<'_, '_>, @@ -136,14 +137,10 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { opt_macro_data = Some(macro_data); DefKind::Macro(macro_kind) } - ItemKind::MacCall(..) => { - visit::walk_item(self, i); - return self.visit_macro_invoc(i.id); - } ItemKind::GlobalAsm(..) => DefKind::GlobalAsm, - ItemKind::Use(..) => { - return visit::walk_item(self, i); - } + ItemKind::Use(..) => return visit::walk_item(self, i), + ItemKind::MacCall(..) => return self.visit_macro_invoc(i.id), + ItemKind::DelegationMac(..) => unreachable!(), }; let def_id = self.create_def(i.id, i.ident.name, def_kind, i.span); @@ -214,7 +211,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { let def_kind = match fi.kind { - ForeignItemKind::Static(_, mutability, _) => { + ForeignItemKind::Static(box StaticForeignItem { ty: _, mutability, expr: _ }) => { DefKind::Static { mutability, nested: false } } ForeignItemKind::Fn(_) => DefKind::Fn, @@ -224,7 +221,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { let def = self.create_def(fi.id, fi.ident.name, def_kind, fi.span); - self.with_parent(def, |this| visit::walk_foreign_item(this, fi)); + self.with_parent(def, |this| visit::walk_item(this, fi)); } fn visit_variant(&mut self, v: &'a Variant) { @@ -283,6 +280,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { AssocItemKind::Const(..) => DefKind::AssocConst, AssocItemKind::Type(..) => DefKind::AssocTy, AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id), + AssocItemKind::DelegationMac(..) => unreachable!(), }; let def = self.create_def(i.id, i.ident.name, def_kind, i.span); @@ -327,16 +325,6 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { ExprKind::Gen(_, _, _) => { self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span) } - ExprKind::ConstBlock(ref constant) => { - let def = self.create_def( - constant.id, - kw::Empty, - DefKind::InlineConst, - constant.value.span, - ); - self.with_parent(def, |this| visit::walk_anon_const(this, constant)); - return; - } _ => self.parent_def, }; diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 12484462f82..856cfbc01e8 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -28,6 +28,7 @@ use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Span, SyntaxContext}; use thin_vec::{thin_vec, ThinVec}; +use tracing::debug; use crate::errors::{ self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive, @@ -43,9 +44,6 @@ use crate::{LexicalScopeBinding, NameBinding, NameBindingKind, PrivacyError, Vis use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet}; use crate::{Segment, UseError}; -#[cfg(test)] -mod tests; - type Res = def::Res<ast::NodeId>; /// A vector of spans and replacements, a message and applicability. @@ -130,13 +128,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.report_with_use_injections(krate); for &(span_use, span_def) in &self.macro_expanded_macro_export_errors { - let msg = "macro-expanded `macro_export` macros from the current crate \ - cannot be referred to by absolute paths"; - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, CRATE_NODE_ID, span_use, - msg, BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def), ); } @@ -147,11 +142,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let NameBindingKind::Import { import, .. } = ambiguity_error.b1.0.kind else { unreachable!() }; - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( AMBIGUOUS_GLOB_IMPORTS, import.root_id, ambiguity_error.ident.span, - diag.msg.to_string(), BuiltinLintDiag::AmbiguousGlobImports { diag }, ); } else { @@ -528,12 +522,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let diag = BuiltinLintDiag::AbsPathWithModule(root_span); - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, node_id, root_span, - "absolute paths must start with `self`, `super`, \ - `crate`, or an external crate name in the 2018 edition", diag, ); } @@ -1617,7 +1609,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let post = format!(", consider renaming `{}` into `{snippet}`", suggestion.candidate); (span, snippet, post) } else { - (span, suggestion.candidate.to_string(), String::new()) + (span, suggestion.candidate.to_ident_string(), String::new()) }; let msg = match suggestion.target { SuggestionTarget::SimilarlyNamed => format!( @@ -3026,14 +3018,3 @@ fn is_span_suitable_for_use_injection(s: Span) -> bool { // import or other generated ones !s.from_expansion() } - -/// Convert the given number into the corresponding ordinal -pub(crate) fn ordinalize(v: usize) -> String { - let suffix = match ((11..=13).contains(&(v % 100)), v % 10) { - (false, 1) => "st", - (false, 2) => "nd", - (false, 3) => "rd", - _ => "th", - }; - format!("{v}{suffix}") -} diff --git a/compiler/rustc_resolve/src/diagnostics/tests.rs b/compiler/rustc_resolve/src/diagnostics/tests.rs deleted file mode 100644 index 2aa6cc61e46..00000000000 --- a/compiler/rustc_resolve/src/diagnostics/tests.rs +++ /dev/null @@ -1,40 +0,0 @@ -use super::ordinalize; - -#[test] -fn test_ordinalize() { - assert_eq!(ordinalize(1), "1st"); - assert_eq!(ordinalize(2), "2nd"); - assert_eq!(ordinalize(3), "3rd"); - assert_eq!(ordinalize(4), "4th"); - assert_eq!(ordinalize(5), "5th"); - // ... - assert_eq!(ordinalize(10), "10th"); - assert_eq!(ordinalize(11), "11th"); - assert_eq!(ordinalize(12), "12th"); - assert_eq!(ordinalize(13), "13th"); - assert_eq!(ordinalize(14), "14th"); - // ... - assert_eq!(ordinalize(20), "20th"); - assert_eq!(ordinalize(21), "21st"); - assert_eq!(ordinalize(22), "22nd"); - assert_eq!(ordinalize(23), "23rd"); - assert_eq!(ordinalize(24), "24th"); - // ... - assert_eq!(ordinalize(30), "30th"); - assert_eq!(ordinalize(31), "31st"); - assert_eq!(ordinalize(32), "32nd"); - assert_eq!(ordinalize(33), "33rd"); - assert_eq!(ordinalize(34), "34th"); - // ... - assert_eq!(ordinalize(7010), "7010th"); - assert_eq!(ordinalize(7011), "7011th"); - assert_eq!(ordinalize(7012), "7012th"); - assert_eq!(ordinalize(7013), "7013th"); - assert_eq!(ordinalize(7014), "7014th"); - // ... - assert_eq!(ordinalize(7020), "7020th"); - assert_eq!(ordinalize(7021), "7021st"); - assert_eq!(ordinalize(7022), "7022nd"); - assert_eq!(ordinalize(7023), "7023rd"); - assert_eq!(ordinalize(7024), "7024th"); -} diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 3443bbe6e11..aab4a3366da 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -11,6 +11,7 @@ use rustc_middle::middle::privacy::Level; use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility}; use rustc_middle::ty::Visibility; use std::mem; +use tracing::info; #[derive(Clone, Copy)] enum ParentId<'a> { @@ -236,7 +237,7 @@ impl<'r, 'ast, 'tcx> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r, 't ast::ItemKind::Impl(..) => return, // Should be unreachable at this stage - ast::ItemKind::MacCall(..) => panic!( + ast::ItemKind::MacCall(..) | ast::ItemKind::DelegationMac(..) => panic!( "ast::ItemKind::MacCall encountered, this should not anymore appear at this stage" ), diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index b0329702d11..edfeacec7e3 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,4 +1,4 @@ -use rustc_errors::{codes::*, Applicability, MultiSpan}; +use rustc_errors::{codes::*, Applicability, ElidedLifetimeInPathSubdiag, MultiSpan}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{ symbol::{Ident, Symbol}, @@ -907,6 +907,8 @@ pub(crate) struct ExplicitAnonymousLivetimeReportError { pub(crate) struct ImplicitElidedLifetimeNotAllowedHere { #[primary_span] pub(crate) span: Span, + #[subdiagnostic] + pub(crate) subdiag: ElidedLifetimeInPathSubdiag, } #[derive(Diagnostic)] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 43a43e01a9a..57db765c07e 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -11,6 +11,7 @@ use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContex use rustc_span::sym; use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; +use tracing::{debug, instrument}; use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst}; use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind}; @@ -523,18 +524,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match binding { Ok(binding) => { if let Some(lint_id) = derive_fallback_lint_id { - this.lint_buffer.buffer_lint_with_diagnostic( + this.lint_buffer.buffer_lint( PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, lint_id, orig_ident.span, - format!( - "cannot find {} `{}` in this scope", - ns.descr(), - ident - ), - BuiltinLintDiag::ProcMacroDeriveResolutionFallback( - orig_ident.span, - ), + BuiltinLintDiag::ProcMacroDeriveResolutionFallback { + span: orig_ident.span, + ns, + ident, + }, ); } let misc_flags = if module == this.graph_root { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 3d9380a3ebd..6bbde26db34 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -34,6 +34,7 @@ use rustc_span::hygiene::LocalExpnId; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::Span; use smallvec::SmallVec; +use tracing::debug; use std::cell::Cell; use std::mem; @@ -536,6 +537,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let determined_imports = mem::take(&mut self.determined_imports); let indeterminate_imports = mem::take(&mut self.indeterminate_imports); + let mut glob_error = false; for (is_indeterminate, import) in determined_imports .iter() .map(|i| (false, i)) @@ -547,6 +549,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.import_dummy_binding(*import, is_indeterminate); if let Some(err) = unresolved_import_error { + glob_error |= import.is_glob(); + if let ImportKind::Single { source, ref source_bindings, .. } = import.kind { if source.name == kw::SelfLower { // Silence `unresolved import` error if E0429 is already emitted @@ -562,7 +566,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { { // In the case of a new import line, throw a diagnostic message // for the previous line. - self.throw_unresolved_import_error(errors); + self.throw_unresolved_import_error(errors, glob_error); errors = vec![]; } if seen_spans.insert(err.span) { @@ -573,7 +577,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if !errors.is_empty() { - self.throw_unresolved_import_error(errors); + self.throw_unresolved_import_error(errors, glob_error); return; } @@ -599,9 +603,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - if !errors.is_empty() { - self.throw_unresolved_import_error(errors); - } + self.throw_unresolved_import_error(errors, glob_error); } pub(crate) fn check_hidden_glob_reexports( @@ -618,11 +620,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && binding.res() != Res::Err && exported_ambiguities.contains(&binding) { - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( AMBIGUOUS_GLOB_REEXPORTS, import.root_id, import.root_span, - "ambiguous glob re-exports", BuiltinLintDiag::AmbiguousGlobReexports { name: key.ident.to_string(), namespace: key.ns.descr().to_string(), @@ -654,11 +655,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && glob_binding.vis.is_public() && !binding.vis.is_public() { - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( HIDDEN_GLOB_REEXPORTS, binding_id, binding.span, - "private item shadows public glob re-export", BuiltinLintDiag::HiddenGlobReexports { name: key.ident.name.to_string(), namespace: key.ns.descr().to_owned(), @@ -673,7 +673,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn throw_unresolved_import_error(&mut self, errors: Vec<(Import<'_>, UnresolvedImportError)>) { + fn throw_unresolved_import_error( + &mut self, + errors: Vec<(Import<'_>, UnresolvedImportError)>, + glob_error: bool, + ) { if errors.is_empty() { return; } @@ -752,7 +756,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - diag.emit(); + let guar = diag.emit(); + if glob_error { + self.glob_error = Some(guar); + } } /// Attempts to resolve the given import, returning: @@ -1014,17 +1021,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && !max_vis.is_at_least(import_vis, self.tcx) { let def_id = self.local_def_id(id); - let msg = format!( - "glob import doesn't reexport anything with visibility `{}` because no imported item is public enough", - import_vis.to_string(def_id, self.tcx) - ); - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( UNUSED_IMPORTS, id, import.span, - msg, BuiltinLintDiag::RedundantImportVisibility { max_vis: max_vis.to_string(def_id, self.tcx), + import_vis: import_vis.to_string(def_id, self.tcx), span: import.span, }, ); @@ -1251,16 +1254,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if !any_successful_reexport { let (ns, binding) = reexport_error.unwrap(); if pub_use_of_private_extern_crate_hack(import, binding) { - let msg = format!( - "extern crate `{ident}` is private, and cannot be \ - re-exported (error E0365), consider declaring with \ - `pub`" - ); self.lint_buffer.buffer_lint( PUB_USE_OF_PRIVATE_EXTERN_CRATE, import_id, import.span, - msg, + BuiltinLintDiag::PrivateExternCrateReexport(ident), ); } else { if ns == TypeNS { @@ -1396,7 +1394,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { UNUSED_IMPORTS, id, import.span, - format!("the item `{source}` is imported redundantly"), BuiltinLintDiag::RedundantImport(redundant_spans, source), ); */ diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index ba1391bc378..0655484ad85 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -12,7 +12,7 @@ use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; use rustc_ast::ptr::P; -use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; +use rustc_ast::visit::{visit_opt, walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::{codes::*, Applicability, DiagArgValue, IntoDiagArg, StashKey}; @@ -21,14 +21,16 @@ use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, Par use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate}; use rustc_middle::middle::resolve_bound_vars::Set1; +use rustc_middle::ty::DelegationFnSig; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, ResolveDocLinks}; -use rustc_session::lint; +use rustc_session::lint::{self, BuiltinLintDiag}; use rustc_session::parse::feature_err; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Span, SyntaxContext}; use smallvec::{smallvec, SmallVec}; +use tracing::{debug, instrument, trace}; use std::assert_matches::debug_assert_matches; use std::borrow::Cow; @@ -46,7 +48,7 @@ use diagnostics::{ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime} #[derive(Copy, Clone, Debug)] struct BindingInfo { span: Span, - annotation: BindingAnnotation, + annotation: BindingMode, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -885,7 +887,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, kind: LifetimeBinderKind::Item, span: generics.span, }, - |this| visit::walk_foreign_item(this, foreign_item), + |this| visit::walk_item(this, foreign_item), ); } ForeignItemKind::Fn(box Fn { ref generics, .. }) => { @@ -897,13 +899,11 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, kind: LifetimeBinderKind::Function, span: generics.span, }, - |this| visit::walk_foreign_item(this, foreign_item), + |this| visit::walk_item(this, foreign_item), ); } ForeignItemKind::Static(..) => { - self.with_static_rib(def_kind, |this| { - visit::walk_foreign_item(this, foreign_item); - }); + self.with_static_rib(def_kind, |this| visit::walk_item(this, foreign_item)) } ForeignItemKind::MacCall(..) => { panic!("unexpanded macro in resolve!") @@ -1675,16 +1675,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { return; } LifetimeRibKind::AnonymousWarn(node_id) => { - let msg = if elided { - "`&` without an explicit lifetime name cannot be used here" - } else { - "`'_` cannot be used here" - }; - self.r.lint_buffer.buffer_lint_with_diagnostic( + self.r.lint_buffer.buffer_lint( lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, node_id, lifetime.ident.span, - msg, lint::BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span: lifetime.ident.span, @@ -1883,20 +1877,18 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // async fn foo(_: std::cell::Ref<u32>) { ... } LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } | LifetimeRibKind::AnonymousWarn(_) => { - let mut err = - self.r.dcx().create_err(errors::ImplicitElidedLifetimeNotAllowedHere { - span: path_span, - }); let sess = self.r.tcx.sess; - rustc_errors::add_elided_lifetime_in_path_suggestion( + let subdiag = rustc_errors::elided_lifetime_in_path_suggestion( sess.source_map(), - &mut err, expected_lifetimes, path_span, !segment.has_generic_args, elided_lifetime_span, ); - err.emit(); + self.r.dcx().emit_err(errors::ImplicitElidedLifetimeNotAllowedHere { + span: path_span, + subdiag, + }); should_lint = false; for id in node_ids { @@ -1968,11 +1960,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } if should_lint { - self.r.lint_buffer.buffer_lint_with_diagnostic( + self.r.lint_buffer.buffer_lint( lint::builtin::ELIDED_LIFETIMES_IN_PATHS, segment_id, elided_lifetime_span, - "hidden lifetime parameters in types are deprecated", lint::BuiltinLintDiag::ElidedLifetimesInPaths( expected_lifetimes, path_span, @@ -2350,8 +2341,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { None => {} } } - } else if let UseTreeKind::Nested(use_trees) = &use_tree.kind { - for (use_tree, _) in use_trees { + } else if let UseTreeKind::Nested { items, .. } = &use_tree.kind { + for (use_tree, _) in items { self.future_proof_import(use_tree); } } @@ -2528,7 +2519,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ItemKind::Use(ref use_tree) => { let maybe_exported = match use_tree.kind { UseTreeKind::Simple(_) | UseTreeKind::Glob => MaybeExported::Ok(item.id), - UseTreeKind::Nested(_) => MaybeExported::NestedUse(&item.vis), + UseTreeKind::Nested { .. } => MaybeExported::NestedUse(&item.vis), }; self.resolve_doc_links(&item.attrs, maybe_exported); @@ -2564,7 +2555,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ItemKind::ExternCrate(..) => {} - ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"), + ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => { + panic!("unexpanded macro in resolve!") + } } } @@ -2852,7 +2845,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { walk_assoc_item(this, generics, LifetimeBinderKind::Item, item) }), - AssocItemKind::MacCall(_) => { + AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => { panic!("unexpanded macro in resolve!") } }; @@ -3119,7 +3112,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }, ); } - AssocItemKind::MacCall(_) => { + AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => { panic!("unexpanded macro in resolve!") } } @@ -3221,7 +3214,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { AssocItemKind::Fn(..) => (E0324, "method"), AssocItemKind::Type(..) => (E0325, "type"), AssocItemKind::Delegation(..) => (E0324, "method"), - AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"), + AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { + span_bug!(span, "unexpanded macro") + } }; let trait_path = path_names_to_string(path); self.report_error( @@ -3285,7 +3280,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { fn resolve_local(&mut self, local: &'ast Local) { debug!("resolving local ({:?})", local); // Resolve the type. - walk_list!(self, visit_ty, &local.ty); + visit_opt!(self, visit_ty, &local.ty); // Resolve the initializer. if let Some((init, els)) = local.kind.init_else_opt() { @@ -3484,8 +3479,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { fn resolve_arm(&mut self, arm: &'ast Arm) { self.with_rib(ValueNS, RibKind::Normal, |this| { this.resolve_pattern_top(&arm.pat, PatternSource::Match); - walk_list!(this, visit_expr, &arm.guard); - walk_list!(this, visit_expr, &arm.body); + visit_opt!(this, visit_expr, &arm.guard); + visit_opt!(this, visit_expr, &arm.body); }); } @@ -3655,14 +3650,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { fn try_resolve_as_non_binding( &mut self, pat_src: PatternSource, - ann: BindingAnnotation, + ann: BindingMode, ident: Ident, has_sub: bool, ) -> Option<Res> { // An immutable (no `mut`) by-value (no `ref`) binding pattern without // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could // also be interpreted as a path to e.g. a constant, variant, etc. - let is_syntactic_ambiguity = !has_sub && ann == BindingAnnotation::NONE; + let is_syntactic_ambiguity = !has_sub && ann == BindingMode::NONE; let ls_binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS)?; let (res, binding) = match ls_binding { @@ -4038,9 +4033,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } #[inline] - /// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items. + /// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items or + // an invalid `use foo::*;` was found, which can cause unbounded ammounts of "item not found" + // errors. We silence them all. fn should_report_errs(&self) -> bool { !(self.r.tcx.sess.opts.actually_rustdoc && self.in_func_body) + && !self.r.glob_error.is_some() } // Resolve in alternative namespaces if resolution in the primary namespace fails. @@ -4507,9 +4505,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.visit_expr(elem); self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::Yes)); } - ExprKind::ConstBlock(ref ct) => { - self.resolve_anon_const(ct, AnonConstKind::InlineConst); - } ExprKind::Index(ref elem, ref idx, _) => { self.resolve_expr(elem, Some(expr)); self.visit_expr(idx); @@ -4751,12 +4746,13 @@ struct ItemInfoCollector<'a, 'b, 'tcx> { 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); - } + let sig = DelegationFnSig { + header: sig.header, + param_count: sig.decl.inputs.len(), + has_self: sig.decl.has_self(), + c_variadic: sig.decl.c_variadic(), + }; + self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig); } } @@ -4792,7 +4788,8 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { | ItemKind::ExternCrate(..) | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(..) - | ItemKind::MacCall(..) => {} + | ItemKind::MacCall(..) + | ItemKind::DelegationMac(..) => {} 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, @@ -4818,7 +4815,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); visit::walk_crate(&mut late_resolution_visitor, krate); for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() { - self.lint_buffer.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label"); + self.lint_buffer.buffer_lint( + lint::builtin::UNUSED_LABELS, + *id, + *span, + BuiltinLintDiag::UnusedLabel, + ); } } } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index d79c638fa07..9daa22f89d2 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -17,6 +17,7 @@ use rustc_ast::{ }; use rustc_ast_pretty::pprust::where_bound_predicate_to_string; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan, SuggestionStyle, @@ -31,7 +32,7 @@ use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use rustc_middle::ty; @@ -40,6 +41,7 @@ use std::iter; use std::ops::Deref; use thin_vec::ThinVec; +use tracing::debug; use super::NoConstantGenericsReason; @@ -2039,12 +2041,15 @@ 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)) => + if self.r.delegation_fn_sigs[&self.r.local_def_id(assoc_item.id)] + .has_self => { AssocSuggestion::MethodWithSelf { called } } ast::AssocItemKind::Delegation(..) => AssocSuggestion::AssocFn { called }, - ast::AssocItemKind::MacCall(_) => continue, + ast::AssocItemKind::MacCall(_) | ast::AssocItemKind::DelegationMac(..) => { + continue; + } }); } } @@ -2062,7 +2067,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { if filter_fn(res) { let def_id = res.def_id(); let has_self = match def_id.as_local() { - Some(def_id) => self.r.has_self.contains(&def_id), + Some(def_id) => { + self.r.delegation_fn_sigs.get(&def_id).map_or(false, |sig| sig.has_self) + } None => self .r .tcx @@ -2645,15 +2652,15 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let deletion_span = if param.bounds.is_empty() { deletion_span() } else { None }; - self.r.lint_buffer.buffer_lint_with_diagnostic( + self.r.lint_buffer.buffer_lint( lint::builtin::SINGLE_USE_LIFETIMES, param.id, param.ident.span, - format!("lifetime parameter `{}` only used once", param.ident), lint::BuiltinLintDiag::SingleUseLifetime { param_span: param.ident.span, use_span: Some((use_span, elidable)), deletion_span, + ident: param.ident, }, ); } @@ -2663,15 +2670,15 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { // if the lifetime originates from expanded code, we won't be able to remove it #104432 if deletion_span.is_some_and(|sp| !sp.in_derive_expansion()) { - self.r.lint_buffer.buffer_lint_with_diagnostic( + self.r.lint_buffer.buffer_lint( lint::builtin::UNUSED_LIFETIMES, param.id, param.ident.span, - format!("lifetime parameter `{}` never used", param.ident), lint::BuiltinLintDiag::SingleUseLifetime { param_span: param.ident.span, use_span: None, deletion_span, + ident: param.ident, }, ); } @@ -2708,8 +2715,17 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { self.suggest_introducing_lifetime( &mut err, Some(lifetime_ref.ident.name.as_str()), - |err, _, span, message, suggestion| { - err.span_suggestion(span, message, suggestion, Applicability::MaybeIncorrect); + |err, _, span, message, suggestion, span_suggs| { + err.multipart_suggestion_with_style( + message, + std::iter::once((span, suggestion)).chain(span_suggs.clone()).collect(), + Applicability::MaybeIncorrect, + if span_suggs.is_empty() { + SuggestionStyle::ShowCode + } else { + SuggestionStyle::ShowAlways + }, + ); true }, ); @@ -2720,13 +2736,20 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { &self, err: &mut Diag<'_>, name: Option<&str>, - suggest: impl Fn(&mut Diag<'_>, bool, Span, Cow<'static, str>, String) -> bool, + suggest: impl Fn( + &mut Diag<'_>, + bool, + Span, + Cow<'static, str>, + String, + Vec<(Span, String)>, + ) -> bool, ) { let mut suggest_note = true; for rib in self.lifetime_ribs.iter().rev() { let mut should_continue = true; match rib.kind { - LifetimeRibKind::Generics { binder: _, span, kind } => { + LifetimeRibKind::Generics { binder, span, kind } => { // Avoid suggesting placing lifetime parameters on constant items unless the relevant // feature is enabled. Suggest the parent item as a possible location if applicable. if let LifetimeBinderKind::ConstItem = kind @@ -2755,11 +2778,53 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { | LifetimeBinderKind::PolyTrait | LifetimeBinderKind::WhereBound ); + + let mut rm_inner_binders: FxIndexSet<Span> = Default::default(); let (span, sugg) = if span.is_empty() { + let mut binder_idents: FxIndexSet<Ident> = Default::default(); + binder_idents.insert(Ident::from_str(name.unwrap_or("'a"))); + + // We need to special case binders in the following situation: + // Change `T: for<'a> Trait<T> + 'b` to `for<'a, 'b> T: Trait<T> + 'b` + // T: for<'a> Trait<T> + 'b + // ^^^^^^^ remove existing inner binder `for<'a>` + // for<'a, 'b> T: Trait<T> + 'b + // ^^^^^^^^^^^ suggest outer binder `for<'a, 'b>` + if let LifetimeBinderKind::WhereBound = kind + && let Some(ast::WherePredicate::BoundPredicate( + ast::WhereBoundPredicate { bounded_ty, bounds, .. }, + )) = self.diag_metadata.current_where_predicate + && bounded_ty.id == binder + { + for bound in bounds { + if let ast::GenericBound::Trait(poly_trait_ref, _) = bound + && let span = poly_trait_ref + .span + .with_hi(poly_trait_ref.trait_ref.path.span.lo()) + && !span.is_empty() + { + rm_inner_binders.insert(span); + poly_trait_ref.bound_generic_params.iter().for_each(|v| { + binder_idents.insert(v.ident); + }); + } + } + } + + let binders_sugg = binder_idents.into_iter().enumerate().fold( + "".to_string(), + |mut binders, (i, x)| { + if i != 0 { + binders += ", "; + } + binders += x.as_str(); + binders + }, + ); let sugg = format!( "{}<{}>{}", if higher_ranked { "for" } else { "" }, - name.unwrap_or("'a"), + binders_sugg, if higher_ranked { " " } else { "" }, ); (span, sugg) @@ -2774,13 +2839,28 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let sugg = format!("{}, ", name.unwrap_or("'a")); (span, sugg) }; + if higher_ranked { let message = Cow::from(format!( "consider making the {} lifetime-generic with a new `{}` lifetime", kind.descr(), name.unwrap_or("'a"), )); - should_continue = suggest(err, true, span, message, sugg); + should_continue = suggest( + err, + true, + span, + message, + sugg, + if !rm_inner_binders.is_empty() { + rm_inner_binders + .into_iter() + .map(|v| (v, "".to_string())) + .collect::<Vec<_>>() + } else { + vec![] + }, + ); err.note_once( "for more information on higher-ranked polymorphism, visit \ https://doc.rust-lang.org/nomicon/hrtb.html", @@ -2788,10 +2868,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } else if let Some(name) = name { let message = Cow::from(format!("consider introducing lifetime `{name}` here")); - should_continue = suggest(err, false, span, message, sugg); + should_continue = suggest(err, false, span, message, sugg, vec![]); } else { let message = Cow::from("consider introducing a named lifetime parameter"); - should_continue = suggest(err, false, span, message, sugg); + should_continue = suggest(err, false, span, message, sugg, vec![]); } } LifetimeRibKind::Item | LifetimeRibKind::ConstParamTy => break, @@ -3027,11 +3107,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { self.suggest_introducing_lifetime( err, None, - |err, higher_ranked, span, message, intro_sugg| { + |err, higher_ranked, span, message, intro_sugg, _| { err.multipart_suggestion_verbose( message, std::iter::once((span, intro_sugg)) - .chain(spans_suggs.iter().cloned()) + .chain(spans_suggs.clone()) .collect(), Applicability::MaybeIncorrect, ); @@ -3155,11 +3235,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { self.suggest_introducing_lifetime( err, None, - |err, higher_ranked, span, message, intro_sugg| { + |err, higher_ranked, span, message, intro_sugg, _| { err.multipart_suggestion_verbose( message, std::iter::once((span, intro_sugg)) - .chain(spans_suggs.iter().cloned()) + .chain(spans_suggs.clone()) .collect(), Applicability::MaybeIncorrect, ); @@ -3303,7 +3383,6 @@ fn mk_where_bound_predicate( poly_trait_ref: &ast::PolyTraitRef, ty: &Ty, ) -> Option<ast::WhereBoundPredicate> { - use rustc_span::DUMMY_SP; let modified_segments = { let mut segments = path.segments.clone(); let [preceding @ .., second_last, last] = segments.as_mut_slice() else { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index b8221d9d7f9..9557b0f5ebc 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -6,9 +6,13 @@ //! //! Type-relative name resolution (methods, fields, associated items) happens in `rustc_hir_analysis`. +// tidy-alphabetical-start +#![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::potential_query_instability)] +#![allow(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] -#![feature(rustdoc_internals)] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(extract_if)] @@ -16,18 +20,9 @@ #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(rustc_attrs)] -#![allow(rustdoc::private_intra_doc_links)] -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::potential_query_instability)] -#![allow(rustc::untranslatable_diagnostic)] -#![allow(internal_features)] - -#[macro_use] -extern crate tracing; +#![feature(rustdoc_internals)] +// tidy-alphabetical-end -use errors::{ - ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst, ParamKindInTyOfConstParam, -}; use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::expand::StrippedCfgItem; use rustc_ast::node_id::NodeMap; @@ -37,13 +32,13 @@ 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, Diag, ErrCode}; -use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind}; +use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed}; +use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind}; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::NonMacroAttrKind; use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS}; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalDefIdSet}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{PrimTy, TraitCandidate}; use rustc_index::IndexVec; @@ -52,27 +47,29 @@ use rustc_middle::metadata::ModChild; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::query::Providers; use rustc_middle::span_bug; -use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt, TyCtxtFeed}; -use rustc_middle::ty::{Feed, ResolverGlobalCtxt, ResolverOutputs}; +use rustc_middle::ty::{self, DelegationFnSig, Feed, MainDefinition, RegisteredTools}; +use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs, TyCtxt, TyCtxtFeed}; use rustc_query_system::ich::StableHashingContext; use rustc_session::lint::builtin::PRIVATE_MACRO_USE; -use rustc_session::lint::LintBuffer; +use rustc_session::lint::{BuiltinLintDiag, LintBuffer}; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; - use smallvec::{smallvec, SmallVec}; use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; use std::fmt; +use tracing::debug; use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion}; +use effective_visibilities::EffectiveVisibilitiesVisitor; +use errors::{ + ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst, ParamKindInTyOfConstParam, +}; use imports::{Import, ImportData, ImportKind, NameResolution}; use late::{HasGenericParams, PathSource, PatternSource, UnnecessaryQualification}; use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; -use crate::effective_visibilities::EffectiveVisibilitiesVisitor; - type Res = def::Res<NodeId>; mod build_reduced_graph; @@ -959,12 +956,11 @@ enum BuiltinMacroState { } struct DeriveData { - resolutions: DeriveResolutions, + resolutions: Vec<DeriveResolution>, helper_attrs: Vec<(usize, Ident)>, has_derive_copy: bool, } -#[derive(Clone)] struct MacroData { ext: Lrc<SyntaxExtension>, rule_spans: Vec<(usize, Span)>, @@ -992,7 +988,6 @@ pub struct Resolver<'a, 'tcx> { extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>, /// N.B., this is used only for better diagnostics, not name resolution itself. - has_self: LocalDefIdSet, field_def_ids: LocalDefIdMap<&'tcx [DefId]>, /// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax. @@ -1042,7 +1037,7 @@ pub struct Resolver<'a, 'tcx> { block_map: NodeMap<Module<'a>>, /// A fake module that contains no definition and no prelude. Used so that /// some AST passes can generate identifiers that only resolve to local or - /// language items. + /// lang items. empty_module: Module<'a>, module_map: FxHashMap<DefId, Module<'a>>, binding_parent_modules: FxHashMap<NameBinding<'a>, Module<'a>>, @@ -1053,6 +1048,7 @@ pub struct Resolver<'a, 'tcx> { /// Maps glob imports to the names of items actually imported. glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>, + glob_error: Option<ErrorGuaranteed>, visibilities_for_hashing: Vec<(LocalDefId, ty::Visibility)>, used_imports: FxHashSet<NodeId>, maybe_unused_trait_imports: FxIndexSet<LocalDefId>, @@ -1149,8 +1145,7 @@ 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>, + delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>, main_def: Option<MainDefinition>, trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>, @@ -1399,7 +1394,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { prelude: None, extern_prelude, - has_self: Default::default(), field_def_ids: Default::default(), field_visibility_spans: FxHashMap::default(), @@ -1424,6 +1418,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ast_transform_scopes: FxHashMap::default(), glob_map: Default::default(), + glob_error: None, visibilities_for_hashing: Default::default(), used_imports: FxHashSet::default(), maybe_unused_trait_imports: Default::default(), @@ -1508,7 +1503,7 @@ 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(), + delegation_fn_sigs: Default::default(), }; let root_parent_scope = ParentScope::module(graph_root, &resolver); @@ -1621,8 +1616,7 @@ 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, + delegation_fn_sigs: self.delegation_fn_sigs, }; ResolverOutputs { global_ctxt, ast_lowering } } @@ -1868,8 +1862,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let NameBindingKind::Import { import, binding } = 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); + self.lint_buffer().buffer_lint( + PRIVATE_MACRO_USE, + import.root_id, + ident.span, + BuiltinLintDiag::MacroIsPrivate(ident), + ); } // 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. diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 2a23ed71753..268e7f06d04 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -15,7 +15,7 @@ use rustc_attr::StabilityLevel; use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, StashKey}; -use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand}; +use rustc_expand::base::{Annotatable, DeriveResolution, Indeterminate, ResolverExpand}; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion}; @@ -29,6 +29,7 @@ use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE}; use rustc_session::lint::builtin::{UNUSED_MACROS, UNUSED_MACRO_RULES}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::parse::feature_err; +use rustc_span::edit_distance::edit_distance; use rustc_span::edition::Edition; use rustc_span::hygiene::{self, ExpnData, ExpnKind, LocalExpnId}; use rustc_span::hygiene::{AstPass, MacroKind}; @@ -141,7 +142,7 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools { } // We implicitly add `rustfmt`, `clippy`, `diagnostic` to known tools, // but it's not an error to register them explicitly. - let predefined_tools = [sym::clippy, sym::rustfmt, sym::diagnostic]; + let predefined_tools = [sym::clippy, sym::rustfmt, sym::diagnostic, sym::miri]; registered_tools.extend(predefined_tools.iter().cloned().map(Ident::with_dummy_span)); registered_tools } @@ -314,7 +315,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { UNUSED_MACROS, node_id, ident.span, - format!("unused macro definition: `{}`", ident.name), + BuiltinLintDiag::UnusedMacroDefinition(ident.name), ); } for (&(def_id, arm_i), &(ident, rule_span)) in self.unused_macro_rules.iter() { @@ -327,11 +328,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { UNUSED_MACRO_RULES, node_id, rule_span, - format!( - "{} rule of macro `{}` is never used", - crate::diagnostics::ordinalize(arm_i + 1), - ident.name - ), + BuiltinLintDiag::MacroRuleNeverUsed(arm_i, ident.name), ); } } @@ -344,7 +341,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { &mut self, expn_id: LocalExpnId, force: bool, - derive_paths: &dyn Fn() -> DeriveResolutions, + derive_paths: &dyn Fn() -> Vec<DeriveResolution>, ) -> Result<(), Indeterminate> { // Block expansion of the container until we resolve all derives in it. // This is required for two reasons: @@ -360,11 +357,11 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { has_derive_copy: false, }); let parent_scope = self.invocation_parent_scopes[&expn_id]; - for (i, (path, _, opt_ext, _)) in entry.resolutions.iter_mut().enumerate() { - if opt_ext.is_none() { - *opt_ext = Some( + for (i, resolution) in entry.resolutions.iter_mut().enumerate() { + if resolution.exts.is_none() { + resolution.exts = Some( match self.resolve_macro_path( - path, + &resolution.path, Some(MacroKind::Derive), &parent_scope, true, @@ -372,7 +369,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { ) { Ok((Some(ext), _)) => { if !ext.helper_attrs.is_empty() { - let last_seg = path.segments.last().unwrap(); + let last_seg = resolution.path.segments.last().unwrap(); let span = last_seg.ident.span.normalize_to_macros_2_0(); entry.helper_attrs.extend( ext.helper_attrs @@ -416,7 +413,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { Ok(()) } - fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option<DeriveResolutions> { + fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option<Vec<DeriveResolution>> { self.derive_data.remove(&expn_id).map(|data| data.resolutions) } @@ -555,28 +552,46 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // We are trying to avoid reporting this error if other related errors were reported. if res != Res::Err && inner_attr && !self.tcx.features().custom_inner_attributes { - let msg = match res { - Res::Def(..) => "inner macro attributes are unstable", - Res::NonMacroAttr(..) => "custom inner attributes are unstable", + let is_macro = match res { + Res::Def(..) => true, + Res::NonMacroAttr(..) => false, _ => unreachable!(), }; if soft_custom_inner_attributes_gate { - self.tcx.sess.psess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg); + self.tcx.sess.psess.buffer_lint( + SOFT_UNSTABLE, + path.span, + node_id, + BuiltinLintDiag::InnerAttributeUnstable { is_macro }, + ); } else { + // FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::InnerAttributeUnstable`) + let msg = if is_macro { + "inner macro attributes are unstable" + } else { + "custom inner attributes are unstable" + }; feature_err(&self.tcx.sess, sym::custom_inner_attributes, path.span, msg).emit(); } } if res == Res::NonMacroAttr(NonMacroAttrKind::Tool) - && path.segments.len() >= 2 - && path.segments[0].ident.name == sym::diagnostic - && path.segments[1].ident.name != sym::on_unimplemented + && let [namespace, attribute, ..] = &*path.segments + && namespace.ident.name == sym::diagnostic + && !(attribute.ident.name == sym::on_unimplemented + || (attribute.ident.name == sym::do_not_recommend + && self.tcx.features().do_not_recommend)) { + let distance = + edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5); + + let typo_name = distance.map(|_| sym::on_unimplemented); + self.tcx.sess.psess.buffer_lint( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, - path.segments[1].span(), + attribute.span(), node_id, - "unknown diagnostic attribute", + BuiltinLintDiag::UnknownDiagnosticAttribute { span: attribute.span(), typo_name }, ); } @@ -776,11 +791,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .invocation_parents .get(&parent_scope.expansion) .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0]); - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( LEGACY_DERIVE_HELPERS, node_id, ident.span, - "derive helper attribute is used before it is introduced", BuiltinLintDiag::LegacyDeriveHelpers(binding.span), ); } @@ -830,8 +844,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature)); if !is_allowed(feature) && !allowed_by_implication { let lint_buffer = &mut self.lint_buffer; - let soft_handler = - |lint, span, msg: String| lint_buffer.buffer_lint(lint, node_id, span, msg); + let soft_handler = |lint, span, msg: String| { + lint_buffer.buffer_lint( + lint, + node_id, + span, + BuiltinLintDiag::UnstableFeature( + // FIXME make this translatable + msg.into(), + ), + ) + }; stability::report_unstable( self.tcx.sess, feature, @@ -847,14 +870,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let Some(depr) = &ext.deprecation { let path = pprust::path_to_string(path); - let (message, lint) = stability::deprecation_message_and_lint(depr, "macro", &path); - stability::early_report_deprecation( + stability::early_report_macro_deprecation( &mut self.lint_buffer, - message, - depr.suggestion, - lint, + depr, span, node_id, + path, ); } } diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 0bc7579918c..66b4981eb55 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -6,8 +6,9 @@ use rustc_middle::ty::TyCtxt; use rustc_span::def_id::DefId; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{InnerSpan, Span, DUMMY_SP}; +use std::mem; use std::ops::Range; -use std::{cmp, mem}; +use tracing::{debug, trace}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum DocFragmentKind { @@ -129,17 +130,20 @@ pub fn unindent_doc_fragments(docs: &mut [DocFragment]) { let Some(min_indent) = docs .iter() .map(|fragment| { - fragment.doc.as_str().lines().fold(usize::MAX, |min_indent, line| { - if line.chars().all(|c| c.is_whitespace()) { - min_indent - } else { + fragment + .doc + .as_str() + .lines() + .filter(|line| line.chars().any(|c| !c.is_whitespace())) + .map(|line| { // Compare against either space or tab, ignoring whether they are // mixed or not. let whitespace = line.chars().take_while(|c| *c == ' ' || *c == '\t').count(); - cmp::min(min_indent, whitespace) - + if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add } - } - }) + whitespace + + (if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add }) + }) + .min() + .unwrap_or(usize::MAX) }) .min() else { @@ -151,13 +155,13 @@ pub fn unindent_doc_fragments(docs: &mut [DocFragment]) { continue; } - let min_indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 { + let indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 { min_indent - add } else { min_indent }; - fragment.indent = min_indent; + fragment.indent = indent; } } |
