diff options
Diffstat (limited to 'compiler/rustc_resolve/src')
| -rw-r--r-- | compiler/rustc_resolve/src/check_unused.rs | 74 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/def_collector.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/diagnostics.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/ident.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/imports.rs | 44 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 36 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/diagnostics.rs | 109 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/lib.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/macros.rs | 63 |
9 files changed, 213 insertions, 164 deletions
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 180e7f6def3..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}; @@ -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 }, ); } @@ -394,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, ); } } @@ -414,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, + ); } _ => {} } @@ -434,20 +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::Unused { spans, remove } => { - fixes.push((remove, String::new())); - spans - } - UnusedSpanResult::PartialUnused { 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); @@ -459,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 @@ -501,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, + }, ); } @@ -552,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 bd062242856..cad10571afe 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -325,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 b28312fa473..856cfbc01e8 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -128,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), ); } @@ -145,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 { @@ -526,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, ); } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index f88725830f1..57db765c07e 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -524,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 f53bcb0e9d0..6bbde26db34 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -537,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)) @@ -548,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 @@ -563,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) { @@ -574,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; } @@ -600,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( @@ -619,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(), @@ -655,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(), @@ -674,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; } @@ -753,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: @@ -1015,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, }, ); @@ -1252,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 { @@ -1397,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 0f585aafdd5..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}; @@ -24,7 +24,7 @@ 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}; @@ -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, @@ -1966,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, @@ -3287,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() { @@ -3486,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); }); } @@ -4040,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. @@ -4509,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); @@ -4822,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 1958fdf1cbc..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; @@ -2651,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, }, ); } @@ -2669,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, }, ); } @@ -2714,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 }, ); @@ -2726,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 @@ -2761,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) @@ -2780,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", @@ -2794,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, @@ -3033,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, ); @@ -3161,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, ); @@ -3309,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 01bcfec4bdc..9557b0f5ebc 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -32,7 +32,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, Diag, ErrCode}; +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, *}; @@ -51,7 +51,7 @@ use rustc_middle::ty::{self, DelegationFnSig, Feed, MainDefinition, RegisteredTo 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}; @@ -1048,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>, @@ -1417,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(), @@ -1860,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 f8d245f94e5..268e7f06d04 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -315,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() { @@ -328,7 +328,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { UNUSED_MACRO_RULES, node_id, rule_span, - format!("rule #{} of macro `{}` is never used", arm_i + 1, ident.name), + BuiltinLintDiag::MacroRuleNeverUsed(arm_i, ident.name), ); } } @@ -552,14 +552,25 @@ 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(); } } @@ -567,22 +578,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if res == Res::NonMacroAttr(NonMacroAttrKind::Tool) && let [namespace, attribute, ..] = &*path.segments && namespace.ident.name == sym::diagnostic - && attribute.ident.name != sym::on_unimplemented + && !(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 help = if distance.is_some() { - BuiltinLintDiag::MaybeTypo { span: attribute.span(), name: sym::on_unimplemented } - } else { - BuiltinLintDiag::Normal - }; - self.tcx.sess.psess.buffer_lint_with_diagnostic( + let typo_name = distance.map(|_| sym::on_unimplemented); + + self.tcx.sess.psess.buffer_lint( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, attribute.span(), node_id, - "unknown diagnostic attribute", - help, + BuiltinLintDiag::UnknownDiagnosticAttribute { span: attribute.span(), typo_name }, ); } @@ -782,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), ); } @@ -836,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, @@ -853,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, ); } } |
