Skip to content

Commit

Permalink
Rollup merge of rust-lang#103051 - davidtwco:translation-tidying-up, …
Browse files Browse the repository at this point in the history
…r=compiler-errors

translation: doc comments with derives, subdiagnostic-less enum variants, more derive use

- Adds support for `doc` attributes in the diagnostic derives so that documentation comments don't result in the derive failing.
- Adds support for enum variants in the subdiagnostic derive to not actually correspond to an addition to a diagnostic.
- Made use of the derive in more places in the `rustc_ast_lowering`, `rustc_ast_passes`, `rustc_lint`, `rustc_session`, `rustc_infer` - taking advantage of recent additions like eager subdiagnostics, multispan suggestions, etc.

cc rust-lang#100717
  • Loading branch information
matthiaskrgr authored Oct 20, 2022
2 parents da11d2f + 913f597 commit dd348af
Show file tree
Hide file tree
Showing 17 changed files with 286 additions and 238 deletions.
59 changes: 18 additions & 41 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use rustc_errors::{
fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay,
SubdiagnosticMessage,
};
use rustc_errors::DiagnosticArgFromDisplay;
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{symbol::Ident, Span, Symbol};

Expand All @@ -15,25 +12,15 @@ pub struct GenericTypeWithParentheses {
pub sub: Option<UseAngleBrackets>,
}

#[derive(Clone, Copy)]
#[derive(Clone, Copy, Subdiagnostic)]
#[multipart_suggestion(ast_lowering::use_angle_brackets, applicability = "maybe-incorrect")]
pub struct UseAngleBrackets {
#[suggestion_part(code = "<")]
pub open_param: Span,
#[suggestion_part(code = ">")]
pub close_param: Span,
}

impl AddToDiagnostic for UseAngleBrackets {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
diag.multipart_suggestion(
fluent::ast_lowering::use_angle_brackets,
vec![(self.open_param, String::from("<")), (self.close_param, String::from(">"))],
Applicability::MaybeIncorrect,
);
}
}

#[derive(Diagnostic)]
#[diag(ast_lowering::invalid_abi, code = "E0703")]
#[note]
Expand Down Expand Up @@ -68,30 +55,20 @@ pub struct AssocTyParentheses {
pub sub: AssocTyParenthesesSub,
}

#[derive(Clone, Copy)]
#[derive(Clone, Copy, Subdiagnostic)]
pub enum AssocTyParenthesesSub {
Empty { parentheses_span: Span },
NotEmpty { open_param: Span, close_param: Span },
}

impl AddToDiagnostic for AssocTyParenthesesSub {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
match self {
Self::Empty { parentheses_span } => diag.multipart_suggestion(
fluent::ast_lowering::remove_parentheses,
vec![(parentheses_span, String::new())],
Applicability::MaybeIncorrect,
),
Self::NotEmpty { open_param, close_param } => diag.multipart_suggestion(
fluent::ast_lowering::use_angle_brackets,
vec![(open_param, String::from("<")), (close_param, String::from(">"))],
Applicability::MaybeIncorrect,
),
};
}
#[multipart_suggestion(ast_lowering::remove_parentheses)]
Empty {
#[suggestion_part(code = "")]
parentheses_span: Span,
},
#[multipart_suggestion(ast_lowering::use_angle_brackets)]
NotEmpty {
#[suggestion_part(code = "<")]
open_param: Span,
#[suggestion_part(code = ">")]
close_param: Span,
},
}

#[derive(Diagnostic)]
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use rustc_ast::*;
use rustc_ast_pretty::pprust::{self, State};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability};
use rustc_macros::Subdiagnostic;
use rustc_parse::validate_attr;
use rustc_session::lint::builtin::{
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
Expand Down Expand Up @@ -1782,15 +1783,17 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
}

/// Used to forbid `let` expressions in certain syntactic locations.
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Subdiagnostic)]
pub(crate) enum ForbiddenLetReason {
/// `let` is not valid and the source environment is not important
GenericForbidden,
/// A let chain with the `||` operator
NotSupportedOr(Span),
#[note(ast_passes::not_supported_or)]
NotSupportedOr(#[primary_span] Span),
/// A let chain with invalid parentheses
///
/// For example, `let 1 = 1 && (expr && expr)` is allowed
/// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
NotSupportedParentheses(Span),
#[note(ast_passes::not_supported_parentheses)]
NotSupportedParentheses(#[primary_span] Span),
}
17 changes: 0 additions & 17 deletions compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,6 @@ pub struct ForbiddenLet {
pub(crate) reason: ForbiddenLetReason,
}

impl AddToDiagnostic for ForbiddenLetReason {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
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(Diagnostic)]
#[diag(ast_passes::forbidden_let_stable)]
#[note]
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_error_messages/locales/en-US/infer.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,9 @@ infer_region_explanation = {$pref_kind ->
}
infer_mismatched_static_lifetime = incompatible lifetime on type
infer_msl_impl_note = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
infer_msl_introduces_static = introduces a `'static` lifetime requirement
infer_msl_unmet_req = because this has an unmet lifetime requirement
infer_msl_trait_note = this has an implicit `'static` lifetime requirement
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/session.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,7 @@ session_crate_name_empty = crate name must not be empty
session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}`
session_expr_parentheses_needed = parentheses are required to parse this as an expression
session_skipping_const_checks = skipping const checks
session_unleashed_feature_help_named = skipping check for `{$gate}` feature
session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate
21 changes: 18 additions & 3 deletions compiler/rustc_errors/src/diagnostic_impls.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use crate::{
fluent, DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg,
};
use rustc_target::abi::TargetDataLayoutErrors;
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};

use rustc_ast as ast;
use rustc_ast_pretty::pprust;
use rustc_hir as hir;
use rustc_lint_defs::Level;
use rustc_span::edition::Edition;
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
use rustc_target::abi::TargetDataLayoutErrors;
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
use std::borrow::Cow;
use std::fmt;
use std::num::ParseIntError;
Expand Down Expand Up @@ -155,6 +155,21 @@ impl IntoDiagnosticArg for ast::token::TokenKind {
}
}

impl IntoDiagnosticArg for Level {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(Cow::Borrowed(match self {
Level::Allow => "-A",
Level::Warn => "-W",
Level::ForceWarn(_) => "--force-warn",
Level::Deny => "-D",
Level::Forbid => "-F",
Level::Expect(_) => {
unreachable!("lints with the level of `expect` should not run this code");
}
}))
}
}

impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
let mut diag;
Expand Down
71 changes: 29 additions & 42 deletions compiler/rustc_infer/src/errors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,47 +459,34 @@ impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
}
}

pub struct ImplNote {
pub impl_span: Option<Span>,
}

impl AddToDiagnostic for ImplNote {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
match self.impl_span {
Some(span) => diag.span_note(span, fluent::infer::msl_impl_note),
None => diag.note(fluent::infer::msl_impl_note),
};
}
}

pub enum TraitSubdiag {
Note { span: Span },
Sugg { span: Span },
// FIXME(#100717): replace with a `Option<Span>` when subdiagnostic supports that
#[derive(Subdiagnostic)]
pub enum DoesNotOutliveStaticFromImpl {
#[note(infer::does_not_outlive_static_from_impl)]
Spanned {
#[primary_span]
span: Span,
},
#[note(infer::does_not_outlive_static_from_impl)]
Unspanned,
}

// FIXME(#100717) used in `Vec<TraitSubdiag>` so requires eager translation/list support
impl AddToDiagnostic for TraitSubdiag {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
match self {
TraitSubdiag::Note { span } => {
diag.span_note(span, "this has an implicit `'static` lifetime requirement");
}
TraitSubdiag::Sugg { span } => {
diag.span_suggestion_verbose(
span,
"consider relaxing the implicit `'static` requirement",
" + '_".to_owned(),
rustc_errors::Applicability::MaybeIncorrect,
);
}
}
}
#[derive(Subdiagnostic)]
pub enum ImplicitStaticLifetimeSubdiag {
#[note(infer::implicit_static_lifetime_note)]
Note {
#[primary_span]
span: Span,
},
#[suggestion_verbose(
infer::implicit_static_lifetime_suggestion,
code = " + '_",
applicability = "maybe-incorrect"
)]
Sugg {
#[primary_span]
span: Span,
},
}

#[derive(Diagnostic)]
Expand All @@ -512,7 +499,7 @@ pub struct MismatchedStaticLifetime<'a> {
#[subdiagnostic]
pub expl: Option<note_and_explain::RegionExplanation<'a>>,
#[subdiagnostic]
pub impl_note: ImplNote,
#[subdiagnostic]
pub trait_subdiags: Vec<TraitSubdiag>,
pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl,
#[subdiagnostic(eager)]
pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
//! to hold.

use crate::errors::{note_and_explain, IntroducesStaticBecauseUnmetLifetimeReq};
use crate::errors::{ImplNote, MismatchedStaticLifetime, TraitSubdiag};
use crate::errors::{
DoesNotOutliveStaticFromImpl, ImplicitStaticLifetimeSubdiag, MismatchedStaticLifetime,
};
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::infer::{SubregionOrigin, TypeTrace};
Expand Down Expand Up @@ -56,7 +58,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
note_and_explain::SuffixKind::Continues,
);
let mut impl_span = None;
let mut trait_subdiags = Vec::new();
let mut implicit_static_lifetimes = Vec::new();
if let Some(impl_node) = self.tcx().hir().get_if_local(*impl_def_id) {
// If an impl is local, then maybe this isn't what they want. Try to
// be as helpful as possible with implicit lifetimes.
Expand Down Expand Up @@ -90,10 +92,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
// Otherwise, point at all implicit static lifetimes

for span in &traits {
trait_subdiags.push(TraitSubdiag::Note { span: *span });
implicit_static_lifetimes
.push(ImplicitStaticLifetimeSubdiag::Note { span: *span });
// It would be nice to put this immediately under the above note, but they get
// pushed to the end.
trait_subdiags.push(TraitSubdiag::Sugg { span: span.shrink_to_hi() });
implicit_static_lifetimes
.push(ImplicitStaticLifetimeSubdiag::Sugg { span: span.shrink_to_hi() });
}
}
} else {
Expand All @@ -105,8 +109,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
cause_span: cause.span,
unmet_lifetime_reqs: multispan_subdiag,
expl,
impl_note: ImplNote { impl_span },
trait_subdiags,
does_not_outlive_static_from_impl: impl_span
.map(|span| DoesNotOutliveStaticFromImpl::Spanned { span })
.unwrap_or(DoesNotOutliveStaticFromImpl::Unspanned),
implicit_static_lifetimes,
};
let reported = self.tcx().sess.emit_err(err);
Some(reported)
Expand Down
25 changes: 2 additions & 23 deletions compiler/rustc_lint/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,34 +88,13 @@ pub struct BuiltinEllpisisInclusiveRangePatterns {
pub replace: String,
}

#[derive(Subdiagnostic)]
#[note(lint::requested_level)]
pub struct RequestedLevel {
pub level: Level,
pub lint_name: String,
}

impl AddToDiagnostic for RequestedLevel {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
diag.note(fluent::lint::requested_level);
diag.set_arg(
"level",
match self.level {
Level::Allow => "-A",
Level::Warn => "-W",
Level::ForceWarn(_) => "--force-warn",
Level::Deny => "-D",
Level::Forbid => "-F",
Level::Expect(_) => {
unreachable!("lints with the level of `expect` should not run this code");
}
},
);
diag.set_arg("lint_name", self.lint_name);
}
}

#[derive(Diagnostic)]
#[diag(lint::unsupported_group, code = "E0602")]
pub struct UnsupportedGroup {
Expand Down
Loading

0 comments on commit dd348af

Please sign in to comment.