@@ -321,7 +321,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
321321}
322322
323323#[ derive( Clone , Debug ) ]
324- pub struct OnUnimplementedFormatString ( Symbol ) ;
324+ pub struct OnUnimplementedFormatString ( Symbol , Span ) ;
325325
326326#[ derive( Debug ) ]
327327pub struct OnUnimplementedDirective {
@@ -350,7 +350,7 @@ pub struct OnUnimplementedNote {
350350pub enum AppendConstMessage {
351351 #[ default]
352352 Default ,
353- Custom ( Symbol ) ,
353+ Custom ( Symbol , Span ) ,
354354}
355355
356356#[ derive( LintDiagnostic ) ]
@@ -372,6 +372,35 @@ impl MalformedOnUnimplementedAttrLint {
372372#[ help]
373373pub struct MissingOptionsForOnUnimplementedAttr ;
374374
375+ #[ derive( LintDiagnostic ) ]
376+ #[ diag( trait_selection_ignored_diagnostic_option) ]
377+ pub struct IgnoredDiagnosticOption {
378+ pub option_name : & ' static str ,
379+ #[ label]
380+ pub span : Span ,
381+ #[ label( trait_selection_other_label) ]
382+ pub prev_span : Span ,
383+ }
384+
385+ impl IgnoredDiagnosticOption {
386+ fn maybe_emit_warning < ' tcx > (
387+ tcx : TyCtxt < ' tcx > ,
388+ item_def_id : DefId ,
389+ new : Option < Span > ,
390+ old : Option < Span > ,
391+ option_name : & ' static str ,
392+ ) {
393+ if let ( Some ( new_item) , Some ( old_item) ) = ( new, old) {
394+ tcx. emit_spanned_lint (
395+ UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES ,
396+ tcx. hir ( ) . local_def_id_to_hir_id ( item_def_id. expect_local ( ) ) ,
397+ new_item,
398+ IgnoredDiagnosticOption { span : new_item, prev_span : old_item, option_name } ,
399+ ) ;
400+ }
401+ }
402+ }
403+
375404impl < ' tcx > OnUnimplementedDirective {
376405 fn parse (
377406 tcx : TyCtxt < ' tcx > ,
@@ -384,8 +413,9 @@ impl<'tcx> OnUnimplementedDirective {
384413 let mut errored = None ;
385414 let mut item_iter = items. iter ( ) ;
386415
387- let parse_value = |value_str| {
388- OnUnimplementedFormatString :: try_parse ( tcx, item_def_id, value_str, span) . map ( Some )
416+ let parse_value = |value_str, value_span| {
417+ OnUnimplementedFormatString :: try_parse ( tcx, item_def_id, value_str, span, value_span)
418+ . map ( Some )
389419 } ;
390420
391421 let condition = if is_root {
@@ -398,7 +428,7 @@ impl<'tcx> OnUnimplementedDirective {
398428 . ok_or_else ( || tcx. sess . emit_err ( InvalidOnClauseInOnUnimplemented { span } ) ) ?;
399429 attr:: eval_condition ( cond, & tcx. sess . parse_sess , Some ( tcx. features ( ) ) , & mut |cfg| {
400430 if let Some ( value) = cfg. value
401- && let Err ( guar) = parse_value ( value)
431+ && let Err ( guar) = parse_value ( value, cfg . span )
402432 {
403433 errored = Some ( guar) ;
404434 }
@@ -417,17 +447,17 @@ impl<'tcx> OnUnimplementedDirective {
417447 for item in item_iter {
418448 if item. has_name ( sym:: message) && message. is_none ( ) {
419449 if let Some ( message_) = item. value_str ( ) {
420- message = parse_value ( message_) ?;
450+ message = parse_value ( message_, item . span ( ) ) ?;
421451 continue ;
422452 }
423453 } else if item. has_name ( sym:: label) && label. is_none ( ) {
424454 if let Some ( label_) = item. value_str ( ) {
425- label = parse_value ( label_) ?;
455+ label = parse_value ( label_, item . span ( ) ) ?;
426456 continue ;
427457 }
428458 } else if item. has_name ( sym:: note) {
429459 if let Some ( note_) = item. value_str ( ) {
430- if let Some ( note) = parse_value ( note_) ? {
460+ if let Some ( note) = parse_value ( note_, item . span ( ) ) ? {
431461 notes. push ( note) ;
432462 continue ;
433463 }
@@ -437,7 +467,7 @@ impl<'tcx> OnUnimplementedDirective {
437467 && !is_diagnostic_namespace_variant
438468 {
439469 if let Some ( parent_label_) = item. value_str ( ) {
440- parent_label = parse_value ( parent_label_) ?;
470+ parent_label = parse_value ( parent_label_, item . span ( ) ) ?;
441471 continue ;
442472 }
443473 } else if item. has_name ( sym:: on)
@@ -470,7 +500,7 @@ impl<'tcx> OnUnimplementedDirective {
470500 && !is_diagnostic_namespace_variant
471501 {
472502 if let Some ( msg) = item. value_str ( ) {
473- append_const_msg = Some ( AppendConstMessage :: Custom ( msg) ) ;
503+ append_const_msg = Some ( AppendConstMessage :: Custom ( msg, item . span ( ) ) ) ;
474504 continue ;
475505 } else if item. is_word ( ) {
476506 append_const_msg = Some ( AppendConstMessage :: Default ) ;
@@ -519,6 +549,54 @@ impl<'tcx> OnUnimplementedDirective {
519549 subcommands. extend ( directive. subcommands ) ;
520550 let mut notes = aggr. notes ;
521551 notes. extend ( directive. notes ) ;
552+ IgnoredDiagnosticOption :: maybe_emit_warning (
553+ tcx,
554+ item_def_id,
555+ directive. message . as_ref ( ) . map ( |f| f. 1 ) ,
556+ aggr. message . as_ref ( ) . map ( |f| f. 1 ) ,
557+ "message" ,
558+ ) ;
559+ IgnoredDiagnosticOption :: maybe_emit_warning (
560+ tcx,
561+ item_def_id,
562+ directive. label . as_ref ( ) . map ( |f| f. 1 ) ,
563+ aggr. label . as_ref ( ) . map ( |f| f. 1 ) ,
564+ "label" ,
565+ ) ;
566+ IgnoredDiagnosticOption :: maybe_emit_warning (
567+ tcx,
568+ item_def_id,
569+ directive. condition . as_ref ( ) . map ( |i| i. span ) ,
570+ aggr. condition . as_ref ( ) . map ( |i| i. span ) ,
571+ "condition" ,
572+ ) ;
573+ IgnoredDiagnosticOption :: maybe_emit_warning (
574+ tcx,
575+ item_def_id,
576+ directive. parent_label . as_ref ( ) . map ( |f| f. 1 ) ,
577+ aggr. parent_label . as_ref ( ) . map ( |f| f. 1 ) ,
578+ "parent_label" ,
579+ ) ;
580+ IgnoredDiagnosticOption :: maybe_emit_warning (
581+ tcx,
582+ item_def_id,
583+ directive. append_const_msg . as_ref ( ) . and_then ( |c| {
584+ if let AppendConstMessage :: Custom ( _, s) = c {
585+ Some ( * s)
586+ } else {
587+ None
588+ }
589+ } ) ,
590+ aggr. append_const_msg . as_ref ( ) . and_then ( |c| {
591+ if let AppendConstMessage :: Custom ( _, s) = c {
592+ Some ( * s)
593+ } else {
594+ None
595+ }
596+ } ) ,
597+ "append_const_msg" ,
598+ ) ;
599+
522600 Ok ( Some ( Self {
523601 condition : aggr. condition . or ( directive. condition ) ,
524602 subcommands,
@@ -556,6 +634,7 @@ impl<'tcx> OnUnimplementedDirective {
556634 item_def_id,
557635 value,
558636 attr. span ,
637+ attr. span ,
559638 ) ?) ,
560639 notes : Vec :: new ( ) ,
561640 parent_label : None ,
@@ -633,7 +712,11 @@ impl<'tcx> OnUnimplementedDirective {
633712 // `with_no_visible_paths` is also used when generating the options,
634713 // so we need to match it here.
635714 ty:: print:: with_no_visible_paths!(
636- OnUnimplementedFormatString ( v) . format( tcx, trait_ref, & options_map)
715+ OnUnimplementedFormatString ( v, cfg. span) . format(
716+ tcx,
717+ trait_ref,
718+ & options_map
719+ )
637720 )
638721 } ) ;
639722
@@ -678,8 +761,9 @@ impl<'tcx> OnUnimplementedFormatString {
678761 item_def_id : DefId ,
679762 from : Symbol ,
680763 err_sp : Span ,
764+ value_span : Span ,
681765 ) -> Result < Self , ErrorGuaranteed > {
682- let result = OnUnimplementedFormatString ( from) ;
766+ let result = OnUnimplementedFormatString ( from, value_span ) ;
683767 result. verify ( tcx, item_def_id, err_sp) ?;
684768 Ok ( result)
685769 }
0 commit comments