#![feature(never_type)]
#![feature(nll)]
#![feature(exhaustive_patterns)]
+#![cfg_attr(not(stage0), feature(min_const_unsafe_fn))]
#![feature(no_core)]
#![feature(on_unimplemented)]
#![feature(optin_builtin_traits)]
/// 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, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+#[derive(Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
pub(crate) struct NonZero<T>(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> {
+ fn clone(&self) -> Self {
+ unsafe { NonZero(self.0) }
+ }
+}
+
impl<T: CoerceUnsized<U>, U> CoerceUnsized<NonZero<U>> for NonZero<T> {}
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<NonZero<U>> for NonZero<T> {}
#[stable(feature = "nonzero", since = "1.28.0")]
#[inline]
pub const unsafe fn new_unchecked(n: $Int) -> Self {
- $Ty(NonZero(n))
+ $Ty(unsafe { NonZero(n) })
}
/// Create a non-zero if the given value is not zero.
#[inline]
pub fn new(n: $Int) -> Option<Self> {
if n != 0 {
- Some($Ty(NonZero(n)))
+ Some($Ty(unsafe { NonZero(n) }))
} else {
None
}
/// Creates a new `Unique` if `ptr` is non-null.
pub fn new(ptr: *mut T) -> Option<Self> {
if !ptr.is_null() {
- Some(Unique { pointer: NonZero(ptr as _), _marker: PhantomData })
+ Some(Unique { pointer: unsafe { NonZero(ptr as _) }, _marker: PhantomData })
} else {
None
}
#[unstable(feature = "ptr_internals", issue = "0")]
impl<'a, T: ?Sized> From<&'a mut T> for Unique<T> {
fn from(reference: &'a mut T) -> Self {
- Unique { pointer: NonZero(reference as _), _marker: PhantomData }
+ Unique { pointer: unsafe { NonZero(reference as _) }, _marker: PhantomData }
}
}
#[unstable(feature = "ptr_internals", issue = "0")]
impl<'a, T: ?Sized> From<&'a T> for Unique<T> {
fn from(reference: &'a T) -> Self {
- Unique { pointer: NonZero(reference as _), _marker: PhantomData }
+ Unique { pointer: unsafe { NonZero(reference as _) }, _marker: PhantomData }
}
}
#[stable(feature = "nonnull", since = "1.25.0")]
#[inline]
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
- NonNull { pointer: NonZero(ptr as _) }
+ NonNull { pointer: unsafe { NonZero(ptr as _) } }
}
/// Creates a new `NonNull` if `ptr` is non-null.
#[inline]
pub fn new(ptr: *mut T) -> Option<Self> {
if !ptr.is_null() {
- Some(NonNull { pointer: NonZero(ptr as _) })
+ Some(NonNull { pointer: unsafe { NonZero(ptr as _) } })
} else {
None
}
impl<'a, T: ?Sized> From<&'a mut T> for NonNull<T> {
#[inline]
fn from(reference: &'a mut T) -> Self {
- NonNull { pointer: NonZero(reference as _) }
+ NonNull { pointer: unsafe { NonZero(reference as _) } }
}
}
impl<'a, T: ?Sized> From<&'a T> for NonNull<T> {
#[inline]
fn from(reference: &'a T) -> Self {
- NonNull { pointer: NonZero(reference as _) }
+ NonNull { pointer: unsafe { NonZero(reference as _) } }
}
}
use syntax::ast;
use syntax::symbol::Symbol;
+use std::ops::Bound;
+
use util;
pub struct UnsafetyChecker<'a, 'tcx: 'a> {
if let &Rvalue::Aggregate(box ref aggregate, _) = rvalue {
match aggregate {
&AggregateKind::Array(..) |
- &AggregateKind::Tuple |
- &AggregateKind::Adt(..) => {}
+ &AggregateKind::Tuple => {}
+ &AggregateKind::Adt(ref def, ..) => {
+ match self.tcx.layout_scalar_valid_range(def.did) {
+ (Bound::Unbounded, Bound::Unbounded) => {},
+ _ => self.require_unsafe(
+ "initializing type with `rustc_layout_scalar_valid_range` attr",
+ "initializing `NonZero` with a `0` violates layout constraints \
+ and is undefined behavior",
+ UnsafetyViolationKind::MinConstFn,
+ ),
+ }
+ }
&AggregateKind::Closure(def_id, _) |
&AggregateKind::Generator(def_id, _, _) => {
let UnsafetyCheckResult {
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![unstable(feature = "humans",
+ reason = "who ever let humans program computers,
+ we're apparently really bad at it",
+ issue = "0")]
+
+#![feature(rustc_const_unstable, const_fn, foo, foo2)]
+#![feature(min_const_unsafe_fn)]
+#![feature(staged_api)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo")]
+const unsafe fn foo() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR can only call other `min_const_fn`
+
+#[unstable(feature = "rust1", issue="0")]
+const unsafe fn foo2() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR can only call other `min_const_fn`
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// conformity is required, even with `const_fn` feature gate
+const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` op
+
+// check whether this function cannot be called even with the feature gate active
+#[unstable(feature = "foo2", issue="0")]
+const unsafe fn foo2_gated() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } //~ ERROR can only call other
+
+fn main() {}
--- /dev/null
+error: can only call other `min_const_fn` within a `min_const_fn`
+ --> $DIR/min_const_unsafe_fn_libstd_stability.rs:26:41
+ |
+LL | const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR can only call other `min_const_fn`
+ | ^^^^^
+
+error: can only call other `min_const_fn` within a `min_const_fn`
+ --> $DIR/min_const_unsafe_fn_libstd_stability.rs:33:42
+ |
+LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR can only call other `min_const_fn`
+ | ^^^^^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+ --> $DIR/min_const_unsafe_fn_libstd_stability.rs:37:33
+ |
+LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` op
+ | ^^^^^^^^^^^^^
+
+error: can only call other `min_const_fn` within a `min_const_fn`
+ --> $DIR/min_const_unsafe_fn_libstd_stability.rs:45:48
+ |
+LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } //~ ERROR can only call other
+ | ^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![unstable(feature = "humans",
+ reason = "who ever let humans program computers,
+ we're apparently really bad at it",
+ issue = "0")]
+
+#![feature(rustc_const_unstable, const_fn, foo, foo2)]
+#![feature(min_const_unsafe_fn)]
+#![feature(staged_api)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo")]
+const fn foo() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const unsafe fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn`
+
+#[unstable(feature = "rust1", issue="0")]
+const fn foo2() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const unsafe fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn`
+
+// check whether this function cannot be called even with the feature gate active
+#[unstable(feature = "foo2", issue="0")]
+const fn foo2_gated() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn`
+
+fn main() {}
--- /dev/null
+error: can only call other `min_const_fn` within a `min_const_fn`
+ --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:26:32
+ |
+LL | const unsafe fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn`
+ | ^^^^^
+
+error: can only call other `min_const_fn` within a `min_const_fn`
+ --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:33:33
+ |
+LL | const unsafe fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn`
+ | ^^^^^^
+
+error: can only call other `min_const_fn` within a `min_const_fn`
+ --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:41:39
+ |
+LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn`
+ | ^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+