1
Fork 0

Migrate more diagnostics

This commit is contained in:
Jean CASPAR 2024-03-24 21:53:18 +00:00
parent 4226dc2045
commit cec9f7f716
5 changed files with 536 additions and 173 deletions

View file

@ -38,6 +38,9 @@ resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion =
resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion = resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion =
this would need to be a `{$suggestion}` this would need to be a `{$suggestion}`
resolve_attributes_starting_with_rustc_are_reserved =
attributes starting with `rustc` are reserved for use by the `rustc` compiler
resolve_bad_macro_import = bad macro import resolve_bad_macro_import = bad macro import
resolve_binding_in_never_pattern = resolve_binding_in_never_pattern =
@ -70,12 +73,19 @@ resolve_cannot_determine_macro_resolution =
cannot determine resolution for the {$kind} `{$path}` cannot determine resolution for the {$kind} `{$path}`
.note = import resolution is stuck, try simplifying macro imports .note = import resolution is stuck, try simplifying macro imports
resolve_cannot_find_builtin_macro_with_name =
cannot find a built-in macro with name `{$ident}`
resolve_cannot_find_ident_in_this_scope = resolve_cannot_find_ident_in_this_scope =
cannot find {$expected} `{$ident}` in this scope cannot find {$expected} `{$ident}` in this scope
resolve_cannot_glob_import_possible_crates = resolve_cannot_glob_import_possible_crates =
cannot glob-import all possible crates cannot glob-import all possible crates
resolve_cannot_use_through_an_import =
cannot use {$article} {$descr} through an import
.note = the {$descr} imported here
resolve_change_import_binding = resolve_change_import_binding =
you can use `as` to change the binding name of the import you can use `as` to change the binding name of the import
@ -88,6 +98,12 @@ resolve_consider_adding_macro_export =
resolve_consider_declaring_with_pub = resolve_consider_declaring_with_pub =
consider declaring type or module `{$ident}` with `pub` consider declaring type or module `{$ident}` with `pub`
resolve_consider_making_the_field_public =
{ $number_of_fields ->
[one] consider making the field publicly accessible
*[other] consider making the fields publicly accessible
}
resolve_consider_marking_as_pub = resolve_consider_marking_as_pub =
consider marking `{$ident}` as `pub` in the imported module consider marking `{$ident}` as `pub` in the imported module
@ -108,6 +124,9 @@ resolve_const_param_in_non_trivial_anon_const =
resolve_const_param_in_ty_of_const_param = resolve_const_param_in_ty_of_const_param =
const parameters may not be used in the type of const parameters const parameters may not be used in the type of const parameters
resolve_constructor_private_if_any_field_private =
a constructor is private if any of the fields is private
resolve_elided_anonymous_lifetime_report_error = resolve_elided_anonymous_lifetime_report_error =
`&` without an explicit lifetime name cannot be used here `&` without an explicit lifetime name cannot be used here
.label = explicit lifetime name needed here .label = explicit lifetime name needed here
@ -133,10 +152,20 @@ resolve_extern_crate_self_requires_renaming =
`extern crate self;` requires renaming `extern crate self;` requires renaming
.suggestion = rename the `self` crate to be able to import it .suggestion = rename the `self` crate to be able to import it
resolve_failed_resolve_unresolve_import = failed to resolve: unresolved import
resolve_failed_resolve_unresolve_import_label = unresolved import
resolve_forward_declared_generic_param = resolve_forward_declared_generic_param =
generic parameters with a default cannot use forward declared identifiers generic parameters with a default cannot use forward declared identifiers
.label = defaulted generic parameters cannot be forward declared .label = defaulted generic parameters cannot be forward declared
resolve_found_an_item_configured_out =
found an item that was configured out
resolve_generic_arguments_in_macro_path =
generic arguments in macro path
resolve_generic_params_from_outer_item = resolve_generic_params_from_outer_item =
can't use {$is_self -> can't use {$is_self ->
[true] `Self` [true] `Self`
@ -171,6 +200,12 @@ resolve_ident_bound_more_than_once_in_same_pattern =
identifier `{$identifier}` is bound more than once in the same pattern identifier `{$identifier}` is bound more than once in the same pattern
.label = used in a pattern more than once .label = used in a pattern more than once
resolve_ident_imported_here_but_it_is_desc =
`{$imported_ident}` is imported here, but it is {$imported_ident_desc}
resolve_ident_in_scope_but_it_is_desc =
`{$imported_ident}` is in scope, but it is {$imported_ident_desc}
resolve_imported_crate = `$crate` may not be imported resolve_imported_crate = `$crate` may not be imported
resolve_imported_macro_not_found = imported macro not found resolve_imported_macro_not_found = imported macro not found
@ -190,6 +225,13 @@ resolve_is_not_directly_importable =
`{$target}` is not directly importable `{$target}` is not directly importable
.label = cannot be imported directly .label = cannot be imported directly
resolve_is_private =
{$ident_descr} `{$ident}` is private
.label = private {$ident_descr}
resolve_item_was_behind_feature =
the item is gated behind the `{$feature}` feature
resolve_items_in_traits_are_not_importable = resolve_items_in_traits_are_not_importable =
items in traits are not importable items in traits are not importable
@ -217,6 +259,7 @@ resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments =
resolve_macro_expected_found = resolve_macro_expected_found =
expected {$expected}, found {$found} `{$macro_path}` expected {$expected}, found {$found} `{$macro_path}`
.label = not {$article} {$expected}
resolve_macro_extern_deprecated = resolve_macro_extern_deprecated =
`#[macro_escape]` is a deprecated synonym for `#[macro_use]` `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
@ -237,11 +280,45 @@ resolve_missing_macro_rules_name = maybe you have forgotten to define a name for
resolve_module_only = resolve_module_only =
visibility must resolve to a module visibility must resolve to a module
resolve_name_defined_multiple_time =
the name `{$name}` is defined multiple times
.note = `{$name}` must be defined only once in the {$descr} namespace of this {$container}
resolve_name_defined_multiple_time_old_binding_definition =
previous definition of the {$old_kind} `{$name}` here
resolve_name_defined_multiple_time_old_binding_import =
previous import of the {$old_kind} `{$name}` here
resolve_name_defined_multiple_time_redefined =
`{$name}` redefined here
resolve_name_defined_multiple_time_reimported =
`{$name}` reimported here
resolve_name_is_already_used_as_generic_parameter = resolve_name_is_already_used_as_generic_parameter =
the name `{$name}` is already used for a generic parameter in this item's generic parameters the name `{$name}` is already used for a generic parameter in this item's generic parameters
.label = already used .label = already used
.first_use_of_name = first use of `{$name}` .first_use_of_name = first use of `{$name}`
resolve_name_reserved_in_attribute_namespace =
name `{$ident}` is reserved in attribute namespace
resolve_note_and_refers_to_the_item_defined_here =
{$first ->
[true] {$dots ->
[true] the {$binding_descr} `{$binding_name}` is defined here...
*[false] the {$binding_descr} `{$binding_name}` is defined here
}
*[false] {$dots ->
[true] ...and refers to the {$binding_descr} `{$binding_name}` which is defined here...
*[false] ...and refers to the {$binding_descr} `{$binding_name}` which is defined here
}
}
resolve_outer_ident_is_not_publicly_reexported =
{$outer_ident_descr} `{$outer_ident}` is not publicly re-exported
resolve_param_in_enum_discriminant = resolve_param_in_enum_discriminant =
generic parameters may not be used in enum discriminant values generic parameters may not be used in enum discriminant values
.label = cannot perform const operation using `{$name}` .label = cannot perform const operation using `{$name}`
@ -275,6 +352,8 @@ resolve_relative_2018 =
resolve_remove_surrounding_derive = resolve_remove_surrounding_derive =
remove from the surrounding `derive()` remove from the surrounding `derive()`
resolve_remove_unnecessary_import = remove unnecessary import
resolve_self_import_can_only_appear_once_in_the_list = resolve_self_import_can_only_appear_once_in_the_list =
`self` import can only appear once in an import list `self` import can only appear once in an import list
.label = can only appear once in an import list .label = can only appear once in an import list
@ -296,13 +375,33 @@ resolve_self_in_generic_param_default =
generic parameters cannot use `Self` in their defaults generic parameters cannot use `Self` in their defaults
.label = `Self` in generic parameter default .label = `Self` in generic parameter default
resolve_similarly_named_defined_here =
similarly named {$candidate_descr} `{$candidate}` defined here
resolve_single_item_defined_here =
{$candidate_descr} `{$candidate}` defined here
resolve_static_lifetime_is_reserved = invalid lifetime parameter name: `{$lifetime}` resolve_static_lifetime_is_reserved = invalid lifetime parameter name: `{$lifetime}`
.label = 'static is a reserved lifetime name .label = 'static is a reserved lifetime name
resolve_suggestion_import_ident_directly =
import `{$ident}` directly
resolve_suggestion_import_ident_through_reexport =
import `{$ident}` through the re-export
resolve_tool_module_imported = resolve_tool_module_imported =
cannot use a tool module through an import cannot use a tool module through an import
.note = the tool module imported here .note = the tool module imported here
resolve_tool_only_accepts_identifiers =
`{$tool}` only accepts identifiers
.label = not an identifier
resolve_tool_was_already_registered =
tool `{$tool}` was already registered
.label = already registered here
resolve_trait_impl_duplicate = resolve_trait_impl_duplicate =
duplicate definitions with name `{$name}`: duplicate definitions with name `{$name}`:
.label = duplicate definition .label = duplicate definition
@ -368,3 +467,10 @@ resolve_variable_is_not_bound_in_all_patterns =
variable `{$name}` is not bound in all patterns variable `{$name}` is not bound in all patterns
resolve_variable_not_in_all_patterns = variable not in all patterns resolve_variable_not_in_all_patterns = variable not in all patterns
resolve_you_could_import_this_desc = you could import this {$desc}
resolve_trait_impl_mismatch =
item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}`
.label = does not match trait
.trait_impl_mismatch_label_item = item in trait

View file

@ -6,8 +6,8 @@ use rustc_ast::{MetaItemKind, NestedMetaItem};
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{ use rustc_errors::{
codes::*, pluralize, report_ambiguity_error, struct_span_code_err, Applicability, Diag, codes::*, report_ambiguity_error, struct_span_code_err, Applicability, Diag, DiagCtxt,
DiagCtxt, ErrorGuaranteed, MultiSpan, SuggestionStyle, ErrorGuaranteed, MultiSpan, SuggestionStyle,
}; };
use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_feature::BUILTIN_ATTRIBUTES;
use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::Namespace::{self, *};
@ -29,10 +29,9 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Span, SyntaxContext}; use rustc_span::{BytePos, Span, SyntaxContext};
use thin_vec::{thin_vec, ThinVec}; use thin_vec::{thin_vec, ThinVec};
use crate::errors::{self, use crate::errors::{
AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive,
ConsiderAddingADerive, ExplicitUnsafeTraits, MacroDefinedLater, MacroSuggMovePosition, ExplicitUnsafeTraits, MacroDefinedLater, MacroSuggMovePosition, MaybeMissingMacroRulesName,
MaybeMissingMacroRulesName,
}; };
use crate::imports::{Import, ImportKind}; use crate::imports::{Import, ImportKind};
use crate::late::{PatternSource, Rib}; use crate::late::{PatternSource, Rib};
@ -226,16 +225,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ModuleKind::Block => "block", ModuleKind::Block => "block",
}; };
let old_noun = match old_binding.is_import_user_facing() {
true => "import",
false => "definition",
};
let new_participle = match new_binding.is_import_user_facing() {
true => "imported",
false => "defined",
};
let (name, span) = let (name, span) =
(ident.name, self.tcx.sess.source_map().guess_head_span(new_binding.span)); (ident.name, self.tcx.sess.source_map().guess_head_span(new_binding.span));
@ -254,35 +243,51 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
(TypeNS, _) => "type", (TypeNS, _) => "type",
}; };
let msg = format!("the name `{name}` is defined multiple times"); let code = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
(true, true) => E0259,
let mut err = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
(true, true) => struct_span_code_err!(self.dcx(), span, E0259, "{}", msg),
(true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() { (true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() {
true => struct_span_code_err!(self.dcx(), span, E0254, "{}", msg), true => E0254,
false => struct_span_code_err!(self.dcx(), span, E0260, "{}", msg), false => E0260,
}, },
_ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) { _ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) {
(false, false) => struct_span_code_err!(self.dcx(), span, E0428, "{}", msg), (false, false) => E0428,
(true, true) => struct_span_code_err!(self.dcx(), span, E0252, "{}", msg), (true, true) => E0252,
_ => struct_span_code_err!(self.dcx(), span, E0255, "{}", msg), _ => E0255,
}, },
}; };
err.note(format!( let label = match new_binding.is_import_user_facing() {
"`{}` must be defined only once in the {} namespace of this {}", true => errors::NameDefinedMultipleTimeLabel::Reimported { span, name },
name, false => errors::NameDefinedMultipleTimeLabel::Redefined { span, name },
ns.descr(), };
container
));
err.span_label(span, format!("`{name}` re{new_participle} here")); let old_binding_label =
if !old_binding.span.is_dummy() && old_binding.span != span { (!old_binding.span.is_dummy() && old_binding.span != span).then(|| {
err.span_label( let span = self.tcx.sess.source_map().guess_head_span(old_binding.span);
self.tcx.sess.source_map().guess_head_span(old_binding.span), match old_binding.is_import_user_facing() {
format!("previous {old_noun} of the {old_kind} `{name}` here"), true => errors::NameDefinedMultipleTimeOldBindingLabel::Import {
); span,
} name,
old_kind,
},
false => errors::NameDefinedMultipleTimeOldBindingLabel::Definition {
span,
name,
old_kind,
},
}
});
let mut err = self
.dcx()
.create_err(errors::NameDefinedMultipleTime {
span,
descr: ns.descr(),
container,
label,
old_binding_label,
})
.with_code(code);
// See https://github.com/rust-lang/rust/issues/32354 // See https://github.com/rust-lang/rust/issues/32354
use NameBindingKind::Import; use NameBindingKind::Import;
@ -330,20 +335,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
match import { match import {
Some((import, span, true)) if should_remove_import && import.is_nested() => { Some((import, span, true)) if should_remove_import && import.is_nested() => {
self.add_suggestion_for_duplicate_nested_use(&mut err, import, span) self.add_suggestion_for_duplicate_nested_use(&mut err, import, span);
} }
Some((import, _, true)) if should_remove_import && !import.is_glob() => { Some((import, _, true)) if should_remove_import && !import.is_glob() => {
// Simple case - remove the entire import. Due to the above match arm, this can // Simple case - remove the entire import. Due to the above match arm, this can
// only be a single use so just remove it entirely. // only be a single use so just remove it entirely.
err.tool_only_span_suggestion( err.subdiagnostic(
import.use_span_with_attributes, self.tcx.dcx(),
"remove unnecessary import", errors::ToolOnlyRemoveUnnecessaryImport {
"", span: import.use_span_with_attributes,
Applicability::MaybeIncorrect, },
); );
} }
Some((import, span, _)) => { Some((import, span, _)) => {
self.add_suggestion_for_rename_of_use(&mut err, name, import, span) self.add_suggestion_for_rename_of_use(&mut err, name, import, span);
} }
_ => {} _ => {}
} }
@ -444,7 +449,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
binding_span: Span, binding_span: Span,
) { ) {
assert!(import.is_nested()); assert!(import.is_nested());
let message = "remove unnecessary import";
// Two examples will be used to illustrate the span manipulations we're doing: // Two examples will be used to illustrate the span manipulations we're doing:
// //
@ -460,22 +464,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// previous imports. // previous imports.
if found_closing_brace { if found_closing_brace {
if let Some(span) = extend_span_to_previous_binding(self.tcx.sess, span) { if let Some(span) = extend_span_to_previous_binding(self.tcx.sess, span) {
err.tool_only_span_suggestion(span, message, "", Applicability::MaybeIncorrect); err.subdiagnostic(self.dcx(), errors::ToolOnlyRemoveUnnecessaryImport { span });
} else { } else {
// Remove the entire line if we cannot extend the span back, this indicates an // Remove the entire line if we cannot extend the span back, this indicates an
// `issue_52891::{self}` case. // `issue_52891::{self}` case.
err.span_suggestion( err.subdiagnostic(
import.use_span_with_attributes, self.dcx(),
message, errors::RemoveUnnecessaryImport { span: import.use_span_with_attributes },
"",
Applicability::MaybeIncorrect,
); );
} }
return; return;
} }
err.span_suggestion(span, message, "", Applicability::MachineApplicable); err.subdiagnostic(self.dcx(), errors::RemoveUnnecessaryImport { span });
} }
pub(crate) fn lint_if_path_starts_with_module( pub(crate) fn lint_if_path_starts_with_module(
@ -571,14 +573,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
resolution_error: ResolutionError<'a>, resolution_error: ResolutionError<'a>,
) -> Diag<'_> { ) -> Diag<'_> {
match resolution_error { match resolution_error {
ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params, def_kind) => { ResolutionError::GenericParamsFromOuterItem(
outer_res,
has_generic_params,
def_kind,
) => {
use errs::GenericParamsFromOuterItemLabel as Label; use errs::GenericParamsFromOuterItemLabel as Label;
let static_or_const = match def_kind { let static_or_const = match def_kind {
DefKind::Static{ .. } => Some(errs::GenericParamsFromOuterItemStaticOrConst::Static), DefKind::Static { .. } => {
Some(errs::GenericParamsFromOuterItemStaticOrConst::Static)
}
DefKind::Const => Some(errs::GenericParamsFromOuterItemStaticOrConst::Const), DefKind::Const => Some(errs::GenericParamsFromOuterItemStaticOrConst::Const),
_ => None, _ => None,
}; };
let is_self = matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }); let is_self =
matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. });
let mut err = errs::GenericParamsFromOuterItem { let mut err = errs::GenericParamsFromOuterItem {
span, span,
label: None, label: None,
@ -677,20 +686,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let origin_sp = origin.iter().copied().collect::<Vec<_>>(); let origin_sp = origin.iter().copied().collect::<Vec<_>>();
let msp = MultiSpan::from_spans(target_sp.clone()); let msp = MultiSpan::from_spans(target_sp.clone());
let mut err = self.dcx().create_err(errors::VariableIsNotBoundInAllPatterns { let mut err = self
multispan: msp, .dcx()
name, .create_err(errors::VariableIsNotBoundInAllPatterns { multispan: msp, name });
});
for sp in target_sp { for sp in target_sp {
err.subdiagnostic(self.dcx(), errors::PatternDoesntBindName { err.subdiagnostic(self.dcx(), errors::PatternDoesntBindName { span: sp, name });
span: sp,
name,
});
} }
for sp in origin_sp { for sp in origin_sp {
err.subdiagnostic(self.dcx(), errors::VariableNotInAllPatterns { err.subdiagnostic(self.dcx(), errors::VariableNotInAllPatterns { span: sp });
span: sp,
});
} }
if could_be_path { if could_be_path {
let import_suggestions = self.lookup_import_candidates( let import_suggestions = self.lookup_import_candidates(
@ -963,17 +966,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
code, code,
trait_item_span, trait_item_span,
trait_path, trait_path,
} => { } => self
self.dcx().struct_span_err( .dcx()
.create_err(errors::TraitImplMismatch {
span, span,
format!( name,
"item `{name}` is an associated {kind}, which doesn't match its trait `{trait_path}`", kind,
), trait_path,
) trait_item_span,
.with_code(code) })
.with_span_label(span, "does not match trait") .with_code(code),
.with_span_label(trait_item_span, "item in trait")
}
ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => self ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => self
.dcx() .dcx()
.create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }), .create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }),
@ -1534,17 +1536,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}; };
if let crate::NameBindingKind::Import { import, .. } = binding.kind { if let crate::NameBindingKind::Import { import, .. } = binding.kind {
if !import.span.is_dummy() { if !import.span.is_dummy() {
err.span_note( let note = errors::IdentImporterHereButItIsDesc {
import.span, span: import.span,
format!("`{ident}` is imported here, but it is {desc}"), imported_ident: ident,
); imported_ident_desc: &desc,
};
err.subdiagnostic(self.tcx.dcx(), note);
// Silence the 'unused import' warning we might get, // Silence the 'unused import' warning we might get,
// since this diagnostic already covers that import. // since this diagnostic already covers that import.
self.record_use(ident, binding, Used::Other); self.record_use(ident, binding, Used::Other);
return; return;
} }
} }
err.note(format!("`{ident}` is in scope, but it is {desc}")); let note = errors::IdentInScopeButItIsDesc {
imported_ident: ident,
imported_ident_desc: &desc,
};
err.subdiagnostic(self.tcx.dcx(), note);
return; return;
} }
} }
@ -1584,20 +1592,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// | ^ // | ^
return false; return false;
} }
let prefix = match suggestion.target { let span = self.tcx.sess.source_map().guess_head_span(def_span);
SuggestionTarget::SimilarlyNamed => "similarly named ", let candidate_descr = suggestion.res.descr();
SuggestionTarget::SingleItem => "", let candidate = suggestion.candidate;
let label = match suggestion.target {
SuggestionTarget::SimilarlyNamed => {
errors::DefinedHere::SimilarlyNamed { span, candidate_descr, candidate }
}
SuggestionTarget::SingleItem => {
errors::DefinedHere::SingleItem { span, candidate_descr, candidate }
}
}; };
err.subdiagnostic(self.tcx.dcx(), label);
err.span_label(
self.tcx.sess.source_map().guess_head_span(def_span),
format!(
"{}{} `{}` defined here",
prefix,
suggestion.res.descr(),
suggestion.candidate,
),
);
} }
let (span, sugg, post) = if let SuggestionTarget::SimilarlyNamed = suggestion.target let (span, sugg, post) = if let SuggestionTarget::SimilarlyNamed = suggestion.target
@ -1751,16 +1757,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|b: NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr }; |b: NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
// Print the primary message. // Print the primary message.
let descr = get_descr(binding); let ident_descr = get_descr(binding);
let mut err = struct_span_code_err!( let mut err =
self.dcx(), self.dcx().create_err(errors::IsPrivate { span: ident.span, ident_descr, ident });
ident.span,
E0603,
"{} `{}` is private",
descr,
ident
);
err.span_label(ident.span, format!("private {descr}"));
let mut not_publicly_reexported = false; let mut not_publicly_reexported = false;
if let Some((this_res, outer_ident)) = outermost_res { if let Some((this_res, outer_ident)) = outermost_res {
@ -1784,10 +1783,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// If we suggest importing a public re-export, don't point at the definition. // If we suggest importing a public re-export, don't point at the definition.
if point_to_def && ident.span != outer_ident.span { if point_to_def && ident.span != outer_ident.span {
not_publicly_reexported = true; not_publicly_reexported = true;
err.span_label( let label = errors::OuterIdentIsNotPubliclyReexported {
outer_ident.span, span: outer_ident.span,
format!("{} `{outer_ident}` is not publicly re-exported", this_res.descr()), outer_ident_descr: this_res.descr(),
); outer_ident,
};
err.subdiagnostic(self.tcx.dcx(), label);
} }
} }
@ -1801,18 +1802,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
{ {
non_exhaustive = Some(attr.span); non_exhaustive = Some(attr.span);
} else if let Some(span) = ctor_fields_span { } else if let Some(span) = ctor_fields_span {
err.span_label(span, "a constructor is private if any of the fields is private"); let label = errors::ConstructorPrivateIfAnyFieldPrivate { span };
err.subdiagnostic(self.tcx.dcx(), label);
if let Res::Def(_, d) = res if let Res::Def(_, d) = res
&& let Some(fields) = self.field_visibility_spans.get(&d) && let Some(fields) = self.field_visibility_spans.get(&d)
{ {
err.multipart_suggestion_verbose( let spans = fields.iter().map(|span| *span).collect();
format!( let sugg =
"consider making the field{} publicly accessible", errors::ConsiderMakingTheFieldPublic { spans, number_of_fields: fields.len() };
pluralize!(fields.len()) err.subdiagnostic(self.tcx.dcx(), sugg);
),
fields.iter().map(|span| (*span, "pub ".to_string())).collect(),
Applicability::MaybeIncorrect,
);
} }
} }
@ -1895,13 +1893,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
NameBindingKind::Res(_) | NameBindingKind::Module(_) => {} NameBindingKind::Res(_) | NameBindingKind::Module(_) => {}
} }
let first = binding == first_binding; let first = binding == first_binding;
let msg = format!(
"{and_refers_to}the {item} `{name}`{which} is defined here{dots}",
and_refers_to = if first { "" } else { "...and refers to " },
item = get_descr(binding),
which = if first { "" } else { " which" },
dots = if next_binding.is_some() { "..." } else { "" },
);
let def_span = self.tcx.sess.source_map().guess_head_span(binding.span); let def_span = self.tcx.sess.source_map().guess_head_span(binding.span);
let mut note_span = MultiSpan::from_span(def_span); let mut note_span = MultiSpan::from_span(def_span);
if !first && binding.vis.is_public() { if !first && binding.vis.is_public() {
@ -1921,7 +1912,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
"cannot be constructed because it is `#[non_exhaustive]`", "cannot be constructed because it is `#[non_exhaustive]`",
); );
} }
err.span_note(note_span, msg); let note = errors::NoteAndRefersToTheItemDefinedHere {
span: note_span,
binding_descr: get_descr(binding),
binding_name: name,
first,
dots: next_binding.is_some(),
};
err.subdiagnostic(self.tcx.dcx(), note);
} }
// We prioritize shorter paths, non-core imports and direct imports over the alternatives. // We prioritize shorter paths, non-core imports and direct imports over the alternatives.
sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0] == "core", *reexport)); sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0] == "core", *reexport));
@ -1935,15 +1933,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
continue; continue;
} }
let path = sugg.join("::"); let path = sugg.join("::");
err.span_suggestion_verbose( let sugg = if reexport {
dedup_span, errors::ImportIdent::ThroughReExport { span: dedup_span, ident, path }
format!( } else {
"import `{ident}` {}", errors::ImportIdent::Directly { span: dedup_span, ident, path }
if reexport { "through the re-export" } else { "directly" } };
), err.subdiagnostic(self.tcx.dcx(), sugg);
path,
Applicability::MachineApplicable,
);
break; break;
} }
@ -2523,13 +2518,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
continue; continue;
} }
err.span_note(name.span, "found an item that was configured out"); let note = errors::FoundItemConfigureOut { span: name.span };
err.subdiagnostic(self.tcx.dcx(), note);
if let MetaItemKind::List(nested) = &cfg.kind if let MetaItemKind::List(nested) = &cfg.kind
&& let NestedMetaItem::MetaItem(meta_item) = &nested[0] && let NestedMetaItem::MetaItem(meta_item) = &nested[0]
&& let MetaItemKind::NameValue(feature_name) = &meta_item.kind && let MetaItemKind::NameValue(feature_name) = &meta_item.kind
{ {
err.note(format!("the item is gated behind the `{}` feature", feature_name.symbol)); let note = errors::ItemWasBehindFeature { feature: feature_name.symbol };
err.subdiagnostic(self.tcx.dcx(), note);
} }
} }
} }

View file

@ -1,3 +1,4 @@
#![allow(dead_code)]
use rustc_errors::{codes::*, Applicability, MultiSpan}; use rustc_errors::{codes::*, Applicability, MultiSpan};
use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{ use rustc_span::{
@ -525,8 +526,10 @@ pub(crate) struct ModuleOnly(#[primary_span] pub(crate) Span);
#[diag(resolve_macro_expected_found)] #[diag(resolve_macro_expected_found)]
pub(crate) struct MacroExpectedFound<'a> { pub(crate) struct MacroExpectedFound<'a> {
#[primary_span] #[primary_span]
#[label]
pub(crate) span: Span, pub(crate) span: Span,
pub(crate) found: &'a str, pub(crate) found: &'a str,
pub(crate) article: &'static str,
pub(crate) expected: &'a str, pub(crate) expected: &'a str,
pub(crate) macro_path: &'a str, pub(crate) macro_path: &'a str,
#[subdiagnostic] #[subdiagnostic]
@ -955,3 +958,267 @@ pub(crate) struct VariableNotInAllPatterns {
#[primary_span] #[primary_span]
pub(crate) span: Span, pub(crate) span: Span,
} }
#[derive(Diagnostic)]
#[diag(resolve_name_defined_multiple_time)]
#[note]
pub(crate) struct NameDefinedMultipleTime {
#[primary_span]
pub(crate) span: Span,
pub(crate) descr: &'static str,
pub(crate) container: &'static str,
#[subdiagnostic]
pub(crate) label: NameDefinedMultipleTimeLabel,
#[subdiagnostic]
pub(crate) old_binding_label: Option<NameDefinedMultipleTimeOldBindingLabel>,
}
#[derive(Subdiagnostic)]
pub(crate) enum NameDefinedMultipleTimeLabel {
#[label(resolve_name_defined_multiple_time_reimported)]
Reimported {
#[primary_span]
span: Span,
name: Symbol,
},
#[label(resolve_name_defined_multiple_time_redefined)]
Redefined {
#[primary_span]
span: Span,
name: Symbol,
},
}
#[derive(Subdiagnostic)]
pub(crate) enum NameDefinedMultipleTimeOldBindingLabel {
#[label(resolve_name_defined_multiple_time_old_binding_import)]
Import {
#[primary_span]
span: Span,
name: Symbol,
old_kind: &'static str,
},
#[label(resolve_name_defined_multiple_time_old_binding_definition)]
Definition {
#[primary_span]
span: Span,
name: Symbol,
old_kind: &'static str,
},
}
#[derive(Diagnostic)]
#[diag(resolve_is_private, code = E0603)]
pub(crate) struct IsPrivate<'a> {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) ident_descr: &'a str,
pub(crate) ident: Ident,
}
#[derive(Diagnostic)]
#[diag(resolve_generic_arguments_in_macro_path)]
pub(crate) struct GenericArgumentsInMacroPath {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_attributes_starting_with_rustc_are_reserved)]
pub(crate) struct AttributesStartingWithRustcAreReserved {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_cannot_use_through_an_import)]
pub(crate) struct CannotUseThroughAnImport {
#[primary_span]
pub(crate) span: Span,
pub(crate) article: &'static str,
pub(crate) descr: &'static str,
#[note]
pub(crate) binding_span: Option<Span>,
}
#[derive(Diagnostic)]
#[diag(resolve_name_reserved_in_attribute_namespace)]
pub(crate) struct NameReservedInAttributeNamespace {
#[primary_span]
pub(crate) span: Span,
pub(crate) ident: Ident,
}
#[derive(Diagnostic)]
#[diag(resolve_cannot_find_builtin_macro_with_name)]
pub(crate) struct CannotFindBuiltinMacroWithName {
#[primary_span]
pub(crate) span: Span,
pub(crate) ident: Ident,
}
#[derive(Diagnostic)]
#[diag(resolve_tool_was_already_registered)]
pub(crate) struct ToolWasAlreadyRegistered {
#[primary_span]
pub(crate) span: Span,
pub(crate) tool: Ident,
#[label]
pub(crate) old_ident_span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_tool_only_accepts_identifiers)]
pub(crate) struct ToolOnlyAcceptsIdentifiers {
#[label]
#[primary_span]
pub(crate) span: Span,
pub(crate) tool: Symbol,
}
#[derive(Subdiagnostic)]
pub(crate) enum DefinedHere {
#[label(resolve_similarly_named_defined_here)]
SimilarlyNamed {
#[primary_span]
span: Span,
candidate_descr: &'static str,
candidate: Symbol,
},
#[label(resolve_single_item_defined_here)]
SingleItem {
#[primary_span]
span: Span,
candidate_descr: &'static str,
candidate: Symbol,
},
}
#[derive(Subdiagnostic)]
#[label(resolve_outer_ident_is_not_publicly_reexported)]
pub(crate) struct OuterIdentIsNotPubliclyReexported {
#[primary_span]
pub(crate) span: Span,
pub(crate) outer_ident_descr: &'static str,
pub(crate) outer_ident: Ident,
}
#[derive(Subdiagnostic)]
#[label(resolve_constructor_private_if_any_field_private)]
pub(crate) struct ConstructorPrivateIfAnyFieldPrivate {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Subdiagnostic)]
#[multipart_suggestion(
resolve_consider_making_the_field_public,
applicability = "maybe-incorrect",
style = "verbose"
)]
pub(crate) struct ConsiderMakingTheFieldPublic {
#[suggestion_part(code = "pub ")]
pub(crate) spans: Vec<Span>,
pub(crate) number_of_fields: usize,
}
#[derive(Subdiagnostic)]
pub(crate) enum ImportIdent {
#[suggestion(
resolve_suggestion_import_ident_through_reexport,
code = "{path}",
applicability = "machine-applicable",
style = "verbose"
)]
ThroughReExport {
#[primary_span]
span: Span,
ident: Ident,
path: String,
},
#[suggestion(
resolve_suggestion_import_ident_directly,
code = "{path}",
applicability = "machine-applicable",
style = "verbose"
)]
Directly {
#[primary_span]
span: Span,
ident: Ident,
path: String,
},
}
#[derive(Subdiagnostic)]
#[note(resolve_note_and_refers_to_the_item_defined_here)]
pub(crate) struct NoteAndRefersToTheItemDefinedHere<'a> {
#[primary_span]
pub(crate) span: MultiSpan,
pub(crate) binding_descr: &'a str,
pub(crate) binding_name: Ident,
pub(crate) first: bool,
pub(crate) dots: bool,
}
#[derive(Subdiagnostic)]
#[suggestion(resolve_remove_unnecessary_import, code = "", applicability = "maybe-incorrect")]
pub(crate) struct RemoveUnnecessaryImport {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Subdiagnostic)]
#[suggestion(
resolve_remove_unnecessary_import,
code = "",
applicability = "maybe-incorrect",
style = "tool-only"
)]
pub(crate) struct ToolOnlyRemoveUnnecessaryImport {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Subdiagnostic)]
#[note(resolve_ident_imported_here_but_it_is_desc)]
pub(crate) struct IdentImporterHereButItIsDesc<'a> {
#[primary_span]
pub(crate) span: Span,
pub(crate) imported_ident: Ident,
pub(crate) imported_ident_desc: &'a str,
}
#[derive(Subdiagnostic)]
#[note(resolve_ident_in_scope_but_it_is_desc)]
pub(crate) struct IdentInScopeButItIsDesc<'a> {
pub(crate) imported_ident: Ident,
pub(crate) imported_ident_desc: &'a str,
}
#[derive(Subdiagnostic)]
#[note(resolve_found_an_item_configured_out)]
pub(crate) struct FoundItemConfigureOut {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Subdiagnostic)]
#[note(resolve_item_was_behind_feature)]
pub(crate) struct ItemWasBehindFeature {
pub(crate) feature: Symbol,
}
#[derive(Diagnostic)]
#[diag(resolve_trait_impl_mismatch)]
pub(crate) struct TraitImplMismatch {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) name: Symbol,
pub(crate) kind: &'static str,
pub(crate) trait_path: String,
#[label(resolve_trait_impl_mismatch_label_item)]
pub(crate) trait_item_span: Span,
}

View file

@ -15,9 +15,7 @@ use rustc_ast::ptr::P;
use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
use rustc_ast::*; use rustc_ast::*;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_errors::{ use rustc_errors::{codes::*, Applicability, DiagArgValue, IntoDiagArg, StashKey};
codes::*, Applicability, DiagArgValue, IntoDiagArg, StashKey,
};
use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};

View file

@ -123,20 +123,18 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools {
match nested_meta.ident() { match nested_meta.ident() {
Some(ident) => { Some(ident) => {
if let Some(old_ident) = registered_tools.replace(ident) { if let Some(old_ident) = registered_tools.replace(ident) {
let msg = format!("{} `{}` was already registered", "tool", ident); tcx.dcx().emit_err(errors::ToolWasAlreadyRegistered {
tcx.dcx() span: ident.span,
.struct_span_err(ident.span, msg) tool: ident,
.with_span_label(old_ident.span, "already registered here") old_ident_span: old_ident.span,
.emit(); });
} }
} }
None => { None => {
let msg = format!("`{}` only accepts identifiers", sym::register_tool); tcx.dcx().emit_err(errors::ToolOnlyAcceptsIdentifiers {
let span = nested_meta.span(); span: nested_meta.span(),
tcx.dcx() tool: sym::register_tool,
.struct_span_err(span, msg) });
.with_span_label(span, "not an identifier")
.emit();
} }
} }
} }
@ -485,13 +483,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// Report errors for the resolved macro. // Report errors for the resolved macro.
for segment in &path.segments { for segment in &path.segments {
if let Some(args) = &segment.args { if let Some(args) = &segment.args {
self.dcx().span_err(args.span(), "generic arguments in macro path"); self.dcx().emit_err(errors::GenericArgumentsInMacroPath { span: args.span() });
} }
if kind == MacroKind::Attr && segment.ident.as_str().starts_with("rustc") { if kind == MacroKind::Attr && segment.ident.as_str().starts_with("rustc") {
self.dcx().span_err( self.dcx().emit_err(errors::AttributesStartingWithRustcAreReserved {
segment.ident.span, span: segment.ident.span,
"attributes starting with `rustc` are reserved for use by the `rustc` compiler", });
);
} }
} }
@ -535,6 +532,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let mut err = MacroExpectedFound { let mut err = MacroExpectedFound {
span: path.span, span: path.span,
expected, expected,
article,
found: res.descr(), found: res.descr(),
macro_path: &path_str, macro_path: &path_str,
remove_surrounding_derive: None, remove_surrounding_derive: None,
@ -550,10 +548,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str }); err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str });
} }
self.dcx() self.dcx().emit_err(err);
.create_err(err)
.with_span_label(path.span, format!("not {article} {expected}"))
.emit();
return Ok((self.dummy_ext(kind), Res::Err)); return Ok((self.dummy_ext(kind), Res::Err));
} }
@ -872,13 +867,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
) { ) {
if let Some(Res::NonMacroAttr(kind)) = res { if let Some(Res::NonMacroAttr(kind)) = res {
if kind != NonMacroAttrKind::Tool && binding.map_or(true, |b| b.is_import()) { if kind != NonMacroAttrKind::Tool && binding.map_or(true, |b| b.is_import()) {
let msg = let binding_span = binding.map(|binding| binding.span);
format!("cannot use {} {} through an import", kind.article(), kind.descr()); self.dcx().emit_err(errors::CannotUseThroughAnImport {
let mut err = self.dcx().struct_span_err(span, msg); span,
if let Some(binding) = binding { article: kind.article(),
err.span_note(binding.span, format!("the {} imported here", kind.descr())); descr: kind.descr(),
} binding_span,
err.emit(); });
} }
} }
} }
@ -889,10 +884,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if ident.name == sym::cfg || ident.name == sym::cfg_attr { if ident.name == sym::cfg || ident.name == sym::cfg_attr {
let macro_kind = self.get_macro(res).map(|macro_data| macro_data.ext.macro_kind()); let macro_kind = self.get_macro(res).map(|macro_data| macro_data.ext.macro_kind());
if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) { if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) {
self.dcx().span_err( self.dcx()
ident.span, .emit_err(errors::NameReservedInAttributeNamespace { span: ident.span, ident });
format!("name `{ident}` is reserved in attribute namespace"),
);
} }
} }
} }
@ -923,8 +916,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} }
} }
} else { } else {
let msg = format!("cannot find a built-in macro with name `{}`", item.ident); self.dcx().emit_err(errors::CannotFindBuiltinMacroWithName {
self.dcx().span_err(item.span, msg); span: item.span,
ident: item.ident,
});
} }
} }