commit:     3c7f958559b2c7561e95f915b7ed287a56333361
Author:     Georgy Yakovlev <gyakovlev <AT> gentoo <DOT> org>
AuthorDate: Tue Jun 20 18:18:58 2023 +0000
Commit:     Georgy Yakovlev <gyakovlev <AT> gentoo <DOT> org>
CommitDate: Tue Jun 20 19:50:46 2023 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=3c7f9585

dev-lang/rust: add 1.67.1 patch for sparc build failures

Bug: https://bugs.gentoo.org/893996
Signed-off-by: Georgy Yakovlev <gyakovlev <AT> gentoo.org>

 dev-lang/rust/files/1.67.1-rustc_expand.patch      | 1427 ++++++++++++++++++++
 .../{rust-1.67.1.ebuild => rust-1.67.1-r1.ebuild}  |    1 +
 2 files changed, 1428 insertions(+)

diff --git a/dev-lang/rust/files/1.67.1-rustc_expand.patch 
b/dev-lang/rust/files/1.67.1-rustc_expand.patch
new file mode 100644
index 000000000000..af778d45c76f
--- /dev/null
+++ b/dev-lang/rust/files/1.67.1-rustc_expand.patch
@@ -0,0 +1,1427 @@
+From 2f9f097cb8b6c27a7e0d7a916e6911fc1f5ecd81 Mon Sep 17 00:00:00 2001
+From: nils <48135649+nilstr...@users.noreply.github.com>
+Date: Tue, 15 Nov 2022 14:24:33 +0100
+Subject: [PATCH] Migrate parts of `rustc_expand` to session diagnostics
+
+This migrates everything but the `mbe` and `proc_macro` modules. It also
+contains a few cleanups and drive-by/accidental diagnostic improvements
+which can be seen in the diff for the UI tests.
+---
+ compiler/rustc_builtin_macros/src/concat.rs   |   2 +-
+ .../rustc_builtin_macros/src/concat_bytes.rs  |   2 +-
+ compiler/rustc_builtin_macros/src/env.rs      |   2 +-
+ .../locales/en-US/expand.ftl                  | 107 ++++++
+ compiler/rustc_errors/src/diagnostic_impls.rs |   6 +
+ compiler/rustc_expand/src/base.rs             |  90 +++--
+ compiler/rustc_expand/src/config.rs           | 106 +++---
+ compiler/rustc_expand/src/errors.rs           | 326 +++++++++++++++++-
+ compiler/rustc_expand/src/expand.rs           |  86 ++---
+ compiler/rustc_expand/src/lib.rs              |   6 +
+ compiler/rustc_expand/src/module.rs           |  80 ++---
+ compiler/rustc_expand/src/tests.rs            |   1 +
+ src/test/rustdoc-ui/doc-cfg.stderr            |   4 +-
+ .../cfg-attr-syntax-validation.stderr         |   2 +-
+ .../macros/macro-in-expression-context.stderr |   8 +-
+ .../ui/proc-macro/attr-invalid-exprs.stderr   |  16 +-
+ src/test/ui/proc-macro/attribute.rs           |   8 +-
+ src/test/ui/proc-macro/attribute.stderr       |   8 +-
+ src/test/ui/proc-macro/expand-expr.stderr     |  16 +-
+ 19 files changed, 640 insertions(+), 236 deletions(-)
+
+diff --git a/compiler/rustc_builtin_macros/src/concat.rs 
b/compiler/rustc_builtin_macros/src/concat.rs
+index e2d71825d556f..9ae65c641fd62 100644
+--- a/compiler/rustc_builtin_macros/src/concat.rs
++++ b/compiler/rustc_builtin_macros/src/concat.rs
+@@ -11,7 +11,7 @@ pub fn expand_concat(
+     sp: rustc_span::Span,
+     tts: TokenStream,
+ ) -> Box<dyn base::MacResult + 'static> {
+-    let Some(es) = base::get_exprs_from_tts(cx, sp, tts) else {
++    let Some(es) = base::get_exprs_from_tts(cx, tts) else {
+         return DummyResult::any(sp);
+     };
+     let mut accumulator = String::new();
+diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs 
b/compiler/rustc_builtin_macros/src/concat_bytes.rs
+index d1124145dcbbb..70ce5a6c41929 100644
+--- a/compiler/rustc_builtin_macros/src/concat_bytes.rs
++++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs
+@@ -137,7 +137,7 @@ pub fn expand_concat_bytes(
+     sp: rustc_span::Span,
+     tts: TokenStream,
+ ) -> Box<dyn base::MacResult + 'static> {
+-    let Some(es) = base::get_exprs_from_tts(cx, sp, tts) else {
++    let Some(es) = base::get_exprs_from_tts(cx, tts) else {
+         return DummyResult::any(sp);
+     };
+     let mut accumulator = Vec::new();
+diff --git a/compiler/rustc_builtin_macros/src/env.rs 
b/compiler/rustc_builtin_macros/src/env.rs
+index 0b4e545f7a3d0..a7283ea601b19 100644
+--- a/compiler/rustc_builtin_macros/src/env.rs
++++ b/compiler/rustc_builtin_macros/src/env.rs
+@@ -52,7 +52,7 @@ pub fn expand_env<'cx>(
+     sp: Span,
+     tts: TokenStream,
+ ) -> Box<dyn base::MacResult + 'cx> {
+-    let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
++    let mut exprs = match get_exprs_from_tts(cx, tts) {
+         Some(exprs) if exprs.is_empty() => {
+             cx.span_err(sp, "env! takes 1 or 2 arguments");
+             return DummyResult::any(sp);
+diff --git a/compiler/rustc_error_messages/locales/en-US/expand.ftl 
b/compiler/rustc_error_messages/locales/en-US/expand.ftl
+index 5720591154f99..df0e8ae5dd8f5 100644
+--- a/compiler/rustc_error_messages/locales/en-US/expand.ftl
++++ b/compiler/rustc_error_messages/locales/en-US/expand.ftl
+@@ -20,3 +20,110 @@ expand_var_still_repeating =
+     variable '{$ident}' is still repeating at this depth
+ 
+ expand_meta_var_dif_seq_matchers = {$msg}
++
++expand_macro_const_stability =
++    macros cannot have const stability attributes
++    .label = invalid const stability attribute
++    .label2 = const stability attribute affects this macro
++
++expand_macro_body_stability =
++    macros cannot have body stability attributes
++    .label = invalid body stability attribute
++    .label2 = body stability attribute affects this macro
++
++expand_resolve_relative_path =
++    cannot resolve relative path in non-file source `{$path}`
++
++expand_attr_no_arguments =
++    attribute must have either one or two arguments
++
++expand_not_a_meta_item =
++    not a meta item
++
++expand_only_one_word =
++    must only be one word
++
++expand_cannot_be_name_of_macro =
++    `{$trait_ident}` cannot be a name of {$macro_type} macro
++
++expand_arg_not_attributes =
++    second argument must be `attributes`
++
++expand_attributes_wrong_form =
++    attribute must be of form: `attributes(foo, bar)`
++
++expand_attribute_meta_item =
++    attribute must be a meta item, not a literal
++
++expand_attribute_single_word =
++    attribute must only be a single word
++
++expand_helper_attribute_name_invalid =
++    `{$name}` cannot be a name of derive helper attribute
++
++expand_expected_comma_in_list =
++    expected token: `,`
++
++expand_only_one_argument =
++    {$name} takes 1 argument
++
++expand_takes_no_arguments =
++    {$name} takes no arguments
++
++expand_feature_included_in_edition =
++    the feature `{$feature}` is included in the Rust {$edition} edition
++
++expand_feature_removed =
++    feature has been removed
++    .label = feature has been removed
++    .reason = {$reason}
++
++expand_feature_not_allowed =
++    the feature `{$name}` is not in the list of allowed features
++
++expand_recursion_limit_reached =
++    recursion limit reached while expanding `{$descr}`
++    .help = consider increasing the recursion limit by adding a 
`#![recursion_limit = "{$suggested_limit}"]` attribute to your crate 
(`{$crate_name}`)
++
++expand_malformed_feature_attribute =
++    malformed `feature` attribute input
++    .expected = expected just one word
++
++expand_remove_expr_not_supported =
++    removing an expression is not supported in this position
++
++expand_invalid_cfg_no_parens = `cfg` is not followed by parentheses
++expand_invalid_cfg_no_predicate = `cfg` predicate is not specified
++expand_invalid_cfg_multiple_predicates = multiple `cfg` predicates are 
specified
++expand_invalid_cfg_predicate_literal = `cfg` predicate key cannot be a literal
++expand_invalid_cfg_expected_syntax = expected syntax is
++
++expand_wrong_fragment_kind =
++    non-{$kind} macro in {$kind} position: {$name}
++
++expand_unsupported_key_value =
++    key-value macro attributes are not supported
++
++expand_incomplete_parse =
++    macro expansion ignores token `{$token}` and any following
++    .label = caused by the macro expansion here
++    .note = the usage of `{$macro_path}!` is likely invalid in {$kind_name} 
context
++    .suggestion_add_semi = you might be missing a semicolon here
++
++expand_remove_node_not_supported =
++    removing {$descr} is not supported in this position
++
++expand_module_circular =
++    circular modules: {$modules}
++
++expand_module_in_block =
++    cannot declare a non-inline module inside a block unless it has a path 
attribute
++    .note = maybe `use` the module `{$name}` instead of redeclaring it
++
++expand_module_file_not_found =
++    file not found for module `{$name}`
++    .help = to create the module `{$name}`, create file "{$default_path}" or 
"{$secondary_path}"
++
++expand_module_multiple_candidates =
++    file for module `{$name}` found at both "{$default_path}" and 
"{$secondary_path}"
++    .help = delete or rename one of them to remove the ambiguity
+diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs 
b/compiler/rustc_errors/src/diagnostic_impls.rs
+index 7155db32e53b7..cb39e997436e0 100644
+--- a/compiler/rustc_errors/src/diagnostic_impls.rs
++++ b/compiler/rustc_errors/src/diagnostic_impls.rs
+@@ -152,6 +152,12 @@ impl IntoDiagnosticArg for ast::Path {
+     }
+ }
+ 
++impl IntoDiagnosticArg for &ast::Path {
++    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
++        DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(self)))
++    }
++}
++
+ impl IntoDiagnosticArg for ast::token::Token {
+     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+         DiagnosticArgValue::Str(pprust::token_to_string(&self))
+diff --git a/compiler/rustc_expand/src/base.rs 
b/compiler/rustc_expand/src/base.rs
+index 9d6a4f9a1fd7d..6f159663e80cf 100644
+--- a/compiler/rustc_expand/src/base.rs
++++ b/compiler/rustc_expand/src/base.rs
+@@ -1,3 +1,11 @@
++#![deny(rustc::untranslatable_diagnostic)]
++
++use crate::errors::{
++    ArgumentNotAttributes, AttrNoArguments, AttributeMetaItem, 
AttributeSingleWord,
++    AttributesWrongForm, CannotBeNameOfMacro, ExpectedCommaInList, 
HelperAttributeNameInvalid,
++    MacroBodyStability, MacroConstStability, NotAMetaItem, OnlyOneArgument, 
OnlyOneWord,
++    ResolveRelativePath, TakesNoArguments,
++};
+ use crate::expand::{self, AstFragment, Invocation};
+ use crate::module::DirOwnership;
+ 
+@@ -789,26 +797,16 @@ impl SyntaxExtension {
+             .unwrap_or_else(|| (None, helper_attrs));
+         let (stability, const_stability, body_stability) = 
attr::find_stability(&sess, attrs, span);
+         if let Some((_, sp)) = const_stability {
+-            sess.parse_sess
+-                .span_diagnostic
+-                .struct_span_err(sp, "macros cannot have const stability 
attributes")
+-                .span_label(sp, "invalid const stability attribute")
+-                .span_label(
+-                    sess.source_map().guess_head_span(span),
+-                    "const stability attribute affects this macro",
+-                )
+-                .emit();
++            sess.emit_err(MacroConstStability {
++                span: sp,
++                head_span: sess.source_map().guess_head_span(span),
++            });
+         }
+         if let Some((_, sp)) = body_stability {
+-            sess.parse_sess
+-                .span_diagnostic
+-                .struct_span_err(sp, "macros cannot have body stability 
attributes")
+-                .span_label(sp, "invalid body stability attribute")
+-                .span_label(
+-                    sess.source_map().guess_head_span(span),
+-                    "body stability attribute affects this macro",
+-                )
+-                .emit();
++            sess.emit_err(MacroBodyStability {
++                span: sp,
++                head_span: sess.source_map().guess_head_span(span),
++            });
+         }
+ 
+         SyntaxExtension {
+@@ -1200,13 +1198,11 @@ pub fn resolve_path(
+                 .expect("attempting to resolve a file path in an external 
file"),
+             FileName::DocTest(path, _) => path,
+             other => {
+-                return Err(parse_sess.span_diagnostic.struct_span_err(
++                return Err(ResolveRelativePath {
+                     span,
+-                    &format!(
+-                        "cannot resolve relative path in non-file source 
`{}`",
+-                        
parse_sess.source_map().filename_for_diagnostics(&other)
+-                    ),
+-                ));
++                    path: 
parse_sess.source_map().filename_for_diagnostics(&other).to_string(),
++                }
++                .into_diagnostic(&parse_sess.span_diagnostic));
+             }
+         };
+         result.pop();
+@@ -1222,6 +1218,8 @@ pub fn resolve_path(
+ /// The returned bool indicates whether an applicable suggestion has already 
been
+ /// added to the diagnostic to avoid emitting multiple suggestions. 
`Err(None)`
+ /// indicates that an ast error was encountered.
++// FIXME(Nilstrieb) Make this function setup translatable
++#[allow(rustc::untranslatable_diagnostic)]
+ pub fn expr_to_spanned_string<'a>(
+     cx: &'a mut ExtCtxt<'_>,
+     expr: P<ast::Expr>,
+@@ -1280,9 +1278,9 @@ pub fn expr_to_string(
+ /// compilation should call
+ /// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
+ /// done as rarely as possible).
+-pub fn check_zero_tts(cx: &ExtCtxt<'_>, sp: Span, tts: TokenStream, name: 
&str) {
++pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: 
&str) {
+     if !tts.is_empty() {
+-        cx.span_err(sp, &format!("{} takes no arguments", name));
++        cx.emit_err(TakesNoArguments { span, name });
+     }
+ }
+ 
+@@ -1304,31 +1302,27 @@ pub fn parse_expr(p: &mut parser::Parser<'_>) -> 
Option<P<ast::Expr>> {
+ /// expect exactly one string literal, or emit an error and return `None`.
+ pub fn get_single_str_from_tts(
+     cx: &mut ExtCtxt<'_>,
+-    sp: Span,
++    span: Span,
+     tts: TokenStream,
+     name: &str,
+ ) -> Option<Symbol> {
+     let mut p = cx.new_parser_from_tts(tts);
+     if p.token == token::Eof {
+-        cx.span_err(sp, &format!("{} takes 1 argument", name));
++        cx.emit_err(OnlyOneArgument { span, name });
+         return None;
+     }
+     let ret = parse_expr(&mut p)?;
+     let _ = p.eat(&token::Comma);
+ 
+     if p.token != token::Eof {
+-        cx.span_err(sp, &format!("{} takes 1 argument", name));
++        cx.emit_err(OnlyOneArgument { span, name });
+     }
+     expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| 
s)
+ }
+ 
+ /// Extracts comma-separated expressions from `tts`.
+ /// On error, emit it, and return `None`.
+-pub fn get_exprs_from_tts(
+-    cx: &mut ExtCtxt<'_>,
+-    sp: Span,
+-    tts: TokenStream,
+-) -> Option<Vec<P<ast::Expr>>> {
++pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, tts: TokenStream) -> 
Option<Vec<P<ast::Expr>>> {
+     let mut p = cx.new_parser_from_tts(tts);
+     let mut es = Vec::new();
+     while p.token != token::Eof {
+@@ -1343,7 +1337,7 @@ pub fn get_exprs_from_tts(
+             continue;
+         }
+         if p.token != token::Eof {
+-            cx.span_err(sp, "expected token: `,`");
++            cx.emit_err(ExpectedCommaInList { span: p.token.span });
+             return None;
+         }
+     }
+@@ -1353,64 +1347,58 @@ pub fn get_exprs_from_tts(
+ pub fn parse_macro_name_and_helper_attrs(
+     diag: &rustc_errors::Handler,
+     attr: &Attribute,
+-    descr: &str,
++    macro_type: &str,
+ ) -> Option<(Symbol, Vec<Symbol>)> {
+     // Once we've located the `#[proc_macro_derive]` attribute, verify
+     // that it's of the form `#[proc_macro_derive(Foo)]` or
+     // `#[proc_macro_derive(Foo, attributes(A, ..))]`
+     let list = attr.meta_item_list()?;
+     if list.len() != 1 && list.len() != 2 {
+-        diag.span_err(attr.span, "attribute must have either one or two 
arguments");
++        diag.emit_err(AttrNoArguments { span: attr.span });
+         return None;
+     }
+     let Some(trait_attr) = list[0].meta_item() else {
+-        diag.span_err(list[0].span(), "not a meta item");
++        diag.emit_err(NotAMetaItem {span: list[0].span()});
+         return None;
+     };
+     let trait_ident = match trait_attr.ident() {
+         Some(trait_ident) if trait_attr.is_word() => trait_ident,
+         _ => {
+-            diag.span_err(trait_attr.span, "must only be one word");
++            diag.emit_err(OnlyOneWord { span: trait_attr.span });
+             return None;
+         }
+     };
+ 
+     if !trait_ident.name.can_be_raw() {
+-        diag.span_err(
+-            trait_attr.span,
+-            &format!("`{}` cannot be a name of {} macro", trait_ident, descr),
+-        );
++        diag.emit_err(CannotBeNameOfMacro { span: trait_attr.span, 
trait_ident, macro_type });
+     }
+ 
+     let attributes_attr = list.get(1);
+     let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
+         if !attr.has_name(sym::attributes) {
+-            diag.span_err(attr.span(), "second argument must be 
`attributes`");
++            diag.emit_err(ArgumentNotAttributes { span: attr.span() });
+         }
+         attr.meta_item_list()
+             .unwrap_or_else(|| {
+-                diag.span_err(attr.span(), "attribute must be of form: 
`attributes(foo, bar)`");
++                diag.emit_err(AttributesWrongForm { span: attr.span() });
+                 &[]
+             })
+             .iter()
+             .filter_map(|attr| {
+                 let Some(attr) = attr.meta_item() else {
+-                    diag.span_err(attr.span(), "not a meta item");
++                    diag.emit_err(AttributeMetaItem { span: attr.span() });
+                     return None;
+                 };
+ 
+                 let ident = match attr.ident() {
+                     Some(ident) if attr.is_word() => ident,
+                     _ => {
+-                        diag.span_err(attr.span, "must only be one word");
++                        diag.emit_err(AttributeSingleWord { span: attr.span 
});
+                         return None;
+                     }
+                 };
+                 if !ident.name.can_be_raw() {
+-                    diag.span_err(
+-                        attr.span,
+-                        &format!("`{}` cannot be a name of derive helper 
attribute", ident),
+-                    );
++                    diag.emit_err(HelperAttributeNameInvalid { span: 
attr.span, name: ident });
+                 }
+ 
+                 Some(ident.name)
+diff --git a/compiler/rustc_expand/src/config.rs 
b/compiler/rustc_expand/src/config.rs
+index 2510795c2e3ed..f4c6f3386ade2 100644
+--- a/compiler/rustc_expand/src/config.rs
++++ b/compiler/rustc_expand/src/config.rs
+@@ -1,5 +1,9 @@
+ //! Conditional compilation stripping.
+ 
++use crate::errors::{
++    FeatureIncludedInEdition, FeatureNotAllowed, FeatureRemoved, 
FeatureRemovedReason, InvalidCfg,
++    MalformedFeatureAttribute, MalformedFeatureAttributeHelp, 
RemoveExprNotSupported,
++};
+ use rustc_ast::ptr::P;
+ use rustc_ast::token::{Delimiter, Token, TokenKind};
+ use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree};
+@@ -10,7 +14,6 @@ use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, 
HasTokens, MetaItem
+ use rustc_attr as attr;
+ use rustc_data_structures::fx::FxHashMap;
+ use rustc_data_structures::map_in_place::MapInPlace;
+-use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
+ use rustc_feature::{Feature, Features, State as FeatureState};
+ use rustc_feature::{
+     ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, 
STABLE_REMOVED_FEATURES,
+@@ -33,18 +36,12 @@ pub struct StripUnconfigured<'a> {
+     pub lint_node_id: NodeId,
+ }
+ 
+-fn get_features(
+-    sess: &Session,
+-    span_handler: &Handler,
+-    krate_attrs: &[ast::Attribute],
+-) -> Features {
+-    fn feature_removed(span_handler: &Handler, span: Span, reason: 
Option<&str>) {
+-        let mut err = struct_span_err!(span_handler, span, E0557, "feature 
has been removed");
+-        err.span_label(span, "feature has been removed");
+-        if let Some(reason) = reason {
+-            err.note(reason);
+-        }
+-        err.emit();
++fn get_features(sess: &Session, krate_attrs: &[ast::Attribute]) -> Features {
++    fn feature_removed(sess: &Session, span: Span, reason: Option<&str>) {
++        sess.emit_err(FeatureRemoved {
++            span,
++            reason: reason.map(|reason| FeatureRemovedReason { reason }),
++        });
+     }
+ 
+     fn active_features_up_to(edition: Edition) -> impl Iterator<Item = 
&'static Feature> {
+@@ -117,34 +114,34 @@ fn get_features(
+             continue;
+         };
+ 
+-        let bad_input = |span| {
+-            struct_span_err!(span_handler, span, E0556, "malformed `feature` 
attribute input")
+-        };
+-
+         for mi in list {
+             let name = match mi.ident() {
+                 Some(ident) if mi.is_word() => ident.name,
+                 Some(ident) => {
+-                    bad_input(mi.span())
+-                        .span_suggestion(
+-                            mi.span(),
+-                            "expected just one word",
+-                            ident.name,
+-                            Applicability::MaybeIncorrect,
+-                        )
+-                        .emit();
++                    sess.emit_err(MalformedFeatureAttribute {
++                        span: mi.span(),
++                        help: MalformedFeatureAttributeHelp::Suggestion {
++                            span: mi.span(),
++                            suggestion: ident.name,
++                        },
++                    });
+                     continue;
+                 }
+                 None => {
+-                    bad_input(mi.span()).span_label(mi.span(), "expected just 
one word").emit();
++                    sess.emit_err(MalformedFeatureAttribute {
++                        span: mi.span(),
++                        help: MalformedFeatureAttributeHelp::Label { span: 
mi.span() },
++                    });
+                     continue;
+                 }
+             };
+ 
+-            if let Some(edition) = edition_enabled_features.get(&name) {
+-                let msg =
+-                    &format!("the feature `{}` is included in the Rust {} 
edition", name, edition);
+-                span_handler.struct_span_warn_with_code(mi.span(), msg, 
error_code!(E0705)).emit();
++            if let Some(&edition) = edition_enabled_features.get(&name) {
++                sess.emit_warning(FeatureIncludedInEdition {
++                    span: mi.span(),
++                    feature: name,
++                    edition,
++                });
+                 continue;
+             }
+ 
+@@ -159,7 +156,7 @@ fn get_features(
+                 if let FeatureState::Removed { reason } | 
FeatureState::Stabilized { reason } =
+                     state
+                 {
+-                    feature_removed(span_handler, mi.span(), *reason);
++                    feature_removed(sess, mi.span(), *reason);
+                     continue;
+                 }
+             }
+@@ -173,14 +170,7 @@ fn get_features(
+ 
+             if let Some(allowed) = 
sess.opts.unstable_opts.allow_features.as_ref() {
+                 if allowed.iter().all(|f| name.as_str() != f) {
+-                    struct_span_err!(
+-                        span_handler,
+-                        mi.span(),
+-                        E0725,
+-                        "the feature `{}` is not in the list of allowed 
features",
+-                        name
+-                    )
+-                    .emit();
++                    sess.emit_err(FeatureNotAllowed { span: mi.span(), name 
});
+                     continue;
+                 }
+             }
+@@ -221,7 +211,7 @@ pub fn features(
+         }
+         Some(attrs) => {
+             krate.attrs = attrs;
+-            let features = get_features(sess, diag, &krate.attrs);
++            let features = get_features(sess, &krate.attrs);
+             if err_count == diag.err_count() {
+                 // Avoid reconfiguring malformed `cfg_attr`s.
+                 strip_unconfigured.features = Some(&features);
+@@ -503,8 +493,7 @@ impl<'a> StripUnconfigured<'a> {
+         // N.B., this is intentionally not part of the visit_expr() function
+         //     in order for filter_map_expr() to be able to avoid this check
+         if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(*a)) {
+-            let msg = "removing an expression is not supported in this 
position";
+-            self.sess.parse_sess.span_diagnostic.span_err(attr.span, msg);
++            self.sess.emit_err(RemoveExprNotSupported { span: attr.span });
+         }
+ 
+         self.process_cfg_attrs(expr);
+@@ -513,27 +502,26 @@ impl<'a> StripUnconfigured<'a> {
+ }
+ 
+ pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a 
MetaItem> {
+-    let error = |span, msg, suggestion: &str| {
+-        let mut err = sess.parse_sess.span_diagnostic.struct_span_err(span, 
msg);
+-        if !suggestion.is_empty() {
+-            err.span_suggestion(
+-                span,
+-                "expected syntax is",
+-                suggestion,
+-                Applicability::HasPlaceholders,
+-            );
+-        }
+-        err.emit();
+-        None
+-    };
+     let span = meta_item.span;
+     match meta_item.meta_item_list() {
+-        None => error(span, "`cfg` is not followed by parentheses", "cfg(/* 
predicate */)"),
+-        Some([]) => error(span, "`cfg` predicate is not specified", ""),
+-        Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are 
specified", ""),
++        None => {
++            sess.emit_err(InvalidCfg::NotFollowedByParens { span });
++            None
++        }
++        Some([]) => {
++            sess.emit_err(InvalidCfg::NoPredicate { span });
++            None
++        }
++        Some([_, .., l]) => {
++            sess.emit_err(InvalidCfg::MultiplePredicates { span: l.span() });
++            None
++        }
+         Some([single]) => match single.meta_item() {
+             Some(meta_item) => Some(meta_item),
+-            None => error(single.span(), "`cfg` predicate key cannot be a 
literal", ""),
++            None => {
++                sess.emit_err(InvalidCfg::PredicateLiteral { span: 
single.span() });
++                None
++            }
+         },
+     }
+ }
+diff --git a/compiler/rustc_expand/src/errors.rs 
b/compiler/rustc_expand/src/errors.rs
+index d383f4832f699..afe5169d3f5c0 100644
+--- a/compiler/rustc_expand/src/errors.rs
++++ b/compiler/rustc_expand/src/errors.rs
+@@ -1,6 +1,10 @@
++use rustc_ast::ast;
+ use rustc_macros::Diagnostic;
+-use rustc_span::symbol::MacroRulesNormalizedIdent;
+-use rustc_span::Span;
++use rustc_session::Limit;
++use rustc_span::edition::Edition;
++use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
++use rustc_span::{Span, Symbol};
++use std::borrow::Cow;
+ 
+ #[derive(Diagnostic)]
+ #[diag(expand_expr_repeat_no_syntax_vars)]
+@@ -46,3 +50,321 @@ pub(crate) struct MetaVarsDifSeqMatchers {
+     pub span: Span,
+     pub msg: String,
+ }
++
++#[derive(Diagnostic)]
++#[diag(expand_resolve_relative_path)]
++pub(crate) struct ResolveRelativePath {
++    #[primary_span]
++    pub span: Span,
++    pub path: String,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_macro_const_stability)]
++pub(crate) struct MacroConstStability {
++    #[primary_span]
++    #[label]
++    pub span: Span,
++    #[label(label2)]
++    pub head_span: Span,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_macro_body_stability)]
++pub(crate) struct MacroBodyStability {
++    #[primary_span]
++    #[label]
++    pub span: Span,
++    #[label(label2)]
++    pub head_span: Span,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_attr_no_arguments)]
++pub(crate) struct AttrNoArguments {
++    #[primary_span]
++    pub span: Span,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_not_a_meta_item)]
++pub(crate) struct NotAMetaItem {
++    #[primary_span]
++    pub span: Span,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_only_one_word)]
++pub(crate) struct OnlyOneWord {
++    #[primary_span]
++    pub span: Span,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_cannot_be_name_of_macro)]
++pub(crate) struct CannotBeNameOfMacro<'a> {
++    #[primary_span]
++    pub span: Span,
++    pub trait_ident: Ident,
++    pub macro_type: &'a str,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_arg_not_attributes)]
++pub(crate) struct ArgumentNotAttributes {
++    #[primary_span]
++    pub span: Span,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_attributes_wrong_form)]
++pub(crate) struct AttributesWrongForm {
++    #[primary_span]
++    pub span: Span,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_attribute_meta_item)]
++pub(crate) struct AttributeMetaItem {
++    #[primary_span]
++    pub span: Span,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_attribute_single_word)]
++pub(crate) struct AttributeSingleWord {
++    #[primary_span]
++    pub span: Span,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_helper_attribute_name_invalid)]
++pub(crate) struct HelperAttributeNameInvalid {
++    #[primary_span]
++    pub span: Span,
++    pub name: Ident,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_expected_comma_in_list)]
++pub(crate) struct ExpectedCommaInList {
++    #[primary_span]
++    pub span: Span,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_only_one_argument)]
++pub(crate) struct OnlyOneArgument<'a> {
++    #[primary_span]
++    pub span: Span,
++    pub name: &'a str,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_takes_no_arguments)]
++pub(crate) struct TakesNoArguments<'a> {
++    #[primary_span]
++    pub span: Span,
++    pub name: &'a str,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_feature_included_in_edition, code = "E0705")]
++pub(crate) struct FeatureIncludedInEdition {
++    #[primary_span]
++    pub span: Span,
++    pub feature: Symbol,
++    pub edition: Edition,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_feature_removed, code = "E0557")]
++pub(crate) struct FeatureRemoved<'a> {
++    #[primary_span]
++    #[label]
++    pub span: Span,
++    #[subdiagnostic]
++    pub reason: Option<FeatureRemovedReason<'a>>,
++}
++
++#[derive(Subdiagnostic)]
++#[note(reason)]
++pub(crate) struct FeatureRemovedReason<'a> {
++    pub reason: &'a str,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_feature_not_allowed, code = "E0725")]
++pub(crate) struct FeatureNotAllowed {
++    #[primary_span]
++    pub span: Span,
++    pub name: Symbol,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_recursion_limit_reached)]
++#[help]
++pub(crate) struct RecursionLimitReached<'a> {
++    #[primary_span]
++    pub span: Span,
++    pub descr: String,
++    pub suggested_limit: Limit,
++    pub crate_name: &'a str,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_malformed_feature_attribute, code = "E0556")]
++pub(crate) struct MalformedFeatureAttribute {
++    #[primary_span]
++    pub span: Span,
++    #[subdiagnostic]
++    pub help: MalformedFeatureAttributeHelp,
++}
++
++#[derive(Subdiagnostic)]
++pub(crate) enum MalformedFeatureAttributeHelp {
++    #[label(expected)]
++    Label {
++        #[primary_span]
++        span: Span,
++    },
++    #[suggestion(expected, code = "{suggestion}", applicability = 
"maybe-incorrect")]
++    Suggestion {
++        #[primary_span]
++        span: Span,
++        suggestion: Symbol,
++    },
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_remove_expr_not_supported)]
++pub(crate) struct RemoveExprNotSupported {
++    #[primary_span]
++    pub span: Span,
++}
++
++#[derive(Diagnostic)]
++pub(crate) enum InvalidCfg {
++    #[diag(expand_invalid_cfg_no_parens)]
++    NotFollowedByParens {
++        #[primary_span]
++        #[suggestion(
++            expand_invalid_cfg_expected_syntax,
++            code = "cfg(/* predicate */)",
++            applicability = "has-placeholders"
++        )]
++        span: Span,
++    },
++    #[diag(expand_invalid_cfg_no_predicate)]
++    NoPredicate {
++        #[primary_span]
++        #[suggestion(
++            expand_invalid_cfg_expected_syntax,
++            code = "cfg(/* predicate */)",
++            applicability = "has-placeholders"
++        )]
++        span: Span,
++    },
++    #[diag(expand_invalid_cfg_multiple_predicates)]
++    MultiplePredicates {
++        #[primary_span]
++        span: Span,
++    },
++    #[diag(expand_invalid_cfg_predicate_literal)]
++    PredicateLiteral {
++        #[primary_span]
++        span: Span,
++    },
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_wrong_fragment_kind)]
++pub(crate) struct WrongFragmentKind<'a> {
++    #[primary_span]
++    pub span: Span,
++    pub kind: &'a str,
++    pub name: &'a ast::Path,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_unsupported_key_value)]
++pub(crate) struct UnsupportedKeyValue {
++    #[primary_span]
++    pub span: Span,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_incomplete_parse)]
++#[note]
++pub(crate) struct IncompleteParse<'a> {
++    #[primary_span]
++    pub span: Span,
++    pub token: Cow<'a, str>,
++    #[label]
++    pub label_span: Span,
++    pub macro_path: &'a ast::Path,
++    pub kind_name: &'a str,
++
++    #[suggestion(
++        suggestion_add_semi,
++        style = "verbose",
++        code = ";",
++        applicability = "maybe-incorrect"
++    )]
++    pub add_semicolon: Option<Span>,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_remove_node_not_supported)]
++pub(crate) struct RemoveNodeNotSupported {
++    #[primary_span]
++    pub span: Span,
++    pub descr: &'static str,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_module_circular)]
++pub(crate) struct ModuleCircular {
++    #[primary_span]
++    pub span: Span,
++    pub modules: String,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_module_in_block)]
++pub(crate) struct ModuleInBlock {
++    #[primary_span]
++    pub span: Span,
++    #[subdiagnostic]
++    pub name: Option<ModuleInBlockName>,
++}
++
++#[derive(Subdiagnostic)]
++#[note(note)]
++pub(crate) struct ModuleInBlockName {
++    #[primary_span]
++    pub span: Span,
++    pub name: Ident,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_module_file_not_found, code = "E0583")]
++#[help]
++pub(crate) struct ModuleFileNotFound {
++    #[primary_span]
++    pub span: Span,
++    pub name: Ident,
++    pub default_path: String,
++    pub secondary_path: String,
++}
++
++#[derive(Diagnostic)]
++#[diag(expand_module_multiple_candidates, code = "E0761")]
++#[help]
++pub(crate) struct ModuleMultipleCandidates {
++    #[primary_span]
++    pub span: Span,
++    pub name: Ident,
++    pub default_path: String,
++    pub secondary_path: String,
++}
+diff --git a/compiler/rustc_expand/src/expand.rs 
b/compiler/rustc_expand/src/expand.rs
+index 1014ec2209c61..e26c16dcd7ee7 100644
+--- a/compiler/rustc_expand/src/expand.rs
++++ b/compiler/rustc_expand/src/expand.rs
+@@ -1,5 +1,9 @@
+ use crate::base::*;
+ use crate::config::StripUnconfigured;
++use crate::errors::{
++    IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, 
RemoveNodeNotSupported,
++    UnsupportedKeyValue, WrongFragmentKind,
++};
+ use crate::hygiene::SyntaxContext;
+ use crate::mbe::diagnostics::annotate_err_with_kind;
+ use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, 
ParsedExternalMod};
+@@ -18,7 +22,7 @@ use rustc_ast::{NestedMetaItem, NodeId, PatKind, StmtKind, 
TyKind};
+ use rustc_ast_pretty::pprust;
+ use rustc_data_structures::map_in_place::MapInPlace;
+ use rustc_data_structures::sync::Lrc;
+-use rustc_errors::{Applicability, PResult};
++use rustc_errors::PResult;
+ use rustc_feature::Features;
+ use rustc_parse::parser::{
+     AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, 
RecoverColon, RecoverComma,
+@@ -606,29 +610,22 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
+             Limit(0) => Limit(2),
+             limit => limit * 2,
+         };
+-        self.cx
+-            .struct_span_err(
+-                expn_data.call_site,
+-                &format!("recursion limit reached while expanding `{}`", 
expn_data.kind.descr()),
+-            )
+-            .help(&format!(
+-                "consider increasing the recursion limit by adding a \
+-                 `#![recursion_limit = \"{}\"]` attribute to your crate 
(`{}`)",
+-                suggested_limit, self.cx.ecfg.crate_name,
+-            ))
+-            .emit();
++
++        self.cx.emit_err(RecursionLimitReached {
++            span: expn_data.call_site,
++            descr: expn_data.kind.descr(),
++            suggested_limit,
++            crate_name: &self.cx.ecfg.crate_name,
++        });
++
+         self.cx.trace_macros_diag();
+     }
+ 
+     /// A macro's expansion does not fit in this fragment kind.
+     /// For example, a non-type macro in a type position.
+     fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: 
&ast::MacCall, span: Span) {
+-        let msg = format!(
+-            "non-{kind} macro in {kind} position: {path}",
+-            kind = kind.name(),
+-            path = pprust::path_to_string(&mac.path),
+-        );
+-        self.cx.span_err(span, &msg);
++        self.cx.emit_err(WrongFragmentKind { span, kind: kind.name(), name: 
&mac.path });
++
+         self.cx.trace_macros_diag();
+     }
+ 
+@@ -707,7 +704,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
+                     };
+                     let attr_item = attr.unwrap_normal_item();
+                     if let AttrArgs::Eq(..) = attr_item.args {
+-                        self.cx.span_err(span, "key-value macro attributes 
are not supported");
++                        self.cx.emit_err(UnsupportedKeyValue { span });
+                     }
+                     let inner_tokens = attr_item.args.inner_tokens();
+                     let Ok(tok_result) = expander.expand(self.cx, span, 
inner_tokens, tokens) else {
+@@ -729,9 +726,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
+                                 }
+                             };
+                             if fragment_kind == AstFragmentKind::Expr && 
items.is_empty() {
+-                                let msg =
+-                                    "removing an expression is not supported 
in this position";
+-                                self.cx.span_err(span, msg);
++                                self.cx.emit_err(RemoveExprNotSupported { 
span });
+                                 fragment_kind.dummy(span)
+                             } else {
+                                 fragment_kind.expect_from_annotatables(items)
+@@ -939,38 +934,32 @@ pub fn parse_ast_fragment<'a>(
+ }
+ 
+ pub fn ensure_complete_parse<'a>(
+-    this: &mut Parser<'a>,
++    parser: &mut Parser<'a>,
+     macro_path: &ast::Path,
+     kind_name: &str,
+     span: Span,
+ ) {
+-    if this.token != token::Eof {
+-        let token = pprust::token_to_string(&this.token);
+-        let msg = format!("macro expansion ignores token `{}` and any 
following", token);
++    if parser.token != token::Eof {
++        let token = pprust::token_to_string(&parser.token);
+         // Avoid emitting backtrace info twice.
+-        let def_site_span = this.token.span.with_ctxt(SyntaxContext::root());
+-        let mut err = this.struct_span_err(def_site_span, &msg);
+-        err.span_label(span, "caused by the macro expansion here");
+-        let msg = format!(
+-            "the usage of `{}!` is likely invalid in {} context",
+-            pprust::path_to_string(macro_path),
+-            kind_name,
+-        );
+-        err.note(&msg);
++        let def_site_span = 
parser.token.span.with_ctxt(SyntaxContext::root());
+ 
+-        let semi_span = this.sess.source_map().next_point(span);
+-        match this.sess.source_map().span_to_snippet(semi_span) {
++        let semi_span = parser.sess.source_map().next_point(span);
++        let add_semicolon = match 
parser.sess.source_map().span_to_snippet(semi_span) {
+             Ok(ref snippet) if &snippet[..] != ";" && kind_name == 
"expression" => {
+-                err.span_suggestion(
+-                    span.shrink_to_hi(),
+-                    "you might be missing a semicolon here",
+-                    ";",
+-                    Applicability::MaybeIncorrect,
+-                );
++                Some(span.shrink_to_hi())
+             }
+-            _ => {}
+-        }
+-        err.emit();
++            _ => None,
++        };
++
++        parser.sess.emit_err(IncompleteParse {
++            span: def_site_span,
++            token,
++            label_span: span,
++            macro_path,
++            kind_name,
++            add_semicolon,
++        });
+     }
+ }
+ 
+@@ -1766,9 +1755,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
+                         if self.expand_cfg_true(node, attr, pos) {
+                             continue;
+                         }
+-                        let msg =
+-                            format!("removing {} is not supported in this 
position", Node::descr());
+-                        self.cx.span_err(span, &msg);
++
++                        self.cx.emit_err(RemoveNodeNotSupported { span, 
descr: Node::descr() });
+                         continue;
+                     }
+                     sym::cfg_attr => {
+diff --git a/compiler/rustc_expand/src/lib.rs 
b/compiler/rustc_expand/src/lib.rs
+index b34de94fb7db4..897268566358a 100644
+--- a/compiler/rustc_expand/src/lib.rs
++++ b/compiler/rustc_expand/src/lib.rs
+@@ -10,6 +10,7 @@
+ #![feature(rustc_attrs)]
+ #![feature(try_blocks)]
+ #![recursion_limit = "256"]
++#![deny(rustc::untranslatable_diagnostic)]
+ 
+ #[macro_use]
+ extern crate rustc_macros;
+@@ -31,8 +32,13 @@ pub mod config;
+ pub mod errors;
+ pub mod expand;
+ pub mod module;
++
++// FIXME(Nilstrieb) Translate proc_macro diagnostics
++#[allow(rustc::untranslatable_diagnostic)]
+ pub mod proc_macro;
+ 
++// FIXME(Nilstrieb) Translate macro_rules diagnostics
++#[allow(rustc::untranslatable_diagnostic)]
+ pub(crate) mod mbe;
+ 
+ // HACK(Centril, #64197): These shouldn't really be here.
+diff --git a/compiler/rustc_expand/src/module.rs 
b/compiler/rustc_expand/src/module.rs
+index 9002a24e42f9d..07f47a9c3a4f2 100644
+--- a/compiler/rustc_expand/src/module.rs
++++ b/compiler/rustc_expand/src/module.rs
+@@ -1,13 +1,17 @@
+ use crate::base::ModuleData;
++use crate::errors::{
++    ModuleCircular, ModuleFileNotFound, ModuleInBlock, ModuleInBlockName, 
ModuleMultipleCandidates,
++};
+ use rustc_ast::ptr::P;
+ use rustc_ast::{token, AttrVec, Attribute, Inline, Item, ModSpans};
+-use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
++use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
+ use rustc_parse::new_parser_from_file;
+ use rustc_parse::validate_attr;
+ use rustc_session::parse::ParseSess;
+ use rustc_session::Session;
+ use rustc_span::symbol::{sym, Ident};
+ use rustc_span::Span;
++use std::iter::once;
+ 
+ use std::path::{self, Path, PathBuf};
+ 
+@@ -242,57 +246,41 @@ pub fn default_submod_path<'a>(
+ 
+ impl ModError<'_> {
+     fn report(self, sess: &Session, span: Span) -> ErrorGuaranteed {
+-        let diag = &sess.parse_sess.span_diagnostic;
+         match self {
+             ModError::CircularInclusion(file_paths) => {
+-                let mut msg = String::from("circular modules: ");
+-                for file_path in &file_paths {
+-                    msg.push_str(&file_path.display().to_string());
+-                    msg.push_str(" -> ");
+-                }
+-                msg.push_str(&file_paths[0].display().to_string());
+-                diag.struct_span_err(span, &msg)
+-            }
+-            ModError::ModInBlock(ident) => {
+-                let msg = "cannot declare a non-inline module inside a block 
unless it has a path attribute";
+-                let mut err = diag.struct_span_err(span, msg);
+-                if let Some(ident) = ident {
+-                    let note =
+-                        format!("maybe `use` the module `{}` instead of 
redeclaring it", ident);
+-                    err.span_note(span, &note);
+-                }
+-                err
++                let path_to_string = |path: &PathBuf| 
path.display().to_string();
++
++                let paths = file_paths
++                    .iter()
++                    .map(path_to_string)
++                    .chain(once(path_to_string(&file_paths[0])))
++                    .collect::<Vec<_>>();
++
++                let modules = paths.join(" -> ");
++
++                sess.emit_err(ModuleCircular { span, modules })
+             }
+-            ModError::FileNotFound(ident, default_path, secondary_path) => {
+-                let mut err = struct_span_err!(
+-                    diag,
++            ModError::ModInBlock(ident) => sess.emit_err(ModuleInBlock {
++                span,
++                name: ident.map(|name| ModuleInBlockName { span, name }),
++            }),
++            ModError::FileNotFound(name, default_path, secondary_path) => {
++                sess.emit_err(ModuleFileNotFound {
+                     span,
+-                    E0583,
+-                    "file not found for module `{}`",
+-                    ident,
+-                );
+-                err.help(&format!(
+-                    "to create the module `{}`, create file \"{}\" or \"{}\"",
+-                    ident,
+-                    default_path.display(),
+-                    secondary_path.display(),
+-                ));
+-                err
++                    name,
++                    default_path: default_path.display().to_string(),
++                    secondary_path: secondary_path.display().to_string(),
++                })
+             }
+-            ModError::MultipleCandidates(ident, default_path, secondary_path) 
=> {
+-                let mut err = struct_span_err!(
+-                    diag,
++            ModError::MultipleCandidates(name, default_path, secondary_path) 
=> {
++                sess.emit_err(ModuleMultipleCandidates {
+                     span,
+-                    E0761,
+-                    "file for module `{}` found at both \"{}\" and \"{}\"",
+-                    ident,
+-                    default_path.display(),
+-                    secondary_path.display(),
+-                );
+-                err.help("delete or rename one of them to remove the 
ambiguity");
+-                err
++                    name,
++                    default_path: default_path.display().to_string(),
++                    secondary_path: secondary_path.display().to_string(),
++                })
+             }
+-            ModError::ParserError(err) => err,
+-        }.emit()
++            ModError::ParserError(mut err) => err.emit(),
++        }
+     }
+ }
+diff --git a/compiler/rustc_expand/src/tests.rs 
b/compiler/rustc_expand/src/tests.rs
+index 539b04535a0d0..8f3bea29ffd28 100644
+--- a/compiler/rustc_expand/src/tests.rs
++++ b/compiler/rustc_expand/src/tests.rs
+@@ -154,6 +154,7 @@ fn test_harness(file_text: &str, span_labels: 
Vec<SpanLabel>, expected_output: &
+             false,
+         );
+         let handler = Handler::with_emitter(true, None, Box::new(emitter));
++        #[allow(rustc::untranslatable_diagnostic)]
+         handler.span_err(msp, "foo");
+ 
+         assert!(
+diff --git a/src/test/rustdoc-ui/doc-cfg.stderr 
b/src/test/rustdoc-ui/doc-cfg.stderr
+index b379f6febe29f..14b7b17e04d3a 100644
+--- a/src/test/rustdoc-ui/doc-cfg.stderr
++++ b/src/test/rustdoc-ui/doc-cfg.stderr
+@@ -2,7 +2,7 @@ error: `cfg` predicate is not specified
+   --> $DIR/doc-cfg.rs:3:7
+    |
+ LL | #[doc(cfg(), cfg(foo, bar))]
+-   |       ^^^^^
++   |       ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
+ 
+ error: multiple `cfg` predicates are specified
+   --> $DIR/doc-cfg.rs:3:23
+@@ -14,7 +14,7 @@ error: `cfg` predicate is not specified
+   --> $DIR/doc-cfg.rs:7:7
+    |
+ LL | #[doc(cfg())]
+-   |       ^^^^^
++   |       ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
+ 
+ error: multiple `cfg` predicates are specified
+   --> $DIR/doc-cfg.rs:8:16
+diff --git 
a/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr 
b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
+index d4bd673b84e1b..d5b4349c00f6f 100644
+--- a/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
++++ b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
+@@ -14,7 +14,7 @@ error: `cfg` predicate is not specified
+   --> $DIR/cfg-attr-syntax-validation.rs:7:1
+    |
+ LL | #[cfg()]
+-   | ^^^^^^^^
++   | ^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
+ 
+ error: multiple `cfg` predicates are specified
+   --> $DIR/cfg-attr-syntax-validation.rs:10:10
+diff --git a/src/test/ui/macros/macro-in-expression-context.stderr 
b/src/test/ui/macros/macro-in-expression-context.stderr
+index 1023189eaa30f..36aba8aa08a0b 100644
+--- a/src/test/ui/macros/macro-in-expression-context.stderr
++++ b/src/test/ui/macros/macro-in-expression-context.stderr
+@@ -5,11 +5,13 @@ LL |         assert_eq!("B", "B");
+    |         ^^^^^^^^^
+ ...
+ LL |     foo!()
+-   |     ------- help: you might be missing a semicolon here: `;`
+-   |     |
+-   |     caused by the macro expansion here
++   |     ------ caused by the macro expansion here
+    |
+    = note: the usage of `foo!` is likely invalid in expression context
++help: you might be missing a semicolon here
++   |
++LL |     foo!();
++   |           +
+ 
+ warning: trailing semicolon in macro used in expression position
+   --> $DIR/macro-in-expression-context.rs:5:29
+diff --git a/src/test/ui/proc-macro/attr-invalid-exprs.stderr 
b/src/test/ui/proc-macro/attr-invalid-exprs.stderr
+index bcb54df0ecac7..f96939bb6efce 100644
+--- a/src/test/ui/proc-macro/attr-invalid-exprs.stderr
++++ b/src/test/ui/proc-macro/attr-invalid-exprs.stderr
+@@ -8,21 +8,25 @@ error: macro expansion ignores token `,` and any following
+   --> $DIR/attr-invalid-exprs.rs:15:13
+    |
+ LL |     let _ = #[duplicate] "Hello, world!";
+-   |             ^^^^^^^^^^^^- help: you might be missing a semicolon here: 
`;`
+-   |             |
+-   |             caused by the macro expansion here
++   |             ^^^^^^^^^^^^ caused by the macro expansion here
+    |
+    = note: the usage of `duplicate!` is likely invalid in expression context
++help: you might be missing a semicolon here
++   |
++LL |     let _ = #[duplicate]; "Hello, world!";
++   |                         +
+ 
+ error: macro expansion ignores token `,` and any following
+   --> $DIR/attr-invalid-exprs.rs:24:9
+    |
+ LL |         #[duplicate]
+-   |         ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;`
+-   |         |
+-   |         caused by the macro expansion here
++   |         ^^^^^^^^^^^^ caused by the macro expansion here
+    |
+    = note: the usage of `duplicate!` is likely invalid in expression context
++help: you might be missing a semicolon here
++   |
++LL |         #[duplicate];
++   |                     +
+ 
+ error: aborting due to 3 previous errors
+ 
+diff --git a/src/test/ui/proc-macro/attribute.rs 
b/src/test/ui/proc-macro/attribute.rs
+index 5531b32362125..9e40e4d9ba63e 100644
+--- a/src/test/ui/proc-macro/attribute.rs
++++ b/src/test/ui/proc-macro/attribute.rs
+@@ -53,19 +53,19 @@ pub fn foo11(input: TokenStream) -> TokenStream { input }
+ pub fn foo12(input: TokenStream) -> TokenStream { input }
+ 
+ #[proc_macro_derive(d13, attributes("a"))]
+-//~^ ERROR: not a meta item
++//~^ ERROR: attribute must be a meta item, not a literal
+ pub fn foo13(input: TokenStream) -> TokenStream { input }
+ 
+ #[proc_macro_derive(d14, attributes(a = ""))]
+-//~^ ERROR: must only be one word
++//~^ ERROR: attribute must only be a single word
+ pub fn foo14(input: TokenStream) -> TokenStream { input }
+ 
+ #[proc_macro_derive(d15, attributes(m::a))]
+-//~^ ERROR: must only be one word
++//~^ ERROR: attribute must only be a single word
+ pub fn foo15(input: TokenStream) -> TokenStream { input }
+ 
+ #[proc_macro_derive(d16, attributes(a(b)))]
+-//~^ ERROR: must only be one word
++//~^ ERROR: attribute must only be a single word
+ pub fn foo16(input: TokenStream) -> TokenStream { input }
+ 
+ #[proc_macro_derive(d17, attributes(self))]
+diff --git a/src/test/ui/proc-macro/attribute.stderr 
b/src/test/ui/proc-macro/attribute.stderr
+index 021e7cad09b69..3269aaf7f917e 100644
+--- a/src/test/ui/proc-macro/attribute.stderr
++++ b/src/test/ui/proc-macro/attribute.stderr
+@@ -70,25 +70,25 @@ error: attribute must be of form: `attributes(foo, bar)`
+ LL | #[proc_macro_derive(d12, attributes)]
+    |                          ^^^^^^^^^^
+ 
+-error: not a meta item
++error: attribute must be a meta item, not a literal
+   --> $DIR/attribute.rs:55:37
+    |
+ LL | #[proc_macro_derive(d13, attributes("a"))]
+    |                                     ^^^
+ 
+-error: must only be one word
++error: attribute must only be a single word
+   --> $DIR/attribute.rs:59:37
+    |
+ LL | #[proc_macro_derive(d14, attributes(a = ""))]
+    |                                     ^^^^^^
+ 
+-error: must only be one word
++error: attribute must only be a single word
+   --> $DIR/attribute.rs:63:37
+    |
+ LL | #[proc_macro_derive(d15, attributes(m::a))]
+    |                                     ^^^^
+ 
+-error: must only be one word
++error: attribute must only be a single word
+   --> $DIR/attribute.rs:67:37
+    |
+ LL | #[proc_macro_derive(d16, attributes(a(b)))]
+diff --git a/src/test/ui/proc-macro/expand-expr.stderr 
b/src/test/ui/proc-macro/expand-expr.stderr
+index c6c4695fd9c43..0004f2fe17f01 100644
+--- a/src/test/ui/proc-macro/expand-expr.stderr
++++ b/src/test/ui/proc-macro/expand-expr.stderr
+@@ -26,21 +26,25 @@ error: macro expansion ignores token `hello` and any 
following
+   --> $DIR/expand-expr.rs:115:47
+    |
+ LL | expand_expr_is!("string", echo_tts!("string"; hello));
+-   |                           --------------------^^^^^-- help: you might be 
missing a semicolon here: `;`
+-   |                           |
+-   |                           caused by the macro expansion here
++   |                           --------------------^^^^^- caused by the macro 
expansion here
+    |
+    = note: the usage of `echo_tts!` is likely invalid in expression context
++help: you might be missing a semicolon here
++   |
++LL | expand_expr_is!("string", echo_tts!("string"; hello););
++   |                                                     +
+ 
+ error: macro expansion ignores token `;` and any following
+   --> $DIR/expand-expr.rs:116:44
+    |
+ LL | expand_expr_is!("string", echo_pm!("string"; hello));
+-   |                           -----------------^-------- help: you might be 
missing a semicolon here: `;`
+-   |                           |
+-   |                           caused by the macro expansion here
++   |                           -----------------^------- caused by the macro 
expansion here
+    |
+    = note: the usage of `echo_pm!` is likely invalid in expression context
++help: you might be missing a semicolon here
++   |
++LL | expand_expr_is!("string", echo_pm!("string"; hello););
++   |                                                    +
+ 
+ error: recursion limit reached while expanding `recursive_expand!`
+   --> $DIR/expand-expr.rs:124:16

diff --git a/dev-lang/rust/rust-1.67.1.ebuild 
b/dev-lang/rust/rust-1.67.1-r1.ebuild
similarity index 99%
rename from dev-lang/rust/rust-1.67.1.ebuild
rename to dev-lang/rust/rust-1.67.1-r1.ebuild
index 4c66b8e3b4c4..663f1323a4ef 100644
--- a/dev-lang/rust/rust-1.67.1.ebuild
+++ b/dev-lang/rust/rust-1.67.1-r1.ebuild
@@ -165,6 +165,7 @@ PATCHES=(
        "${FILESDIR}"/1.65.0-ignore-broken-and-non-applicable-tests.patch
        "${FILESDIR}"/1.62.1-musl-dynamic-linking.patch
        "${FILESDIR}"/1.67.0-doc-wasm.patch
+       "${FILESDIR}"/1.67.1-rustc_expand.patch
 )
 
 S="${WORKDIR}/${MY_P}-src"

Reply via email to