Skip to content

Commit 949bdd8

Browse files
committed
Add regression test
1 parent ad5aa23 commit 949bdd8

File tree

4 files changed

+59
-5
lines changed

4 files changed

+59
-5
lines changed

Diff for: compiler/rustc_mir/src/transform/check_consts/validation.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -789,10 +789,10 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
789789
}
790790
}
791791

792+
#[instrument(skip(self))]
792793
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
793794
use rustc_target::spec::abi::Abi::RustIntrinsic;
794795

795-
trace!("visit_terminator: terminator={:?} location={:?}", terminator, location);
796796
self.super_terminator(terminator, location);
797797

798798
match &terminator.kind {
@@ -816,6 +816,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
816816

817817
// Attempting to call a trait method?
818818
if let Some(trait_id) = tcx.trait_of_item(callee) {
819+
trace!("attempting to call a trait method");
819820
if !self.tcx.features().const_trait_impl {
820821
self.check_op(ops::FnCallNonConst);
821822
return;
@@ -871,13 +872,13 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
871872
return;
872873
}
873874

875+
let is_intrinsic = tcx.fn_sig(callee).abi() == RustIntrinsic;
876+
874877
// HACK: This is to "unstabilize" the `transmute` intrinsic
875878
// within const fns. `transmute` is allowed in all other const contexts.
876879
// This won't really scale to more intrinsics or functions. Let's allow const
877880
// transmutes in const fn before we add more hacks to this.
878-
if tcx.fn_sig(callee).abi() == RustIntrinsic
879-
&& tcx.item_name(callee) == sym::transmute
880-
{
881+
if is_intrinsic && tcx.item_name(callee) == sym::transmute {
881882
self.check_op(ops::Transmute);
882883
return;
883884
}
@@ -890,6 +891,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
890891
// If the `const fn` we are trying to call is not const-stable, ensure that we have
891892
// the proper feature gate enabled.
892893
if let Some(gate) = is_unstable_const_fn(tcx, callee) {
894+
trace!(?gate, "calling unstable const fn");
893895
if self.span.allows_unstable(gate) {
894896
return;
895897
}
@@ -904,12 +906,14 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
904906
// If this crate is not using stability attributes, or the caller is not claiming to be a
905907
// stable `const fn`, that is all that is required.
906908
if !self.ccx.is_const_stable_const_fn() {
909+
trace!("crate not using stability attributes or caller not stably const");
907910
return;
908911
}
909912

910913
// Otherwise, we are something const-stable calling a const-unstable fn.
911914

912915
if super::rustc_allow_const_fn_unstable(tcx, caller, gate) {
916+
trace!("rustc_allow_const_fn_unstable gate active");
913917
return;
914918
}
915919

@@ -923,10 +927,16 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
923927
let callee_is_unstable_unmarked = tcx.lookup_const_stability(callee).is_none()
924928
&& tcx.lookup_stability(callee).map_or(false, |s| s.level.is_unstable());
925929
if callee_is_unstable_unmarked {
926-
if self.ccx.is_const_stable_const_fn() {
930+
trace!("callee_is_unstable_unmarked");
931+
// We do not use `const` modifiers for intrinsic "functions", as intrinsics are
932+
// `extern` funtions, and these have way to get marked `const`. So instead we
933+
// use `rustc_const_(un)stable` attributes to mean that the intrinsic is `const`
934+
if self.ccx.is_const_stable_const_fn() || is_intrinsic {
927935
self.check_op(ops::FnCallUnstable(callee, None));
936+
return;
928937
}
929938
}
939+
trace!("permitting call");
930940
}
931941

932942
// Forbid all `Drop` terminators unless the place being dropped is a local with no

Diff for: src/test/ui/consts/intrinsic_without_const_stab.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// check-pass
2+
3+
#![feature(intrinsics, staged_api, const_intrinsic_copy)]
4+
#![stable(feature = "core", since = "1.6.0")]
5+
6+
#[stable(feature = "rust1", since = "1.0.0")]
7+
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
8+
#[inline]
9+
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
10+
extern "rust-intrinsic" {
11+
fn copy<T>(src: *const T, dst: *mut T, count: usize);
12+
}
13+
14+
// Even though the `copy` intrinsic lacks stability attributes, this works, because it
15+
// inherits its stability attributes from its parent. That includes `rustc_const_(un)stable`
16+
// attributes.
17+
unsafe { copy(src, dst, count) }
18+
}
19+
20+
fn main() {}
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![feature(intrinsics, staged_api, const_intrinsic_copy)]
2+
#![stable(feature = "core", since = "1.6.0")]
3+
4+
extern "rust-intrinsic" {
5+
fn copy<T>(src: *const T, dst: *mut T, count: usize);
6+
}
7+
8+
#[stable(feature = "rust1", since = "1.0.0")]
9+
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
10+
#[inline]
11+
pub const unsafe fn stuff<T>(src: *const T, dst: *mut T, count: usize) {
12+
unsafe { copy(src, dst, count) } //~ ERROR calls in constant functions are limited
13+
}
14+
15+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
2+
--> $DIR/intrinsic_without_const_stab_fail.rs:12:14
3+
|
4+
LL | unsafe { copy(src, dst, count) }
5+
| ^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0015`.

0 commit comments

Comments
 (0)