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

Migrate rustc_ast_passes diagnostics to SessionDiagnostic and translatable messages (first part) #100694

Merged
merged 16 commits into from
Aug 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3595,6 +3595,7 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_feature",
"rustc_macros",
"rustc_parse",
"rustc_session",
"rustc_span",
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast_passes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_feature = { path = "../rustc_feature" }
rustc_macros = { path = "../rustc_macros" }
rustc_parse = { path = "../rustc_parse" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
Expand Down
248 changes: 80 additions & 168 deletions compiler/rustc_ast_passes/src/ast_validation.rs

Large diffs are not rendered by default.

248 changes: 248 additions & 0 deletions compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
//! Errors emitted by ast_passes.

use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic};
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
use rustc_span::{Span, Symbol};

use crate::ast_validation::ForbiddenLetReason;

#[derive(SessionDiagnostic)]
#[diag(ast_passes::forbidden_let)]
#[note]
pub struct ForbiddenLet {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub(crate) reason: ForbiddenLetReason,
}

impl AddSubdiagnostic for ForbiddenLetReason {
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
match self {
Self::GenericForbidden => {}
Self::NotSupportedOr(span) => {
diag.span_note(span, fluent::ast_passes::not_supported_or);
}
Self::NotSupportedParentheses(span) => {
diag.span_note(span, fluent::ast_passes::not_supported_parentheses);
}
}
}
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::forbidden_assoc_constraint)]
pub struct ForbiddenAssocConstraint {
#[primary_span]
pub span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::keyword_lifetime)]
pub struct KeywordLifetime {
#[primary_span]
pub span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::invalid_label)]
pub struct InvalidLabel {
#[primary_span]
pub span: Span,
pub name: Symbol,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::invalid_visibility, code = "E0449")]
pub struct InvalidVisibility {
#[primary_span]
pub span: Span,
#[label(ast_passes::implied)]
pub implied: Option<Span>,
#[subdiagnostic]
pub note: Option<InvalidVisibilityNote>,
}

#[derive(SessionSubdiagnostic)]
pub enum InvalidVisibilityNote {
#[note(ast_passes::individual_impl_items)]
IndividualImplItems,
#[note(ast_passes::individual_foreign_items)]
IndividualForeignItems,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::trait_fn_async, code = "E0706")]
#[note]
#[note(ast_passes::note2)]
pub struct TraitFnAsync {
#[primary_span]
pub fn_span: Span,
#[label]
pub span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::trait_fn_const, code = "E0379")]
pub struct TraitFnConst {
#[primary_span]
#[label]
pub span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::forbidden_lifetime_bound)]
pub struct ForbiddenLifetimeBound {
#[primary_span]
pub spans: Vec<Span>,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::forbidden_non_lifetime_param)]
pub struct ForbiddenNonLifetimeParam {
#[primary_span]
pub spans: Vec<Span>,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::fn_param_too_many)]
pub struct FnParamTooMany {
#[primary_span]
pub span: Span,
pub max_num_args: usize,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::fn_param_c_var_args_only)]
pub struct FnParamCVarArgsOnly {
#[primary_span]
pub span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::fn_param_c_var_args_not_last)]
pub struct FnParamCVarArgsNotLast {
#[primary_span]
pub span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::fn_param_doc_comment)]
pub struct FnParamDocComment {
#[primary_span]
#[label]
pub span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::fn_param_forbidden_attr)]
pub struct FnParamForbiddenAttr {
#[primary_span]
pub span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::fn_param_forbidden_self)]
#[note]
pub struct FnParamForbiddenSelf {
#[primary_span]
#[label]
pub span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::forbidden_default)]
pub struct ForbiddenDefault {
#[primary_span]
pub span: Span,
#[label]
pub def_span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::assoc_const_without_body)]
pub struct AssocConstWithoutBody {
#[primary_span]
pub span: Span,
#[suggestion(code = " = <expr>;", applicability = "has-placeholders")]
pub replace_span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::assoc_fn_without_body)]
pub struct AssocFnWithoutBody {
#[primary_span]
pub span: Span,
#[suggestion(code = " {{ <body> }}", applicability = "has-placeholders")]
pub replace_span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::assoc_type_without_body)]
pub struct AssocTypeWithoutBody {
#[primary_span]
pub span: Span,
#[suggestion(code = " = <type>;", applicability = "has-placeholders")]
pub replace_span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::const_without_body)]
pub struct ConstWithoutBody {
#[primary_span]
pub span: Span,
#[suggestion(code = " = <expr>;", applicability = "has-placeholders")]
pub replace_span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::static_without_body)]
pub struct StaticWithoutBody {
#[primary_span]
pub span: Span,
#[suggestion(code = " = <expr>;", applicability = "has-placeholders")]
pub replace_span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::ty_alias_without_body)]
pub struct TyAliasWithoutBody {
#[primary_span]
pub span: Span,
#[suggestion(code = " = <type>;", applicability = "has-placeholders")]
pub replace_span: Span,
}

#[derive(SessionDiagnostic)]
#[diag(ast_passes::fn_without_body)]
pub struct FnWithoutBody {
#[primary_span]
pub span: Span,
#[suggestion(code = " {{ <body> }}", applicability = "has-placeholders")]
pub replace_span: Span,
#[subdiagnostic]
pub extern_block_suggestion: Option<ExternBlockSuggestion>,
}

pub struct ExternBlockSuggestion {
pub start_span: Span,
pub end_span: Span,
pub abi: Option<Symbol>,
}

impl AddSubdiagnostic for ExternBlockSuggestion {
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
let start_suggestion = if let Some(abi) = self.abi {
format!("extern \"{}\" {{", abi)
} else {
"extern {".to_owned()
};
let end_suggestion = " }".to_owned();

diag.multipart_suggestion(
fluent::ast_passes::extern_block_suggestion,
vec![(self.start_span, start_suggestion), (self.end_span, end_suggestion)],
Applicability::MaybeIncorrect,
);
}
}
1 change: 1 addition & 0 deletions compiler/rustc_ast_passes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#![recursion_limit = "256"]

pub mod ast_validation;
mod errors;
pub mod feature_gate;
pub mod node_count;
pub mod show_span;
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1176,7 +1176,7 @@ fn create_lints_for_named_arguments_used_positionally(cx: &mut Context<'_, '_>)

cx.ecx.buffered_early_lint.push(BufferedEarlyLint {
span: MultiSpan::from_span(named_arg.positional_named_arg_span),
msg: msg.clone(),
msg: msg.into(),
node_id: ast::CRATE_NODE_ID,
lint_id: LintId::of(&NAMED_ARGUMENTS_USED_POSITIONALLY),
diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally {
Expand Down
93 changes: 93 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/ast_passes.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
ast_passes_forbidden_let =
`let` expressions are not supported here
.note = only supported directly in conditions of `if` and `while` expressions
.not_supported_or = `||` operators are not supported in let chain expressions
.not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains
ast_passes_deprecated_where_clause_location =
where clause not allowed here
ast_passes_forbidden_assoc_constraint =
associated type bounds are not allowed within structs, enums, or unions
ast_passes_keyword_lifetime =
lifetimes cannot use keyword names
ast_passes_invalid_label =
invalid label name `{$name}`
ast_passes_invalid_visibility =
unnecessary visibility qualifier
.implied = `pub` not permitted here because it's implied
.individual_impl_items = place qualifiers on individual impl items instead
.individual_foreign_items = place qualifiers on individual foreign items instead
ast_passes_trait_fn_async =
functions in traits cannot be declared `async`
.label = `async` because of this
.note = `async` trait functions are not currently supported
.note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: it would be nice if this was slightly more descriptive

ast_passes_trait_fn_const =
functions in traits cannot be declared const
.label = functions in traits cannot be const
ast_passes_forbidden_lifetime_bound =
lifetime bounds cannot be used in this context
ast_passes_forbidden_non_lifetime_param =
only lifetime parameters can be used in this context
ast_passes_fn_param_too_many =
function can not have more than {$max_num_args} arguments
ast_passes_fn_param_c_var_args_only =
C-variadic function must be declared with at least one named argument
ast_passes_fn_param_c_var_args_not_last =
`...` must be the last argument of a C-variadic function
ast_passes_fn_param_doc_comment =
documentation comments cannot be applied to function parameters
.label = doc comments are not allowed here
ast_passes_fn_param_forbidden_attr =
allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
ast_passes_fn_param_forbidden_self =
`self` parameter is only allowed in associated functions
.label = not semantically valid as function parameter
.note = associated functions are those in `impl` or `trait` definitions
ast_passes_forbidden_default =
`default` is only allowed on items in trait impls
.label = `default` because of this
ast_passes_assoc_const_without_body =
associated constant in `impl` without body
.suggestion = provide a definition for the constant
ast_passes_assoc_fn_without_body =
associated function in `impl` without body
.suggestion = provide a definition for the function
ast_passes_assoc_type_without_body =
associated type in `impl` without body
.suggestion = provide a definition for the type
ast_passes_const_without_body =
free constant item without body
.suggestion = provide a definition for the constant
ast_passes_static_without_body =
free static item without body
.suggestion = provide a definition for the static
ast_passes_ty_alias_without_body =
free type alias without body
.suggestion = provide a definition for the type
ast_passes_fn_without_body =
free function without a body
.suggestion = provide a definition for the function
.extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block
1 change: 1 addition & 0 deletions compiler/rustc_error_messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub use unic_langid::{langid, LanguageIdentifier};

// Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module.
fluent_messages! {
ast_passes => "../locales/en-US/ast_passes.ftl",
borrowck => "../locales/en-US/borrowck.ftl",
builtin_macros => "../locales/en-US/builtin_macros.ftl",
const_eval => "../locales/en-US/const_eval.ftl",
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/early.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
lint_id.lint,
Some(span),
|lint| {
lint.build(&msg).emit();
lint.build(msg).emit();
},
diagnostic,
);
Expand Down
Loading