未验证 提交 e11511df 编写于 作者: D Dylan DPC 提交者: GitHub

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
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};
......@@ -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]
......@@ -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)]
......
......@@ -14,6 +14,7 @@
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,
......@@ -1805,15 +1806,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),
}
......@@ -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]
......
......@@ -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
......
......@@ -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
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;
......@@ -155,6 +155,21 @@ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
}
}
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;
......
......@@ -459,47 +459,34 @@ fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, _: F)
}
}
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)]
......@@ -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>,
}
......@@ -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};
......@@ -56,7 +58,7 @@ pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorGuaran
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.
......@@ -90,10 +92,12 @@ pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorGuaran
// 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 {
......@@ -105,8 +109,10 @@ pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorGuaran
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)
......
......@@ -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 {
......
......@@ -5,7 +5,7 @@
DiagnosticDeriveError,
};
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,
HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
};
......@@ -152,8 +152,12 @@ pub fn body<'s>(&mut self, variant: &VariantInfo<'s>) -> TokenStream {
fn parse_subdiag_attribute(
&self,
attr: &Attribute,
) -> Result<(SubdiagnosticKind, Path), DiagnosticDeriveError> {
let (subdiag, slug) = SubdiagnosticKind::from_attr(attr, self)?;
) -> Result<Option<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
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 {
let meta = attr.parse_meta()?;
......@@ -170,7 +174,7 @@ fn parse_subdiag_attribute(
SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
});
Ok((subdiag, slug))
Ok(Some((subdiag, slug)))
}
/// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct
......@@ -182,6 +186,11 @@ fn generate_structure_code_for_attr(
) -> Result<TokenStream, DiagnosticDeriveError> {
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 = name.as_str();
let meta = attr.parse_meta()?;
......@@ -250,7 +259,11 @@ fn generate_structure_code_for_attr(
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);
match subdiag {
SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
......@@ -291,6 +304,11 @@ fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> Token
.attrs
.iter()
.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 needs_clone =
name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_));
......@@ -397,8 +415,11 @@ fn generate_inner_field_code(
_ => (),
}
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);
match subdiag {
SubdiagnosticKind::Label => {
......
......@@ -5,9 +5,9 @@
DiagnosticDeriveError,
};
use crate::diagnostics::utils::{
build_field_mapping, new_code_ident, report_error_if_not_applied_to_applicability,
report_error_if_not_applied_to_span, FieldInfo, FieldInnerTy, FieldMap, HasFieldMap, SetOnce,
SpannedOption, SubdiagnosticKind,
build_field_mapping, is_doc_comment, new_code_ident,
report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, FieldInfo,
FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
};
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
......@@ -41,8 +41,14 @@ pub(crate) fn into_tokens<'a>(self, mut structure: Structure<'a>) -> TokenStream
}
}
if matches!(ast.data, syn::Data::Enum(..)) {
let is_enum = matches!(ast.data, syn::Data::Enum(..));
if is_enum {
for attr in &ast.attrs {
// Always allow documentation comments.
if is_doc_comment(attr) {
continue;
}
span_err(
attr.span().unwrap(),
"unsupported type attribute for subdiagnostic enum",
......@@ -62,6 +68,7 @@ pub(crate) fn into_tokens<'a>(self, mut structure: Structure<'a>) -> TokenStream
span_field: None,
applicability: None,
has_suggestion_parts: false,
is_enum,
};
builder.into_tokens().unwrap_or_else(|v| v.to_compile_error())
});
......@@ -79,7 +86,7 @@ pub(crate) fn into_tokens<'a>(self, mut structure: Structure<'a>) -> TokenStream
gen impl rustc_errors::AddToDiagnostic for @Self {
fn add_to_diagnostic_with<__F>(self, #diag: &mut rustc_errors::Diagnostic, #f: __F)
where
__F: Fn(
__F: core::ops::Fn(
&mut rustc_errors::Diagnostic,
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
/// during finalization if still `false`.
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> {
......@@ -173,7 +183,11 @@ fn identify_kind(&mut self) -> Result<Vec<(SubdiagnosticKind, Path)>, Diagnostic
let mut kind_slugs = vec![];
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 name = attr.path.segments.last().unwrap().ident.to_string();
......@@ -227,6 +241,11 @@ fn generate_field_attr_code(
ast.attrs
.iter()
.map(|attr| {
// Always allow documentation comments.
if is_doc_comment(attr) {
return quote! {};
}
let info = FieldInfo {
binding,
ty: inner_ty.inner_type().unwrap_or(&ast.ty),
......@@ -290,6 +309,8 @@ fn generate_field_code_inner_path(
report_error_if_not_applied_to_span(attr, &info)?;
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);
}
......@@ -443,10 +464,16 @@ fn generate_field_code_inner_list(
pub fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
let kind_slugs = self.identify_kind()?;
if kind_slugs.is_empty() {
throw_span_err!(
self.variant.ast().ident.span().unwrap(),
"subdiagnostic kind not specified"
);
if self.is_enum {
// It's okay for a variant to not be a subdiagnostic at all..
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();
......
......@@ -477,7 +477,12 @@ impl SubdiagnosticKind {
pub(super) fn from_attr(
attr: &Attribute,
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 name = attr.path.segments.last().unwrap().ident.to_string();
......@@ -526,7 +531,9 @@ pub(super) fn from_attr(
| SubdiagnosticKind::Note
| SubdiagnosticKind::Help
| SubdiagnosticKind::Warn
| SubdiagnosticKind::MultipartSuggestion { .. } => return Ok((kind, None)),
| SubdiagnosticKind::MultipartSuggestion { .. } => {
return Ok(Some((kind, None)));
}
SubdiagnosticKind::Suggestion { .. } => {
throw_span_err!(span, "suggestion without `code = \"...\"`")
}
......@@ -626,7 +633,7 @@ pub(super) fn from_attr(
| SubdiagnosticKind::MultipartSuggestion { .. } => {}
}
Ok((kind, slug))
Ok(Some((kind, slug)))
}
}
......@@ -654,3 +661,7 @@ fn span(&self) -> Option<proc_macro2::Span> {
pub(super) fn should_generate_set_arg(field: &Field) -> bool {
field.attrs.is_empty()
}
pub(super) fn is_doc_comment(attr: &Attribute) -> bool {
attr.path.segments.last().unwrap().ident.to_string() == "doc"
}
use std::num::NonZeroU32;
use crate::cgu_reuse_tracker::CguReuse;
use rustc_errors::{
fluent, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, MultiSpan,
};
use rustc_errors::MultiSpan;
use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
......@@ -148,24 +146,15 @@ pub struct CrateNameEmpty {
pub span: Option<Span>,
}
#[derive(Diagnostic)]
#[diag(session::invalid_character_in_create_name)]
pub struct InvalidCharacterInCrateName<'a> {
#[primary_span]
pub span: Option<Span>,
pub character: char,
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)]
#[multipart_suggestion(session::expr_parentheses_needed, applicability = "machine-applicable")]
pub struct ExprParenthesesNeeded {
......@@ -180,3 +169,25 @@ pub fn surrounding(s: Span) -> Self {
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::errors::{
CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, LinkerPluginToWindowsNotSupported,
NotCircumventFeature, ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist,
SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported,
SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, SkippingConstChecks,
SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget,
TargetRequiresUnwindTables, UnstableVirtualFunctionElimination, UnsupportedDwarfVersion,
TargetRequiresUnwindTables, UnleashedFeatureHelp, UnstableVirtualFunctionElimination,
UnsupportedDwarfVersion,
};
use crate::parse::{add_feature_diagnostics, ParseSess};
use crate::search_paths::{PathKind, SearchPath};
......@@ -232,21 +233,19 @@ fn check_miri_unleashed_features(&self) {
if !unleashed_features.is_empty() {
let mut must_err = false;
// Create a diagnostic pointing at where things got unleashed.
// FIXME(#100717): needs eager translation/lists
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
let mut diag = self.struct_warn("skipping const checks");
for &(span, feature_gate) in unleashed_features.iter() {
// FIXME: `span_label` doesn't do anything, so we use "help" as a hack.
if let Some(gate) = feature_gate {
diag.span_help(span, &format!("skipping check for `{gate}` feature"));
// The unleash flag must *not* be used to just "hack around" feature gates.
must_err = true;
} else {
diag.span_help(span, "skipping check that does not even have a feature gate");
}
}
diag.emit();
self.emit_warning(SkippingConstChecks {
unleashed_features: unleashed_features
.iter()
.map(|(span, gate)| {
gate.map(|gate| {
must_err = true;
UnleashedFeatureHelp::Named { span: *span, gate }
})
.unwrap_or(UnleashedFeatureHelp::Unnamed { span: *span })
})
.collect(),
});
// If we should err, make sure we did.
if must_err && self.has_errors().is_none() {
// We have skipped a feature gate, and not run into other errors... reject.
......
......@@ -749,3 +749,12 @@ struct SubdiagnosticEagerSuggestion {
#[subdiagnostic(eager)]
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,
},
B {
//~^ ERROR subdiagnostic kind not specified
#[primary_span]
span: Span,
var: String,
......@@ -641,3 +640,24 @@ struct BJ {
span: Span,
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 = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^
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`
--> $DIR/subdiagnostic-derive.rs:251:5
--> $DIR/subdiagnostic-derive.rs:250:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
error: label without `#[primary_span]` field
--> $DIR/subdiagnostic-derive.rs:248:1
--> $DIR/subdiagnostic-derive.rs:247:1
|
LL | / #[label(parser::add_paren)]
LL | |
......@@ -159,13 +153,13 @@ LL | | }
| |_^
error: `#[applicability]` is only valid on suggestions
--> $DIR/subdiagnostic-derive.rs:261:5
--> $DIR/subdiagnostic-derive.rs:260:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: `#[bar]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:271:5
--> $DIR/subdiagnostic-derive.rs:270:5
|
LL | #[bar]
| ^^^^^^
......@@ -173,13 +167,13 @@ LL | #[bar]
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
error: `#[bar = ...]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:282:5
--> $DIR/subdiagnostic-derive.rs:281:5
|
LL | #[bar = "..."]
| ^^^^^^^^^^^^^^
error: `#[bar(...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:293:5
--> $DIR/subdiagnostic-derive.rs:292:5
|
LL | #[bar("...")]
| ^^^^^^^^^^^^^
......@@ -187,7 +181,7 @@ LL | #[bar("...")]
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
error: unexpected unsupported untagged union
--> $DIR/subdiagnostic-derive.rs:309:1
--> $DIR/subdiagnostic-derive.rs:308:1
|
LL | / union AC {
LL | |
......@@ -197,7 +191,7 @@ LL | | }
| |_^
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)]
| ^^^^^^^^^^^^^^^^^
......@@ -205,67 +199,67 @@ LL | #[label(parser::add_paren, parser::add_paren)]
= help: a diagnostic slug must be the first argument to the attribute
error: specified multiple times
--> $DIR/subdiagnostic-derive.rs:337:5
--> $DIR/subdiagnostic-derive.rs:336:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/subdiagnostic-derive.rs:334:5
--> $DIR/subdiagnostic-derive.rs:333:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
error: subdiagnostic kind not specified
--> $DIR/subdiagnostic-derive.rs:343:8
--> $DIR/subdiagnostic-derive.rs:342:8
|
LL | struct AG {
| ^^
error: specified multiple times
--> $DIR/subdiagnostic-derive.rs:380:47
--> $DIR/subdiagnostic-derive.rs:379:47
|
LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
| ^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/subdiagnostic-derive.rs:380:33
--> $DIR/subdiagnostic-derive.rs:379:33
|
LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
| ^^^^^^^^^^^^
error: specified multiple times
--> $DIR/subdiagnostic-derive.rs:398:5
--> $DIR/subdiagnostic-derive.rs:397:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/subdiagnostic-derive.rs:395:5
--> $DIR/subdiagnostic-derive.rs:394:5
|
LL | #[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]
| ^^^^^^^^^^^^^^^^
error: suggestion without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:421:1
--> $DIR/subdiagnostic-derive.rs:420:1
|
LL | #[suggestion(parser::add_paren)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: invalid applicability
--> $DIR/subdiagnostic-derive.rs:431:46
--> $DIR/subdiagnostic-derive.rs:430:46
|
LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
| ^^^^^^^^^^^^^^^^^^^^^
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 | |
......@@ -275,25 +269,25 @@ LL | | }
| |_^
error: unsupported type attribute for subdiagnostic enum
--> $DIR/subdiagnostic-derive.rs:463:1
--> $DIR/subdiagnostic-derive.rs:462:1
|
LL | #[label]
| ^^^^^^^^
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")]
| ^^^^^^^
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")]
| ^^^^^^^
error: `#[suggestion_part]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:525:5
--> $DIR/subdiagnostic-derive.rs:524:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
......@@ -301,7 +295,7 @@ LL | #[suggestion_part]
= help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead
error: `#[suggestion_part(...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:528:5
--> $DIR/subdiagnostic-derive.rs:527:5
|
LL | #[suggestion_part(code = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
......@@ -309,7 +303,7 @@ LL | #[suggestion_part(code = "...")]
= help: `#[suggestion_part(...)]` is only valid in multipart suggestions
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 | |
......@@ -321,7 +315,7 @@ LL | | }
| |_^
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")]
| ^^^^^^^^^^^^
......@@ -329,7 +323,7 @@ LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "ma
= help: only `applicability` is a valid nested attributes
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 | |
......@@ -340,19 +334,19 @@ LL | | }
| |_^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:547:5
--> $DIR/subdiagnostic-derive.rs:546:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:555:5
--> $DIR/subdiagnostic-derive.rs:554:5
|
LL | #[suggestion_part()]
| ^^^^^^^^^^^^^^^^^^^^
error: `#[primary_span]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:564:5
--> $DIR/subdiagnostic-derive.rs:563:5
|
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]`
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 | |
......@@ -372,19 +366,19 @@ LL | | }
| |_^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:572:5
--> $DIR/subdiagnostic-derive.rs:571:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:575:5
--> $DIR/subdiagnostic-derive.rs:574:5
|
LL | #[suggestion_part()]
| ^^^^^^^^^^^^^^^^^^^^
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")]
| ^^^^^^^^^^^
......@@ -392,31 +386,31 @@ LL | #[suggestion_part(foo = "bar")]
= help: `code` is the only valid nested attribute
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 = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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()]
| ^^^^^^^^^^^^^^^^^^^^
error: specified multiple times
--> $DIR/subdiagnostic-derive.rs:592:37
--> $DIR/subdiagnostic-derive.rs:591:37
|
LL | #[suggestion_part(code = "...", code = ",,,")]
| ^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/subdiagnostic-derive.rs:592:23
--> $DIR/subdiagnostic-derive.rs:591:23
|
LL | #[suggestion_part(code = "...", code = ",,,")]
| ^^^^^^^^^^^^
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]
| ^^^^^^^^^^^^^^^^
......@@ -458,19 +452,19 @@ LL | #[bar("...")]
| ^^^
error: cannot find attribute `bar` in this scope
--> $DIR/subdiagnostic-derive.rs:271:7
--> $DIR/subdiagnostic-derive.rs:270:7
|
LL | #[bar]
| ^^^
error: cannot find attribute `bar` in this scope
--> $DIR/subdiagnostic-derive.rs:282:7
--> $DIR/subdiagnostic-derive.rs:281:7
|
LL | #[bar = "..."]
| ^^^
error: cannot find attribute `bar` in this scope
--> $DIR/subdiagnostic-derive.rs:293:7
--> $DIR/subdiagnostic-derive.rs:292:7
|
LL | #[bar("...")]
| ^^^
......@@ -481,6 +475,6 @@ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent`
LL | #[label(slug)]
| ^^^^ 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`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册