about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-11-02 08:49:49 +0100
committerRalf Jung <post@ralfj.de>2024-11-04 23:27:46 +0100
commita741b33c145a5f1fa3e7f42a4488750ce8719d4f (patch)
tree9a1455ea42e9fe3816128a3b059881b4d6ddaa70
parent5069434c816aa13ffd2807cf95133ade5a9306df (diff)
downloadrust-a741b33c145a5f1fa3e7f42a4488750ce8719d4f.tar.gz
rust-a741b33c145a5f1fa3e7f42a4488750ce8719d4f.zip
when an intrinsic has a const-stable fallback body, we can easily expose it on stable
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs16
-rw-r--r--compiler/rustc_middle/src/ty/util.rs3
-rw-r--r--tests/ui/consts/auxiliary/unstable_intrinsic.rs2
-rw-r--r--tests/ui/consts/const-unstable-intrinsic.rs12
-rw-r--r--tests/ui/consts/const-unstable-intrinsic.stderr12
5 files changed, 37 insertions, 8 deletions
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index 1c17421e782..aea3d5bd3e7 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -739,6 +739,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                     // We use `intrinsic.const_stable` to determine if this can be safely exposed to
                     // stable code, rather than `const_stable_indirect`. This is to make
                     // `#[rustc_const_stable_indirect]` an attribute that is always safe to add.
+                    // We also ask is_safe_to_expose_on_stable_const_fn; this determines whether the intrinsic
+                    // fallback body is safe to expose on stable.
+                    let is_const_stable = intrinsic.const_stable
+                        || (!intrinsic.must_be_overridden
+                            && tcx.is_const_fn(callee)
+                            && is_safe_to_expose_on_stable_const_fn(tcx, callee));
                     match tcx.lookup_const_stability(callee) {
                         None => {
                             // Non-const intrinsic.
@@ -748,7 +754,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                             // Intrinsic does not need a separate feature gate (we rely on the
                             // regular stability checker). However, we have to worry about recursive
                             // const stability.
-                            if !intrinsic.const_stable && self.enforce_recursive_const_stability() {
+                            if !is_const_stable && self.enforce_recursive_const_stability() {
                                 self.dcx().emit_err(errors::UnmarkedIntrinsicExposed {
                                     span: self.span,
                                     def_path: self.tcx.def_path_str(callee),
@@ -763,12 +769,14 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                             self.check_op(ops::IntrinsicUnstable {
                                 name: intrinsic.name,
                                 feature,
-                                const_stable: intrinsic.const_stable,
+                                const_stable: is_const_stable,
                             });
                         }
                         Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
-                            // All good. But ensure this is indeed a const-stable intrinsic.
-                            assert!(intrinsic.const_stable);
+                            // All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it
+                            // can be *directly* invoked from stable const code) does not always
+                            // have the `#[rustc_const_stable_intrinsic]` attribute (which controls
+                            // exposing an intrinsic indirectly); we accept this call anyway.
                         }
                     }
                     // This completes the checks for intrinsics.
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index b5811824683..6ffd149ef14 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1789,8 +1789,7 @@ pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Intrinsi
         Some(ty::IntrinsicDef {
             name: tcx.item_name(def_id.into()),
             must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden),
-            const_stable: tcx.has_attr(def_id, sym::rustc_const_stable_intrinsic)
-                || tcx.lookup_const_stability(def_id).is_some_and(|s| s.is_const_stable()),
+            const_stable: tcx.has_attr(def_id, sym::rustc_const_stable_intrinsic),
         })
     } else {
         None
diff --git a/tests/ui/consts/auxiliary/unstable_intrinsic.rs b/tests/ui/consts/auxiliary/unstable_intrinsic.rs
index 0749e7e6df8..9e53a8feb5d 100644
--- a/tests/ui/consts/auxiliary/unstable_intrinsic.rs
+++ b/tests/ui/consts/auxiliary/unstable_intrinsic.rs
@@ -3,9 +3,11 @@
 
 #[unstable(feature = "unstable", issue = "42")]
 #[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
 
 #[unstable(feature = "unstable", issue = "42")]
 #[rustc_const_unstable(feature = "unstable", issue = "42")]
 #[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
diff --git a/tests/ui/consts/const-unstable-intrinsic.rs b/tests/ui/consts/const-unstable-intrinsic.rs
index fbe491e0671..56b552b6a3f 100644
--- a/tests/ui/consts/const-unstable-intrinsic.rs
+++ b/tests/ui/consts/const-unstable-intrinsic.rs
@@ -30,11 +30,13 @@ const fn const_main() {
 
 #[unstable(feature = "local", issue = "42")]
 #[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
 
 #[unstable(feature = "local", issue = "42")]
 #[rustc_const_unstable(feature = "local", issue = "42")]
 #[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -43,6 +45,7 @@ pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
 pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
     // Const stability attributes are not inherited from parent items.
     #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
     const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
         unimplemented!()
     }
@@ -50,3 +53,12 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
     unsafe { copy(src, dst, count) }
     //~^ ERROR cannot be (indirectly) exposed to stable
 }
+
+// Ensure that a fallback body is recursively-const-checked.
+mod fallback {
+    #[rustc_intrinsic]
+    const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
+        super::size_of_val(src);
+        //~^ ERROR cannot be (indirectly) exposed to stable
+    }
+}
diff --git a/tests/ui/consts/const-unstable-intrinsic.stderr b/tests/ui/consts/const-unstable-intrinsic.stderr
index 2cf76732cf2..3e605f3d003 100644
--- a/tests/ui/consts/const-unstable-intrinsic.stderr
+++ b/tests/ui/consts/const-unstable-intrinsic.stderr
@@ -60,13 +60,21 @@ LL | const fn const_main() {
    |
 
 error: intrinsic `copy::copy` cannot be (indirectly) exposed to stable
-  --> $DIR/const-unstable-intrinsic.rs:50:14
+  --> $DIR/const-unstable-intrinsic.rs:53:14
    |
 LL |     unsafe { copy(src, dst, count) }
    |              ^^^^^^^^^^^^^^^^^^^^^
    |
    = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
 
-error: aborting due to 7 previous errors
+error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable
+  --> $DIR/const-unstable-intrinsic.rs:61:9
+   |
+LL |         super::size_of_val(src);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
+
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0658`.