Rollup merge of #103051 - davidtwco:translation-tidying-up, 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 #100717
This commit is contained in:
commit
e11511dfa6
17 changed files with 286 additions and 238 deletions
|
@ -1,7 +1,4 @@
|
||||||
use rustc_errors::{
|
use rustc_errors::DiagnosticArgFromDisplay;
|
||||||
fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay,
|
|
||||||
SubdiagnosticMessage,
|
|
||||||
};
|
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||||
|
|
||||||
|
@ -15,25 +12,15 @@ pub struct GenericTypeWithParentheses {
|
||||||
pub sub: Option<UseAngleBrackets>,
|
pub sub: Option<UseAngleBrackets>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(ast_lowering::use_angle_brackets, applicability = "maybe-incorrect")]
|
||||||
pub struct UseAngleBrackets {
|
pub struct UseAngleBrackets {
|
||||||
|
#[suggestion_part(code = "<")]
|
||||||
pub open_param: Span,
|
pub open_param: Span,
|
||||||
|
#[suggestion_part(code = ">")]
|
||||||
pub close_param: Span,
|
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)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_lowering::invalid_abi, code = "E0703")]
|
#[diag(ast_lowering::invalid_abi, code = "E0703")]
|
||||||
#[note]
|
#[note]
|
||||||
|
@ -68,30 +55,20 @@ pub struct AssocTyParentheses {
|
||||||
pub sub: AssocTyParenthesesSub,
|
pub sub: AssocTyParenthesesSub,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Subdiagnostic)]
|
||||||
pub enum AssocTyParenthesesSub {
|
pub enum AssocTyParenthesesSub {
|
||||||
Empty { parentheses_span: Span },
|
#[multipart_suggestion(ast_lowering::remove_parentheses)]
|
||||||
NotEmpty { open_param: Span, close_param: Span },
|
Empty {
|
||||||
}
|
#[suggestion_part(code = "")]
|
||||||
|
parentheses_span: Span,
|
||||||
impl AddToDiagnostic for AssocTyParenthesesSub {
|
},
|
||||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
#[multipart_suggestion(ast_lowering::use_angle_brackets)]
|
||||||
where
|
NotEmpty {
|
||||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
#[suggestion_part(code = "<")]
|
||||||
{
|
open_param: Span,
|
||||||
match self {
|
#[suggestion_part(code = ">")]
|
||||||
Self::Empty { parentheses_span } => diag.multipart_suggestion(
|
close_param: Span,
|
||||||
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,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
|
|
@ -14,6 +14,7 @@ use rustc_ast::*;
|
||||||
use rustc_ast_pretty::pprust::{self, State};
|
use rustc_ast_pretty::pprust::{self, State};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability};
|
use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability};
|
||||||
|
use rustc_macros::Subdiagnostic;
|
||||||
use rustc_parse::validate_attr;
|
use rustc_parse::validate_attr;
|
||||||
use rustc_session::lint::builtin::{
|
use rustc_session::lint::builtin::{
|
||||||
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
|
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||||
|
@ -1805,15 +1806,17 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used to forbid `let` expressions in certain syntactic locations.
|
/// Used to forbid `let` expressions in certain syntactic locations.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Subdiagnostic)]
|
||||||
pub(crate) enum ForbiddenLetReason {
|
pub(crate) enum ForbiddenLetReason {
|
||||||
/// `let` is not valid and the source environment is not important
|
/// `let` is not valid and the source environment is not important
|
||||||
GenericForbidden,
|
GenericForbidden,
|
||||||
/// A let chain with the `||` operator
|
/// A let chain with the `||` operator
|
||||||
NotSupportedOr(Span),
|
#[note(ast_passes::not_supported_or)]
|
||||||
|
NotSupportedOr(#[primary_span] Span),
|
||||||
/// A let chain with invalid parentheses
|
/// A let chain with invalid parentheses
|
||||||
///
|
///
|
||||||
/// For example, `let 1 = 1 && (expr && expr)` is allowed
|
/// For example, `let 1 = 1 && (expr && expr)` is allowed
|
||||||
/// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
|
/// 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),
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,23 +16,6 @@ pub struct ForbiddenLet {
|
||||||
pub(crate) reason: ForbiddenLetReason,
|
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)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes::forbidden_let_stable)]
|
#[diag(ast_passes::forbidden_let_stable)]
|
||||||
#[note]
|
#[note]
|
||||||
|
|
|
@ -164,7 +164,9 @@ infer_region_explanation = {$pref_kind ->
|
||||||
}
|
}
|
||||||
|
|
||||||
infer_mismatched_static_lifetime = incompatible lifetime on type
|
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_introduces_static = introduces a `'static` lifetime requirement
|
||||||
infer_msl_unmet_req = because this has an unmet lifetime requirement
|
infer_msl_unmet_req = because this has an unmet lifetime requirement
|
||||||
infer_msl_trait_note = this has an implicit `'static` lifetime requirement
|
infer_msl_trait_note = this has an implicit `'static` lifetime requirement
|
||||||
|
|
|
@ -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_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_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
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
fluent, DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg,
|
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 as ast;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_lint_defs::Level;
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
|
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::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::num::ParseIntError;
|
use std::num::ParseIntError;
|
||||||
|
@ -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<'_> {
|
impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
|
||||||
fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
|
fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
|
||||||
let mut diag;
|
let mut diag;
|
||||||
|
|
|
@ -459,47 +459,34 @@ impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ImplNote {
|
// FIXME(#100717): replace with a `Option<Span>` when subdiagnostic supports that
|
||||||
pub impl_span: Option<Span>,
|
#[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,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for ImplNote {
|
#[derive(Subdiagnostic)]
|
||||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
pub enum ImplicitStaticLifetimeSubdiag {
|
||||||
where
|
#[note(infer::implicit_static_lifetime_note)]
|
||||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
Note {
|
||||||
{
|
#[primary_span]
|
||||||
match self.impl_span {
|
span: Span,
|
||||||
Some(span) => diag.span_note(span, fluent::infer::msl_impl_note),
|
},
|
||||||
None => diag.note(fluent::infer::msl_impl_note),
|
#[suggestion_verbose(
|
||||||
};
|
infer::implicit_static_lifetime_suggestion,
|
||||||
}
|
code = " + '_",
|
||||||
}
|
applicability = "maybe-incorrect"
|
||||||
|
)]
|
||||||
pub enum TraitSubdiag {
|
Sugg {
|
||||||
Note { span: Span },
|
#[primary_span]
|
||||||
Sugg { span: Span },
|
span: Span,
|
||||||
}
|
},
|
||||||
|
|
||||||
// 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(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
@ -512,7 +499,7 @@ pub struct MismatchedStaticLifetime<'a> {
|
||||||
#[subdiagnostic]
|
#[subdiagnostic]
|
||||||
pub expl: Option<note_and_explain::RegionExplanation<'a>>,
|
pub expl: Option<note_and_explain::RegionExplanation<'a>>,
|
||||||
#[subdiagnostic]
|
#[subdiagnostic]
|
||||||
pub impl_note: ImplNote,
|
pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl,
|
||||||
#[subdiagnostic]
|
#[subdiagnostic(eager)]
|
||||||
pub trait_subdiags: Vec<TraitSubdiag>,
|
pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
//! to hold.
|
//! to hold.
|
||||||
|
|
||||||
use crate::errors::{note_and_explain, IntroducesStaticBecauseUnmetLifetimeReq};
|
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::error_reporting::nice_region_error::NiceRegionError;
|
||||||
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
||||||
use crate::infer::{SubregionOrigin, TypeTrace};
|
use crate::infer::{SubregionOrigin, TypeTrace};
|
||||||
|
@ -56,7 +58,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
note_and_explain::SuffixKind::Continues,
|
note_and_explain::SuffixKind::Continues,
|
||||||
);
|
);
|
||||||
let mut impl_span = None;
|
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 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
|
// If an impl is local, then maybe this isn't what they want. Try to
|
||||||
// be as helpful as possible with implicit lifetimes.
|
// be as helpful as possible with implicit lifetimes.
|
||||||
|
@ -90,10 +92,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
// Otherwise, point at all implicit static lifetimes
|
// Otherwise, point at all implicit static lifetimes
|
||||||
|
|
||||||
for span in &traits {
|
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
|
// It would be nice to put this immediately under the above note, but they get
|
||||||
// pushed to the end.
|
// 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 {
|
} else {
|
||||||
|
@ -105,8 +109,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
cause_span: cause.span,
|
cause_span: cause.span,
|
||||||
unmet_lifetime_reqs: multispan_subdiag,
|
unmet_lifetime_reqs: multispan_subdiag,
|
||||||
expl,
|
expl,
|
||||||
impl_note: ImplNote { impl_span },
|
does_not_outlive_static_from_impl: impl_span
|
||||||
trait_subdiags,
|
.map(|span| DoesNotOutliveStaticFromImpl::Spanned { span })
|
||||||
|
.unwrap_or(DoesNotOutliveStaticFromImpl::Unspanned),
|
||||||
|
implicit_static_lifetimes,
|
||||||
};
|
};
|
||||||
let reported = self.tcx().sess.emit_err(err);
|
let reported = self.tcx().sess.emit_err(err);
|
||||||
Some(reported)
|
Some(reported)
|
||||||
|
|
|
@ -88,34 +88,13 @@ pub struct BuiltinEllpisisInclusiveRangePatterns {
|
||||||
pub replace: String,
|
pub replace: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[note(lint::requested_level)]
|
||||||
pub struct RequestedLevel {
|
pub struct RequestedLevel {
|
||||||
pub level: Level,
|
pub level: Level,
|
||||||
pub lint_name: String,
|
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)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(lint::unsupported_group, code = "E0602")]
|
#[diag(lint::unsupported_group, code = "E0602")]
|
||||||
pub struct UnsupportedGroup {
|
pub struct UnsupportedGroup {
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::diagnostics::error::{
|
||||||
DiagnosticDeriveError,
|
DiagnosticDeriveError,
|
||||||
};
|
};
|
||||||
use crate::diagnostics::utils::{
|
use crate::diagnostics::utils::{
|
||||||
build_field_mapping, report_error_if_not_applied_to_span, report_type_error,
|
build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error,
|
||||||
should_generate_set_arg, type_is_unit, type_matches_path, FieldInfo, FieldInnerTy, FieldMap,
|
should_generate_set_arg, type_is_unit, type_matches_path, FieldInfo, FieldInnerTy, FieldMap,
|
||||||
HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
|
HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
|
||||||
};
|
};
|
||||||
|
@ -152,8 +152,12 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
|
||||||
fn parse_subdiag_attribute(
|
fn parse_subdiag_attribute(
|
||||||
&self,
|
&self,
|
||||||
attr: &Attribute,
|
attr: &Attribute,
|
||||||
) -> Result<(SubdiagnosticKind, Path), DiagnosticDeriveError> {
|
) -> Result<Option<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
|
||||||
let (subdiag, slug) = SubdiagnosticKind::from_attr(attr, self)?;
|
let Some((subdiag, slug)) = SubdiagnosticKind::from_attr(attr, self)? else {
|
||||||
|
// Some attributes aren't errors - like documentation comments - but also aren't
|
||||||
|
// subdiagnostics.
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag {
|
if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag {
|
||||||
let meta = attr.parse_meta()?;
|
let meta = attr.parse_meta()?;
|
||||||
|
@ -170,7 +174,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
|
||||||
SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
|
SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok((subdiag, slug))
|
Ok(Some((subdiag, slug)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct
|
/// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct
|
||||||
|
@ -182,6 +186,11 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
|
||||||
) -> Result<TokenStream, DiagnosticDeriveError> {
|
) -> Result<TokenStream, DiagnosticDeriveError> {
|
||||||
let diag = &self.parent.diag;
|
let diag = &self.parent.diag;
|
||||||
|
|
||||||
|
// Always allow documentation comments.
|
||||||
|
if is_doc_comment(attr) {
|
||||||
|
return Ok(quote! {});
|
||||||
|
}
|
||||||
|
|
||||||
let name = attr.path.segments.last().unwrap().ident.to_string();
|
let name = attr.path.segments.last().unwrap().ident.to_string();
|
||||||
let name = name.as_str();
|
let name = name.as_str();
|
||||||
let meta = attr.parse_meta()?;
|
let meta = attr.parse_meta()?;
|
||||||
|
@ -250,7 +259,11 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
|
||||||
return Ok(tokens);
|
return Ok(tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (subdiag, slug) = self.parse_subdiag_attribute(attr)?;
|
let Some((subdiag, slug)) = self.parse_subdiag_attribute(attr)? else {
|
||||||
|
// Some attributes aren't errors - like documentation comments - but also aren't
|
||||||
|
// subdiagnostics.
|
||||||
|
return Ok(quote! {});
|
||||||
|
};
|
||||||
let fn_ident = format_ident!("{}", subdiag);
|
let fn_ident = format_ident!("{}", subdiag);
|
||||||
match subdiag {
|
match subdiag {
|
||||||
SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
|
SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
|
||||||
|
@ -291,6 +304,11 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
|
||||||
.attrs
|
.attrs
|
||||||
.iter()
|
.iter()
|
||||||
.map(move |attr| {
|
.map(move |attr| {
|
||||||
|
// Always allow documentation comments.
|
||||||
|
if is_doc_comment(attr) {
|
||||||
|
return quote! {};
|
||||||
|
}
|
||||||
|
|
||||||
let name = attr.path.segments.last().unwrap().ident.to_string();
|
let name = attr.path.segments.last().unwrap().ident.to_string();
|
||||||
let needs_clone =
|
let needs_clone =
|
||||||
name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_));
|
name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_));
|
||||||
|
@ -397,8 +415,11 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
let (subdiag, slug) = self.parse_subdiag_attribute(attr)?;
|
let Some((subdiag, slug)) = self.parse_subdiag_attribute(attr)? else {
|
||||||
|
// Some attributes aren't errors - like documentation comments - but also aren't
|
||||||
|
// subdiagnostics.
|
||||||
|
return Ok(quote! {});
|
||||||
|
};
|
||||||
let fn_ident = format_ident!("{}", subdiag);
|
let fn_ident = format_ident!("{}", subdiag);
|
||||||
match subdiag {
|
match subdiag {
|
||||||
SubdiagnosticKind::Label => {
|
SubdiagnosticKind::Label => {
|
||||||
|
|
|
@ -5,9 +5,9 @@ use crate::diagnostics::error::{
|
||||||
DiagnosticDeriveError,
|
DiagnosticDeriveError,
|
||||||
};
|
};
|
||||||
use crate::diagnostics::utils::{
|
use crate::diagnostics::utils::{
|
||||||
build_field_mapping, new_code_ident, report_error_if_not_applied_to_applicability,
|
build_field_mapping, is_doc_comment, new_code_ident,
|
||||||
report_error_if_not_applied_to_span, FieldInfo, FieldInnerTy, FieldMap, HasFieldMap, SetOnce,
|
report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, FieldInfo,
|
||||||
SpannedOption, SubdiagnosticKind,
|
FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
|
||||||
};
|
};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
@ -41,8 +41,14 @@ impl SubdiagnosticDeriveBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if matches!(ast.data, syn::Data::Enum(..)) {
|
let is_enum = matches!(ast.data, syn::Data::Enum(..));
|
||||||
|
if is_enum {
|
||||||
for attr in &ast.attrs {
|
for attr in &ast.attrs {
|
||||||
|
// Always allow documentation comments.
|
||||||
|
if is_doc_comment(attr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
span_err(
|
span_err(
|
||||||
attr.span().unwrap(),
|
attr.span().unwrap(),
|
||||||
"unsupported type attribute for subdiagnostic enum",
|
"unsupported type attribute for subdiagnostic enum",
|
||||||
|
@ -62,6 +68,7 @@ impl SubdiagnosticDeriveBuilder {
|
||||||
span_field: None,
|
span_field: None,
|
||||||
applicability: None,
|
applicability: None,
|
||||||
has_suggestion_parts: false,
|
has_suggestion_parts: false,
|
||||||
|
is_enum,
|
||||||
};
|
};
|
||||||
builder.into_tokens().unwrap_or_else(|v| v.to_compile_error())
|
builder.into_tokens().unwrap_or_else(|v| v.to_compile_error())
|
||||||
});
|
});
|
||||||
|
@ -79,7 +86,7 @@ impl SubdiagnosticDeriveBuilder {
|
||||||
gen impl rustc_errors::AddToDiagnostic for @Self {
|
gen impl rustc_errors::AddToDiagnostic for @Self {
|
||||||
fn add_to_diagnostic_with<__F>(self, #diag: &mut rustc_errors::Diagnostic, #f: __F)
|
fn add_to_diagnostic_with<__F>(self, #diag: &mut rustc_errors::Diagnostic, #f: __F)
|
||||||
where
|
where
|
||||||
__F: Fn(
|
__F: core::ops::Fn(
|
||||||
&mut rustc_errors::Diagnostic,
|
&mut rustc_errors::Diagnostic,
|
||||||
rustc_errors::SubdiagnosticMessage
|
rustc_errors::SubdiagnosticMessage
|
||||||
) -> rustc_errors::SubdiagnosticMessage,
|
) -> rustc_errors::SubdiagnosticMessage,
|
||||||
|
@ -122,6 +129,9 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||||
/// Set to true when a `#[suggestion_part]` field is encountered, used to generate an error
|
/// Set to true when a `#[suggestion_part]` field is encountered, used to generate an error
|
||||||
/// during finalization if still `false`.
|
/// during finalization if still `false`.
|
||||||
has_suggestion_parts: bool,
|
has_suggestion_parts: bool,
|
||||||
|
|
||||||
|
/// Set to true when this variant is an enum variant rather than just the body of a struct.
|
||||||
|
is_enum: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'parent, 'a> HasFieldMap for SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
impl<'parent, 'a> HasFieldMap for SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||||
|
@ -173,7 +183,11 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||||
let mut kind_slugs = vec![];
|
let mut kind_slugs = vec![];
|
||||||
|
|
||||||
for attr in self.variant.ast().attrs {
|
for attr in self.variant.ast().attrs {
|
||||||
let (kind, slug) = SubdiagnosticKind::from_attr(attr, self)?;
|
let Some((kind, slug)) = SubdiagnosticKind::from_attr(attr, self)? else {
|
||||||
|
// Some attributes aren't errors - like documentation comments - but also aren't
|
||||||
|
// subdiagnostics.
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
let Some(slug) = slug else {
|
let Some(slug) = slug else {
|
||||||
let name = attr.path.segments.last().unwrap().ident.to_string();
|
let name = attr.path.segments.last().unwrap().ident.to_string();
|
||||||
|
@ -227,6 +241,11 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||||
ast.attrs
|
ast.attrs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|attr| {
|
.map(|attr| {
|
||||||
|
// Always allow documentation comments.
|
||||||
|
if is_doc_comment(attr) {
|
||||||
|
return quote! {};
|
||||||
|
}
|
||||||
|
|
||||||
let info = FieldInfo {
|
let info = FieldInfo {
|
||||||
binding,
|
binding,
|
||||||
ty: inner_ty.inner_type().unwrap_or(&ast.ty),
|
ty: inner_ty.inner_type().unwrap_or(&ast.ty),
|
||||||
|
@ -290,6 +309,8 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||||
report_error_if_not_applied_to_span(attr, &info)?;
|
report_error_if_not_applied_to_span(attr, &info)?;
|
||||||
|
|
||||||
let binding = info.binding.binding.clone();
|
let binding = info.binding.binding.clone();
|
||||||
|
// FIXME(#100717): support `Option<Span>` on `primary_span` like in the
|
||||||
|
// diagnostic derive
|
||||||
self.span_field.set_once(binding, span);
|
self.span_field.set_once(binding, span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,10 +464,16 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||||
pub fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
|
pub fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
|
||||||
let kind_slugs = self.identify_kind()?;
|
let kind_slugs = self.identify_kind()?;
|
||||||
if kind_slugs.is_empty() {
|
if kind_slugs.is_empty() {
|
||||||
throw_span_err!(
|
if self.is_enum {
|
||||||
self.variant.ast().ident.span().unwrap(),
|
// It's okay for a variant to not be a subdiagnostic at all..
|
||||||
"subdiagnostic kind not specified"
|
return Ok(quote! {});
|
||||||
);
|
} else {
|
||||||
|
// ..but structs should always be _something_.
|
||||||
|
throw_span_err!(
|
||||||
|
self.variant.ast().ident.span().unwrap(),
|
||||||
|
"subdiagnostic kind not specified"
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect();
|
let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect();
|
||||||
|
|
|
@ -477,7 +477,12 @@ impl SubdiagnosticKind {
|
||||||
pub(super) fn from_attr(
|
pub(super) fn from_attr(
|
||||||
attr: &Attribute,
|
attr: &Attribute,
|
||||||
fields: &impl HasFieldMap,
|
fields: &impl HasFieldMap,
|
||||||
) -> Result<(SubdiagnosticKind, Option<Path>), DiagnosticDeriveError> {
|
) -> Result<Option<(SubdiagnosticKind, Option<Path>)>, DiagnosticDeriveError> {
|
||||||
|
// Always allow documentation comments.
|
||||||
|
if is_doc_comment(attr) {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
let span = attr.span().unwrap();
|
let span = attr.span().unwrap();
|
||||||
|
|
||||||
let name = attr.path.segments.last().unwrap().ident.to_string();
|
let name = attr.path.segments.last().unwrap().ident.to_string();
|
||||||
|
@ -526,7 +531,9 @@ impl SubdiagnosticKind {
|
||||||
| SubdiagnosticKind::Note
|
| SubdiagnosticKind::Note
|
||||||
| SubdiagnosticKind::Help
|
| SubdiagnosticKind::Help
|
||||||
| SubdiagnosticKind::Warn
|
| SubdiagnosticKind::Warn
|
||||||
| SubdiagnosticKind::MultipartSuggestion { .. } => return Ok((kind, None)),
|
| SubdiagnosticKind::MultipartSuggestion { .. } => {
|
||||||
|
return Ok(Some((kind, None)));
|
||||||
|
}
|
||||||
SubdiagnosticKind::Suggestion { .. } => {
|
SubdiagnosticKind::Suggestion { .. } => {
|
||||||
throw_span_err!(span, "suggestion without `code = \"...\"`")
|
throw_span_err!(span, "suggestion without `code = \"...\"`")
|
||||||
}
|
}
|
||||||
|
@ -626,7 +633,7 @@ impl SubdiagnosticKind {
|
||||||
| SubdiagnosticKind::MultipartSuggestion { .. } => {}
|
| SubdiagnosticKind::MultipartSuggestion { .. } => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((kind, slug))
|
Ok(Some((kind, slug)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,3 +661,7 @@ impl quote::IdentFragment for SubdiagnosticKind {
|
||||||
pub(super) fn should_generate_set_arg(field: &Field) -> bool {
|
pub(super) fn should_generate_set_arg(field: &Field) -> bool {
|
||||||
field.attrs.is_empty()
|
field.attrs.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn is_doc_comment(attr: &Attribute) -> bool {
|
||||||
|
attr.path.segments.last().unwrap().ident.to_string() == "doc"
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
|
|
||||||
use crate::cgu_reuse_tracker::CguReuse;
|
use crate::cgu_reuse_tracker::CguReuse;
|
||||||
use rustc_errors::{
|
use rustc_errors::MultiSpan;
|
||||||
fluent, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, MultiSpan,
|
|
||||||
};
|
|
||||||
use rustc_macros::Diagnostic;
|
use rustc_macros::Diagnostic;
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
|
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
|
||||||
|
@ -148,24 +146,15 @@ pub struct CrateNameEmpty {
|
||||||
pub span: Option<Span>,
|
pub span: Option<Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(session::invalid_character_in_create_name)]
|
||||||
pub struct InvalidCharacterInCrateName<'a> {
|
pub struct InvalidCharacterInCrateName<'a> {
|
||||||
|
#[primary_span]
|
||||||
pub span: Option<Span>,
|
pub span: Option<Span>,
|
||||||
pub character: char,
|
pub character: char,
|
||||||
pub crate_name: &'a str,
|
pub crate_name: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoDiagnostic<'_> for InvalidCharacterInCrateName<'_> {
|
|
||||||
fn into_diagnostic(self, sess: &Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
|
||||||
let mut diag = sess.struct_err(fluent::session::invalid_character_in_create_name);
|
|
||||||
if let Some(sp) = self.span {
|
|
||||||
diag.set_span(sp);
|
|
||||||
}
|
|
||||||
diag.set_arg("character", self.character);
|
|
||||||
diag.set_arg("crate_name", self.crate_name);
|
|
||||||
diag
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
#[derive(Subdiagnostic)]
|
||||||
#[multipart_suggestion(session::expr_parentheses_needed, applicability = "machine-applicable")]
|
#[multipart_suggestion(session::expr_parentheses_needed, applicability = "machine-applicable")]
|
||||||
pub struct ExprParenthesesNeeded {
|
pub struct ExprParenthesesNeeded {
|
||||||
|
@ -180,3 +169,25 @@ impl ExprParenthesesNeeded {
|
||||||
ExprParenthesesNeeded { left: s.shrink_to_lo(), right: s.shrink_to_hi() }
|
ExprParenthesesNeeded { left: s.shrink_to_lo(), right: s.shrink_to_hi() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(session::skipping_const_checks)]
|
||||||
|
pub struct SkippingConstChecks {
|
||||||
|
#[subdiagnostic(eager)]
|
||||||
|
pub unleashed_features: Vec<UnleashedFeatureHelp>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
pub enum UnleashedFeatureHelp {
|
||||||
|
#[help(session::unleashed_feature_help_named)]
|
||||||
|
Named {
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
gate: Symbol,
|
||||||
|
},
|
||||||
|
#[help(session::unleashed_feature_help_unnamed)]
|
||||||
|
Unnamed {
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
|
@ -5,9 +5,10 @@ use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, S
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, LinkerPluginToWindowsNotSupported,
|
CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, LinkerPluginToWindowsNotSupported,
|
||||||
NotCircumventFeature, ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist,
|
NotCircumventFeature, ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist,
|
||||||
SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported,
|
SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, SkippingConstChecks,
|
||||||
SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget,
|
SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget,
|
||||||
TargetRequiresUnwindTables, UnstableVirtualFunctionElimination, UnsupportedDwarfVersion,
|
TargetRequiresUnwindTables, UnleashedFeatureHelp, UnstableVirtualFunctionElimination,
|
||||||
|
UnsupportedDwarfVersion,
|
||||||
};
|
};
|
||||||
use crate::parse::{add_feature_diagnostics, ParseSess};
|
use crate::parse::{add_feature_diagnostics, ParseSess};
|
||||||
use crate::search_paths::{PathKind, SearchPath};
|
use crate::search_paths::{PathKind, SearchPath};
|
||||||
|
@ -232,21 +233,19 @@ impl Session {
|
||||||
if !unleashed_features.is_empty() {
|
if !unleashed_features.is_empty() {
|
||||||
let mut must_err = false;
|
let mut must_err = false;
|
||||||
// Create a diagnostic pointing at where things got unleashed.
|
// Create a diagnostic pointing at where things got unleashed.
|
||||||
// FIXME(#100717): needs eager translation/lists
|
self.emit_warning(SkippingConstChecks {
|
||||||
#[allow(rustc::untranslatable_diagnostic)]
|
unleashed_features: unleashed_features
|
||||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
.iter()
|
||||||
let mut diag = self.struct_warn("skipping const checks");
|
.map(|(span, gate)| {
|
||||||
for &(span, feature_gate) in unleashed_features.iter() {
|
gate.map(|gate| {
|
||||||
// FIXME: `span_label` doesn't do anything, so we use "help" as a hack.
|
must_err = true;
|
||||||
if let Some(gate) = feature_gate {
|
UnleashedFeatureHelp::Named { span: *span, gate }
|
||||||
diag.span_help(span, &format!("skipping check for `{gate}` feature"));
|
})
|
||||||
// The unleash flag must *not* be used to just "hack around" feature gates.
|
.unwrap_or(UnleashedFeatureHelp::Unnamed { span: *span })
|
||||||
must_err = true;
|
})
|
||||||
} else {
|
.collect(),
|
||||||
diag.span_help(span, "skipping check that does not even have a feature gate");
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
diag.emit();
|
|
||||||
// If we should err, make sure we did.
|
// If we should err, make sure we did.
|
||||||
if must_err && self.has_errors().is_none() {
|
if must_err && self.has_errors().is_none() {
|
||||||
// We have skipped a feature gate, and not run into other errors... reject.
|
// We have skipped a feature gate, and not run into other errors... reject.
|
||||||
|
|
|
@ -749,3 +749,12 @@ struct SubdiagnosticEagerSuggestion {
|
||||||
#[subdiagnostic(eager)]
|
#[subdiagnostic(eager)]
|
||||||
sub: SubdiagnosticWithSuggestion,
|
sub: SubdiagnosticWithSuggestion,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// with a doc comment on the type..
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(compiletest::example, code = "E0123")]
|
||||||
|
struct WithDocComment {
|
||||||
|
/// ..and the field
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
}
|
||||||
|
|
|
@ -237,7 +237,6 @@ enum V {
|
||||||
var: String,
|
var: String,
|
||||||
},
|
},
|
||||||
B {
|
B {
|
||||||
//~^ ERROR subdiagnostic kind not specified
|
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
span: Span,
|
span: Span,
|
||||||
var: String,
|
var: String,
|
||||||
|
@ -641,3 +640,24 @@ struct BJ {
|
||||||
span: Span,
|
span: Span,
|
||||||
r#type: String,
|
r#type: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// with a doc comment on the type..
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[label(parser::add_paren)]
|
||||||
|
struct BK {
|
||||||
|
/// ..and the field
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// with a doc comment on the type..
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
enum BL {
|
||||||
|
/// ..and the variant..
|
||||||
|
#[label(parser::add_paren)]
|
||||||
|
Foo {
|
||||||
|
/// ..and the field
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -134,20 +134,14 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute
|
||||||
LL | #[label(code = "...")]
|
LL | #[label(code = "...")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: subdiagnostic kind not specified
|
|
||||||
--> $DIR/subdiagnostic-derive.rs:239:5
|
|
||||||
|
|
|
||||||
LL | B {
|
|
||||||
| ^
|
|
||||||
|
|
||||||
error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
|
error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
|
||||||
--> $DIR/subdiagnostic-derive.rs:251:5
|
--> $DIR/subdiagnostic-derive.rs:250:5
|
||||||
|
|
|
|
||||||
LL | #[primary_span]
|
LL | #[primary_span]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: label without `#[primary_span]` field
|
error: label without `#[primary_span]` field
|
||||||
--> $DIR/subdiagnostic-derive.rs:248:1
|
--> $DIR/subdiagnostic-derive.rs:247:1
|
||||||
|
|
|
|
||||||
LL | / #[label(parser::add_paren)]
|
LL | / #[label(parser::add_paren)]
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -159,13 +153,13 @@ LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
||||||
error: `#[applicability]` is only valid on suggestions
|
error: `#[applicability]` is only valid on suggestions
|
||||||
--> $DIR/subdiagnostic-derive.rs:261:5
|
--> $DIR/subdiagnostic-derive.rs:260:5
|
||||||
|
|
|
|
||||||
LL | #[applicability]
|
LL | #[applicability]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[bar]` is not a valid attribute
|
error: `#[bar]` is not a valid attribute
|
||||||
--> $DIR/subdiagnostic-derive.rs:271:5
|
--> $DIR/subdiagnostic-derive.rs:270:5
|
||||||
|
|
|
|
||||||
LL | #[bar]
|
LL | #[bar]
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
@ -173,13 +167,13 @@ LL | #[bar]
|
||||||
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
|
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
|
||||||
|
|
||||||
error: `#[bar = ...]` is not a valid attribute
|
error: `#[bar = ...]` is not a valid attribute
|
||||||
--> $DIR/subdiagnostic-derive.rs:282:5
|
--> $DIR/subdiagnostic-derive.rs:281:5
|
||||||
|
|
|
|
||||||
LL | #[bar = "..."]
|
LL | #[bar = "..."]
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[bar(...)]` is not a valid attribute
|
error: `#[bar(...)]` is not a valid attribute
|
||||||
--> $DIR/subdiagnostic-derive.rs:293:5
|
--> $DIR/subdiagnostic-derive.rs:292:5
|
||||||
|
|
|
|
||||||
LL | #[bar("...")]
|
LL | #[bar("...")]
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
@ -187,7 +181,7 @@ LL | #[bar("...")]
|
||||||
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
|
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
|
||||||
|
|
||||||
error: unexpected unsupported untagged union
|
error: unexpected unsupported untagged union
|
||||||
--> $DIR/subdiagnostic-derive.rs:309:1
|
--> $DIR/subdiagnostic-derive.rs:308:1
|
||||||
|
|
|
|
||||||
LL | / union AC {
|
LL | / union AC {
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -197,7 +191,7 @@ LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
||||||
error: `#[label(parser::add_paren)]` is not a valid attribute
|
error: `#[label(parser::add_paren)]` is not a valid attribute
|
||||||
--> $DIR/subdiagnostic-derive.rs:324:28
|
--> $DIR/subdiagnostic-derive.rs:323:28
|
||||||
|
|
|
|
||||||
LL | #[label(parser::add_paren, parser::add_paren)]
|
LL | #[label(parser::add_paren, parser::add_paren)]
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
@ -205,67 +199,67 @@ LL | #[label(parser::add_paren, parser::add_paren)]
|
||||||
= help: a diagnostic slug must be the first argument to the attribute
|
= help: a diagnostic slug must be the first argument to the attribute
|
||||||
|
|
||||||
error: specified multiple times
|
error: specified multiple times
|
||||||
--> $DIR/subdiagnostic-derive.rs:337:5
|
--> $DIR/subdiagnostic-derive.rs:336:5
|
||||||
|
|
|
|
||||||
LL | #[primary_span]
|
LL | #[primary_span]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: previously specified here
|
note: previously specified here
|
||||||
--> $DIR/subdiagnostic-derive.rs:334:5
|
--> $DIR/subdiagnostic-derive.rs:333:5
|
||||||
|
|
|
|
||||||
LL | #[primary_span]
|
LL | #[primary_span]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: subdiagnostic kind not specified
|
error: subdiagnostic kind not specified
|
||||||
--> $DIR/subdiagnostic-derive.rs:343:8
|
--> $DIR/subdiagnostic-derive.rs:342:8
|
||||||
|
|
|
|
||||||
LL | struct AG {
|
LL | struct AG {
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: specified multiple times
|
error: specified multiple times
|
||||||
--> $DIR/subdiagnostic-derive.rs:380:47
|
--> $DIR/subdiagnostic-derive.rs:379:47
|
||||||
|
|
|
|
||||||
LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
|
LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: previously specified here
|
note: previously specified here
|
||||||
--> $DIR/subdiagnostic-derive.rs:380:33
|
--> $DIR/subdiagnostic-derive.rs:379:33
|
||||||
|
|
|
|
||||||
LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
|
LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error: specified multiple times
|
error: specified multiple times
|
||||||
--> $DIR/subdiagnostic-derive.rs:398:5
|
--> $DIR/subdiagnostic-derive.rs:397:5
|
||||||
|
|
|
|
||||||
LL | #[applicability]
|
LL | #[applicability]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: previously specified here
|
note: previously specified here
|
||||||
--> $DIR/subdiagnostic-derive.rs:395:5
|
--> $DIR/subdiagnostic-derive.rs:394:5
|
||||||
|
|
|
|
||||||
LL | #[applicability]
|
LL | #[applicability]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
|
error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
|
||||||
--> $DIR/subdiagnostic-derive.rs:408:5
|
--> $DIR/subdiagnostic-derive.rs:407:5
|
||||||
|
|
|
|
||||||
LL | #[applicability]
|
LL | #[applicability]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: suggestion without `code = "..."`
|
error: suggestion without `code = "..."`
|
||||||
--> $DIR/subdiagnostic-derive.rs:421:1
|
--> $DIR/subdiagnostic-derive.rs:420:1
|
||||||
|
|
|
|
||||||
LL | #[suggestion(parser::add_paren)]
|
LL | #[suggestion(parser::add_paren)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: invalid applicability
|
error: invalid applicability
|
||||||
--> $DIR/subdiagnostic-derive.rs:431:46
|
--> $DIR/subdiagnostic-derive.rs:430:46
|
||||||
|
|
|
|
||||||
LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
|
LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: suggestion without `#[primary_span]` field
|
error: suggestion without `#[primary_span]` field
|
||||||
--> $DIR/subdiagnostic-derive.rs:449:1
|
--> $DIR/subdiagnostic-derive.rs:448:1
|
||||||
|
|
|
|
||||||
LL | / #[suggestion(parser::add_paren, code = "...")]
|
LL | / #[suggestion(parser::add_paren, code = "...")]
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -275,25 +269,25 @@ LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
||||||
error: unsupported type attribute for subdiagnostic enum
|
error: unsupported type attribute for subdiagnostic enum
|
||||||
--> $DIR/subdiagnostic-derive.rs:463:1
|
--> $DIR/subdiagnostic-derive.rs:462:1
|
||||||
|
|
|
|
||||||
LL | #[label]
|
LL | #[label]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: `var` doesn't refer to a field on this type
|
error: `var` doesn't refer to a field on this type
|
||||||
--> $DIR/subdiagnostic-derive.rs:483:39
|
--> $DIR/subdiagnostic-derive.rs:482:39
|
||||||
|
|
|
|
||||||
LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
|
LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: `var` doesn't refer to a field on this type
|
error: `var` doesn't refer to a field on this type
|
||||||
--> $DIR/subdiagnostic-derive.rs:502:43
|
--> $DIR/subdiagnostic-derive.rs:501:43
|
||||||
|
|
|
|
||||||
LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
|
LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: `#[suggestion_part]` is not a valid attribute
|
error: `#[suggestion_part]` is not a valid attribute
|
||||||
--> $DIR/subdiagnostic-derive.rs:525:5
|
--> $DIR/subdiagnostic-derive.rs:524:5
|
||||||
|
|
|
|
||||||
LL | #[suggestion_part]
|
LL | #[suggestion_part]
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -301,7 +295,7 @@ LL | #[suggestion_part]
|
||||||
= help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead
|
= help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead
|
||||||
|
|
||||||
error: `#[suggestion_part(...)]` is not a valid attribute
|
error: `#[suggestion_part(...)]` is not a valid attribute
|
||||||
--> $DIR/subdiagnostic-derive.rs:528:5
|
--> $DIR/subdiagnostic-derive.rs:527:5
|
||||||
|
|
|
|
||||||
LL | #[suggestion_part(code = "...")]
|
LL | #[suggestion_part(code = "...")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -309,7 +303,7 @@ LL | #[suggestion_part(code = "...")]
|
||||||
= help: `#[suggestion_part(...)]` is only valid in multipart suggestions
|
= help: `#[suggestion_part(...)]` is only valid in multipart suggestions
|
||||||
|
|
||||||
error: suggestion without `#[primary_span]` field
|
error: suggestion without `#[primary_span]` field
|
||||||
--> $DIR/subdiagnostic-derive.rs:522:1
|
--> $DIR/subdiagnostic-derive.rs:521:1
|
||||||
|
|
|
|
||||||
LL | / #[suggestion(parser::add_paren, code = "...")]
|
LL | / #[suggestion(parser::add_paren, code = "...")]
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -321,7 +315,7 @@ LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
||||||
error: `#[multipart_suggestion(code = ...)]` is not a valid attribute
|
error: `#[multipart_suggestion(code = ...)]` is not a valid attribute
|
||||||
--> $DIR/subdiagnostic-derive.rs:537:43
|
--> $DIR/subdiagnostic-derive.rs:536:43
|
||||||
|
|
|
|
||||||
LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
|
LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -329,7 +323,7 @@ LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "ma
|
||||||
= help: only `applicability` is a valid nested attributes
|
= help: only `applicability` is a valid nested attributes
|
||||||
|
|
||||||
error: multipart suggestion without any `#[suggestion_part(...)]` fields
|
error: multipart suggestion without any `#[suggestion_part(...)]` fields
|
||||||
--> $DIR/subdiagnostic-derive.rs:537:1
|
--> $DIR/subdiagnostic-derive.rs:536:1
|
||||||
|
|
|
|
||||||
LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
|
LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -340,19 +334,19 @@ LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
||||||
error: `#[suggestion_part(...)]` attribute without `code = "..."`
|
error: `#[suggestion_part(...)]` attribute without `code = "..."`
|
||||||
--> $DIR/subdiagnostic-derive.rs:547:5
|
--> $DIR/subdiagnostic-derive.rs:546:5
|
||||||
|
|
|
|
||||||
LL | #[suggestion_part]
|
LL | #[suggestion_part]
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[suggestion_part(...)]` attribute without `code = "..."`
|
error: `#[suggestion_part(...)]` attribute without `code = "..."`
|
||||||
--> $DIR/subdiagnostic-derive.rs:555:5
|
--> $DIR/subdiagnostic-derive.rs:554:5
|
||||||
|
|
|
|
||||||
LL | #[suggestion_part()]
|
LL | #[suggestion_part()]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[primary_span]` is not a valid attribute
|
error: `#[primary_span]` is not a valid attribute
|
||||||
--> $DIR/subdiagnostic-derive.rs:564:5
|
--> $DIR/subdiagnostic-derive.rs:563:5
|
||||||
|
|
|
|
||||||
LL | #[primary_span]
|
LL | #[primary_span]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
@ -360,7 +354,7 @@ LL | #[primary_span]
|
||||||
= help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]`
|
= help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]`
|
||||||
|
|
||||||
error: multipart suggestion without any `#[suggestion_part(...)]` fields
|
error: multipart suggestion without any `#[suggestion_part(...)]` fields
|
||||||
--> $DIR/subdiagnostic-derive.rs:561:1
|
--> $DIR/subdiagnostic-derive.rs:560:1
|
||||||
|
|
|
|
||||||
LL | / #[multipart_suggestion(parser::add_paren)]
|
LL | / #[multipart_suggestion(parser::add_paren)]
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -372,19 +366,19 @@ LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
||||||
error: `#[suggestion_part(...)]` attribute without `code = "..."`
|
error: `#[suggestion_part(...)]` attribute without `code = "..."`
|
||||||
--> $DIR/subdiagnostic-derive.rs:572:5
|
--> $DIR/subdiagnostic-derive.rs:571:5
|
||||||
|
|
|
|
||||||
LL | #[suggestion_part]
|
LL | #[suggestion_part]
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[suggestion_part(...)]` attribute without `code = "..."`
|
error: `#[suggestion_part(...)]` attribute without `code = "..."`
|
||||||
--> $DIR/subdiagnostic-derive.rs:575:5
|
--> $DIR/subdiagnostic-derive.rs:574:5
|
||||||
|
|
|
|
||||||
LL | #[suggestion_part()]
|
LL | #[suggestion_part()]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[suggestion_part(foo = ...)]` is not a valid attribute
|
error: `#[suggestion_part(foo = ...)]` is not a valid attribute
|
||||||
--> $DIR/subdiagnostic-derive.rs:578:23
|
--> $DIR/subdiagnostic-derive.rs:577:23
|
||||||
|
|
|
|
||||||
LL | #[suggestion_part(foo = "bar")]
|
LL | #[suggestion_part(foo = "bar")]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
@ -392,31 +386,31 @@ LL | #[suggestion_part(foo = "bar")]
|
||||||
= help: `code` is the only valid nested attribute
|
= help: `code` is the only valid nested attribute
|
||||||
|
|
||||||
error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
|
error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
|
||||||
--> $DIR/subdiagnostic-derive.rs:581:5
|
--> $DIR/subdiagnostic-derive.rs:580:5
|
||||||
|
|
|
|
||||||
LL | #[suggestion_part(code = "...")]
|
LL | #[suggestion_part(code = "...")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
|
error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
|
||||||
--> $DIR/subdiagnostic-derive.rs:584:5
|
--> $DIR/subdiagnostic-derive.rs:583:5
|
||||||
|
|
|
|
||||||
LL | #[suggestion_part()]
|
LL | #[suggestion_part()]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: specified multiple times
|
error: specified multiple times
|
||||||
--> $DIR/subdiagnostic-derive.rs:592:37
|
--> $DIR/subdiagnostic-derive.rs:591:37
|
||||||
|
|
|
|
||||||
LL | #[suggestion_part(code = "...", code = ",,,")]
|
LL | #[suggestion_part(code = "...", code = ",,,")]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: previously specified here
|
note: previously specified here
|
||||||
--> $DIR/subdiagnostic-derive.rs:592:23
|
--> $DIR/subdiagnostic-derive.rs:591:23
|
||||||
|
|
|
|
||||||
LL | #[suggestion_part(code = "...", code = ",,,")]
|
LL | #[suggestion_part(code = "...", code = ",,,")]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."`
|
error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."`
|
||||||
--> $DIR/subdiagnostic-derive.rs:621:5
|
--> $DIR/subdiagnostic-derive.rs:620:5
|
||||||
|
|
|
|
||||||
LL | #[applicability]
|
LL | #[applicability]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
@ -458,19 +452,19 @@ LL | #[bar("...")]
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: cannot find attribute `bar` in this scope
|
error: cannot find attribute `bar` in this scope
|
||||||
--> $DIR/subdiagnostic-derive.rs:271:7
|
--> $DIR/subdiagnostic-derive.rs:270:7
|
||||||
|
|
|
|
||||||
LL | #[bar]
|
LL | #[bar]
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: cannot find attribute `bar` in this scope
|
error: cannot find attribute `bar` in this scope
|
||||||
--> $DIR/subdiagnostic-derive.rs:282:7
|
--> $DIR/subdiagnostic-derive.rs:281:7
|
||||||
|
|
|
|
||||||
LL | #[bar = "..."]
|
LL | #[bar = "..."]
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: cannot find attribute `bar` in this scope
|
error: cannot find attribute `bar` in this scope
|
||||||
--> $DIR/subdiagnostic-derive.rs:293:7
|
--> $DIR/subdiagnostic-derive.rs:292:7
|
||||||
|
|
|
|
||||||
LL | #[bar("...")]
|
LL | #[bar("...")]
|
||||||
| ^^^
|
| ^^^
|
||||||
|
@ -481,6 +475,6 @@ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent`
|
||||||
LL | #[label(slug)]
|
LL | #[label(slug)]
|
||||||
| ^^^^ not found in `rustc_errors::fluent`
|
| ^^^^ not found in `rustc_errors::fluent`
|
||||||
|
|
||||||
error: aborting due to 68 previous errors
|
error: aborting due to 67 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0425`.
|
For more information about this error, try `rustc --explain E0425`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue