about summary refs log tree commit diff
diff options
context:
space:
mode:
authormejrs <59372212+mejrs@users.noreply.github.com>2025-03-27 23:09:44 +0100
committermejrs <59372212+mejrs@users.noreply.github.com>2025-04-10 17:28:23 +0200
commitba9f51b05503a567cb637db03eaa943c59e36922 (patch)
tree1d1f2c7d4385f16f490fda0b7bccd512a14df710
parent2007c8994db6d46533f84f4697fea5734c6df53d (diff)
downloadrust-ba9f51b05503a567cb637db03eaa943c59e36922.tar.gz
rust-ba9f51b05503a567cb637db03eaa943c59e36922.zip
Parse condition options into a struct
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs178
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_condition.rs45
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs110
3 files changed, 168 insertions, 165 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
index 6a7f3223421..7d8ecba3b2e 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
@@ -2,14 +2,13 @@ use std::iter;
 use std::path::PathBuf;
 
 use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit};
-use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::codes::*;
 use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{AttrArgs, Attribute};
 use rustc_middle::bug;
-use rustc_middle::ty::print::PrintTraitRefExt as _;
-use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, TyCtxt};
+use rustc_middle::ty::print::PrintTraitRefExt;
+use rustc_middle::ty::{self, GenericArgsRef, GenericParamDef, GenericParamDefKind, TyCtxt};
 use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES;
 use rustc_span::{Span, Symbol, sym};
 use tracing::{debug, info};
@@ -17,9 +16,9 @@ use {rustc_attr_parsing as attr, rustc_hir as hir};
 
 use super::{ObligationCauseCode, PredicateObligation};
 use crate::error_reporting::TypeErrCtxt;
-use crate::error_reporting::traits::on_unimplemented_condition::Condition;
+use crate::error_reporting::traits::on_unimplemented_condition::{Condition, ConditionOptions};
 use crate::error_reporting::traits::on_unimplemented_format::errors::*;
-use crate::error_reporting::traits::on_unimplemented_format::{Ctx, FormatString};
+use crate::error_reporting::traits::on_unimplemented_format::{Ctx, FormatArgs, FormatString};
 use crate::errors::{
     EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
 };
@@ -107,86 +106,81 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             .unwrap_or_else(|| (trait_pred.def_id(), trait_pred.skip_binder().trait_ref.args));
         let trait_pred = trait_pred.skip_binder();
 
-        let mut flags = vec![];
+        let mut self_types = vec![];
+        let mut generic_args: Vec<(Symbol, String)> = vec![];
+        let mut crate_local = false;
         // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): HIR is not present for RPITITs,
         // but I guess we could synthesize one here. We don't see any errors that rely on
         // that yet, though.
-        let enclosure = self.describe_enclosure(obligation.cause.body_id).map(|t| t.to_owned());
-        flags.push((sym::ItemContext, enclosure));
+        let item_context = self
+            .describe_enclosure(obligation.cause.body_id)
+            .map(|t| t.to_owned())
+            .unwrap_or(String::new());
 
-        match obligation.cause.code() {
+        let direct = match obligation.cause.code() {
             ObligationCauseCode::BuiltinDerived(..)
             | ObligationCauseCode::ImplDerived(..)
-            | ObligationCauseCode::WellFormedDerived(..) => {}
+            | ObligationCauseCode::WellFormedDerived(..) => false,
             _ => {
                 // this is a "direct", user-specified, rather than derived,
                 // obligation.
-                flags.push((sym::direct, None));
+                true
             }
-        }
-
-        if let Some(k) = obligation.cause.span.desugaring_kind() {
-            flags.push((sym::from_desugaring, None));
-            flags.push((sym::from_desugaring, Some(format!("{k:?}"))));
-        }
+        };
 
-        if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
-            flags.push((sym::cause, Some("MainFunctionType".to_string())));
-        }
+        let from_desugaring = obligation.cause.span.desugaring_kind().map(|k| format!("{k:?}"));
 
-        flags.push((sym::Trait, Some(trait_pred.trait_ref.print_trait_sugared().to_string())));
+        let cause = if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
+            Some("MainFunctionType".to_string())
+        } else {
+            None
+        };
 
         // Add all types without trimmed paths or visible paths, ensuring they end up with
         // their "canonical" def path.
         ty::print::with_no_trimmed_paths!(ty::print::with_no_visible_paths!({
             let generics = self.tcx.generics_of(def_id);
             let self_ty = trait_pred.self_ty();
-            // This is also included through the generics list as `Self`,
-            // but the parser won't allow you to use it
-            flags.push((sym::_Self, Some(self_ty.to_string())));
+            self_types.push(self_ty.to_string());
             if let Some(def) = self_ty.ty_adt_def() {
                 // We also want to be able to select self's original
                 // signature with no type arguments resolved
-                flags.push((
-                    sym::_Self,
-                    Some(self.tcx.type_of(def.did()).instantiate_identity().to_string()),
-                ));
+                self_types.push(self.tcx.type_of(def.did()).instantiate_identity().to_string());
             }
 
-            for param in generics.own_params.iter() {
-                let value = match param.kind {
+            for GenericParamDef { name, kind, index, .. } in generics.own_params.iter() {
+                let value = match kind {
                     GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
-                        args[param.index as usize].to_string()
+                        args[*index as usize].to_string()
                     }
                     GenericParamDefKind::Lifetime => continue,
                 };
-                let name = param.name;
-                flags.push((name, Some(value)));
+                generic_args.push((*name, value));
 
-                if let GenericParamDefKind::Type { .. } = param.kind {
-                    let param_ty = args[param.index as usize].expect_ty();
+                if let GenericParamDefKind::Type { .. } = kind {
+                    let param_ty = args[*index as usize].expect_ty();
                     if let Some(def) = param_ty.ty_adt_def() {
                         // We also want to be able to select the parameter's
                         // original signature with no type arguments resolved
-                        flags.push((
-                            name,
-                            Some(self.tcx.type_of(def.did()).instantiate_identity().to_string()),
+                        generic_args.push((
+                            *name,
+                            self.tcx.type_of(def.did()).instantiate_identity().to_string(),
                         ));
                     }
                 }
             }
 
             if let Some(true) = self_ty.ty_adt_def().map(|def| def.did().is_local()) {
-                flags.push((sym::crate_local, None));
+                crate_local = true;
             }
 
             // Allow targeting all integers using `{integral}`, even if the exact type was resolved
             if self_ty.is_integral() {
-                flags.push((sym::_Self, Some("{integral}".to_owned())));
+                self_types.push("{integral}".to_owned());
             }
 
             if self_ty.is_array_slice() {
-                flags.push((sym::_Self, Some("&[]".to_owned())));
+                self_types.push("&[]".to_owned());
             }
 
             if self_ty.is_fn() {
@@ -201,53 +195,51 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         hir::Safety::Unsafe => "unsafe fn",
                     }
                 };
-                flags.push((sym::_Self, Some(shortname.to_owned())));
+                self_types.push(shortname.to_owned());
             }
 
             // Slices give us `[]`, `[{ty}]`
             if let ty::Slice(aty) = self_ty.kind() {
-                flags.push((sym::_Self, Some("[]".to_string())));
+                self_types.push("[]".to_owned());
                 if let Some(def) = aty.ty_adt_def() {
                     // We also want to be able to select the slice's type's original
                     // signature with no type arguments resolved
-                    flags.push((
-                        sym::_Self,
-                        Some(format!("[{}]", self.tcx.type_of(def.did()).instantiate_identity())),
-                    ));
+                    self_types
+                        .push(format!("[{}]", self.tcx.type_of(def.did()).instantiate_identity()));
                 }
                 if aty.is_integral() {
-                    flags.push((sym::_Self, Some("[{integral}]".to_string())));
+                    self_types.push("[{integral}]".to_string());
                 }
             }
 
             // Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
             if let ty::Array(aty, len) = self_ty.kind() {
-                flags.push((sym::_Self, Some("[]".to_string())));
+                self_types.push("[]".to_string());
                 let len = len.try_to_target_usize(self.tcx);
-                flags.push((sym::_Self, Some(format!("[{aty}; _]"))));
+                self_types.push(format!("[{aty}; _]"));
                 if let Some(n) = len {
-                    flags.push((sym::_Self, Some(format!("[{aty}; {n}]"))));
+                    self_types.push(format!("[{aty}; {n}]"));
                 }
                 if let Some(def) = aty.ty_adt_def() {
                     // We also want to be able to select the array's type's original
                     // signature with no type arguments resolved
                     let def_ty = self.tcx.type_of(def.did()).instantiate_identity();
-                    flags.push((sym::_Self, Some(format!("[{def_ty}; _]"))));
+                    self_types.push(format!("[{def_ty}; _]"));
                     if let Some(n) = len {
-                        flags.push((sym::_Self, Some(format!("[{def_ty}; {n}]"))));
+                        self_types.push(format!("[{def_ty}; {n}]"));
                     }
                 }
                 if aty.is_integral() {
-                    flags.push((sym::_Self, Some("[{integral}; _]".to_string())));
+                    self_types.push("[{integral}; _]".to_string());
                     if let Some(n) = len {
-                        flags.push((sym::_Self, Some(format!("[{{integral}}; {n}]"))));
+                        self_types.push(format!("[{{integral}}; {n}]"));
                     }
                 }
             }
             if let ty::Dynamic(traits, _, _) = self_ty.kind() {
                 for t in traits.iter() {
                     if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() {
-                        flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id))))
+                        self_types.push(self.tcx.def_path_str(trait_ref.def_id));
                     }
                 }
             }
@@ -257,14 +249,51 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 && let ty::Slice(sty) = ref_ty.kind()
                 && sty.is_integral()
             {
-                flags.push((sym::_Self, Some("&[{integral}]".to_owned())));
+                self_types.push("&[{integral}]".to_owned());
             }
         }));
 
-        flags.push((sym::This, Some(self.tcx.def_path_str(trait_pred.trait_ref.def_id))));
+        let this = self.tcx.def_path_str(trait_pred.trait_ref.def_id).to_string();
+        let trait_sugared = trait_pred.trait_ref.print_trait_sugared().to_string();
+
+        let condition_options = ConditionOptions {
+            self_types,
+            from_desugaring,
+            cause,
+            crate_local,
+            direct,
+            generic_args,
+        };
+
+        // Unlike the generic_args earlier,
+        // this one is *not* collected under `with_no_trimmed_paths!`
+        // for printing the type to the user
+        let generic_args = self
+            .tcx
+            .generics_of(trait_pred.trait_ref.def_id)
+            .own_params
+            .iter()
+            .filter_map(|param| {
+                let value = match param.kind {
+                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
+                        if let Some(ty) = trait_pred.trait_ref.args[param.index as usize].as_type()
+                        {
+                            self.tcx.short_string(ty, long_ty_file)
+                        } else {
+                            trait_pred.trait_ref.args[param.index as usize].to_string()
+                        }
+                    }
+                    GenericParamDefKind::Lifetime => return None,
+                };
+                let name = param.name;
+                Some((name, value))
+            })
+            .collect();
+
+        let format_args = FormatArgs { this, trait_sugared, generic_args, item_context };
 
         if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, def_id) {
-            command.evaluate(self.tcx, trait_pred.trait_ref, &flags, long_ty_file)
+            command.evaluate(self.tcx, trait_pred.trait_ref, &condition_options, &format_args)
         } else {
             OnUnimplementedNote::default()
         }
@@ -634,23 +663,23 @@ impl<'tcx> OnUnimplementedDirective {
         &self,
         tcx: TyCtxt<'tcx>,
         trait_ref: ty::TraitRef<'tcx>,
-        options: &[(Symbol, Option<String>)],
-        long_ty_file: &mut Option<PathBuf>,
+        condition_options: &ConditionOptions,
+        args: &FormatArgs,
     ) -> OnUnimplementedNote {
         let mut message = None;
         let mut label = None;
         let mut notes = Vec::new();
         let mut parent_label = None;
         let mut append_const_msg = None;
-        info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
-
-        let options_map: FxHashMap<Symbol, String> =
-            options.iter().filter_map(|(k, v)| v.clone().map(|v| (*k, v))).collect();
+        info!(
+            "evaluate({:?}, trait_ref={:?}, options={:?}, args ={:?})",
+            self, trait_ref, condition_options, args
+        );
 
         for command in self.subcommands.iter().chain(Some(self)).rev() {
             debug!(?command);
             if let Some(ref condition) = command.condition
-                && !condition.matches_predicate(tcx, options, &options_map)
+                && !condition.matches_predicate(tcx, condition_options)
             {
                 debug!("evaluate: skipping {:?} due to condition", command);
                 continue;
@@ -674,14 +703,10 @@ impl<'tcx> OnUnimplementedDirective {
         }
 
         OnUnimplementedNote {
-            label: label.map(|l| l.1.format(tcx, trait_ref, &options_map, long_ty_file)),
-            message: message.map(|m| m.1.format(tcx, trait_ref, &options_map, long_ty_file)),
-            notes: notes
-                .into_iter()
-                .map(|n| n.format(tcx, trait_ref, &options_map, long_ty_file))
-                .collect(),
-            parent_label: parent_label
-                .map(|e_s| e_s.format(tcx, trait_ref, &options_map, long_ty_file)),
+            label: label.map(|l| l.1.format(tcx, trait_ref, args)),
+            message: message.map(|m| m.1.format(tcx, trait_ref, args)),
+            notes: notes.into_iter().map(|n| n.format(tcx, trait_ref, args)).collect(),
+            parent_label: parent_label.map(|e_s| e_s.format(tcx, trait_ref, args)),
             append_const_msg,
         }
     }
@@ -759,8 +784,7 @@ impl<'tcx> OnUnimplementedFormatString {
         &self,
         tcx: TyCtxt<'tcx>,
         trait_ref: ty::TraitRef<'tcx>,
-        options: &FxHashMap<Symbol, String>,
-        long_ty_file: &mut Option<PathBuf>,
+        args: &FormatArgs,
     ) -> String {
         let trait_def_id = trait_ref.def_id;
         let ctx = if self.is_diagnostic_namespace_variant {
@@ -770,7 +794,7 @@ impl<'tcx> OnUnimplementedFormatString {
         };
 
         if let Ok(s) = FormatString::parse(self.symbol, self.span, &ctx) {
-            s.format(tcx, trait_ref, options, long_ty_file)
+            s.format(args)
         } else {
             // we cannot return errors from processing the format string as hard error here
             // as the diagnostic namespace guarantees that malformed input cannot cause an error
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_condition.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_condition.rs
index 4c852c1023a..491ba6d7ffc 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_condition.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_condition.rs
@@ -1,9 +1,8 @@
 use rustc_ast::MetaItemInner;
 use rustc_attr_parsing as attr;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_parse_format::{ParseMode, Parser, Piece, Position};
-use rustc_span::{Span, Symbol, sym};
+use rustc_span::{Span, Symbol, kw, sym};
 
 pub static ALLOWED_CONDITION_SYMBOLS: &[Symbol] = &[
     sym::from_desugaring,
@@ -26,12 +25,7 @@ impl Condition {
         self.inner.span()
     }
 
-    pub fn matches_predicate<'tcx>(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        options: &[(Symbol, Option<String>)],
-        options_map: &FxHashMap<Symbol, String>,
-    ) -> bool {
+    pub fn matches_predicate<'tcx>(&self, tcx: TyCtxt<'tcx>, options: &ConditionOptions) -> bool {
         attr::eval_condition(&self.inner, tcx.sess, Some(tcx.features()), &mut |cfg| {
             let value = cfg.value.map(|v| {
                 // `with_no_visible_paths` is also used when generating the options,
@@ -44,8 +38,8 @@ impl Condition {
                             Piece::NextArgument(a) => match a.position {
                                 Position::ArgumentNamed(arg) => {
                                     let s = Symbol::intern(arg);
-                                    match options_map.get(&s) {
-                                        Some(val) => val.to_string(),
+                                    match options.generic_args.iter().find(|(k, _)| *k == s) {
+                                        Some((_, val)) => val.to_string(),
                                         None => format!("{{{arg}}}"),
                                     }
                                 }
@@ -58,7 +52,36 @@ impl Condition {
                 })
             });
 
-            options.contains(&(cfg.name, value))
+            options.contains(cfg.name, &value)
         })
     }
 }
+
+#[derive(Debug)]
+pub struct ConditionOptions {
+    pub self_types: Vec<String>,
+    pub from_desugaring: Option<String>,
+    pub cause: Option<String>,
+    pub crate_local: bool,
+    pub direct: bool,
+    pub generic_args: Vec<(Symbol, String)>,
+}
+
+impl ConditionOptions {
+    pub fn contains(&self, key: Symbol, value: &Option<String>) -> bool {
+        match (key, value) {
+            (sym::_Self | kw::SelfUpper, Some(value)) => self.self_types.contains(&value),
+            // from_desugaring as a flag
+            (sym::from_desugaring, None) => self.from_desugaring.is_some(),
+            // from_desugaring as key == value
+            (sym::from_desugaring, v) => *v == self.from_desugaring,
+            (sym::cause, Some(value)) => self.cause.as_deref() == Some(value),
+            (sym::crate_local, None) => self.crate_local,
+            (sym::direct, None) => self.direct,
+            (other, Some(value)) => {
+                self.generic_args.iter().any(|(k, v)| *k == other && v == value)
+            }
+            _ => false,
+        }
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs
index 21db207496c..1bf15a34509 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs
@@ -1,10 +1,5 @@
-use std::fmt::Write;
-use std::path::PathBuf;
-
 use errors::*;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_middle::span_bug;
-use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 use rustc_parse_format::{
     Alignment, Argument, Count, FormatSpec, InnerSpan, ParseError, ParseMode, Parser,
     Piece as RpfPiece, Position,
@@ -13,6 +8,7 @@ use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES;
 use rustc_span::def_id::DefId;
 use rustc_span::{BytePos, Pos, Span, Symbol, kw, sym};
 
+#[allow(dead_code)]
 pub struct FormatString {
     input: Symbol,
     input_span: Span,
@@ -99,6 +95,24 @@ impl FormatWarning {
     }
 }
 
+#[derive(Debug)]
+pub struct ConditionOptions {
+    pub self_types: Vec<String>,
+    pub from_desugaring: Option<String>,
+    pub cause: Option<String>,
+    pub crate_local: bool,
+    pub direct: bool,
+    pub generic_args: Vec<(Symbol, String)>,
+}
+
+#[derive(Debug)]
+pub struct FormatArgs {
+    pub this: String,
+    pub trait_sugared: String,
+    pub item_context: String,
+    pub generic_args: Vec<(Symbol, String)>,
+}
+
 impl FormatString {
     pub fn parse(input: Symbol, input_span: Span, ctx: &Ctx<'_>) -> Result<Self, Vec<ParseError>> {
         let s = input.as_str();
@@ -126,92 +140,34 @@ impl FormatString {
         }
     }
 
-    pub fn format<'tcx>(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        trait_ref: ty::TraitRef<'tcx>,
-        options: &FxHashMap<Symbol, String>,
-        long_ty_file: &mut Option<PathBuf>,
-    ) -> String {
-        let generics = tcx.generics_of(trait_ref.def_id);
-        let generic_map = generics
-            .own_params
-            .iter()
-            .filter_map(|param| {
-                let value = match param.kind {
-                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
-                        if let Some(ty) = trait_ref.args[param.index as usize].as_type() {
-                            tcx.short_string(ty, long_ty_file)
-                        } else {
-                            trait_ref.args[param.index as usize].to_string()
-                        }
-                    }
-                    GenericParamDefKind::Lifetime => return None,
-                };
-                let name = param.name;
-                Some((name, value))
-            })
-            .collect::<FxHashMap<Symbol, String>>();
-
+    pub fn format(&self, args: &FormatArgs) -> String {
         let mut ret = String::new();
         for piece in &self.pieces {
             match piece {
                 Piece::Lit(s) | Piece::Arg(FormatArg::AsIs(s)) => ret.push_str(&s),
 
                 // `A` if we have `trait Trait<A> {}` and `note = "i'm the actual type of {A}"`
-                Piece::Arg(FormatArg::GenericParam { generic_param, span }) => {
+                Piece::Arg(FormatArg::GenericParam { generic_param, .. }) => {
                     // Should always be some but we can't raise errors here
-                    if let Some(value) = generic_map.get(&generic_param) {
-                        ret.push_str(value);
-                    } else if cfg!(debug_assertions) {
-                        span_bug!(*span, "invalid generic parameter");
-                    } else {
-                        let _ = ret.write_fmt(format_args!("{{{}}}", generic_param.as_str()));
-                    }
+                    let value = match args.generic_args.iter().find(|(p, _)| p == generic_param) {
+                        Some((_, val)) => val.to_string(),
+                        None => generic_param.to_string(),
+                    };
+                    ret.push_str(&value);
                 }
                 // `{Self}`
                 Piece::Arg(FormatArg::SelfUpper) => {
-                    let Some(slf) = generic_map.get(&kw::SelfUpper) else {
-                        span_bug!(
-                            self.input_span,
-                            "broken format string {:?} for {:?}: \
-                                  no argument matching `Self`",
-                            self.input,
-                            trait_ref,
-                        )
+                    let slf = match args.generic_args.iter().find(|(p, _)| *p == kw::SelfUpper) {
+                        Some((_, val)) => val.to_string(),
+                        None => "Self".to_string(),
                     };
                     ret.push_str(&slf);
                 }
 
                 // It's only `rustc_onunimplemented` from here
-                Piece::Arg(FormatArg::This) => {
-                    let Some(this) = options.get(&sym::This) else {
-                        span_bug!(
-                            self.input_span,
-                            "broken format string {:?} for {:?}: \
-                                      no argument matching This",
-                            self.input,
-                            trait_ref,
-                        )
-                    };
-                    ret.push_str(this);
-                }
-                Piece::Arg(FormatArg::Trait) => {
-                    let Some(this) = options.get(&sym::Trait) else {
-                        span_bug!(
-                            self.input_span,
-                            "broken format string {:?} for {:?}: \
-                                      no argument matching Trait",
-                            self.input,
-                            trait_ref,
-                        )
-                    };
-                    ret.push_str(this);
-                }
-                Piece::Arg(FormatArg::ItemContext) => {
-                    let itemcontext = options.get(&sym::ItemContext);
-                    ret.push_str(itemcontext.unwrap_or(&String::new()));
-                }
+                Piece::Arg(FormatArg::This) => ret.push_str(&args.this),
+                Piece::Arg(FormatArg::Trait) => ret.push_str(&args.trait_sugared),
+                Piece::Arg(FormatArg::ItemContext) => ret.push_str(&args.item_context),
             }
         }
         ret