@@ -23,8 +23,8 @@ use rustc_hir::def::DefKind;
2323use rustc_hir:: def_id:: LocalModDefId ;
2424use rustc_hir:: intravisit:: { self , Visitor } ;
2525use rustc_hir:: {
26- self as hir, Attribute , CRATE_HIR_ID , CRATE_OWNER_ID , FnSig , ForeignItem , HirId , Item ,
27- ItemKind , MethodKind , PartialConstStability , Safety , Stability , StabilityLevel , Target ,
26+ self as hir, Attribute , CRATE_HIR_ID , CRATE_OWNER_ID , Constness , FnSig , ForeignItem , HirId ,
27+ Item , ItemKind , MethodKind , PartialConstStability , Safety , Stability , StabilityLevel , Target ,
2828 TraitItem , find_attr,
2929} ;
3030use rustc_macros:: LintDiagnostic ;
@@ -55,6 +55,10 @@ use crate::{errors, fluent_generated as fluent};
5555#[ diag( passes_diagnostic_diagnostic_on_unimplemented_only_for_traits) ]
5656struct DiagnosticOnUnimplementedOnlyForTraits ;
5757
58+ #[ derive( LintDiagnostic ) ]
59+ #[ diag( passes_diagnostic_diagnostic_on_const_only_for_trait_impls) ]
60+ struct DiagnosticOnConstOnlyForTraitImpls ;
61+
5862fn target_from_impl_item < ' tcx > ( tcx : TyCtxt < ' tcx > , impl_item : & hir:: ImplItem < ' _ > ) -> Target {
5963 match impl_item. kind {
6064 hir:: ImplItemKind :: Const ( ..) => Target :: AssocConst ,
@@ -294,6 +298,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
294298 [ sym:: diagnostic, sym:: on_unimplemented, ..] => {
295299 self . check_diagnostic_on_unimplemented ( attr. span ( ) , hir_id, target)
296300 }
301+ [ sym:: diagnostic, sym:: on_const, ..] => {
302+ self . check_diagnostic_on_const ( attr. span ( ) , hir_id, target, item)
303+ }
297304 [ sym:: thread_local, ..] => self . check_thread_local ( attr, span, target) ,
298305 [ sym:: doc, ..] => self . check_doc_attrs (
299306 attr,
@@ -517,6 +524,31 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
517524 }
518525 }
519526
527+ /// Checks if `#[diagnostic::on_const]` is applied to a trait impl
528+ fn check_diagnostic_on_const (
529+ & self ,
530+ attr_span : Span ,
531+ hir_id : HirId ,
532+ target : Target ,
533+ item : Option < ItemLike < ' _ > > ,
534+ ) {
535+ if matches ! ( target, Target :: Impl { of_trait: true } ) {
536+ match item. unwrap ( ) {
537+ ItemLike :: Item ( it) => match it. expect_impl ( ) . constness {
538+ Constness :: Const => { }
539+ Constness :: NotConst => return ,
540+ } ,
541+ ItemLike :: ForeignItem => { }
542+ }
543+ }
544+ self . tcx . emit_node_span_lint (
545+ MISPLACED_DIAGNOSTIC_ATTRIBUTES ,
546+ hir_id,
547+ attr_span,
548+ DiagnosticOnConstOnlyForTraitImpls ,
549+ ) ;
550+ }
551+
520552 /// Checks if an `#[inline]` is applied to a function or a closure.
521553 fn check_inline ( & self , hir_id : HirId , attr_span : Span , kind : & InlineAttr , target : Target ) {
522554 match target {
0 commit comments