@@ -325,7 +325,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
325325}
326326
327327#[ derive( Clone , Debug ) ]
328- pub struct OnUnimplementedFormatString ( Symbol ) ;
328+ pub struct OnUnimplementedFormatString ( Symbol , Span ) ;
329329
330330#[ derive( Debug ) ]
331331pub struct OnUnimplementedDirective {
@@ -354,7 +354,7 @@ pub struct OnUnimplementedNote {
354354pub enum AppendConstMessage {
355355 #[ default]
356356 Default ,
357- Custom ( Symbol ) ,
357+ Custom ( Symbol , Span ) ,
358358}
359359
360360#[ derive( LintDiagnostic ) ]
@@ -376,6 +376,35 @@ impl MalformedOnUnimplementedAttrLint {
376376#[ help]
377377pub struct MissingOptionsForOnUnimplementedAttr ;
378378
379+ #[ derive( LintDiagnostic ) ]
380+ #[ diag( trait_selection_ignored_diagnostic_option) ]
381+ pub struct IgnoredDiagnosticOption {
382+ pub option_name : & ' static str ,
383+ #[ label]
384+ pub span : Span ,
385+ #[ label( trait_selection_other_label) ]
386+ pub prev_span : Span ,
387+ }
388+
389+ impl IgnoredDiagnosticOption {
390+ fn maybe_emit_warning < ' tcx > (
391+ tcx : TyCtxt < ' tcx > ,
392+ item_def_id : DefId ,
393+ new : Option < Span > ,
394+ old : Option < Span > ,
395+ option_name : & ' static str ,
396+ ) {
397+ if let ( Some ( new_item) , Some ( old_item) ) = ( new, old) {
398+ tcx. emit_spanned_lint (
399+ UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES ,
400+ tcx. hir ( ) . local_def_id_to_hir_id ( item_def_id. expect_local ( ) ) ,
401+ new_item,
402+ IgnoredDiagnosticOption { span : new_item, prev_span : old_item, option_name } ,
403+ ) ;
404+ }
405+ }
406+ }
407+
379408impl < ' tcx > OnUnimplementedDirective {
380409 fn parse (
381410 tcx : TyCtxt < ' tcx > ,
@@ -388,8 +417,9 @@ impl<'tcx> OnUnimplementedDirective {
388417 let mut errored = None ;
389418 let mut item_iter = items. iter ( ) ;
390419
391- let parse_value = |value_str| {
392- OnUnimplementedFormatString :: try_parse ( tcx, item_def_id, value_str, span) . map ( Some )
420+ let parse_value = |value_str, value_span| {
421+ OnUnimplementedFormatString :: try_parse ( tcx, item_def_id, value_str, span, value_span)
422+ . map ( Some )
393423 } ;
394424
395425 let condition = if is_root {
@@ -402,7 +432,7 @@ impl<'tcx> OnUnimplementedDirective {
402432 . ok_or_else ( || tcx. sess . emit_err ( InvalidOnClauseInOnUnimplemented { span } ) ) ?;
403433 attr:: eval_condition ( cond, & tcx. sess . parse_sess , Some ( tcx. features ( ) ) , & mut |cfg| {
404434 if let Some ( value) = cfg. value
405- && let Err ( guar) = parse_value ( value)
435+ && let Err ( guar) = parse_value ( value, cfg . span )
406436 {
407437 errored = Some ( guar) ;
408438 }
@@ -421,17 +451,17 @@ impl<'tcx> OnUnimplementedDirective {
421451 for item in item_iter {
422452 if item. has_name ( sym:: message) && message. is_none ( ) {
423453 if let Some ( message_) = item. value_str ( ) {
424- message = parse_value ( message_) ?;
454+ message = parse_value ( message_, item . span ( ) ) ?;
425455 continue ;
426456 }
427457 } else if item. has_name ( sym:: label) && label. is_none ( ) {
428458 if let Some ( label_) = item. value_str ( ) {
429- label = parse_value ( label_) ?;
459+ label = parse_value ( label_, item . span ( ) ) ?;
430460 continue ;
431461 }
432462 } else if item. has_name ( sym:: note) {
433463 if let Some ( note_) = item. value_str ( ) {
434- if let Some ( note) = parse_value ( note_) ? {
464+ if let Some ( note) = parse_value ( note_, item . span ( ) ) ? {
435465 notes. push ( note) ;
436466 continue ;
437467 }
@@ -441,7 +471,7 @@ impl<'tcx> OnUnimplementedDirective {
441471 && !is_diagnostic_namespace_variant
442472 {
443473 if let Some ( parent_label_) = item. value_str ( ) {
444- parent_label = parse_value ( parent_label_) ?;
474+ parent_label = parse_value ( parent_label_, item . span ( ) ) ?;
445475 continue ;
446476 }
447477 } else if item. has_name ( sym:: on)
@@ -474,7 +504,7 @@ impl<'tcx> OnUnimplementedDirective {
474504 && !is_diagnostic_namespace_variant
475505 {
476506 if let Some ( msg) = item. value_str ( ) {
477- append_const_msg = Some ( AppendConstMessage :: Custom ( msg) ) ;
507+ append_const_msg = Some ( AppendConstMessage :: Custom ( msg, item . span ( ) ) ) ;
478508 continue ;
479509 } else if item. is_word ( ) {
480510 append_const_msg = Some ( AppendConstMessage :: Default ) ;
@@ -523,6 +553,54 @@ impl<'tcx> OnUnimplementedDirective {
523553 subcommands. extend ( directive. subcommands ) ;
524554 let mut notes = aggr. notes ;
525555 notes. extend ( directive. notes ) ;
556+ IgnoredDiagnosticOption :: maybe_emit_warning (
557+ tcx,
558+ item_def_id,
559+ directive. message . as_ref ( ) . map ( |f| f. 1 ) ,
560+ aggr. message . as_ref ( ) . map ( |f| f. 1 ) ,
561+ "message" ,
562+ ) ;
563+ IgnoredDiagnosticOption :: maybe_emit_warning (
564+ tcx,
565+ item_def_id,
566+ directive. label . as_ref ( ) . map ( |f| f. 1 ) ,
567+ aggr. label . as_ref ( ) . map ( |f| f. 1 ) ,
568+ "label" ,
569+ ) ;
570+ IgnoredDiagnosticOption :: maybe_emit_warning (
571+ tcx,
572+ item_def_id,
573+ directive. condition . as_ref ( ) . map ( |i| i. span ) ,
574+ aggr. condition . as_ref ( ) . map ( |i| i. span ) ,
575+ "condition" ,
576+ ) ;
577+ IgnoredDiagnosticOption :: maybe_emit_warning (
578+ tcx,
579+ item_def_id,
580+ directive. parent_label . as_ref ( ) . map ( |f| f. 1 ) ,
581+ aggr. parent_label . as_ref ( ) . map ( |f| f. 1 ) ,
582+ "parent_label" ,
583+ ) ;
584+ IgnoredDiagnosticOption :: maybe_emit_warning (
585+ tcx,
586+ item_def_id,
587+ directive. append_const_msg . as_ref ( ) . and_then ( |c| {
588+ if let AppendConstMessage :: Custom ( _, s) = c {
589+ Some ( * s)
590+ } else {
591+ None
592+ }
593+ } ) ,
594+ aggr. append_const_msg . as_ref ( ) . and_then ( |c| {
595+ if let AppendConstMessage :: Custom ( _, s) = c {
596+ Some ( * s)
597+ } else {
598+ None
599+ }
600+ } ) ,
601+ "append_const_msg" ,
602+ ) ;
603+
526604 Ok ( Some ( Self {
527605 condition : aggr. condition . or ( directive. condition ) ,
528606 subcommands,
@@ -560,6 +638,7 @@ impl<'tcx> OnUnimplementedDirective {
560638 item_def_id,
561639 value,
562640 attr. span ,
641+ attr. span ,
563642 ) ?) ,
564643 notes : Vec :: new ( ) ,
565644 parent_label : None ,
@@ -636,7 +715,7 @@ impl<'tcx> OnUnimplementedDirective {
636715 let value = cfg. value . map ( |v| {
637716 // `with_no_visible_paths` is also used when generating the options,
638717 // so we need to match it here.
639- ty:: print:: with_no_visible_paths!( OnUnimplementedFormatString ( v) . format( tcx, trait_ref, & options_map) )
718+ ty:: print:: with_no_visible_paths!( OnUnimplementedFormatString ( v, cfg . span ) . format( tcx, trait_ref, & options_map) )
640719 } ) ;
641720
642721 options. contains ( & ( cfg. name , value) )
@@ -680,8 +759,9 @@ impl<'tcx> OnUnimplementedFormatString {
680759 item_def_id : DefId ,
681760 from : Symbol ,
682761 err_sp : Span ,
762+ value_span : Span ,
683763 ) -> Result < Self , ErrorGuaranteed > {
684- let result = OnUnimplementedFormatString ( from) ;
764+ let result = OnUnimplementedFormatString ( from, value_span ) ;
685765 result. verify ( tcx, item_def_id, err_sp) ?;
686766 Ok ( result)
687767 }
0 commit comments