diff options
| author | León Orell Valerian Liehr <me@fmease.dev> | 2023-10-30 10:48:18 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-10-30 10:48:18 +0100 |
| commit | 5eb76fac7cd9920b004b29e10ec3f360abe5ad48 (patch) | |
| tree | 7e5c6d7729d5bd41e6d1bdd888d3d582c42a119c /compiler/rustc_trait_selection/src | |
| parent | 098bb3703c59be69351dd792977d654ed2e9ff94 (diff) | |
| parent | 160b1793b2e29cfb10d7c7a5932ccb7f991f02bd (diff) | |
| download | rust-5eb76fac7cd9920b004b29e10ec3f360abe5ad48.tar.gz rust-5eb76fac7cd9920b004b29e10ec3f360abe5ad48.zip | |
Rollup merge of #117205 - weiznich:multiple_notes_for_on_unimplemented, r=compiler-errors
Allows `#[diagnostic::on_unimplemented]` attributes to have multiple notes This commit extends the `#[diagnostic::on_unimplemented]` (and `#[rustc_on_unimplemented]`) attributes to allow multiple `note` options. This enables emitting multiple notes for custom error messages. For now I've opted to not change any of the existing usages of `#[rustc_on_unimplemented]` and just updated the relevant compile tests. r? `@compiler-errors` I'm happy to adjust any of the existing changed location to emit the old error message if that's desired.
Diffstat (limited to 'compiler/rustc_trait_selection/src')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs | 32 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs | 14 |
2 files changed, 24 insertions, 22 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index c96e41b88bd..a5508c74134 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -319,7 +319,7 @@ pub struct OnUnimplementedDirective { pub subcommands: Vec<OnUnimplementedDirective>, pub message: Option<OnUnimplementedFormatString>, pub label: Option<OnUnimplementedFormatString>, - pub note: Option<OnUnimplementedFormatString>, + pub notes: Vec<OnUnimplementedFormatString>, pub parent_label: Option<OnUnimplementedFormatString>, pub append_const_msg: Option<AppendConstMessage>, } @@ -329,7 +329,7 @@ pub struct OnUnimplementedDirective { pub struct OnUnimplementedNote { pub message: Option<String>, pub label: Option<String>, - pub note: Option<String>, + pub notes: Vec<String>, pub parent_label: Option<String>, // If none, should fall back to a generic message pub append_const_msg: Option<AppendConstMessage>, @@ -399,7 +399,7 @@ impl<'tcx> OnUnimplementedDirective { let mut message = None; let mut label = None; - let mut note = None; + let mut notes = Vec::new(); let mut parent_label = None; let mut subcommands = vec![]; let mut append_const_msg = None; @@ -415,10 +415,12 @@ impl<'tcx> OnUnimplementedDirective { label = parse_value(label_)?; continue; } - } else if item.has_name(sym::note) && note.is_none() { + } else if item.has_name(sym::note) { if let Some(note_) = item.value_str() { - note = parse_value(note_)?; - continue; + if let Some(note) = parse_value(note_)? { + notes.push(note); + continue; + } } } else if item.has_name(sym::parent_label) && parent_label.is_none() @@ -432,7 +434,7 @@ impl<'tcx> OnUnimplementedDirective { && is_root && message.is_none() && label.is_none() - && note.is_none() + && notes.is_empty() && !is_diagnostic_namespace_variant // FIXME(diagnostic_namespace): disallow filters for now { @@ -487,7 +489,7 @@ impl<'tcx> OnUnimplementedDirective { subcommands, message, label, - note, + notes, parent_label, append_const_msg, })) @@ -505,12 +507,14 @@ impl<'tcx> OnUnimplementedDirective { if let Some(aggr) = aggr { let mut subcommands = aggr.subcommands; subcommands.extend(directive.subcommands); + let mut notes = aggr.notes; + notes.extend(directive.notes); Ok(Some(Self { condition: aggr.condition.or(directive.condition), subcommands, message: aggr.message.or(directive.message), label: aggr.label.or(directive.label), - note: aggr.note.or(directive.note), + notes, parent_label: aggr.parent_label.or(directive.parent_label), append_const_msg: aggr.append_const_msg.or(directive.append_const_msg), })) @@ -543,7 +547,7 @@ impl<'tcx> OnUnimplementedDirective { value, attr.span, )?), - note: None, + notes: Vec::new(), parent_label: None, append_const_msg: None, })) @@ -600,7 +604,7 @@ impl<'tcx> OnUnimplementedDirective { ) -> OnUnimplementedNote { let mut message = None; let mut label = None; - let mut note = 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); @@ -637,9 +641,7 @@ impl<'tcx> OnUnimplementedDirective { label = Some(label_.clone()); } - if let Some(ref note_) = command.note { - note = Some(note_.clone()); - } + notes.extend(command.notes.clone()); if let Some(ref parent_label_) = command.parent_label { parent_label = Some(parent_label_.clone()); @@ -651,7 +653,7 @@ impl<'tcx> OnUnimplementedDirective { OnUnimplementedNote { label: label.map(|l| l.format(tcx, trait_ref, &options_map)), message: message.map(|m| m.format(tcx, trait_ref, &options_map)), - note: note.map(|n| n.format(tcx, trait_ref, &options_map)), + notes: notes.into_iter().map(|n| n.format(tcx, trait_ref, &options_map)).collect(), parent_label: parent_label.map(|e_s| e_s.format(tcx, trait_ref, &options_map)), append_const_msg, } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index a697c6650b2..f9ce81ce165 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -445,7 +445,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let OnUnimplementedNote { message, label, - note, + notes, parent_label, append_const_msg, } = self.on_unimplemented_note(trait_ref, &obligation); @@ -453,21 +453,21 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id()); let is_unsize = Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait(); - let (message, note, append_const_msg) = if is_try_conversion { + let (message, notes, append_const_msg) = if is_try_conversion { ( Some(format!( "`?` couldn't convert the error to `{}`", trait_ref.skip_binder().self_ty(), )), - Some( + vec![ "the question mark operation (`?`) implicitly performs a \ conversion on the error value using the `From` trait" .to_owned(), - ), + ], Some(AppendConstMessage::Default), ) } else { - (message, note, append_const_msg) + (message, notes, append_const_msg) }; let err_msg = self.get_standard_error_message( @@ -588,9 +588,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let Some((msg, span)) = type_def { err.span_label(span, msg); } - if let Some(s) = note { + for note in notes { // If it has a custom `#[rustc_on_unimplemented]` note, let's display it - err.note(s); + err.note(note); } if let Some(s) = parent_label { let body = obligation.cause.body_id; |
