@@ -5,6 +5,7 @@ use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit};
55use rustc_errors:: codes:: * ;
66use rustc_errors:: { ErrorGuaranteed , struct_span_code_err} ;
77use rustc_hir as hir;
8+ use rustc_hir:: def:: DefKind ;
89use rustc_hir:: def_id:: { DefId , LocalDefId } ;
910use rustc_hir:: { AttrArgs , Attribute } ;
1011use rustc_macros:: LintDiagnostic ;
@@ -103,7 +104,27 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
103104 if trait_pred. polarity ( ) != ty:: PredicatePolarity :: Positive {
104105 return OnUnimplementedNote :: default ( ) ;
105106 }
107+ let ( condition_options, format_args) =
108+ self . on_unimplemented_components ( trait_pred, obligation, long_ty_path) ;
109+ if let Ok ( Some ( command) ) = OnUnimplementedDirective :: of_item ( self . tcx , trait_pred. def_id ( ) )
110+ {
111+ command. evaluate (
112+ self . tcx ,
113+ trait_pred. skip_binder ( ) . trait_ref ,
114+ & condition_options,
115+ & format_args,
116+ )
117+ } else {
118+ OnUnimplementedNote :: default ( )
119+ }
120+ }
106121
122+ pub ( crate ) fn on_unimplemented_components (
123+ & self ,
124+ trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
125+ obligation : & PredicateObligation < ' tcx > ,
126+ long_ty_path : & mut Option < PathBuf > ,
127+ ) -> ( ConditionOptions , FormatArgs < ' tcx > ) {
107128 let ( def_id, args) = self
108129 . impl_similar_to ( trait_pred, obligation)
109130 . unwrap_or_else ( || ( trait_pred. def_id ( ) , trait_pred. skip_binder ( ) . trait_ref . args ) ) ;
@@ -293,12 +314,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
293314 . collect ( ) ;
294315
295316 let format_args = FormatArgs { this, trait_sugared, generic_args, item_context } ;
296-
297- if let Ok ( Some ( command) ) = OnUnimplementedDirective :: of_item ( self . tcx , def_id) {
298- command. evaluate ( self . tcx , trait_pred. trait_ref , & condition_options, & format_args)
299- } else {
300- OnUnimplementedNote :: default ( )
301- }
317+ ( condition_options, format_args)
302318 }
303319}
304320
@@ -325,7 +341,7 @@ pub struct OnUnimplementedDirective {
325341}
326342
327343/// For the `#[rustc_on_unimplemented]` attribute
328- #[ derive( Default ) ]
344+ #[ derive( Default , Debug ) ]
329345pub struct OnUnimplementedNote {
330346 pub message : Option < String > ,
331347 pub label : Option < String > ,
@@ -562,17 +578,21 @@ impl<'tcx> OnUnimplementedDirective {
562578 }
563579
564580 pub fn of_item ( tcx : TyCtxt < ' tcx > , item_def_id : DefId ) -> Result < Option < Self > , ErrorGuaranteed > {
565- if !tcx. is_trait ( item_def_id) {
581+ let attr = if tcx. is_trait ( item_def_id) {
582+ sym:: on_unimplemented
583+ } else if let DefKind :: Impl { of_trait : true } = tcx. def_kind ( item_def_id) {
584+ sym:: on_const
585+ } else {
566586 // It could be a trait_alias (`trait MyTrait = SomeOtherTrait`)
567587 // or an implementation (`impl MyTrait for Foo {}`)
568588 //
569589 // We don't support those.
570590 return Ok ( None ) ;
571- }
591+ } ;
572592 if let Some ( attr) = tcx. get_attr ( item_def_id, sym:: rustc_on_unimplemented) {
573593 return Self :: parse_attribute ( attr, false , tcx, item_def_id) ;
574594 } else {
575- tcx. get_attrs_by_path ( item_def_id, & [ sym:: diagnostic, sym :: on_unimplemented ] )
595+ tcx. get_attrs_by_path ( item_def_id, & [ sym:: diagnostic, attr ] )
576596 . filter_map ( |attr| Self :: parse_attribute ( attr, true , tcx, item_def_id) . transpose ( ) )
577597 . try_fold ( None , |aggr : Option < Self > , directive| {
578598 let directive = directive?;
0 commit comments