@@ -702,6 +702,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
702702                    // We use `intrinsic.const_stable` to determine if this can be safely exposed to 
703703                    // stable code, rather than `const_stable_indirect`. This is to make 
704704                    // `#[rustc_const_stable_indirect]` an attribute that is always safe to add. 
705+                     // We also ask is_safe_to_expose_on_stable_const_fn; this determines whether the intrinsic 
706+                     // fallback body is safe to expose on stable. 
707+                     let  is_const_stable = intrinsic. const_stable 
708+                         || ( !intrinsic. must_be_overridden 
709+                             && tcx. is_const_fn ( callee) 
710+                             && is_safe_to_expose_on_stable_const_fn ( tcx,  callee) ) ; 
705711                    match  tcx. lookup_const_stability ( callee)  { 
706712                        None  => { 
707713                            // Non-const intrinsic. 
@@ -711,7 +717,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
711717                            // Intrinsic does not need a separate feature gate (we rely on the 
712718                            // regular stability checker). However, we have to worry about recursive 
713719                            // const stability. 
714-                             if  !intrinsic . const_stable  && self . enforce_recursive_const_stability ( )  { 
720+                             if  !is_const_stable  && self . enforce_recursive_const_stability ( )  { 
715721                                self . dcx ( ) . emit_err ( errors:: UnmarkedIntrinsicExposed  { 
716722                                    span :  self . span , 
717723                                    def_path :  self . tcx . def_path_str ( callee) , 
@@ -726,12 +732,14 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
726732                            self . check_op ( ops:: IntrinsicUnstable  { 
727733                                name :  intrinsic. name , 
728734                                feature, 
729-                                 const_stable :  intrinsic . const_stable , 
735+                                 const_stable :  is_const_stable , 
730736                            } ) ; 
731737                        } 
732738                        Some ( ConstStability  {  level :  StabilityLevel :: Stable  {  .. } ,  .. } )  => { 
733-                             // All good. But ensure this is indeed a const-stable intrinsic. 
734-                             assert ! ( intrinsic. const_stable) ; 
739+                             // All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it 
740+                             // can be *directly* invoked from stable const code) does not always 
741+                             // have the `#[rustc_const_stable_intrinsic]` attribute (which controls 
742+                             // exposing an intrinsic indirectly); we accept this call anyway. 
735743                        } 
736744                    } 
737745                    // This completes the checks for intrinsics. 
0 commit comments