Also make immutable references to non-freeze restricted value range types unsafe

This commit is contained in:
Oliver Scherer 2018-11-04 13:45:26 +01:00
parent 081c49783f
commit 1894a5fe2c
5 changed files with 33 additions and 6 deletions

View file

@ -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> {}

View file

@ -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> {}

View file

@ -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);
}
}

View file

@ -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
}

View file

@ -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`.