Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc_parse: diagnostics migration, v4 #105670

Merged
merged 11 commits into from
Feb 2, 2023
4 changes: 4 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,7 @@ hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` la
hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect
.suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
188 changes: 188 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/parse.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,191 @@ parse_where_clause_before_tuple_struct_body = where clauses are not allowed befo
.name_label = while parsing this tuple struct
.body_label = the struct body
.suggestion = move the body before the where clause
parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015
.label = to use `async fn`, switch to Rust 2018 or later
parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later
parse_self_argument_pointer = cannot pass `self` by raw pointer
.label = cannot pass `self` by raw pointer
parse_visibility_not_followed_by_item = visibility `{$vis}` is not followed by an item
.label = the visibility
.help = you likely meant to define an item, e.g., `{$vis} fn foo() {"{}"}`
parse_default_not_followed_by_item = `default` is not followed by an item
.label = the `default` qualifier
.note = only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
parse_missing_struct_for_struct_definition = missing `struct` for struct definition
.suggestion = add `struct` here to parse `{$ident}` as a public struct
parse_missing_fn_for_function_definition = missing `fn` for function definition
.suggestion = add `fn` here to parse `{$ident}` as a public function
parse_missing_fn_for_method_definition = missing `fn` for method definition
.suggestion = add `fn` here to parse `{$ident}` as a public method
parse_ambiguous_missing_keyword_for_item_definition = missing `fn` or `struct` for function or struct definition
.suggestion = if you meant to call a macro, try
.help = if you meant to call a macro, remove the `pub` and add a trailing `!` after the identifier
parse_missing_trait_in_trait_impl = missing trait in a trait impl
.suggestion_add_trait = add a trait here
.suggestion_remove_for = for an inherent impl, drop this `for`
parse_missing_for_in_trait_impl = missing `for` in a trait impl
.suggestion = add `for` here
parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
parse_non_item_in_item_list = non-item in item list
.suggestion_use_const_not_let = consider using `const` instead of `let` for associated const
.label_list_start = item list starts here
.label_non_item = non-item starts here
.label_list_end = item list ends here
.suggestion_remove_semicolon = consider removing this semicolon
parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases
parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto`
parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe`
parse_associated_static_item_not_allowed = associated `static` items are not allowed
parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
.label = dash-separated idents are not valid
.suggestion = if the original crate name uses dashes you need to use underscores in the code
parse_extern_item_cannot_be_const = extern items cannot be `const`
.suggestion = try using a static value
.note = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
parse_const_global_cannot_be_mutable = const globals cannot be mutable
.label = cannot be mutable
.suggestion = you might want to declare a static instead
parse_missing_const_type = missing type for `{$kind}` item
.suggestion = provide a type for the item
parse_enum_struct_mutually_exclusive = `enum` and `struct` are mutually exclusive
.suggestion = replace `enum struct` with
parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name
parse_unexpected_token_after_struct_name_found_reserved_identifier = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved identifier `{$token}`
parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}`
parse_unexpected_token_after_struct_name_found_reserved_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved keyword `{$token}`
parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}`
parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}`
parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters
.note = you cannot use `Self` as a generic parameter because it is reserved for associated items
parse_multiple_where_clauses = cannot define duplicate `where` clauses on an item
.label = previous `where` clause starts here
.suggestion = consider joining the two `where` clauses into one
parse_nonterminal_expected_item_keyword = expected an item keyword
parse_nonterminal_expected_statement = expected a statement
parse_nonterminal_expected_ident = expected ident, found `{$token}`
parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}`
parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
parse_sugg_remove_leading_vert_in_pattern = remove the `|`
parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||`
parse_unexpected_vert_vert_before_function_parameter = unexpected `||` before function parameter
.suggestion = remove the `||`
parse_label_while_parsing_or_pattern_here = while parsing this or-pattern starting here
parse_unexpected_vert_vert_in_pattern = unexpected token `||` in pattern
.suggestion = use a single `|` to separate multiple alternative patterns
parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern
.suggestion = remove the `{$token}`
parse_dotdotdot_rest_pattern = unexpected `...`
.label = not a valid pattern
.suggestion = for a rest pattern, use `..` instead of `...`
parse_pattern_on_wrong_side_of_at = pattern on wrong side of `@`
.label_pattern = pattern on the left, should be on the right
.label_binding = binding on the right, should be on the left
.suggestion = switch the order
parse_expected_binding_left_of_at = left-hand side of `@` must be a binding
.label_lhs = interpreted as a pattern, not a binding
.label_rhs = also a pattern
.note = bindings are `x`, `mut x`, `ref x`, and `ref mut x`
parse_ambiguous_range_pattern = the range pattern here has ambiguous interpretation
.suggestion = add parentheses to clarify the precedence
parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in pattern
.suggestion = remove the lifetime
parse_ref_mut_order_incorrect = the order of `mut` and `ref` is incorrect
.suggestion = try switching the order
parse_mut_on_nested_ident_pattern = `mut` must be attached to each individual binding
.suggestion = add `mut` to each binding
parse_mut_on_non_ident_pattern = `mut` must be followed by a named binding
.suggestion = remove the `mut` prefix
parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable @ pattern`
parse_repeated_mut_in_pattern = `mut` on a binding may not be repeated
.suggestion = remove the additional `mut`s
parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` are not allowed
.suggestion = use `..=` instead
parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern
parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `...`
.suggestion = to omit remaining fields, use one fewer `.`
parse_expected_comma_after_pattern_field = expected `,`
parse_return_types_use_thin_arrow = return types are denoted using `->`
.suggestion = use `->` instead
parse_need_plus_after_trait_object_lifetime = lifetime in trait object type must be followed by `+`
parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyword in raw pointer type
.suggestion = add `mut` or `const` here
parse_lifetime_after_mut = lifetime must precede `mut`
.suggestion = place the lifetime before `mut`
parse_dyn_after_mut = `mut` must precede `dyn`
.suggestion = place `mut` before `dyn`
parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const`
.label = `const` because of this
.suggestion = remove the `const` qualifier
parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async`
.label = `async` because of this
.suggestion = remove the `async` qualifier
parse_nested_c_variadic_type = C-variadic type `...` may not be nested inside another type
parse_invalid_dyn_keyword = invalid `dyn` keyword
.help = `dyn` is only needed at the start of a trait `+`-separated list
.suggestion = remove this keyword
parse_negative_bounds_not_supported = negative bounds are not supported
.label = negative bounds are not supported
.suggestion = {$num_bounds ->
[one] remove the bound
*[other] remove the bounds
}
parse_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
parse_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
13 changes: 0 additions & 13 deletions compiler/rustc_errors/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_error_messages::fluent_value_from_str_list_sep_by_and;
use rustc_error_messages::FluentValue;
use rustc_lint_defs::{Applicability, LintExpectationId};
use rustc_span::edition::LATEST_STABLE_EDITION;
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use std::borrow::Cow;
Expand Down Expand Up @@ -555,18 +554,6 @@ impl Diagnostic {
self
}

/// Help the user upgrade to the latest edition.
/// This is factored out to make sure it does the right thing with `Cargo.toml`.
pub fn help_use_latest_edition(&mut self) -> &mut Self {
if std::env::var_os("CARGO").is_some() {
self.help(&format!("set `edition = \"{}\"` in `Cargo.toml`", LATEST_STABLE_EDITION));
} else {
self.help(&format!("pass `--edition {}` to `rustc`", LATEST_STABLE_EDITION));
}
self.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
self
}

/// Disallow attaching suggestions this diagnostic.
/// Any suggestions attached e.g. with the `span_suggestion_*` methods
/// (before and after the call to `disable_suggestions`) will be ignored.
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_errors/src/diagnostic_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
sp: impl Into<MultiSpan>,
msg: impl Into<SubdiagnosticMessage>,
) -> &mut Self);
forward!(pub fn help_use_latest_edition(&mut self,) -> &mut Self);
forward!(pub fn set_is_lint(&mut self,) -> &mut Self);

forward!(pub fn disable_suggestions(&mut self,) -> &mut Self);
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_errors/src/diagnostic_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,14 @@ impl IntoDiagnosticArg for rustc_data_structures::small_c_str::SmallCStr {
}
}

impl IntoDiagnosticArg for ast::Visibility {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
let s = pprust::vis_to_string(&self);
let s = s.trim_end().to_string();
DiagnosticArgValue::Str(Cow::Owned(s))
}
}

impl IntoDiagnosticArg for Level {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(Cow::Borrowed(self.to_cmd_flag()))
Expand Down
27 changes: 26 additions & 1 deletion compiler/rustc_hir_typeck/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, MultiSpan, SubdiagnosticMessage};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::ty::Ty;
use rustc_span::{symbol::Ident, Span};
use rustc_span::{
edition::{Edition, LATEST_STABLE_EDITION},
symbol::Ident,
Span,
};

#[derive(Diagnostic)]
#[diag(hir_typeck_field_multiply_specified_in_initializer, code = "E0062")]
Expand Down Expand Up @@ -205,3 +209,24 @@ pub struct LangStartIncorrectRetTy<'tcx> {
pub expected_ty: Ty<'tcx>,
pub found_ty: Ty<'tcx>,
}

#[derive(Subdiagnostic)]
pub enum HelpUseLatestEdition {
#[help(hir_typeck_help_set_edition_cargo)]
#[note(hir_typeck_note_edition_guide)]
Cargo { edition: Edition },
#[help(hir_typeck_help_set_edition_standalone)]
#[note(hir_typeck_note_edition_guide)]
Standalone { edition: Edition },
}

impl HelpUseLatestEdition {
pub fn new() -> Self {
let edition = LATEST_STABLE_EDITION;
if std::env::var_os("CARGO").is_some() {
Self::Cargo { edition }
} else {
Self::Standalone { edition }
}
}
}
8 changes: 4 additions & 4 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::coercion::DynamicCoerceMany;
use crate::errors::TypeMismatchFruTypo;
use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive};
use crate::errors::{
FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct,
FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition,
YieldExprOutsideOfGenerator,
};
use crate::fatally_break_rust;
Expand All @@ -23,8 +23,8 @@ use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId,
ErrorGuaranteed, StashKey,
pluralize, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
DiagnosticId, ErrorGuaranteed, StashKey,
};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
Expand Down Expand Up @@ -2433,7 +2433,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We know by construction that `<expr>.await` is either on Rust 2015
// or results in `ExprKind::Await`. Suggest switching the edition to 2018.
err.note("to `.await` a `Future`, switch to Rust 2018 or later");
err.help_use_latest_edition();
HelpUseLatestEdition::new().add_to_diagnostic(&mut err);
}

err.emit();
Expand Down
21 changes: 13 additions & 8 deletions compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,11 +322,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
let generated_code = self
.generate_inner_field_code(
attr,
FieldInfo {
binding: binding_info,
ty: inner_ty.inner_type().unwrap_or(&field.ty),
span: &field.span(),
},
FieldInfo { binding: binding_info, ty: inner_ty, span: &field.span() },
binding,
)
.unwrap_or_else(|v| v.to_compile_error());
Expand Down Expand Up @@ -418,9 +414,9 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
}
SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
if type_matches_path(info.ty, &["rustc_span", "Span"]) {
if type_matches_path(info.ty.inner_type(), &["rustc_span", "Span"]) {
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
} else if type_is_unit(info.ty) {
} else if type_is_unit(info.ty.inner_type()) {
Ok(self.add_subdiagnostic(&fn_ident, slug))
} else {
report_type_error(attr, "`Span` or `()`")?
Expand All @@ -432,6 +428,15 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
code_field,
code_init,
} => {
if let FieldInnerTy::Vec(_) = info.ty {
throw_invalid_attr!(attr, &meta, |diag| {
diag
.note("`#[suggestion(...)]` applied to `Vec` field is ambiguous")
.help("to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]`")
.help("to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]`")
});
}

let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?;

if let Some((static_applicability, span)) = static_applicability {
Expand Down Expand Up @@ -489,7 +494,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
&self,
info: FieldInfo<'_>,
) -> Result<(TokenStream, SpannedOption<TokenStream>), DiagnosticDeriveError> {
match &info.ty {
match &info.ty.inner_type() {
// If `ty` is `Span` w/out applicability, then use `Applicability::Unspecified`.
ty @ Type::Path(..) if type_matches_path(ty, &["rustc_span", "Span"]) => {
let binding = &info.binding.binding;
Expand Down
Loading