From a091a6567c210686fdbc77cd1c5d5bca5e86cd3d Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 3 Aug 2018 13:27:35 +0200 Subject: [PATCH] Make sure the feature gate actually works and never allows promoting these operations --- src/librustc_mir/transform/qualify_consts.rs | 40 ++++++++++--------- src/test/ui/const-eval/const_raw_ptr_ops.rs | 27 +++++++++++++ .../ui/const-eval/const_raw_ptr_ops.stderr | 36 +++++++++++++++++ .../ui/const-eval/promoted_raw_ptr_ops.rs | 18 +++++++++ .../ui/const-eval/promoted_raw_ptr_ops.stderr | 35 ++++++++++++++++ src/test/ui/error-codes/E0395.stderr | 2 +- 6 files changed, 138 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/const-eval/const_raw_ptr_ops.rs create mode 100644 src/test/ui/const-eval/const_raw_ptr_ops.stderr create mode 100644 src/test/ui/const-eval/promoted_raw_ptr_ops.rs create mode 100644 src/test/ui/const-eval/promoted_raw_ptr_ops.stderr diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 1a66a1751ff..d876ee77e76 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -491,20 +491,21 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { this.super_place(place, context, location); match proj.elem { ProjectionElem::Deref => { - this.add(Qualif::NOT_CONST); - - let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx); - if let ty::TyRawPtr(_) = base_ty.sty { - if this.mode != Mode::Fn && - !this.tcx.sess.features_untracked().const_raw_ptr_deref { - emit_feature_err( - &this.tcx.sess.parse_sess, "const_raw_ptr_deref", - this.span, GateIssue::Language, - &format!( - "dereferencing raw pointers in {}s is unstable", - this.mode, - ), - ); + if let Mode::Fn = this.mode { + this.add(Qualif::NOT_CONST); + } else { + let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx); + if let ty::TyRawPtr(_) = base_ty.sty { + if !this.tcx.sess.features_untracked().const_raw_ptr_deref { + emit_feature_err( + &this.tcx.sess.parse_sess, "const_raw_ptr_deref", + this.span, GateIssue::Language, + &format!( + "dereferencing raw pointers in {}s is unstable", + this.mode, + ), + ); + } } } } @@ -726,9 +727,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { match (cast_in, cast_out) { (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => { - self.add(Qualif::NOT_CONST); - if self.mode != Mode::Fn && - !self.tcx.sess.features_untracked().const_raw_ptr_to_usize_cast { + if let Mode::Fn = self.mode { + self.add(Qualif::NOT_CONST); + } else if !self.tcx.sess.features_untracked().const_raw_ptr_to_usize_cast { emit_feature_err( &self.tcx.sess.parse_sess, "const_raw_ptr_to_usize_cast", self.span, GateIssue::Language, @@ -750,8 +751,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { op == BinOp::Ge || op == BinOp::Gt || op == BinOp::Offset); - self.add(Qualif::NOT_CONST); - if self.mode != Mode::Fn { + if let Mode::Fn = self.mode { + self.add(Qualif::NOT_CONST); + } else if !self.tcx.sess.features_untracked().const_compare_raw_pointers { emit_feature_err( &self.tcx.sess.parse_sess, "const_compare_raw_pointers", diff --git a/src/test/ui/const-eval/const_raw_ptr_ops.rs b/src/test/ui/const-eval/const_raw_ptr_ops.rs new file mode 100644 index 00000000000..9121c67b8b9 --- /dev/null +++ b/src/test/ui/const-eval/const_raw_ptr_ops.rs @@ -0,0 +1,27 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(const_raw_ptr_to_usize_cast, const_compare_raw_pointers, const_raw_ptr_deref)] + +fn main() {} + +// unconst and bad, will thus error in miri +const X: bool = &1 as *const i32 == &2 as *const i32; //~ ERROR cannot be used +// unconst and fine +const X2: bool = 42 as *const i32 == 43 as *const i32; +// unconst and fine +const Y: usize = 42usize as *const i32 as usize + 1; +// unconst and bad, will thus error in miri +const Y2: usize = &1 as *const i32 as usize + 1; //~ ERROR cannot be used +// unconst and fine +const Z: i32 = unsafe { *(&1 as *const i32) }; +// unconst and bad, will thus error in miri +const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR cannot be used +const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR cannot be used \ No newline at end of file diff --git a/src/test/ui/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/const-eval/const_raw_ptr_ops.stderr new file mode 100644 index 00000000000..a9442be081d --- /dev/null +++ b/src/test/ui/const-eval/const_raw_ptr_ops.stderr @@ -0,0 +1,36 @@ +error: this constant cannot be used + --> $DIR/const_raw_ptr_ops.rs:16:1 + | +LL | const X: bool = &1 as *const i32 == &2 as *const i32; //~ ERROR cannot be used + | ^^^^^^^^^^^^^^^^------------------------------------^ + | | + | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants + | + = note: #[deny(const_err)] on by default + +error: this constant cannot be used + --> $DIR/const_raw_ptr_ops.rs:22:1 + | +LL | const Y2: usize = &1 as *const i32 as usize + 1; //~ ERROR cannot be used + | ^^^^^^^^^^^^^^^^^^-----------------------------^ + | | + | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants + +error: this constant cannot be used + --> $DIR/const_raw_ptr_ops.rs:26:1 + | +LL | const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR cannot be used + | ^^^^^^^^^^^^^^^^^^^^^^^^^-------------------^^^ + | | + | tried to access memory with alignment 2, but alignment 4 is required + +error: this constant cannot be used + --> $DIR/const_raw_ptr_ops.rs:27:1 + | +LL | const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR cannot be used + | ^^^^^^^^^^^^^^^^^^^^^^^^^-------------------^^^ + | | + | a memory access tried to interpret some bytes as a pointer + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/const-eval/promoted_raw_ptr_ops.rs b/src/test/ui/const-eval/promoted_raw_ptr_ops.rs new file mode 100644 index 00000000000..30e7648f04d --- /dev/null +++ b/src/test/ui/const-eval/promoted_raw_ptr_ops.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(const_raw_ptr_to_usize_cast, const_compare_raw_pointers, const_raw_ptr_deref)] + +fn main() { + let x: &'static bool = &(42 as *const i32 == 43 as *const i32); + //~^ ERROR does not live long enough + let y: &'static usize = &(&1 as *const i32 as usize + 1); //~ ERROR does not live long enough + let z: &'static i32 = &(unsafe { *(42 as *const i32) }); //~ ERROR does not live long enough +} \ No newline at end of file diff --git a/src/test/ui/const-eval/promoted_raw_ptr_ops.stderr b/src/test/ui/const-eval/promoted_raw_ptr_ops.stderr new file mode 100644 index 00000000000..90c73c095fb --- /dev/null +++ b/src/test/ui/const-eval/promoted_raw_ptr_ops.stderr @@ -0,0 +1,35 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/promoted_raw_ptr_ops.rs:14:29 + | +LL | let x: &'static bool = &(42 as *const i32 == 43 as *const i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +... +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/promoted_raw_ptr_ops.rs:16:30 + | +LL | let y: &'static usize = &(&1 as *const i32 as usize + 1); //~ ERROR does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | let z: &'static i32 = &(unsafe { *(42 as *const i32) }); //~ ERROR does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/promoted_raw_ptr_ops.rs:17:28 + | +LL | let z: &'static i32 = &(unsafe { *(42 as *const i32) }); //~ ERROR does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr index 90f9ab9ec36..0fb9a9e854d 100644 --- a/src/test/ui/error-codes/E0395.stderr +++ b/src/test/ui/error-codes/E0395.stderr @@ -1,5 +1,5 @@ error[E0658]: comparing raw pointers inside static (see issue #53020) - --> $DIR/E0395.rs:14:22 + --> $DIR/E0395.rs:16:22 | LL | static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^