@@ -9,7 +9,7 @@ use rustc_hir as hir;
9
9
use rustc_hir:: def:: { DefKind , Res } ;
10
10
use rustc_hir:: def_id:: { DefId , LocalDefId , CRATE_DEF_INDEX , LOCAL_CRATE } ;
11
11
use rustc_hir:: intravisit:: { self , NestedVisitorMap , Visitor } ;
12
- use rustc_hir:: { Generics , HirId , Item , StructField , Variant } ;
12
+ use rustc_hir:: { Generics , HirId , Item , StructField , TraitRef , Ty , TyKind , Variant } ;
13
13
use rustc_middle:: hir:: map:: Map ;
14
14
use rustc_middle:: middle:: privacy:: AccessLevels ;
15
15
use rustc_middle:: middle:: stability:: { DeprecationEntry , Index } ;
@@ -538,7 +538,31 @@ impl Visitor<'tcx> for Checker<'tcx> {
538
538
// For implementations of traits, check the stability of each item
539
539
// individually as it's possible to have a stable trait with unstable
540
540
// items.
541
- hir:: ItemKind :: Impl { of_trait : Some ( ref t) , items, .. } => {
541
+ hir:: ItemKind :: Impl { of_trait : Some ( ref t) , self_ty, items, .. } => {
542
+ // If this impl block has an #[unstable] attribute, give an
543
+ // error if all involved types and traits are stable, because
544
+ // it will have no effect.
545
+ // See: https://github.com/rust-lang/rust/issues/55436
546
+ if let ( Some ( Stability { level : attr:: Unstable { .. } , .. } ) , _) =
547
+ attr:: find_stability ( & self . tcx . sess , & item. attrs , item. span )
548
+ {
549
+ let mut c = CheckTraitImplStable { tcx : self . tcx , fully_stable : true } ;
550
+ c. visit_ty ( self_ty) ;
551
+ c. visit_trait_ref ( t) ;
552
+ if c. fully_stable {
553
+ let span = item
554
+ . attrs
555
+ . iter ( )
556
+ . find ( |a| a. has_name ( sym:: unstable) )
557
+ . map_or ( item. span , |a| a. span ) ;
558
+ self . tcx . sess . span_warn (
559
+ span,
560
+ "An `#[unstable]` annotation here has no effect. \
561
+ See issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information.",
562
+ ) ;
563
+ }
564
+ }
565
+
542
566
if let Res :: Def ( DefKind :: Trait , trait_did) = t. path . res {
543
567
for impl_item_ref in items {
544
568
let impl_item = self . tcx . hir ( ) . impl_item ( impl_item_ref. id ) ;
@@ -598,6 +622,44 @@ impl Visitor<'tcx> for Checker<'tcx> {
598
622
}
599
623
}
600
624
625
+ struct CheckTraitImplStable < ' tcx > {
626
+ tcx : TyCtxt < ' tcx > ,
627
+ fully_stable : bool ,
628
+ }
629
+
630
+ impl Visitor < ' tcx > for CheckTraitImplStable < ' tcx > {
631
+ type Map = Map < ' tcx > ;
632
+
633
+ fn nested_visit_map ( & mut self ) -> NestedVisitorMap < Self :: Map > {
634
+ NestedVisitorMap :: None
635
+ }
636
+
637
+ fn visit_path ( & mut self , path : & ' tcx hir:: Path < ' tcx > , _id : hir:: HirId ) {
638
+ if let Some ( def_id) = path. res . opt_def_id ( ) {
639
+ if let Some ( stab) = self . tcx . lookup_stability ( def_id) {
640
+ self . fully_stable &= stab. level . is_stable ( ) ;
641
+ }
642
+ }
643
+ intravisit:: walk_path ( self , path)
644
+ }
645
+
646
+ fn visit_trait_ref ( & mut self , t : & ' tcx TraitRef < ' tcx > ) {
647
+ if let Res :: Def ( DefKind :: Trait , trait_did) = t. path . res {
648
+ if let Some ( stab) = self . tcx . lookup_stability ( trait_did) {
649
+ self . fully_stable &= stab. level . is_stable ( ) ;
650
+ }
651
+ }
652
+ intravisit:: walk_trait_ref ( self , t)
653
+ }
654
+
655
+ fn visit_ty ( & mut self , t : & ' tcx Ty < ' tcx > ) {
656
+ if let TyKind :: Never = t. kind {
657
+ self . fully_stable = false ;
658
+ }
659
+ intravisit:: walk_ty ( self , t)
660
+ }
661
+ }
662
+
601
663
/// Given the list of enabled features that were not language features (i.e., that
602
664
/// were expected to be library features), and the list of features used from
603
665
/// libraries, identify activated features that don't exist and error about them.
0 commit comments