Rollup merge of #152250 - JonathanBrouwer:convert_finish, r=jdonszelmann

Remove support for slugs in diagnostic messages

This PR contains 5 commits, and is best reviewed commit-by-commit:
- https://github.com/rust-lang/rust/pull/152250/changes/ea8733133cacf4496a2766b3d002492cc29ea7bf Removes support from slugs from `rustc_errors`
- https://github.com/rust-lang/rust/pull/152250/changes/62dd37131f6f43d0dab3e26cf125cd841a08e003 Removes support from slugs from `rustc_macros` (which declares `derive(Diagnostic)`)
- https://github.com/rust-lang/rust/pull/152250/changes/2289e6cfb7e379eba777a10df0a6f474f9450b02 Adjuist the `ui-fulldeps` testsuite to match the changes in `rustc_macros`
- https://github.com/rust-lang/rust/pull/152250/changes/0db0acd6993cbdf84384b00773d7509df6bc20fb Removes support for the fallback bundle (which previously contained all messages, but is now empty) from `rustc_driver_impl` and `rustc_session`
- https://github.com/rust-lang/rust/pull/152250/changes/81d42146040c4a6b3d252e3dc3ac32e563694796 Removes an integration test that tested the translation system using fluent
This commit is contained in:
Jonathan Brouwer 2026-02-08 19:15:25 +01:00 committed by GitHub
commit 7fbde8b9c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 217 additions and 660 deletions

View file

@ -108,11 +108,9 @@ use crate::session_diagnostics::{
};
pub fn default_translator() -> Translator {
Translator::with_fallback_bundle(DEFAULT_LOCALE_RESOURCES.to_vec(), false)
Translator::new()
}
pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[];
/// Exit status code used for successful compilation and help output.
pub const EXIT_SUCCESS: i32 = 0;
@ -219,7 +217,6 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
output_dir: odir,
ice_file,
file_loader: None,
locale_resources: DEFAULT_LOCALE_RESOURCES.to_vec(),
lint_caps: Default::default(),
psess_created: None,
hash_untracked_state: None,
@ -1528,7 +1525,7 @@ fn report_ice(
extra_info: fn(&DiagCtxt),
using_internal_features: &AtomicBool,
) {
let translator = default_translator();
let translator = Translator::new();
let emitter =
Box::new(rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter::new(
stderr_destination(rustc_errors::ColorConfig::Auto),

View file

@ -230,9 +230,6 @@ pub fn fallback_fluent_bundle(
})))
}
/// Identifier for the Fluent message/attribute corresponding to a diagnostic message.
type FluentId = Cow<'static, str>;
/// Abstraction over a message in a subdiagnostic (i.e. label, note, help, etc) to support both
/// translatable and non-translatable diagnostic messages.
///
@ -244,18 +241,9 @@ type FluentId = Cow<'static, str>;
pub enum SubdiagMessage {
/// Non-translatable diagnostic message.
Str(Cow<'static, str>),
/// Identifier of a Fluent message. Instances of this variant are generated by the
/// `Subdiagnostic` derive.
FluentIdentifier(FluentId),
/// An inline Fluent message. Instances of this variant are generated by the
/// `Subdiagnostic` derive.
Inline(Cow<'static, str>),
/// Attribute of a Fluent message. Needs to be combined with a Fluent identifier to produce an
/// actual translated message. Instances of this variant are generated by the `fluent_messages`
/// macro.
///
/// <https://projectfluent.org/fluent/guide/attributes.html>
FluentAttr(FluentId),
}
impl From<String> for SubdiagMessage {
@ -288,12 +276,6 @@ pub enum DiagMessage {
/// are translated when they are added to the parent diagnostic. This is one of the ways
/// this variant of `DiagMessage` is produced.
Str(Cow<'static, str>),
/// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic
/// message. Yet to be translated.
///
/// <https://projectfluent.org/fluent/guide/hello.html>
/// <https://projectfluent.org/fluent/guide/attributes.html>
FluentIdentifier(FluentId, Option<FluentId>),
/// An inline Fluent message, containing the to be translated diagnostic message.
Inline(Cow<'static, str>),
}
@ -305,27 +287,16 @@ impl DiagMessage {
/// - If the `SubdiagMessage` is non-translatable then return the message as a `DiagMessage`.
/// - If `self` is non-translatable then return `self`'s message.
pub fn with_subdiagnostic_message(&self, sub: SubdiagMessage) -> Self {
let attr = match sub {
SubdiagMessage::Str(s) => return DiagMessage::Str(s),
SubdiagMessage::FluentIdentifier(id) => {
return DiagMessage::FluentIdentifier(id, None);
}
SubdiagMessage::Inline(s) => return DiagMessage::Inline(s),
SubdiagMessage::FluentAttr(attr) => attr,
};
match self {
DiagMessage::FluentIdentifier(id, _) => {
DiagMessage::FluentIdentifier(id.clone(), Some(attr))
}
_ => panic!("Tried to add a subdiagnostic to a message without a fluent identifier"),
match sub {
SubdiagMessage::Str(s) => DiagMessage::Str(s),
SubdiagMessage::Inline(s) => DiagMessage::Inline(s),
}
}
pub fn as_str(&self) -> Option<&str> {
match self {
DiagMessage::Str(s) => Some(s),
DiagMessage::FluentIdentifier(_, _) | DiagMessage::Inline(_) => None,
DiagMessage::Inline(_) => None,
}
}
}
@ -355,10 +326,6 @@ impl From<DiagMessage> for SubdiagMessage {
fn from(val: DiagMessage) -> Self {
match val {
DiagMessage::Str(s) => SubdiagMessage::Str(s),
DiagMessage::FluentIdentifier(id, None) => SubdiagMessage::FluentIdentifier(id),
// There isn't really a sensible behaviour for this because it loses information but
// this is the most sensible of the behaviours.
DiagMessage::FluentIdentifier(_, Some(attr)) => SubdiagMessage::FluentAttr(attr),
DiagMessage::Inline(s) => SubdiagMessage::Inline(s),
}
}

View file

@ -45,7 +45,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
rustc_span::create_default_session_globals_then(|| {
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
sm.new_source_file(filename(&sm, "test.rs"), code.to_owned());
let translator = Translator::with_fallback_bundle(vec![], false);
let translator = Translator::new();
let output = Arc::new(Mutex::new(Vec::new()));
let je = JsonEmitter::new(

View file

@ -83,8 +83,6 @@ pub mod error;
pub mod json;
mod lock;
pub mod markdown;
#[cfg(test)]
mod tests;
pub mod timings;
pub mod translation;

View file

@ -1,182 +0,0 @@
use std::sync::{Arc, LazyLock};
use rustc_data_structures::sync::IntoDynSyncSend;
use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError};
use rustc_error_messages::{DiagMessage, langid};
use crate::FluentBundle;
use crate::error::{TranslateError, TranslateErrorKind};
use crate::fluent_bundle::*;
use crate::translation::Translator;
fn make_translator(ftl: &'static str) -> Translator {
let resource = FluentResource::try_new(ftl.into()).expect("Failed to parse an FTL string.");
let langid_en = langid!("en-US");
let mut bundle: FluentBundle =
IntoDynSyncSend(crate::fluent_bundle::bundle::FluentBundle::new_concurrent(vec![
langid_en,
]));
bundle.add_resource(resource).expect("Failed to add FTL resources to the bundle.");
Translator {
fluent_bundle: None,
fallback_fluent_bundle: Arc::new(LazyLock::new(Box::new(|| bundle))),
}
}
#[test]
fn wellformed_fluent() {
let translator = make_translator("mir_build_borrow_of_moved_value = borrow of moved value
.label = value moved into `{$name}` here
.occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait
.value_borrowed_label = value borrowed here after move
.suggestion = borrow this binding in the pattern to avoid moving the value");
let mut args = FluentArgs::new();
args.set("name", "Foo");
args.set("ty", "std::string::String");
{
let message = DiagMessage::FluentIdentifier(
"mir_build_borrow_of_moved_value".into(),
Some("suggestion".into()),
);
assert_eq!(
translator.translate_message(&message, &args).unwrap(),
"borrow this binding in the pattern to avoid moving the value"
);
}
{
let message = DiagMessage::FluentIdentifier(
"mir_build_borrow_of_moved_value".into(),
Some("value_borrowed_label".into()),
);
assert_eq!(
translator.translate_message(&message, &args).unwrap(),
"value borrowed here after move"
);
}
{
let message = DiagMessage::FluentIdentifier(
"mir_build_borrow_of_moved_value".into(),
Some("occurs_because_label".into()),
);
assert_eq!(
translator.translate_message(&message, &args).unwrap(),
"move occurs because `\u{2068}Foo\u{2069}` has type `\u{2068}std::string::String\u{2069}` which does not implement the `Copy` trait"
);
{
let message = DiagMessage::FluentIdentifier(
"mir_build_borrow_of_moved_value".into(),
Some("label".into()),
);
assert_eq!(
translator.translate_message(&message, &args).unwrap(),
"value moved into `\u{2068}Foo\u{2069}` here"
);
}
}
}
#[test]
fn misformed_fluent() {
let translator = make_translator("mir_build_borrow_of_moved_value = borrow of moved value
.label = value moved into `{name}` here
.occurs_because_label = move occurs because `{$oops}` has type `{$ty}` which does not implement the `Copy` trait
.suggestion = borrow this binding in the pattern to avoid moving the value");
let mut args = FluentArgs::new();
args.set("name", "Foo");
args.set("ty", "std::string::String");
{
let message = DiagMessage::FluentIdentifier(
"mir_build_borrow_of_moved_value".into(),
Some("value_borrowed_label".into()),
);
let err = translator.translate_message(&message, &args).unwrap_err();
assert!(
matches!(
&err,
TranslateError::Two {
primary: box TranslateError::One {
kind: TranslateErrorKind::PrimaryBundleMissing,
..
},
fallback: box TranslateError::One {
kind: TranslateErrorKind::AttributeMissing { attr: "value_borrowed_label" },
..
}
}
),
"{err:#?}"
);
assert_eq!(
format!("{err}"),
"failed while formatting fluent string `mir_build_borrow_of_moved_value`: \nthe attribute `value_borrowed_label` was missing\nhelp: add `.value_borrowed_label = <message>`\n"
);
}
{
let message = DiagMessage::FluentIdentifier(
"mir_build_borrow_of_moved_value".into(),
Some("label".into()),
);
let err = translator.translate_message(&message, &args).unwrap_err();
if let TranslateError::Two {
primary: box TranslateError::One { kind: TranslateErrorKind::PrimaryBundleMissing, .. },
fallback: box TranslateError::One { kind: TranslateErrorKind::Fluent { errs }, .. },
} = &err
&& let [
FluentError::ResolverError(ResolverError::Reference(
ReferenceKind::Message { id, .. } | ReferenceKind::Variable { id, .. },
)),
] = &**errs
&& id == "name"
{
} else {
panic!("{err:#?}")
};
assert_eq!(
format!("{err}"),
"failed while formatting fluent string `mir_build_borrow_of_moved_value`: \nargument `name` exists but was not referenced correctly\nhelp: try using `{$name}` instead\n"
);
}
{
let message = DiagMessage::FluentIdentifier(
"mir_build_borrow_of_moved_value".into(),
Some("occurs_because_label".into()),
);
let err = translator.translate_message(&message, &args).unwrap_err();
if let TranslateError::Two {
primary: box TranslateError::One { kind: TranslateErrorKind::PrimaryBundleMissing, .. },
fallback: box TranslateError::One { kind: TranslateErrorKind::Fluent { errs }, .. },
} = &err
&& let [
FluentError::ResolverError(ResolverError::Reference(
ReferenceKind::Message { id, .. } | ReferenceKind::Variable { id, .. },
)),
] = &**errs
&& id == "oops"
{
} else {
panic!("{err:#?}")
};
assert_eq!(
format!("{err}"),
"failed while formatting fluent string `mir_build_borrow_of_moved_value`: \nthe fluent string has an argument `oops` that was not found.\nhelp: the arguments `name` and `ty` are available\n"
);
}
}

View file

@ -1,5 +1,4 @@
use std::borrow::Cow;
use std::env;
use std::error::Report;
use std::sync::Arc;
@ -7,7 +6,7 @@ pub use rustc_error_messages::{FluentArgs, LazyFallbackBundle};
use rustc_error_messages::{langid, register_functions};
use tracing::{debug, trace};
use crate::error::{TranslateError, TranslateErrorKind};
use crate::error::TranslateError;
use crate::fluent_bundle::FluentResource;
use crate::{DiagArg, DiagMessage, FluentBundle, Style, fluent_bundle};
@ -35,24 +34,11 @@ pub struct Translator {
/// Localized diagnostics for the locale requested by the user. If no language was requested by
/// the user then this will be `None` and `fallback_fluent_bundle` should be used.
pub fluent_bundle: Option<Arc<FluentBundle>>,
/// Return `FluentBundle` with localized diagnostics for the default locale of the compiler.
/// Used when the user has not requested a specific language or when a localized diagnostic is
/// unavailable for the requested locale.
pub fallback_fluent_bundle: LazyFallbackBundle,
}
impl Translator {
pub fn with_fallback_bundle(
resources: Vec<&'static str>,
with_directionality_markers: bool,
) -> Translator {
Translator {
fluent_bundle: None,
fallback_fluent_bundle: crate::fallback_fluent_bundle(
resources,
with_directionality_markers,
),
}
pub fn new() -> Translator {
Translator { fluent_bundle: None }
}
/// Convert `DiagMessage`s to a string, performing translation if necessary.
@ -76,11 +62,8 @@ impl Translator {
args: &'a FluentArgs<'_>,
) -> Result<Cow<'a, str>, TranslateError<'a>> {
trace!(?message, ?args);
let (identifier, attr) = match message {
DiagMessage::Str(msg) => {
return Ok(Cow::Borrowed(msg));
}
DiagMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
match message {
DiagMessage::Str(msg) => Ok(Cow::Borrowed(msg)),
// This translates an inline fluent diagnostic message
// It does this by creating a new `FluentBundle` with only one message,
// and then translating using this bundle.
@ -98,71 +81,11 @@ impl Translator {
let mut errs = vec![];
let translated = bundle.format_pattern(value, Some(args), &mut errs).to_string();
debug!(?translated, ?errs);
return if errs.is_empty() {
if errs.is_empty() {
Ok(Cow::Owned(translated))
} else {
Err(TranslateError::fluent(&Cow::Borrowed(GENERATED_MSG_ID), args, errs))
};
}
};
let translate_with_bundle =
|bundle: &'a FluentBundle| -> Result<Cow<'_, str>, TranslateError<'_>> {
let message = bundle
.get_message(identifier)
.ok_or(TranslateError::message(identifier, args))?;
let value = match attr {
Some(attr) => message
.get_attribute(attr)
.ok_or(TranslateError::attribute(identifier, args, attr))?
.value(),
None => message.value().ok_or(TranslateError::value(identifier, args))?,
};
debug!(?message, ?value);
let mut errs = vec![];
let translated = bundle.format_pattern(value, Some(args), &mut errs);
debug!(?translated, ?errs);
if errs.is_empty() {
Ok(translated)
} else {
Err(TranslateError::fluent(identifier, args, errs))
}
};
try {
match self.fluent_bundle.as_ref().map(|b| translate_with_bundle(b)) {
// The primary bundle was present and translation succeeded
Some(Ok(t)) => t,
// If `translate_with_bundle` returns `Err` with the primary bundle, this is likely
// just that the primary bundle doesn't contain the message being translated, so
// proceed to the fallback bundle.
Some(Err(
primary @ TranslateError::One {
kind: TranslateErrorKind::MessageMissing, ..
},
)) => translate_with_bundle(&self.fallback_fluent_bundle)
.map_err(|fallback| primary.and(fallback))?,
// Always yeet out for errors on debug (unless
// `RUSTC_TRANSLATION_NO_DEBUG_ASSERT` is set in the environment - this allows
// local runs of the test suites, of builds with debug assertions, to test the
// behaviour in a normal build).
Some(Err(primary))
if cfg!(debug_assertions)
&& env::var("RUSTC_TRANSLATION_NO_DEBUG_ASSERT").is_err() =>
{
do yeet primary
}
// ..otherwise, for end users, an error about this wouldn't be useful or actionable, so
// just hide it and try with the fallback bundle.
Some(Err(primary)) => translate_with_bundle(&self.fallback_fluent_bundle)
.map_err(|fallback| primary.and(fallback))?,
// The primary bundle is missing, proceed to the fallback bundle
None => translate_with_bundle(&self.fallback_fluent_bundle)
.map_err(|fallback| TranslateError::primary(identifier, args).and(fallback))?,
}
}
}

View file

@ -332,9 +332,6 @@ pub struct Config {
/// bjorn3 for "hooking rust-analyzer's VFS into rustc at some point for
/// running rustc without having to save". (See #102759.)
pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
/// The list of fluent resources, used for lints declared with
/// [`Diagnostic`](rustc_errors::Diagnostic) and [`LintDiagnostic`](rustc_errors::LintDiagnostic).
pub locale_resources: Vec<&'static str>,
pub lint_caps: FxHashMap<lint::LintId, lint::Level>,
@ -458,7 +455,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
temps_dir,
},
bundle,
config.locale_resources,
config.lint_caps,
target,
util::rustc_version_str().unwrap_or("unknown"),

View file

@ -72,7 +72,6 @@ where
sessopts,
io,
None,
vec![],
Default::default(),
target,
"",

View file

@ -1,7 +1,5 @@
#![deny(unused_must_use)]
use std::cell::RefCell;
use proc_macro2::TokenStream;
use quote::quote;
use synstructure::Structure;
@ -22,7 +20,6 @@ impl<'a> DiagnosticDerive<'a> {
pub(crate) fn into_tokens(self) -> TokenStream {
let DiagnosticDerive { mut structure } = self;
let kind = DiagnosticDeriveKind::Diagnostic;
let messages = RefCell::new(Vec::new());
let implementation = kind.each_variant(&mut structure, |mut builder, variant| {
let preamble = builder.preamble(variant);
let body = builder.body(variant);
@ -30,7 +27,6 @@ impl<'a> DiagnosticDerive<'a> {
let Some(message) = builder.primary_message() else {
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
};
messages.borrow_mut().push(message.clone());
let message = message.diag_message(Some(variant));
let init = quote! {
@ -52,9 +48,7 @@ impl<'a> DiagnosticDerive<'a> {
});
// A lifetime of `'a` causes conflicts, but `_sess` is fine.
// FIXME(edition_2024): Fix the `keyword_idents_2024` lint to not trigger here?
#[allow(keyword_idents_2024)]
let mut imp = structure.gen_impl(quote! {
structure.gen_impl(quote! {
gen impl<'_sess, G> rustc_errors::Diagnostic<'_sess, G> for @Self
where G: rustc_errors::EmissionGuarantee
{
@ -67,11 +61,7 @@ impl<'a> DiagnosticDerive<'a> {
#implementation
}
}
});
for test in messages.borrow().iter().map(|s| s.generate_test(&structure)) {
imp.extend(test);
}
imp
})
}
}
@ -88,7 +78,6 @@ impl<'a> LintDiagnosticDerive<'a> {
pub(crate) fn into_tokens(self) -> TokenStream {
let LintDiagnosticDerive { mut structure } = self;
let kind = DiagnosticDeriveKind::LintDiagnostic;
let messages = RefCell::new(Vec::new());
let implementation = kind.each_variant(&mut structure, |mut builder, variant| {
let preamble = builder.preamble(variant);
let body = builder.body(variant);
@ -96,7 +85,6 @@ impl<'a> LintDiagnosticDerive<'a> {
let Some(message) = builder.primary_message() else {
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
};
messages.borrow_mut().push(message.clone());
let message = message.diag_message(Some(variant));
let primary_message = quote! {
diag.primary_message(#message);
@ -112,9 +100,7 @@ impl<'a> LintDiagnosticDerive<'a> {
}
});
// FIXME(edition_2024): Fix the `keyword_idents_2024` lint to not trigger here?
#[allow(keyword_idents_2024)]
let mut imp = structure.gen_impl(quote! {
structure.gen_impl(quote! {
gen impl<'__a> rustc_errors::LintDiagnostic<'__a, ()> for @Self {
#[track_caller]
fn decorate_lint<'__b>(
@ -124,11 +110,6 @@ impl<'a> LintDiagnosticDerive<'a> {
#implementation;
}
}
});
for test in messages.borrow().iter().map(|s| s.generate_test(&structure)) {
imp.extend(test);
}
imp
})
}
}

View file

@ -4,7 +4,7 @@ use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote, quote_spanned};
use syn::parse::ParseStream;
use syn::spanned::Spanned;
use syn::{Attribute, LitStr, Meta, Path, Token, Type, parse_quote};
use syn::{Attribute, LitStr, Meta, Path, Token, Type};
use synstructure::{BindingInfo, Structure, VariantInfo};
use super::utils::SubdiagnosticVariant;
@ -109,24 +109,14 @@ impl DiagnosticDeriveVariantBuilder {
pub(crate) fn primary_message(&self) -> Option<&Message> {
match self.message.as_ref() {
None => {
span_err(self.span, "diagnostic slug not specified")
span_err(self.span, "diagnostic message not specified")
.help(
"specify the slug as the first argument to the `#[diag(...)]` \
attribute, such as `#[diag(hir_analysis_example_error)]`",
"specify the message as the first argument to the `#[diag(...)]` \
attribute, such as `#[diag(\"Example error\")]`",
)
.emit();
None
}
Some(Message::Slug(slug))
if let Some(Mismatch { slug_name, crate_name, slug_prefix }) =
Mismatch::check(slug) =>
{
span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match")
.note(format!("slug is `{slug_name}` but the crate name is `{crate_name}`"))
.help(format!("expected a slug starting with `{slug_prefix}_...`"))
.emit();
None
}
Some(msg) => Some(msg),
}
}
@ -177,25 +167,15 @@ impl DiagnosticDeriveVariantBuilder {
.help("consider creating a `Subdiagnostic` instead"));
}
// For subdiagnostics without a message specified, insert a placeholder slug
let slug = subdiag.slug.unwrap_or_else(|| {
Message::Slug(match subdiag.kind {
SubdiagnosticKind::Label => parse_quote! { _subdiag::label },
SubdiagnosticKind::Note => parse_quote! { _subdiag::note },
SubdiagnosticKind::NoteOnce => parse_quote! { _subdiag::note_once },
SubdiagnosticKind::Help => parse_quote! { _subdiag::help },
SubdiagnosticKind::HelpOnce => parse_quote! { _subdiag::help_once },
SubdiagnosticKind::Warn => parse_quote! { _subdiag::warn },
SubdiagnosticKind::Suggestion { .. } => parse_quote! { _subdiag::suggestion },
SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
})
});
let Some(message) = subdiag.message else {
throw_invalid_attr!(attr, |diag| diag.help("subdiagnostic message is missing"))
};
Ok(Some((subdiag.kind, slug, false)))
Ok(Some((subdiag.kind, message, false)))
}
/// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct
/// attributes like `#[diag(..)]`, such as the slug and error code. Generates
/// attributes like `#[diag(..)]`, such as the message and error code. Generates
/// diagnostic builder calls for setting error code and creating note/help messages.
fn generate_structure_code_for_attr(
&mut self,
@ -213,9 +193,6 @@ impl DiagnosticDeriveVariantBuilder {
if name == "diag" {
let mut tokens = TokenStream::new();
attr.parse_args_with(|input: ParseStream<'_>| {
let mut input = &*input;
let slug_recovery_point = input.fork();
if input.peek(LitStr) {
// Parse an inline message
let message = input.parse::<LitStr>()?;
@ -226,15 +203,8 @@ impl DiagnosticDeriveVariantBuilder {
)
.emit();
}
self.message = Some(Message::Inline(message.span(), message.value()));
} else {
// Parse a slug
let slug = input.parse::<Path>()?;
if input.is_empty() || input.peek(Token![,]) {
self.message = Some(Message::Slug(slug));
} else {
input = &slug_recovery_point;
}
self.message =
Some(Message { message_span: message.span(), value: message.value() });
}
// Parse arguments
@ -248,7 +218,7 @@ impl DiagnosticDeriveVariantBuilder {
if input.peek(Token![,]) {
span_err(
arg_name.span().unwrap(),
"diagnostic slug must be the first argument",
"diagnostic message must be the first argument",
)
.emit();
continue;
@ -265,7 +235,7 @@ impl DiagnosticDeriveVariantBuilder {
}
_ => {
span_err(arg_name.span().unwrap(), "unknown argument")
.note("only the `code` parameter is valid after the slug")
.note("only the `code` parameter is valid after the message")
.emit();
}
}
@ -276,7 +246,7 @@ impl DiagnosticDeriveVariantBuilder {
return Ok(tokens);
}
let Some((subdiag, slug, _no_span)) = self.parse_subdiag_attribute(attr)? else {
let Some((subdiag, message, _no_span)) = self.parse_subdiag_attribute(attr)? else {
// Some attributes aren't errors - like documentation comments - but also aren't
// subdiagnostics.
return Ok(quote! {});
@ -287,7 +257,7 @@ impl DiagnosticDeriveVariantBuilder {
| SubdiagnosticKind::NoteOnce
| SubdiagnosticKind::Help
| SubdiagnosticKind::HelpOnce
| SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, slug, variant)),
| SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, message, variant)),
SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => {
throw_invalid_attr!(attr, |diag| diag
.help("`#[label]` and `#[suggestion]` can only be applied to fields"));
@ -406,7 +376,7 @@ impl DiagnosticDeriveVariantBuilder {
_ => (),
}
let Some((subdiag, slug, _no_span)) = self.parse_subdiag_attribute(attr)? else {
let Some((subdiag, message, _no_span)) = self.parse_subdiag_attribute(attr)? else {
// Some attributes aren't errors - like documentation comments - but also aren't
// subdiagnostics.
return Ok(quote! {});
@ -415,7 +385,7 @@ impl DiagnosticDeriveVariantBuilder {
match subdiag {
SubdiagnosticKind::Label => {
report_error_if_not_applied_to_span(attr, &info)?;
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug, variant))
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, message, variant))
}
SubdiagnosticKind::Note
| SubdiagnosticKind::NoteOnce
@ -426,11 +396,11 @@ impl DiagnosticDeriveVariantBuilder {
if type_matches_path(inner, &["rustc_span", "Span"])
|| type_matches_path(inner, &["rustc_span", "MultiSpan"])
{
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug, variant))
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, message, variant))
} else if type_is_unit(inner)
|| (matches!(info.ty, FieldInnerTy::Plain(_)) && type_is_bool(inner))
{
Ok(self.add_subdiagnostic(&fn_ident, slug, variant))
Ok(self.add_subdiagnostic(&fn_ident, message, variant))
} else {
report_type_error(attr, "`Span`, `MultiSpan`, `bool` or `()`")?
}
@ -456,7 +426,7 @@ impl DiagnosticDeriveVariantBuilder {
applicability.set_once(quote! { #static_applicability }, span);
}
let message = slug.diag_message(Some(variant));
let message = message.diag_message(Some(variant));
let applicability = applicability
.value()
.unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified });
@ -477,7 +447,7 @@ impl DiagnosticDeriveVariantBuilder {
}
}
/// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current slug
/// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current message
/// and `fluent_attr_identifier`.
fn add_spanned_subdiagnostic(
&self,
@ -496,7 +466,7 @@ impl DiagnosticDeriveVariantBuilder {
}
}
/// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug
/// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current message
/// and `fluent_attr_identifier`.
fn add_subdiagnostic(
&self,
@ -567,27 +537,3 @@ impl DiagnosticDeriveVariantBuilder {
}
}
}
struct Mismatch {
slug_name: String,
crate_name: String,
slug_prefix: String,
}
impl Mismatch {
/// Checks whether the slug starts with the crate name it's in.
fn check(slug: &syn::Path) -> Option<Mismatch> {
// If this is missing we're probably in a test, so bail.
let crate_name = std::env::var("CARGO_CRATE_NAME").ok()?;
// If we're not in a "rustc_" crate, bail.
let Some(("rustc", slug_prefix)) = crate_name.split_once('_') else { return None };
let slug_name = slug.segments.first()?.ident.to_string();
if slug_name.starts_with(slug_prefix) {
return None;
}
Some(Mismatch { slug_name, slug_prefix: slug_prefix.to_string(), crate_name })
}
}

View file

@ -2,16 +2,15 @@ use fluent_bundle::FluentResource;
use fluent_syntax::ast::{Expression, InlineExpression, Pattern, PatternElement};
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::Path;
use syn::ext::IdentExt;
use synstructure::{Structure, VariantInfo};
use synstructure::VariantInfo;
use crate::diagnostics::error::span_err;
#[derive(Clone)]
pub(crate) enum Message {
Slug(Path),
Inline(Span, String),
pub(crate) struct Message {
pub message_span: Span,
pub value: String,
}
impl Message {
@ -19,69 +18,9 @@ impl Message {
/// The passed `variant` is used to check whether all variables in the message are used.
/// For subdiagnostics, we cannot check this.
pub(crate) fn diag_message(&self, variant: Option<&VariantInfo<'_>>) -> TokenStream {
match self {
Message::Slug(slug) => {
quote! { crate::fluent_generated::#slug }
}
Message::Inline(message_span, message) => {
verify_fluent_message(*message_span, &message, variant);
quote! { rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed(#message)) }
}
}
}
/// Generates a `#[test]` that verifies that all referenced variables
/// exist on this structure.
pub(crate) fn generate_test(&self, structure: &Structure<'_>) -> TokenStream {
match self {
Message::Slug(slug) => {
// FIXME: We can't identify variables in a subdiagnostic
for field in structure.variants().iter().flat_map(|v| v.ast().fields.iter()) {
for attr_name in field.attrs.iter().filter_map(|at| at.path().get_ident()) {
if attr_name == "subdiagnostic" {
return quote!();
}
}
}
use std::sync::atomic::{AtomicUsize, Ordering};
// We need to make sure that the same diagnostic slug can be used multiple times without
// causing an error, so just have a global counter here.
static COUNTER: AtomicUsize = AtomicUsize::new(0);
let slug = slug.get_ident().unwrap();
let ident = quote::format_ident!(
"verify_{slug}_{}",
COUNTER.fetch_add(1, Ordering::Relaxed)
);
let ref_slug = quote::format_ident!("{slug}_refs");
let struct_name = &structure.ast().ident;
let variables: Vec<_> = structure
.variants()
.iter()
.flat_map(|v| {
v.ast()
.fields
.iter()
.filter_map(|f| f.ident.as_ref().map(|i| i.to_string()))
})
.collect();
// tidy errors on `#[test]` outside of test files, so we use `#[test ]` to work around this
quote! {
#[cfg(test)]
#[test ]
fn #ident() {
let variables = [#(#variables),*];
for vref in crate::fluent_generated::#ref_slug {
assert!(variables.contains(vref), "{}: variable `{vref}` not found ({})", stringify!(#struct_name), stringify!(#slug));
}
}
}
}
Message::Inline(..) => {
// We don't generate a test for inline diagnostics, we can verify these at compile-time!
// This verification is done in the `diag_message` function above
quote! {}
}
}
let message = &self.value;
verify_fluent_message(self.message_span, &message, variant);
quote! { rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed(#message)) }
}
}

View file

@ -186,10 +186,10 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
fn identify_kind(
&mut self,
) -> Result<Vec<(SubdiagnosticKind, Message)>, DiagnosticDeriveError> {
let mut kind_slugs = vec![];
let mut kind_messages = vec![];
for attr in self.variant.ast().attrs {
let Some(SubdiagnosticVariant { kind, slug }) =
let Some(SubdiagnosticVariant { kind, message }) =
SubdiagnosticVariant::from_attr(attr, &self.fields)?
else {
// Some attributes aren't errors - like documentation comments - but also aren't
@ -197,22 +197,22 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
continue;
};
let Some(slug) = slug else {
let Some(message) = message else {
let name = attr.path().segments.last().unwrap().ident.to_string();
let name = name.as_str();
throw_span_err!(
attr.span().unwrap(),
format!(
"diagnostic slug must be first argument of a `#[{name}(...)]` attribute"
"diagnostic message must be first argument of a `#[{name}(...)]` attribute"
)
);
};
kind_slugs.push((kind, slug));
kind_messages.push((kind, message));
}
Ok(kind_slugs)
Ok(kind_messages)
}
/// Generates the code for a field with no attributes.
@ -498,9 +498,9 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
}
pub(crate) fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
let kind_slugs = self.identify_kind()?;
let kind_messages = self.identify_kind()?;
let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect();
let kind_stats: KindsStatistics = kind_messages.iter().map(|(kind, _msg)| kind).collect();
let init = if kind_stats.has_multipart_suggestion {
quote! { let mut suggestions = Vec::new(); }
@ -516,7 +516,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
.map(|binding| self.generate_field_attr_code(binding, kind_stats))
.collect();
if kind_slugs.is_empty() && !self.has_subdiagnostic {
if kind_messages.is_empty() && !self.has_subdiagnostic {
if self.is_enum {
// It's okay for a variant to not be a subdiagnostic at all..
return Ok(quote! {});
@ -533,9 +533,9 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
let diag = &self.parent.diag;
let mut calls = TokenStream::new();
for (kind, slug) in kind_slugs {
for (kind, messages) in kind_messages {
let message = format_ident!("__message");
let message_stream = slug.diag_message(None);
let message_stream = messages.diag_message(None);
calls.extend(quote! { let #message = #diag.eagerly_translate(#message_stream); });
let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind);

View file

@ -267,7 +267,7 @@ pub(super) type FieldMap = HashMap<String, TokenStream>;
///
/// ```ignore (not-usage-example)
/// /// Suggest `==` when users wrote `===`.
/// #[suggestion(slug = "parser-not-javascript-eq", code = "{lhs} == {rhs}")]
/// #[suggestion("example message", code = "{lhs} == {rhs}")]
/// struct NotJavaScriptEq {
/// #[primary_span]
/// span: Span,
@ -588,13 +588,13 @@ pub(super) enum SubdiagnosticKind {
pub(super) struct SubdiagnosticVariant {
pub(super) kind: SubdiagnosticKind,
pub(super) slug: Option<Message>,
pub(super) message: Option<Message>,
}
impl SubdiagnosticVariant {
/// Constructs a `SubdiagnosticVariant` from a field or type attribute such as `#[note]`,
/// `#[error(parser::add_paren)]` or `#[suggestion(code = "...")]`. Returns the
/// `SubdiagnosticKind` and the diagnostic slug, if specified.
/// `#[error("add parenthesis")]` or `#[suggestion(code = "...")]`. Returns the
/// `SubdiagnosticKind` and the diagnostic message, if specified.
pub(super) fn from_attr(
attr: &Attribute,
fields: &FieldMap,
@ -660,11 +660,11 @@ impl SubdiagnosticVariant {
let list = match &attr.meta {
Meta::List(list) => {
// An attribute with properties, such as `#[suggestion(code = "...")]` or
// `#[error(some::slug)]`
// `#[error("message")]`
list
}
Meta::Path(_) => {
// An attribute without a slug or other properties, such as `#[note]` - return
// An attribute without a message or other properties, such as `#[note]` - return
// without further processing.
//
// Only allow this if there are no mandatory properties, such as `code = "..."` in
@ -677,7 +677,7 @@ impl SubdiagnosticVariant {
| SubdiagnosticKind::HelpOnce
| SubdiagnosticKind::Warn
| SubdiagnosticKind::MultipartSuggestion { .. } => {
return Ok(Some(SubdiagnosticVariant { kind, slug: None }));
return Ok(Some(SubdiagnosticVariant { kind, message: None }));
}
SubdiagnosticKind::Suggestion { .. } => {
throw_span_err!(span, "suggestion without `code = \"...\"`")
@ -692,45 +692,34 @@ impl SubdiagnosticVariant {
let mut code = None;
let mut suggestion_kind = None;
let mut slug = None;
let mut message = None;
list.parse_args_with(|input: ParseStream<'_>| {
let mut is_first = true;
while !input.is_empty() {
// Try to parse an inline diagnostic message
if input.peek(LitStr) {
let message = input.parse::<LitStr>()?;
if !message.suffix().is_empty() {
let inline_message = input.parse::<LitStr>()?;
if !inline_message.suffix().is_empty() {
span_err(
message.span().unwrap(),
inline_message.span().unwrap(),
"Inline message is not allowed to have a suffix",
).emit();
}
if !input.is_empty() { input.parse::<Token![,]>()?; }
if is_first {
slug = Some(Message::Inline(message.span(), message.value()));
message = Some(Message { message_span: inline_message.span(), value: inline_message.value() });
is_first = false;
} else {
span_err(message.span().unwrap(), "a diagnostic message must be the first argument to the attribute").emit();
}
continue
}
// Try to parse a slug instead
let arg_name: Path = input.parse::<Path>()?;
let arg_name_span = arg_name.span().unwrap();
if input.is_empty() || input.parse::<Token![,]>().is_ok() {
if is_first {
slug = Some(Message::Slug(arg_name));
is_first = false;
} else {
span_err(arg_name_span, "a diagnostic slug must be the first argument to the attribute").emit();
span_err(inline_message.span().unwrap(), "a diagnostic message must be the first argument to the attribute").emit();
}
continue
}
is_first = false;
// Try to parse an argument
let arg_name: Path = input.parse::<Path>()?;
let arg_name_span = arg_name.span().unwrap();
match (arg_name.require_ident()?.to_string().as_str(), &mut kind) {
("code", SubdiagnosticKind::Suggestion { code_field, .. }) => {
let code_init = build_suggestion_code(
@ -836,7 +825,7 @@ impl SubdiagnosticVariant {
| SubdiagnosticKind::Warn => {}
}
Ok(Some(SubdiagnosticVariant { kind, slug }))
Ok(Some(SubdiagnosticVariant { kind, message }))
}
}

View file

@ -42,7 +42,7 @@ fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> {
fn create_test_handler(theme: OutputTheme) -> (DiagCtxt, Arc<SourceMap>, Arc<Mutex<Vec<u8>>>) {
let output = Arc::new(Mutex::new(Vec::new()));
let source_map = Arc::new(SourceMap::new(FilePathMapping::empty()));
let translator = Translator::with_fallback_bundle(vec![], false);
let translator = Translator::new();
let shared: Box<dyn Write + Send> = Box::new(Shared { data: output.clone() });
let auto_stream = AutoStream::never(shared);
let dcx = DiagCtxt::new(Box::new(
@ -89,7 +89,7 @@ where
/// Maps a string to tts, using a made-up filename.
pub(crate) fn string_to_stream(source_str: String) -> TokenStream {
let psess = ParseSess::new(vec![]);
let psess = ParseSess::new();
unwrap_or_emit_fatal(source_str_to_stream(
&psess,
filename(psess.source_map(), "bogofile"),
@ -2239,12 +2239,12 @@ fn sp(a: u32, b: u32) -> Span {
/// Parses a string, return an expression.
fn string_to_expr(source_str: String) -> Box<ast::Expr> {
with_error_checking_parse(source_str, &ParseSess::new(vec![]), |p| p.parse_expr())
with_error_checking_parse(source_str, &ParseSess::new(), |p| p.parse_expr())
}
/// Parses a string, returns an item.
fn string_to_item(source_str: String) -> Option<Box<ast::Item>> {
with_error_checking_parse(source_str, &ParseSess::new(vec![]), |p| {
with_error_checking_parse(source_str, &ParseSess::new(), |p| {
p.parse_item(ForceCollect::No, AllowConstBlockItems::Yes)
})
}
@ -2480,7 +2480,7 @@ let mut fflags: c_int = wb();
#[test]
fn crlf_doc_comments() {
create_default_session_globals_then(|| {
let psess = ParseSess::new(vec![]);
let psess = ParseSess::new();
let name_1 = FileName::Custom("crlf_source_1".to_string());
let source = "/// doc comment\r\nfn foo() {}".to_string();
@ -2515,7 +2515,7 @@ fn ttdelim_span() {
}
create_default_session_globals_then(|| {
let psess = ParseSess::new(vec![]);
let psess = ParseSess::new();
let expr = parse_expr_from_source_str(
filename(psess.source_map(), "foo"),
"foo!( fn main() { body } )".to_string(),
@ -2551,7 +2551,7 @@ fn look_ahead() {
let sym_S = Symbol::intern("S");
let raw_no = IdentIsRaw::No;
let psess = ParseSess::new(vec![]);
let psess = ParseSess::new();
let mut p = string_to_parser(&psess, "fn f(x: u32) { x } struct S;".to_string());
// Current position is the `fn`.
@ -2626,7 +2626,7 @@ fn look_ahead_non_outermost_stream() {
let sym_S = Symbol::intern("S");
let raw_no = IdentIsRaw::No;
let psess = ParseSess::new(vec![]);
let psess = ParseSess::new();
let mut p = string_to_parser(&psess, "mod m { fn f(x: u32) { x } struct S; }".to_string());
// Move forward to the `fn`, which is not within the outermost token
@ -2658,7 +2658,7 @@ fn look_ahead_non_outermost_stream() {
#[test]
fn debug_lookahead() {
create_default_session_globals_then(|| {
let psess = ParseSess::new(vec![]);
let psess = ParseSess::new();
let mut p = string_to_parser(&psess, "fn f(x: u32) { x } struct S;".to_string());
// Current position is the `fn`.
@ -2879,7 +2879,7 @@ fn debug_lookahead() {
#[test]
fn out_of_line_mod() {
create_default_session_globals_then(|| {
let psess = ParseSess::new(vec![]);
let psess = ParseSess::new();
let item = parse_item_from_source_str(
filename(psess.source_map(), "foo"),
"mod foo { struct S; mod this_does_not_exist; }".to_owned(),

View file

@ -280,8 +280,8 @@ pub struct ParseSess {
impl ParseSess {
/// Used for testing.
pub fn new(locale_resources: Vec<&'static str>) -> Self {
let translator = Translator::with_fallback_bundle(locale_resources, false);
pub fn new() -> Self {
let translator = Translator::new();
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
let emitter = Box::new(
AnnotateSnippetEmitter::new(stderr_destination(ColorConfig::Auto), translator)
@ -314,7 +314,7 @@ impl ParseSess {
}
pub fn emitter_with_note(note: String) -> Self {
let translator = Translator::with_fallback_bundle(vec![], false);
let translator = Translator::new();
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
let emitter = Box::new(AnnotateSnippetEmitter::new(
stderr_destination(ColorConfig::Auto),

View file

@ -19,7 +19,7 @@ use rustc_errors::timings::TimingSectionHandler;
use rustc_errors::translation::Translator;
use rustc_errors::{
Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, FatalAbort,
TerminalUrl, fallback_fluent_bundle,
TerminalUrl,
};
use rustc_hir::limit::Limit;
use rustc_macros::HashStable_Generic;
@ -967,7 +967,6 @@ pub fn build_session(
sopts: config::Options,
io: CompilerIO,
fluent_bundle: Option<Arc<rustc_errors::FluentBundle>>,
fluent_resources: Vec<&'static str>,
driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
target: Target,
cfg_version: &'static str,
@ -985,13 +984,7 @@ pub fn build_session(
let cap_lints_allow = sopts.lint_cap.is_some_and(|cap| cap == lint::Allow);
let can_emit_warnings = !(warnings_allow || cap_lints_allow);
let translator = Translator {
fluent_bundle,
fallback_fluent_bundle: fallback_fluent_bundle(
fluent_resources,
sopts.unstable_opts.translate_directionality_markers,
),
};
let translator = Translator { fluent_bundle };
let source_map = rustc_span::source_map::get_source_map().unwrap();
let emitter = default_emitter(&sopts, Arc::clone(&source_map), translator);
@ -1430,7 +1423,7 @@ impl EarlyDiagCtxt {
fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> {
// FIXME(#100717): early errors aren't translated at the moment, so this is fine, but it will
// need to reference every crate that might emit an early error for translation to work.
let translator = Translator::with_fallback_bundle(vec![], false);
let translator = Translator::new();
let emitter: Box<DynEmitter> = match output {
config::ErrorOutputType::HumanReadable { kind, color_config } => match kind {
HumanReadableErrorType { short, unicode } => Box::new(

View file

@ -63,7 +63,7 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option<String
let snippet = source_map.span_to_snippet(span).ok()?;
// Create a Parser.
let psess = ParseSess::new(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec());
let psess = ParseSess::new();
let file_name = FileName::macro_expansion_source_code(&snippet);
let mut parser = match rustc_parse::new_parser_from_source_str(
&psess,

View file

@ -289,7 +289,6 @@ pub(crate) fn create_config(
output_file: None,
output_dir: None,
file_loader: None,
locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
lint_caps,
psess_created: None,
hash_untracked_state: None,

View file

@ -188,7 +188,6 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions
output_file: None,
output_dir: None,
file_loader: None,
locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
lint_caps,
psess_created: None,
hash_untracked_state: None,

View file

@ -29,7 +29,7 @@ pub fn main() {
}
fn parse() {
let psess = ParseSess::new(vec![]);
let psess = ParseSess::new();
let path = Path::new(file!());
let path = path.canonicalize().unwrap();

View file

@ -219,7 +219,7 @@ fn main() {
}
fn run() {
let psess = ParseSess::new(vec![]);
let psess = ParseSess::new();
iter_exprs(2, &mut |mut e| {
// If the pretty printer is correct, then `parse(print(e))` should be identical to `e`,

View file

@ -196,7 +196,7 @@ fn main() -> ExitCode {
};
rustc_span::create_default_session_globals_then(|| {
let psess = &ParseSess::new(vec![]);
let psess = &ParseSess::new();
for &source_code in EXPRS {
let Some(expr) = parse_expr(psess, source_code) else {

View file

@ -64,7 +64,6 @@ fn compile(code: String, output: PathBuf, sysroot: Sysroot, linker: Option<&Path
output_dir: None,
ice_file: None,
file_loader: None,
locale_resources: Vec::new(),
lint_caps: Default::default(),
psess_created: None,
hash_untracked_state: None,

View file

@ -45,9 +45,9 @@ struct Hello {}
//~^ ERROR unsupported type attribute for diagnostic derive enum
enum DiagnosticOnEnum {
Foo,
//~^ ERROR diagnostic slug not specified
//~^ ERROR diagnostic message not specified
Bar,
//~^ ERROR diagnostic slug not specified
//~^ ERROR diagnostic message not specified
}
#[derive(Diagnostic)]
@ -59,28 +59,28 @@ struct WrongStructAttrStyle {}
#[derive(Diagnostic)]
#[nonsense("this is an example message", code = E0123)]
//~^ ERROR `#[nonsense(...)]` is not a valid attribute
//~^^ ERROR diagnostic slug not specified
//~^^ ERROR diagnostic message not specified
//~^^^ ERROR cannot find attribute `nonsense` in this scope
struct InvalidStructAttr {}
#[derive(Diagnostic)]
#[diag(code = E0123)]
//~^ ERROR diagnostic slug not specified
//~^ ERROR diagnostic message not specified
struct InvalidLitNestedAttr {}
#[derive(Diagnostic)]
#[diag(nonsense("foo"), code = E0123, slug = "foo")]
//~^ ERROR derive(Diagnostic): diagnostic slug not specified
//~^ ERROR derive(Diagnostic): diagnostic message not specified
struct InvalidNestedStructAttr1 {}
#[derive(Diagnostic)]
#[diag(nonsense = "...", code = E0123, slug = "foo")]
//~^ ERROR diagnostic slug not specified
//~^ ERROR diagnostic message not specified
struct InvalidNestedStructAttr2 {}
#[derive(Diagnostic)]
#[diag(nonsense = 4, code = E0123, slug = "foo")]
//~^ ERROR diagnostic slug not specified
//~^ ERROR diagnostic message not specified
struct InvalidNestedStructAttr3 {}
#[derive(Diagnostic)]
@ -109,15 +109,15 @@ struct CodeSpecifiedTwice {}
#[derive(Diagnostic)]
#[diag("this is an example message", no_crate::example, code = E0123)]
//~^ ERROR diagnostic slug must be the first argument
//~^ ERROR diagnostic message must be the first argument
struct SlugSpecifiedTwice {}
#[derive(Diagnostic)]
struct KindNotProvided {} //~ ERROR diagnostic slug not specified
struct KindNotProvided {} //~ ERROR diagnostic message not specified
#[derive(Diagnostic)]
#[diag(code = E0123)]
//~^ ERROR diagnostic slug not specified
//~^ ERROR diagnostic message not specified
struct SlugNotProvided {}
#[derive(Diagnostic)]
@ -467,7 +467,15 @@ struct BoolField {
#[diag("this is an example message", code = E0123)]
struct LabelWithTrailingPath {
#[label("with a label", foo)]
//~^ ERROR a diagnostic slug must be the first argument to the attribute
//~^ ERROR derive(Diagnostic): no nested attribute expected here
span: Span,
}
#[derive(Diagnostic)]
#[diag("this is an example message", code = E0123)]
struct LabelWithTrailingMessage {
#[label("with a label", "and another one?")]
//~^ ERROR derive(Diagnostic): a diagnostic message must be the first argument to the attribute
span: Span,
}
@ -516,28 +524,28 @@ struct ErrorWithWarn {
#[derive(Diagnostic)]
#[error("this is an example message", code = E0123)]
//~^ ERROR `#[error(...)]` is not a valid attribute
//~| ERROR diagnostic slug not specified
//~| ERROR diagnostic message not specified
//~| ERROR cannot find attribute `error` in this scope
struct ErrorAttribute {}
#[derive(Diagnostic)]
#[warn_("this is an example message", code = E0123)]
//~^ ERROR `#[warn_(...)]` is not a valid attribute
//~| ERROR diagnostic slug not specified
//~| ERROR diagnostic message not specified
//~| ERROR cannot find attribute `warn_` in this scope
struct WarnAttribute {}
#[derive(Diagnostic)]
#[lint("this is an example message", code = E0123)]
//~^ ERROR `#[lint(...)]` is not a valid attribute
//~| ERROR diagnostic slug not specified
//~| ERROR diagnostic message not specified
//~| ERROR cannot find attribute `lint` in this scope
struct LintAttributeOnSessionDiag {}
#[derive(LintDiagnostic)]
#[lint("this is an example message", code = E0123)]
//~^ ERROR `#[lint(...)]` is not a valid attribute
//~| ERROR diagnostic slug not specified
//~| ERROR diagnostic message not specified
//~| ERROR cannot find attribute `lint` in this scope
struct LintAttributeOnLintDiag {}

View file

@ -4,21 +4,21 @@ error: derive(Diagnostic): unsupported type attribute for diagnostic derive enum
LL | #[diag("this is an example message", code = E0123)]
| ^
error: derive(Diagnostic): diagnostic slug not specified
error: derive(Diagnostic): diagnostic message not specified
--> $DIR/diagnostic-derive-inline.rs:47:5
|
LL | Foo,
| ^^^
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
= help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
error: derive(Diagnostic): diagnostic slug not specified
error: derive(Diagnostic): diagnostic message not specified
--> $DIR/diagnostic-derive-inline.rs:49:5
|
LL | Bar,
| ^^^
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
= help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
error: expected parentheses: #[diag(...)]
--> $DIR/diagnostic-derive-inline.rs:55:8
@ -32,45 +32,45 @@ error: derive(Diagnostic): `#[nonsense(...)]` is not a valid attribute
LL | #[nonsense("this is an example message", code = E0123)]
| ^
error: derive(Diagnostic): diagnostic slug not specified
error: derive(Diagnostic): diagnostic message not specified
--> $DIR/diagnostic-derive-inline.rs:60:1
|
LL | #[nonsense("this is an example message", code = E0123)]
| ^
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
= help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
error: derive(Diagnostic): diagnostic slug not specified
error: derive(Diagnostic): diagnostic message not specified
--> $DIR/diagnostic-derive-inline.rs:67:1
|
LL | #[diag(code = E0123)]
| ^
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
= help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
error: derive(Diagnostic): diagnostic slug not specified
error: derive(Diagnostic): diagnostic message not specified
--> $DIR/diagnostic-derive-inline.rs:72:1
|
LL | #[diag(nonsense("foo"), code = E0123, slug = "foo")]
| ^
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
= help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
error: derive(Diagnostic): diagnostic slug not specified
error: derive(Diagnostic): diagnostic message not specified
--> $DIR/diagnostic-derive-inline.rs:77:1
|
LL | #[diag(nonsense = "...", code = E0123, slug = "foo")]
| ^
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
= help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
error: derive(Diagnostic): diagnostic slug not specified
error: derive(Diagnostic): diagnostic message not specified
--> $DIR/diagnostic-derive-inline.rs:82:1
|
LL | #[diag(nonsense = 4, code = E0123, slug = "foo")]
| ^
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
= help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
error: derive(Diagnostic): unknown argument
--> $DIR/diagnostic-derive-inline.rs:87:52
@ -78,7 +78,7 @@ error: derive(Diagnostic): unknown argument
LL | #[diag("this is an example message", code = E0123, slug = "foo")]
| ^^^^
|
= note: only the `code` parameter is valid after the slug
= note: only the `code` parameter is valid after the message
error: derive(Diagnostic): `#[suggestion = ...]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:94:5
@ -110,27 +110,27 @@ note: previously specified here
LL | #[diag("this is an example message", code = E0123, code = E0456)]
| ^^^^
error: derive(Diagnostic): diagnostic slug must be the first argument
error: derive(Diagnostic): diagnostic message must be the first argument
--> $DIR/diagnostic-derive-inline.rs:111:38
|
LL | #[diag("this is an example message", no_crate::example, code = E0123)]
| ^^^^^^^^
error: derive(Diagnostic): diagnostic slug not specified
error: derive(Diagnostic): diagnostic message not specified
--> $DIR/diagnostic-derive-inline.rs:116:1
|
LL | struct KindNotProvided {}
| ^^^^^^
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
= help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
error: derive(Diagnostic): diagnostic slug not specified
error: derive(Diagnostic): diagnostic message not specified
--> $DIR/diagnostic-derive-inline.rs:119:1
|
LL | #[diag(code = E0123)]
| ^
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
= help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
error: derive(Diagnostic): the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
--> $DIR/diagnostic-derive-inline.rs:130:5
@ -276,26 +276,32 @@ error: derive(Diagnostic): the `#[help(...)]` attribute can only be applied to f
LL | #[help("with a help")]
| ^
error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute
error: derive(Diagnostic): no nested attribute expected here
--> $DIR/diagnostic-derive-inline.rs:469:29
|
LL | #[label("with a label", foo)]
| ^^^
error: derive(Diagnostic): no nested attribute expected here
error: derive(Diagnostic): a diagnostic message must be the first argument to the attribute
--> $DIR/diagnostic-derive-inline.rs:477:29
|
LL | #[label("with a label", "and another one?")]
| ^^^^^^^^^^^^^^^^^^
error: derive(Diagnostic): no nested attribute expected here
--> $DIR/diagnostic-derive-inline.rs:485:29
|
LL | #[label("with a label", foo = "...")]
| ^^^
error: derive(Diagnostic): no nested attribute expected here
--> $DIR/diagnostic-derive-inline.rs:485:29
--> $DIR/diagnostic-derive-inline.rs:493:29
|
LL | #[label("with a label", foo("..."))]
| ^^^
error: derive(Diagnostic): `#[primary_span]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:497:5
--> $DIR/diagnostic-derive-inline.rs:505:5
|
LL | #[primary_span]
| ^
@ -303,75 +309,75 @@ LL | #[primary_span]
= help: the `primary_span` field attribute is not valid for lint diagnostics
error: derive(Diagnostic): `#[error(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:517:1
--> $DIR/diagnostic-derive-inline.rs:525:1
|
LL | #[error("this is an example message", code = E0123)]
| ^
error: derive(Diagnostic): diagnostic slug not specified
--> $DIR/diagnostic-derive-inline.rs:517:1
error: derive(Diagnostic): diagnostic message not specified
--> $DIR/diagnostic-derive-inline.rs:525:1
|
LL | #[error("this is an example message", code = E0123)]
| ^
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
= help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
error: derive(Diagnostic): `#[warn_(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:524:1
--> $DIR/diagnostic-derive-inline.rs:532:1
|
LL | #[warn_("this is an example message", code = E0123)]
| ^
error: derive(Diagnostic): diagnostic slug not specified
--> $DIR/diagnostic-derive-inline.rs:524:1
error: derive(Diagnostic): diagnostic message not specified
--> $DIR/diagnostic-derive-inline.rs:532:1
|
LL | #[warn_("this is an example message", code = E0123)]
| ^
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
= help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:531:1
--> $DIR/diagnostic-derive-inline.rs:539:1
|
LL | #[lint("this is an example message", code = E0123)]
| ^
error: derive(Diagnostic): diagnostic slug not specified
--> $DIR/diagnostic-derive-inline.rs:531:1
error: derive(Diagnostic): diagnostic message not specified
--> $DIR/diagnostic-derive-inline.rs:539:1
|
LL | #[lint("this is an example message", code = E0123)]
| ^
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
= help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:538:1
--> $DIR/diagnostic-derive-inline.rs:546:1
|
LL | #[lint("this is an example message", code = E0123)]
| ^
error: derive(Diagnostic): diagnostic slug not specified
--> $DIR/diagnostic-derive-inline.rs:538:1
error: derive(Diagnostic): diagnostic message not specified
--> $DIR/diagnostic-derive-inline.rs:546:1
|
LL | #[lint("this is an example message", code = E0123)]
| ^
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
= help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
error: derive(Diagnostic): attribute specified multiple times
--> $DIR/diagnostic-derive-inline.rs:547:53
--> $DIR/diagnostic-derive-inline.rs:555:53
|
LL | #[suggestion("with a suggestion", code = "...", code = ",,,")]
| ^^^^
|
note: previously specified here
--> $DIR/diagnostic-derive-inline.rs:547:39
--> $DIR/diagnostic-derive-inline.rs:555:39
|
LL | #[suggestion("with a suggestion", code = "...", code = ",,,")]
| ^^^^
error: derive(Diagnostic): wrong types for suggestion
--> $DIR/diagnostic-derive-inline.rs:556:24
--> $DIR/diagnostic-derive-inline.rs:564:24
|
LL | suggestion: (Span, usize),
| ^^^^^
@ -379,7 +385,7 @@ LL | suggestion: (Span, usize),
= help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
error: derive(Diagnostic): wrong types for suggestion
--> $DIR/diagnostic-derive-inline.rs:564:17
--> $DIR/diagnostic-derive-inline.rs:572:17
|
LL | suggestion: (Span,),
| ^^^^^^^
@ -387,13 +393,13 @@ LL | suggestion: (Span,),
= help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
error: derive(Diagnostic): suggestion without `code = "..."`
--> $DIR/diagnostic-derive-inline.rs:571:5
--> $DIR/diagnostic-derive-inline.rs:579:5
|
LL | #[suggestion("with a suggestion")]
| ^
error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:578:1
--> $DIR/diagnostic-derive-inline.rs:586:1
|
LL | #[multipart_suggestion("with a suggestion")]
| ^
@ -401,7 +407,7 @@ LL | #[multipart_suggestion("with a suggestion")]
= help: consider creating a `Subdiagnostic` instead
error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:581:1
--> $DIR/diagnostic-derive-inline.rs:589:1
|
LL | #[multipart_suggestion()]
| ^
@ -409,7 +415,7 @@ LL | #[multipart_suggestion()]
= help: consider creating a `Subdiagnostic` instead
error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:585:5
--> $DIR/diagnostic-derive-inline.rs:593:5
|
LL | #[multipart_suggestion("with a suggestion")]
| ^
@ -417,7 +423,7 @@ LL | #[multipart_suggestion("with a suggestion")]
= help: consider creating a `Subdiagnostic` instead
error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:593:1
--> $DIR/diagnostic-derive-inline.rs:601:1
|
LL | #[suggestion("with a suggestion", code = "...")]
| ^
@ -425,41 +431,35 @@ LL | #[suggestion("with a suggestion", code = "...")]
= help: `#[label]` and `#[suggestion]` can only be applied to fields
error: derive(Diagnostic): `#[label]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:602:1
--> $DIR/diagnostic-derive-inline.rs:610:1
|
LL | #[label]
| ^
|
= help: `#[label]` and `#[suggestion]` can only be applied to fields
= help: subdiagnostic message is missing
error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:636:5
--> $DIR/diagnostic-derive-inline.rs:644:5
|
LL | #[subdiagnostic(bad)]
| ^
error: derive(Diagnostic): `#[subdiagnostic = ...]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:644:5
--> $DIR/diagnostic-derive-inline.rs:652:5
|
LL | #[subdiagnostic = "bad"]
| ^
error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:652:5
--> $DIR/diagnostic-derive-inline.rs:660:5
|
LL | #[subdiagnostic(bad, bad)]
| ^
error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:660:5
|
LL | #[subdiagnostic("bad")]
| ^
error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:668:5
|
LL | #[subdiagnostic(eager)]
LL | #[subdiagnostic("bad")]
| ^
error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute
@ -469,37 +469,43 @@ LL | #[subdiagnostic(eager)]
| ^
error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:697:5
--> $DIR/diagnostic-derive-inline.rs:684:5
|
LL | #[subdiagnostic(eager)]
| ^
error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:705:5
|
LL | #[subdiagnostic(eager)]
| ^
error: derive(Diagnostic): expected at least one string literal for `code(...)`
--> $DIR/diagnostic-derive-inline.rs:728:44
--> $DIR/diagnostic-derive-inline.rs:736:44
|
LL | #[suggestion("with a suggestion", code())]
| ^
error: derive(Diagnostic): `code(...)` must contain only string literals
--> $DIR/diagnostic-derive-inline.rs:736:44
--> $DIR/diagnostic-derive-inline.rs:744:44
|
LL | #[suggestion("with a suggestion", code(foo))]
| ^^^
error: unexpected token, expected `)`
--> $DIR/diagnostic-derive-inline.rs:736:44
--> $DIR/diagnostic-derive-inline.rs:744:44
|
LL | #[suggestion("with a suggestion", code(foo))]
| ^^^
error: expected string literal
--> $DIR/diagnostic-derive-inline.rs:745:46
--> $DIR/diagnostic-derive-inline.rs:753:46
|
LL | #[suggestion("with a suggestion", code = 3)]
| ^
error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute
--> $DIR/diagnostic-derive-inline.rs:760:5
--> $DIR/diagnostic-derive-inline.rs:768:5
|
LL | #[suggestion("with a suggestion", code = "")]
| ^
@ -509,7 +515,7 @@ LL | #[suggestion("with a suggestion", code = "")]
= help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]`
error: derive(Diagnostic): Variable `nosub` not found in diagnostic
--> $DIR/diagnostic-derive-inline.rs:772:8
--> $DIR/diagnostic-derive-inline.rs:780:8
|
LL | #[diag("does not exist: {$nosub}")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -529,7 +535,7 @@ LL | #[nonsense]
| ^^^^^^^^
error: cannot find attribute `error` in this scope
--> $DIR/diagnostic-derive-inline.rs:517:3
--> $DIR/diagnostic-derive-inline.rs:525:3
|
LL | #[error("this is an example message", code = E0123)]
| ^^^^^
@ -541,7 +547,7 @@ LL | struct ErrorAttribute {}
|
error: cannot find attribute `warn_` in this scope
--> $DIR/diagnostic-derive-inline.rs:524:3
--> $DIR/diagnostic-derive-inline.rs:532:3
|
LL | #[warn_("this is an example message", code = E0123)]
| ^^^^^
@ -553,7 +559,7 @@ LL + #[warn("this is an example message", code = E0123)]
|
error: cannot find attribute `lint` in this scope
--> $DIR/diagnostic-derive-inline.rs:531:3
--> $DIR/diagnostic-derive-inline.rs:539:3
|
LL | #[lint("this is an example message", code = E0123)]
| ^^^^
@ -565,7 +571,7 @@ LL + #[link("this is an example message", code = E0123)]
|
error: cannot find attribute `lint` in this scope
--> $DIR/diagnostic-derive-inline.rs:538:3
--> $DIR/diagnostic-derive-inline.rs:546:3
|
LL | #[lint("this is an example message", code = E0123)]
| ^^^^
@ -577,7 +583,7 @@ LL + #[link("this is an example message", code = E0123)]
|
error: cannot find attribute `multipart_suggestion` in this scope
--> $DIR/diagnostic-derive-inline.rs:578:3
--> $DIR/diagnostic-derive-inline.rs:586:3
|
LL | #[multipart_suggestion("with a suggestion")]
| ^^^^^^^^^^^^^^^^^^^^
@ -589,7 +595,7 @@ LL | struct MultipartSuggestion {
|
error: cannot find attribute `multipart_suggestion` in this scope
--> $DIR/diagnostic-derive-inline.rs:581:3
--> $DIR/diagnostic-derive-inline.rs:589:3
|
LL | #[multipart_suggestion()]
| ^^^^^^^^^^^^^^^^^^^^
@ -601,7 +607,7 @@ LL | struct MultipartSuggestion {
|
error: cannot find attribute `multipart_suggestion` in this scope
--> $DIR/diagnostic-derive-inline.rs:585:7
--> $DIR/diagnostic-derive-inline.rs:593:7
|
LL | #[multipart_suggestion("with a suggestion")]
| ^^^^^^^^^^^^^^^^^^^^
@ -630,6 +636,6 @@ note: required by a bound in `Diag::<'a, G>::arg`
= note: in this macro invocation
= note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 80 previous errors
error: aborting due to 81 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -54,7 +54,7 @@ struct C {
#[derive(Subdiagnostic)]
#[label]
//~^ ERROR diagnostic slug must be first argument
//~^ ERROR diagnostic message must be first argument
struct D {
#[primary_span]
span: Span,
@ -83,7 +83,7 @@ struct F {
#[derive(Subdiagnostic)]
#[label(bug = "...")]
//~^ ERROR no nested attribute expected here
//~| ERROR diagnostic slug must be first argument
//~| ERROR diagnostic message must be first argument
struct G {
#[primary_span]
span: Span,
@ -93,7 +93,7 @@ struct G {
#[derive(Subdiagnostic)]
#[label(slug = 4)]
//~^ ERROR no nested attribute expected here
//~| ERROR diagnostic slug must be first argument
//~| ERROR diagnostic message must be first argument
struct J {
#[primary_span]
span: Span,
@ -103,7 +103,7 @@ struct J {
#[derive(Subdiagnostic)]
#[label(slug("..."))]
//~^ ERROR no nested attribute expected here
//~| ERROR diagnostic slug must be first argument
//~| ERROR diagnostic message must be first argument
struct K {
#[primary_span]
span: Span,
@ -112,7 +112,7 @@ struct K {
#[derive(Subdiagnostic)]
#[label()]
//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
//~^ ERROR diagnostic message must be first argument of a `#[label(...)]` attribute
struct M {
#[primary_span]
span: Span,
@ -201,7 +201,7 @@ enum T {
#[derive(Subdiagnostic)]
enum U {
#[label(code = "...")]
//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
//~^ ERROR diagnostic message must be first argument of a `#[label(...)]` attribute
//~| ERROR no nested attribute expected here
A {
#[primary_span]
@ -303,7 +303,7 @@ struct AD {
#[derive(Subdiagnostic)]
#[label("example message", no_crate::example)]
//~^ ERROR a diagnostic slug must be the first argument to the attribute
//~^ ERROR expected this path to be an identifier
struct AE {
#[primary_span]
span: Span,
@ -771,7 +771,7 @@ struct SuggestionStyleInvalid2 {
#[derive(Subdiagnostic)]
#[suggestion("example message", code = "", style)]
//~^ ERROR a diagnostic slug must be the first argument to the attribute
//~^ ERROR expected `=`
struct SuggestionStyleInvalid3 {
#[primary_span]
sub: Span,

View file

@ -4,7 +4,7 @@ error: derive(Diagnostic): label without `#[primary_span]` field
LL | #[label("example message")]
| ^
error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute
error: derive(Diagnostic): diagnostic message must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive-inline.rs:56:1
|
LL | #[label]
@ -28,7 +28,7 @@ error: derive(Diagnostic): no nested attribute expected here
LL | #[label(bug = "...")]
| ^^^
error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute
error: derive(Diagnostic): diagnostic message must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive-inline.rs:84:1
|
LL | #[label(bug = "...")]
@ -40,7 +40,7 @@ error: derive(Diagnostic): no nested attribute expected here
LL | #[label(slug = 4)]
| ^^^^
error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute
error: derive(Diagnostic): diagnostic message must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive-inline.rs:94:1
|
LL | #[label(slug = 4)]
@ -52,13 +52,13 @@ error: derive(Diagnostic): no nested attribute expected here
LL | #[label(slug("..."))]
| ^^^^
error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute
error: derive(Diagnostic): diagnostic message must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive-inline.rs:104:1
|
LL | #[label(slug("..."))]
| ^
error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute
error: derive(Diagnostic): diagnostic message must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive-inline.rs:114:1
|
LL | #[label()]
@ -112,7 +112,7 @@ error: derive(Diagnostic): no nested attribute expected here
LL | #[label(code = "...")]
| ^^^^
error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute
error: derive(Diagnostic): diagnostic message must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive-inline.rs:203:5
|
LL | #[label(code = "...")]
@ -168,11 +168,11 @@ LL | | b: u64,
LL | | }
| |_^
error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute
error: expected this path to be an identifier
--> $DIR/subdiagnostic-derive-inline.rs:305:28
|
LL | #[label("example message", no_crate::example)]
| ^^^^^^^^
| ^^^^^^^^^^^^^^^^^
error: derive(Diagnostic): attribute specified multiple times
--> $DIR/subdiagnostic-derive-inline.rs:318:5
@ -464,11 +464,11 @@ error: expected string literal
LL | #[suggestion("example message", code = "", style = 42)]
| ^^
error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute
--> $DIR/subdiagnostic-derive-inline.rs:773:44
error: expected `=`
--> $DIR/subdiagnostic-derive-inline.rs:773:49
|
LL | #[suggestion("example message", code = "", style)]
| ^^^^^
| ^
error: expected `=`
--> $DIR/subdiagnostic-derive-inline.rs:781:49