about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Scherer <github35764891676564198441@oli-obk.de>2018-11-04 13:45:26 +0100
committerOliver Scherer <github35764891676564198441@oli-obk.de>2018-12-04 10:17:36 +0100
commit1894a5fe2c72a1e22897026f34e5f9035cc169ff (patch)
tree6ed8ba0526340f76b4918ba8159f53f47f4177c0
parent081c49783f5cfc24f66f3ac36244d816567cc120 (diff)
downloadrust-1894a5fe2c72a1e22897026f34e5f9035cc169ff.tar.gz
rust-1894a5fe2c72a1e22897026f34e5f9035cc169ff.zip
Also make immutable references to non-freeze restricted value range types unsafe
-rw-r--r--src/libcore/marker.rs2
-rw-r--r--src/libcore/nonzero.rs9
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs6
-rw-r--r--src/test/ui/unsafe/ranged_ints3.rs11
-rw-r--r--src/test/ui/unsafe/ranged_ints3.stderr11
5 files changed, 33 insertions, 6 deletions
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index 3bcdfabbb24..23f07773f3f 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -596,7 +596,7 @@ mod impls {
 /// This affects, for example, whether a `static` of that type is
 /// placed in read-only static memory or writable static memory.
 #[lang = "freeze"]
-unsafe auto trait Freeze {}
+pub(crate) unsafe auto trait Freeze {}
 
 impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
 unsafe impl<T: ?Sized> Freeze for PhantomData<T> {}
diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs
index 22d93a5301e..a89c6ca60cb 100644
--- a/src/libcore/nonzero.rs
+++ b/src/libcore/nonzero.rs
@@ -11,22 +11,23 @@
 //! Exposes the NonZero lang item which provides optimization hints.
 
 use ops::{CoerceUnsized, DispatchFromDyn};
+use marker::Freeze;
 
 /// A wrapper type for raw pointers and integers that will never be
 /// NULL or 0 that might allow certain optimizations.
 #[rustc_layout_scalar_valid_range_start(1)]
 #[derive(Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
 #[repr(transparent)]
-pub(crate) struct NonZero<T>(pub(crate) T);
+pub(crate) struct NonZero<T: Freeze>(pub(crate) T);
 
 // Do not call `T::clone` as theoretically it could turn the field into `0`
 // invalidating `NonZero`'s invariant.
-impl<T: Copy> Clone for NonZero<T> {
+impl<T: Copy + Freeze> Clone for NonZero<T> {
     fn clone(&self) -> Self {
         unsafe { NonZero(self.0) }
     }
 }
 
-impl<T: CoerceUnsized<U>, U> CoerceUnsized<NonZero<U>> for NonZero<T> {}
+impl<T: CoerceUnsized<U> + Freeze, U: Freeze> CoerceUnsized<NonZero<U>> for NonZero<T> {}
 
-impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<NonZero<U>> for NonZero<T> {}
+impl<T: DispatchFromDyn<U> + Freeze, U: Freeze> DispatchFromDyn<NonZero<U>> for NonZero<T> {}
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 2a80f27ecab..c7a785ad2c5 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -187,7 +187,11 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                             kind: UnsafetyViolationKind::BorrowPacked(lint_root)
                         }], &[]);
                     }
-                    if context.is_mutating_use() {
+                    let is_freeze = base
+                        .ty(self.mir, self.tcx)
+                        .to_ty(self.tcx)
+                        .is_freeze(self.tcx, self.param_env, self.source_info.span);
+                    if context.is_mutating_use() || !is_freeze {
                         self.check_mut_borrowing_layout_constrained_field(place);
                     }
                 }
diff --git a/src/test/ui/unsafe/ranged_ints3.rs b/src/test/ui/unsafe/ranged_ints3.rs
new file mode 100644
index 00000000000..d68c712227a
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3.rs
@@ -0,0 +1,11 @@
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+    let mut x = unsafe { NonZero(Cell::new(1)) };
+    let y = &x.0; //~ ERROR borrow of layout constrained field is unsafe
+}
diff --git a/src/test/ui/unsafe/ranged_ints3.stderr b/src/test/ui/unsafe/ranged_ints3.stderr
new file mode 100644
index 00000000000..b5aa9089b5f
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3.stderr
@@ -0,0 +1,11 @@
+error[E0133]: borrow of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints3.rs:10:13
+   |
+LL |     let y = &x.0; //~ ERROR borrow of layout constrained field is unsafe
+   |             ^^^^ borrow of layout constrained field
+   |
+   = note: references to fields of layout constrained fields lose the constraints
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.