Skip to content

Commit 57ed415

Browse files
committed
when an intrinsic has a const-stable fallback body, we can easily expose it on stable
1 parent e67c4ee commit 57ed415

File tree

5 files changed

+37
-8
lines changed

5 files changed

+37
-8
lines changed

Diff for: compiler/rustc_const_eval/src/check_consts/check.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -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.

Diff for: compiler/rustc_middle/src/ty/util.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1790,8 +1790,7 @@ pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Intrinsi
17901790
Some(ty::IntrinsicDef {
17911791
name: tcx.item_name(def_id.into()),
17921792
must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden),
1793-
const_stable: tcx.has_attr(def_id, sym::rustc_const_stable_intrinsic)
1794-
|| tcx.lookup_const_stability(def_id).is_some_and(|s| s.is_const_stable()),
1793+
const_stable: tcx.has_attr(def_id, sym::rustc_const_stable_intrinsic),
17951794
})
17961795
} else {
17971796
None

Diff for: tests/ui/consts/auxiliary/unstable_intrinsic.rs

+2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33

44
#[unstable(feature = "unstable", issue = "42")]
55
#[rustc_intrinsic]
6+
#[rustc_intrinsic_must_be_overridden]
67
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
78

89
#[unstable(feature = "unstable", issue = "42")]
910
#[rustc_const_unstable(feature = "unstable", issue = "42")]
1011
#[rustc_intrinsic]
12+
#[rustc_intrinsic_must_be_overridden]
1113
pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }

Diff for: tests/ui/consts/const-unstable-intrinsic.rs

+12
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ const fn const_main() {
3030

3131
#[unstable(feature = "local", issue = "42")]
3232
#[rustc_intrinsic]
33+
#[rustc_intrinsic_must_be_overridden]
3334
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
3435

3536
#[unstable(feature = "local", issue = "42")]
3637
#[rustc_const_unstable(feature = "local", issue = "42")]
3738
#[rustc_intrinsic]
39+
#[rustc_intrinsic_must_be_overridden]
3840
pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
3941

4042
#[stable(feature = "rust1", since = "1.0.0")]
@@ -43,10 +45,20 @@ pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
4345
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
4446
// Const stability attributes are not inherited from parent items.
4547
#[rustc_intrinsic]
48+
#[rustc_intrinsic_must_be_overridden]
4649
const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
4750
unimplemented!()
4851
}
4952

5053
unsafe { copy(src, dst, count) }
5154
//~^ ERROR cannot be (indirectly) exposed to stable
5255
}
56+
57+
// Ensure that a fallback body is recursively-const-checked.
58+
mod fallback {
59+
#[rustc_intrinsic]
60+
const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
61+
super::size_of_val(src);
62+
//~^ ERROR cannot be (indirectly) exposed to stable
63+
}
64+
}

Diff for: tests/ui/consts/const-unstable-intrinsic.stderr

+10-2
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,21 @@ LL | const fn const_main() {
6060
|
6161

6262
error: intrinsic `copy::copy` cannot be (indirectly) exposed to stable
63-
--> $DIR/const-unstable-intrinsic.rs:50:14
63+
--> $DIR/const-unstable-intrinsic.rs:53:14
6464
|
6565
LL | unsafe { copy(src, dst, count) }
6666
| ^^^^^^^^^^^^^^^^^^^^^
6767
|
6868
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
6969

70-
error: aborting due to 7 previous errors
70+
error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable
71+
--> $DIR/const-unstable-intrinsic.rs:61:9
72+
|
73+
LL | super::size_of_val(src);
74+
| ^^^^^^^^^^^^^^^^^^^^^^^
75+
|
76+
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
77+
78+
error: aborting due to 8 previous errors
7179

7280
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)