Skip to content

Commit 3ef863b

Browse files
committed
Place unions, pointer casts and pointer derefs behind extra feature gates
1 parent 9e472c2 commit 3ef863b

20 files changed

+118
-131
lines changed

src/libcore/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
#![feature(concat_idents)]
8383
#![feature(const_fn)]
8484
#![feature(const_int_ops)]
85+
#![feature(const_fn_union)]
8586
#![feature(custom_attribute)]
8687
#![feature(doc_cfg)]
8788
#![feature(doc_spotlight)]

src/librustc_mir/diagnostics.rs

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -619,38 +619,6 @@ If you really want global mutable state, try using `static mut` or a global
619619
`UnsafeCell`.
620620
"##,
621621

622-
E0018: r##"
623-
624-
The value of static and constant integers must be known at compile time. You
625-
can't cast a pointer to an integer because the address of a pointer can
626-
vary.
627-
628-
For example, if you write:
629-
630-
```compile_fail,E0018
631-
static MY_STATIC: u32 = 42;
632-
static MY_STATIC_ADDR: usize = &MY_STATIC as *const _ as usize;
633-
static WHAT: usize = (MY_STATIC_ADDR^17) + MY_STATIC_ADDR;
634-
```
635-
636-
Then `MY_STATIC_ADDR` would contain the address of `MY_STATIC`. However,
637-
the address can change when the program is linked, as well as change
638-
between different executions due to ASLR, and many linkers would
639-
not be able to calculate the value of `WHAT`.
640-
641-
On the other hand, static and constant pointers can point either to
642-
a known numeric address or to the address of a symbol.
643-
644-
```
645-
static MY_STATIC: u32 = 42;
646-
static MY_STATIC_ADDR: &'static u32 = &MY_STATIC;
647-
const CONST_ADDR: *const u8 = 0x5f3759df as *const u8;
648-
```
649-
650-
This does not pose a problem by itself because they can't be
651-
accessed directly.
652-
"##,
653-
654622
E0019: r##"
655623
A function call isn't allowed in the const's initialization expression
656624
because the expression's value must be known at compile-time. Erroneous code
@@ -1208,29 +1176,6 @@ fn main() {
12081176
```
12091177
"##,
12101178

1211-
E0396: r##"
1212-
The value behind a raw pointer can't be determined at compile-time
1213-
(or even link-time), which means it can't be used in a constant
1214-
expression. Erroneous code example:
1215-
1216-
```compile_fail,E0396
1217-
const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
1218-
1219-
const VALUE: u8 = unsafe { *REG_ADDR };
1220-
// error: raw pointers cannot be dereferenced in constants
1221-
```
1222-
1223-
A possible fix is to dereference your pointer at some point in run-time.
1224-
1225-
For example:
1226-
1227-
```
1228-
const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
1229-
1230-
let reg_value = unsafe { *REG_ADDR };
1231-
```
1232-
"##,
1233-
12341179
E0492: r##"
12351180
A borrow of a constant containing interior mutability was attempted. Erroneous
12361181
code example:

src/librustc_mir/transform/qualify_consts.rs

Lines changed: 37 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -495,37 +495,41 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
495495

496496
let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
497497
if let ty::TyRawPtr(_) = base_ty.sty {
498-
if this.mode != Mode::Fn {
499-
let mut err = struct_span_err!(
500-
this.tcx.sess,
501-
this.span,
502-
E0396,
503-
"raw pointers cannot be dereferenced in {}s",
504-
this.mode
498+
if this.mode != Mode::Fn &&
499+
!this.tcx.sess.features_untracked().const_raw_ptr_deref {
500+
emit_feature_err(
501+
&this.tcx.sess.parse_sess, "const_raw_ptr_deref",
502+
this.span, GateIssue::Language,
503+
&format!(
504+
"dereferencing raw pointers in {}s is unstable",
505+
this.mode,
506+
),
505507
);
506-
err.span_label(this.span,
507-
"dereference of raw pointer in constant");
508-
if this.tcx.sess.teach(&err.get_code().unwrap()) {
509-
err.note(
510-
"The value behind a raw pointer can't be determined \
511-
at compile-time (or even link-time), which means it \
512-
can't be used in a constant expression."
513-
);
514-
err.help("A possible fix is to dereference your pointer \
515-
at some point in run-time.");
516-
}
517-
err.emit();
518508
}
519509
}
520510
}
521511

522512
ProjectionElem::Field(..) |
523513
ProjectionElem::Index(_) => {
524-
if this.mode == Mode::Fn {
525-
let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
526-
if let Some(def) = base_ty.ty_adt_def() {
527-
if def.is_union() {
528-
this.not_const();
514+
let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
515+
if let Some(def) = base_ty.ty_adt_def() {
516+
if def.is_union() {
517+
match this.mode {
518+
Mode::Fn => {},
519+
Mode::ConstFn => {
520+
if !this.tcx.sess.features_untracked().const_fn_union {
521+
emit_feature_err(
522+
&this.tcx.sess.parse_sess, "const_fn_union",
523+
this.span, GateIssue::Language,
524+
"unions in const fn are unstable",
525+
);
526+
}
527+
},
528+
529+
| Mode::Static
530+
| Mode::StaticMut
531+
| Mode::Const
532+
=> {},
529533
}
530534
}
531535
}
@@ -723,43 +727,16 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
723727
(CastTy::Ptr(_), CastTy::Int(_)) |
724728
(CastTy::FnPtr, CastTy::Int(_)) => {
725729
self.add(Qualif::NOT_CONST);
726-
if self.mode != Mode::Fn {
727-
let mut err = struct_span_err!(
728-
self.tcx.sess,
729-
self.span,
730-
E0018,
731-
"raw pointers cannot be cast to integers in {}s",
732-
self.mode
730+
if self.mode != Mode::Fn &&
731+
!self.tcx.sess.features_untracked().const_raw_ptr_deref {
732+
emit_feature_err(
733+
&self.tcx.sess.parse_sess, "const_raw_ptr_deref",
734+
self.span, GateIssue::Language,
735+
&format!(
736+
"casting pointers to integers in {}s is unstable",
737+
self.mode,
738+
),
733739
);
734-
if self.tcx.sess.teach(&err.get_code().unwrap()) {
735-
err.note("\
736-
The value of static and constant integers must be known at compile time. You can't cast a pointer \
737-
to an integer because the address of a pointer can vary.
738-
739-
For example, if you write:
740-
741-
```
742-
static MY_STATIC: u32 = 42;
743-
static MY_STATIC_ADDR: usize = &MY_STATIC as *const _ as usize;
744-
static WHAT: usize = (MY_STATIC_ADDR^17) + MY_STATIC_ADDR;
745-
```
746-
747-
Then `MY_STATIC_ADDR` would contain the address of `MY_STATIC`. However, the address can change \
748-
when the program is linked, as well as change between different executions due to ASLR, and many \
749-
linkers would not be able to calculate the value of `WHAT`.
750-
751-
On the other hand, static and constant pointers can point either to a known numeric address or to \
752-
the address of a symbol.
753-
754-
```
755-
static MY_STATIC: u32 = 42;
756-
static MY_STATIC_ADDR: &'static u32 = &MY_STATIC;
757-
const CONST_ADDR: *const u8 = 0x5f3759df as *const u8;
758-
```
759-
760-
This does not pose a problem by itself because they can't be accessed directly.");
761-
}
762-
err.emit();
763740
}
764741
}
765742
_ => {}

src/libsyntax/feature_gate.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,15 @@ declare_features! (
216216
// Allows let bindings and destructuring in `const fn` functions and constants.
217217
(active, const_let, "1.22.1", Some(48821), None),
218218

219+
// Allows accessing fields of unions inside const fn
220+
(active, const_fn_union, "1.27.0", Some(51909), None),
221+
222+
// Allows casting raw pointers to `usize` during const eval
223+
(active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None),
224+
225+
// Allows dereferencing raw pointers during const eval
226+
(active, const_raw_ptr_deref, "1.27.0", Some(51911), None),
227+
219228
// Allows using #[prelude_import] on glob `use` items.
220229
//
221230
// rustc internal

src/test/compile-fail/cast-ptr-to-int-const.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
const X: u32 = main as u32; //~ ERROR E0018
12+
const X: u32 = main as u32; //~ ERROR casting pointers to integers in constants is unstable
1313
const Y: u32 = 0;
14-
const Z: u32 = &Y as *const u32 as u32; //~ ERROR E0018
14+
const Z: u32 = &Y as *const u32 as u32; //~ ERROR is unstable
1515
}

src/test/ui/const-deref-ptr.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
// Check that you can't dereference raw pointers in constants.
1212

1313
fn main() {
14-
static C: u64 = unsafe {*(0xdeadbeef as *const u64)}; //~ ERROR E0396
14+
static C: u64 = unsafe {*(0xdeadbeef as *const u64)};
15+
//~^ ERROR dereferencing raw pointers in statics is unstable
1516
println!("{}", C);
1617
}

src/test/ui/const-deref-ptr.stderr

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
error[E0396]: raw pointers cannot be dereferenced in statics
1+
error[E0658]: dereferencing raw pointers in statics is unstable (see issue #51911)
22
--> $DIR/const-deref-ptr.rs:14:29
33
|
4-
LL | static C: u64 = unsafe {*(0xdeadbeef as *const u64)}; //~ ERROR E0396
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer in constant
4+
LL | static C: u64 = unsafe {*(0xdeadbeef as *const u64)};
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
68

79
error: aborting due to previous error
810

9-
For more information about this error, try `rustc --explain E0396`.
11+
For more information about this error, try `rustc --explain E0658`.

src/test/ui/const-eval/const_transmute.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
// compile-pass
1212
// run-pass
1313

14+
#![feature(const_fn_union)]
15+
1416
union Transmute<T: Copy, U: Copy> {
1517
t: T,
1618
u: U,

src/test/ui/const-eval/promoted_const_fn_fail.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
// compile-pass
1212

13-
#![feature(const_fn)]
13+
#![feature(const_fn, const_fn_union)]
1414

1515
#![deny(const_err)]
1616

src/test/ui/const-eval/ref_to_float_transmute.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
//compile-pass
1212

13+
#![feature(const_fn_union)]
14+
1315
fn main() {}
1416

1517
static FOO: u32 = 42;

0 commit comments

Comments
 (0)