@@ -9,6 +9,7 @@ use rustc_hir::def_id::DefId;
99use rustc_middle:: ty:: GenericArgsRef ;
1010use rustc_middle:: ty:: { self , GenericParamDefKind , TyCtxt } ;
1111use rustc_parse_format:: { ParseMode , Parser , Piece , Position } ;
12+ use rustc_session:: lint:: builtin:: UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES ;
1213use rustc_span:: symbol:: { kw, sym, Symbol } ;
1314use rustc_span:: { Span , DUMMY_SP } ;
1415use std:: iter;
@@ -336,14 +337,19 @@ pub enum AppendConstMessage {
336337 Custom ( Symbol ) ,
337338}
338339
340+ #[ derive( LintDiagnostic ) ]
341+ #[ diag( trait_selection_malformed_on_unimplemented_attr) ]
342+ pub struct NoValueInOnUnimplementedLint ;
343+
339344impl < ' tcx > OnUnimplementedDirective {
340345 fn parse (
341346 tcx : TyCtxt < ' tcx > ,
342347 item_def_id : DefId ,
343348 items : & [ NestedMetaItem ] ,
344349 span : Span ,
345350 is_root : bool ,
346- ) -> Result < Self , ErrorGuaranteed > {
351+ is_diagnostic_namespace_variant : bool ,
352+ ) -> Result < Option < Self > , ErrorGuaranteed > {
347353 let mut errored = None ;
348354 let mut item_iter = items. iter ( ) ;
349355
@@ -391,7 +397,10 @@ impl<'tcx> OnUnimplementedDirective {
391397 note = parse_value ( note_) ?;
392398 continue ;
393399 }
394- } else if item. has_name ( sym:: parent_label) && parent_label. is_none ( ) {
400+ } else if item. has_name ( sym:: parent_label)
401+ && parent_label. is_none ( )
402+ && !is_diagnostic_namespace_variant
403+ {
395404 if let Some ( parent_label_) = item. value_str ( ) {
396405 parent_label = parse_value ( parent_label_) ?;
397406 continue ;
@@ -401,15 +410,30 @@ impl<'tcx> OnUnimplementedDirective {
401410 && message. is_none ( )
402411 && label. is_none ( )
403412 && note. is_none ( )
413+ && !is_diagnostic_namespace_variant
414+ // FIXME(diagnostic_namespace): disallow filters for now
404415 {
405416 if let Some ( items) = item. meta_item_list ( ) {
406- match Self :: parse ( tcx, item_def_id, & items, item. span ( ) , false ) {
407- Ok ( subcommand) => subcommands. push ( subcommand) ,
417+ match Self :: parse (
418+ tcx,
419+ item_def_id,
420+ & items,
421+ item. span ( ) ,
422+ false ,
423+ is_diagnostic_namespace_variant,
424+ ) {
425+ Ok ( Some ( subcommand) ) => subcommands. push ( subcommand) ,
426+ Ok ( None ) => bug ! (
427+ "This cannot happen for now as we only reach that if `is_diagnostic_namespace_variant` is false"
428+ ) ,
408429 Err ( reported) => errored = Some ( reported) ,
409430 } ;
410431 continue ;
411432 }
412- } else if item. has_name ( sym:: append_const_msg) && append_const_msg. is_none ( ) {
433+ } else if item. has_name ( sym:: append_const_msg)
434+ && append_const_msg. is_none ( )
435+ && !is_diagnostic_namespace_variant
436+ {
413437 if let Some ( msg) = item. value_str ( ) {
414438 append_const_msg = Some ( AppendConstMessage :: Custom ( msg) ) ;
415439 continue ;
@@ -419,47 +443,82 @@ impl<'tcx> OnUnimplementedDirective {
419443 }
420444 }
421445
422- // nothing found
423- tcx. sess . emit_err ( NoValueInOnUnimplemented { span : item. span ( ) } ) ;
446+ if is_diagnostic_namespace_variant {
447+ tcx. emit_spanned_lint (
448+ UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES ,
449+ tcx. hir ( ) . local_def_id_to_hir_id ( item_def_id. expect_local ( ) ) ,
450+ vec ! [ item. span( ) ] ,
451+ NoValueInOnUnimplementedLint ,
452+ ) ;
453+ } else {
454+ // nothing found
455+ tcx. sess . emit_err ( NoValueInOnUnimplemented { span : item. span ( ) } ) ;
456+ }
424457 }
425458
426459 if let Some ( reported) = errored {
427- Err ( reported)
460+ if is_diagnostic_namespace_variant { Ok ( None ) } else { Err ( reported) }
428461 } else {
429- Ok ( OnUnimplementedDirective {
462+ Ok ( Some ( OnUnimplementedDirective {
430463 condition,
431464 subcommands,
432465 message,
433466 label,
434467 note,
435468 parent_label,
436469 append_const_msg,
437- } )
470+ } ) )
438471 }
439472 }
440473
441474 pub fn of_item ( tcx : TyCtxt < ' tcx > , item_def_id : DefId ) -> Result < Option < Self > , ErrorGuaranteed > {
442- let Some ( attr) = tcx. get_attr ( item_def_id, sym:: rustc_on_unimplemented) else {
475+ let mut is_diagnostic_namespace_variant = false ;
476+ let Some ( attr) = tcx. get_attr ( item_def_id, sym:: rustc_on_unimplemented) . or_else ( || {
477+ if tcx. features ( ) . diagnostic_namespace {
478+ is_diagnostic_namespace_variant = true ;
479+ tcx. get_attrs_by_path ( item_def_id, & [ sym:: diagnostic, sym:: on_unimplemented] ) . next ( )
480+ } else {
481+ None
482+ }
483+ } ) else {
443484 return Ok ( None ) ;
444485 } ;
445486
446487 let result = if let Some ( items) = attr. meta_item_list ( ) {
447- Self :: parse ( tcx, item_def_id, & items, attr. span , true ) . map ( Some )
488+ Self :: parse ( tcx, item_def_id, & items, attr. span , true , is_diagnostic_namespace_variant )
448489 } else if let Some ( value) = attr. value_str ( ) {
449- Ok ( Some ( OnUnimplementedDirective {
450- condition : None ,
451- message : None ,
452- subcommands : vec ! [ ] ,
453- label : Some ( OnUnimplementedFormatString :: try_parse (
454- tcx,
455- item_def_id,
456- value,
490+ if !is_diagnostic_namespace_variant {
491+ Ok ( Some ( OnUnimplementedDirective {
492+ condition : None ,
493+ message : None ,
494+ subcommands : vec ! [ ] ,
495+ label : Some ( OnUnimplementedFormatString :: try_parse (
496+ tcx,
497+ item_def_id,
498+ value,
499+ attr. span ,
500+ ) ?) ,
501+ note : None ,
502+ parent_label : None ,
503+ append_const_msg : None ,
504+ } ) )
505+ } else {
506+ tcx. emit_spanned_lint (
507+ UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES ,
508+ tcx. hir ( ) . local_def_id_to_hir_id ( item_def_id. expect_local ( ) ) ,
457509 attr. span ,
458- ) ?) ,
459- note : None ,
460- parent_label : None ,
461- append_const_msg : None ,
462- } ) )
510+ NoValueInOnUnimplementedLint ,
511+ ) ;
512+ Ok ( None )
513+ }
514+ } else if is_diagnostic_namespace_variant {
515+ tcx. emit_spanned_lint (
516+ UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES ,
517+ tcx. hir ( ) . local_def_id_to_hir_id ( item_def_id. expect_local ( ) ) ,
518+ attr. span ,
519+ NoValueInOnUnimplementedLint ,
520+ ) ;
521+ Ok ( None )
463522 } else {
464523 let reported =
465524 tcx. sess . delay_span_bug ( DUMMY_SP , "of_item: neither meta_item_list nor value_str" ) ;
0 commit comments