33use std:: assert_matches:: assert_matches;
44use std:: borrow:: Cow ;
55use std:: mem;
6+ use std:: num:: NonZero ;
67use std:: ops:: Deref ;
78
89use rustc_attr:: { ConstStability , StabilityLevel } ;
@@ -780,7 +781,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
780781 }
781782 }
782783 Some ( ConstStability {
783- level : StabilityLevel :: Unstable { implied_by : implied_feature, .. } ,
784+ level : StabilityLevel :: Unstable { implied_by : implied_feature, issue , .. } ,
784785 feature,
785786 ..
786787 } ) => {
@@ -803,7 +804,23 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
803804 // to allow this.
804805 let feature_enabled = callee. is_local ( )
805806 || tcx. features ( ) . enabled ( feature)
806- || implied_feature. is_some_and ( |f| tcx. features ( ) . enabled ( f) ) ;
807+ || implied_feature. is_some_and ( |f| tcx. features ( ) . enabled ( f) )
808+ || {
809+ // When we're compiling the compiler itself we may pull in
810+ // crates from crates.io, but those crates may depend on other
811+ // crates also pulled in from crates.io. We want to ideally be
812+ // able to compile everything without requiring upstream
813+ // modifications, so in the case that this looks like a
814+ // `rustc_private` crate (e.g., a compiler crate) and we also have
815+ // the `-Z force-unstable-if-unmarked` flag present (we're
816+ // compiling a compiler crate), then let this missing feature
817+ // annotation slide.
818+ // This matches what we do in `eval_stability_allow_unstable` for
819+ // regular stability.
820+ feature == sym:: rustc_private
821+ && issue == NonZero :: new ( 27812 )
822+ && self . tcx . sess . opts . unstable_opts . force_unstable_if_unmarked
823+ } ;
807824 // We do *not* honor this if we are in the "danger zone": we have to enforce
808825 // recursive const-stability and the callee is not safe-to-expose. In that
809826 // case we need `check_op` to do the check.
0 commit comments