@@ -801,22 +801,47 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
801
801
// FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem
802
802
let const_stab = attrs:: find_attr!( attrs, AttributeKind :: ConstStability { stability, ..} => * stability) ;
803
803
804
+ let unstable_feature_stab =
805
+ find_attr ! ( attrs, AttributeKind :: AllowUnstableFeature ( i) => i)
806
+ . map ( |i| i. as_slice ( ) )
807
+ . unwrap_or_default ( ) ;
808
+
804
809
// If this impl block has an #[unstable] attribute, give an
805
810
// error if all involved types and traits are stable, because
806
811
// it will have no effect.
807
812
// See: https://github.com/rust-lang/rust/issues/55436
813
+ //
814
+ // The exception is when there is both #[unstable_feature_bound(..)] and
815
+ // #![unstable(feature = "..", issue = "..")] that have the same symbol because
816
+ // that can effectively mark an impl as unstable.
817
+ //
818
+ // For example:
819
+ // ```
820
+ // #[unstable_feature_bound(feat_foo)]
821
+ // #![unstable(feature = "feat_foo", issue = "none")]
822
+ // impl Foo for Bar {}
823
+ // ```
808
824
if let Some ( (
809
- Stability { level : attrs:: StabilityLevel :: Unstable { .. } , .. } ,
825
+ Stability { level : attrs:: StabilityLevel :: Unstable { ..} , feature } ,
810
826
span,
811
827
) ) = stab
812
828
{
813
829
let mut c = CheckTraitImplStable { tcx : self . tcx , fully_stable : true } ;
814
830
c. visit_ty_unambig ( self_ty) ;
815
831
c. visit_trait_ref ( t) ;
816
832
833
+ // Skip the lint if the impl is marked as unstable using
834
+ // #[unstable_feature_bound(..)]
835
+ let mut unstable_feature_bound_in_effect = false ;
836
+ for ( unstable_bound_feat_name, _) in unstable_feature_stab {
837
+ if * unstable_bound_feat_name == feature {
838
+ unstable_feature_bound_in_effect = true ;
839
+ }
840
+ }
841
+
817
842
// do not lint when the trait isn't resolved, since resolution error should
818
843
// be fixed first
819
- if t. path . res != Res :: Err && c. fully_stable {
844
+ if t. path . res != Res :: Err && c. fully_stable && !unstable_feature_bound_in_effect {
820
845
self . tcx . emit_node_span_lint (
821
846
INEFFECTIVE_UNSTABLE_TRAIT_IMPL ,
822
847
item. hir_id ( ) ,
0 commit comments