@@ -736,16 +736,25 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
736736
737737 // Intrinsics are language primitives, not regular calls, so treat them separately.
738738 if let Some ( intrinsic) = tcx. intrinsic ( callee) {
739+ // We use `intrinsic.const_stable` to determine if this can be safely exposed to
740+ // stable code, rather than `const_stable_indirect`. This is to make
741+ // `#[rustc_const_stable_indirect]` an attribute that is always safe to add.
742+ // We also ask is_safe_to_expose_on_stable_const_fn; this determines whether the intrinsic
743+ // fallback body is safe to expose on stable.
744+ let is_const_stable = intrinsic. const_stable
745+ || ( !intrinsic. must_be_overridden
746+ && tcx. is_const_fn ( callee)
747+ && is_safe_to_expose_on_stable_const_fn ( tcx, callee) ) ;
739748 match tcx. lookup_const_stability ( callee) {
740749 None => {
741750 // Non-const intrinsic.
742751 self . check_op ( ops:: IntrinsicNonConst { name : intrinsic. name } ) ;
743752 }
744- Some ( ConstStability { feature : None , const_stable_indirect , .. } ) => {
753+ Some ( ConstStability { feature : None , .. } ) => {
745754 // Intrinsic does not need a separate feature gate (we rely on the
746755 // regular stability checker). However, we have to worry about recursive
747756 // const stability.
748- if !const_stable_indirect && self . enforce_recursive_const_stability ( ) {
757+ if !is_const_stable && self . enforce_recursive_const_stability ( ) {
749758 self . dcx ( ) . emit_err ( errors:: UnmarkedIntrinsicExposed {
750759 span : self . span ,
751760 def_path : self . tcx . def_path_str ( callee) ,
@@ -755,17 +764,19 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
755764 Some ( ConstStability {
756765 feature : Some ( feature) ,
757766 level : StabilityLevel :: Unstable { .. } ,
758- const_stable_indirect,
759767 ..
760768 } ) => {
761769 self . check_op ( ops:: IntrinsicUnstable {
762770 name : intrinsic. name ,
763771 feature,
764- const_stable_indirect ,
772+ const_stable : is_const_stable ,
765773 } ) ;
766774 }
767775 Some ( ConstStability { level : StabilityLevel :: Stable { .. } , .. } ) => {
768- // All good.
776+ // All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it
777+ // can be *directly* invoked from stable const code) does not always
778+ // have the `#[rustc_const_stable_intrinsic]` attribute (which controls
779+ // exposing an intrinsic indirectly); we accept this call anyway.
769780 }
770781 }
771782 // This completes the checks for intrinsics.
0 commit comments