Auto merge of #71230 - Dylan-DPC:rollup-rofigbv, r=Dylan-DPC

Rollup of 7 pull requests

Successful merges:

 - #70578 (Add long error explanation for E0657)
 - #70910 (Hides default fns inside Fuse impl to avoid exposing it to any crate)
 - #71164 (reword Miri validity errors: undefined -> uninitialized)
 - #71182 (Add some regression tests)
 - #71206 (Miri error messages: avoid try terminology)
 - #71220 (Dogfood or_patterns in the standard library)
 - #71225 (Fix typo in Default trait docs: Provides -> Provide)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-04-17 04:15:18 +00:00
commit 861996e138
30 changed files with 513 additions and 97 deletions

View File

@ -2058,12 +2058,7 @@ where
(Excluded(s), Excluded(e)) if s == e => {
panic!("range start and end are equal and excluded in BTreeMap")
}
(Included(s), Included(e))
| (Included(s), Excluded(e))
| (Excluded(s), Included(e))
| (Excluded(s), Excluded(e))
if s > e =>
{
(Included(s) | Excluded(s), Included(e) | Excluded(e)) if s > e => {
panic!("range start is greater than range end in BTreeMap")
}
_ => {}

View File

@ -103,6 +103,7 @@
#![feature(new_uninit)]
#![feature(nll)]
#![feature(optin_builtin_traits)]
#![feature(or_patterns)]
#![feature(pattern)]
#![feature(ptr_internals)]
#![feature(ptr_offset_from)]

View File

@ -858,7 +858,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
fn le(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(Less) | Some(Equal))
matches!(self.partial_cmp(other), Some(Less | Equal))
}
/// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
@ -895,7 +895,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
fn ge(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(Greater) | Some(Equal))
matches!(self.partial_cmp(other), Some(Greater | Equal))
}
}

View File

@ -54,7 +54,7 @@
///
/// ## How can I implement `Default`?
///
/// Provides an implementation for the `default()` method that returns the value of
/// Provide an implementation for the `default()` method that returns the value of
/// your type that should be the default:
///
/// ```

View File

@ -44,6 +44,19 @@ macro_rules! fuse {
};
}
// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`.
// Implementing this as a directly-expanded macro helps codegen performance.
macro_rules! unchecked {
($self:ident) => {
match $self {
Fuse { iter: Some(iter) } => iter,
// SAFETY: the specialized iterator never sets `None`
Fuse { iter: None } => unsafe { intrinsics::unreachable() },
}
};
}
// Any implementation here is made internal to avoid exposing default fns outside this trait
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> Iterator for Fuse<I>
where
@ -51,6 +64,193 @@ where
{
type Item = <I as Iterator>::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
FuseImpl::next(self)
}
#[inline]
fn nth(&mut self, n: usize) -> Option<I::Item> {
FuseImpl::nth(self, n)
}
#[inline]
fn last(self) -> Option<Self::Item> {
FuseImpl::last(self)
}
#[inline]
fn count(self) -> usize {
FuseImpl::count(self)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
FuseImpl::size_hint(self)
}
#[inline]
fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
where
Self: Sized,
Fold: FnMut(Acc, Self::Item) -> R,
R: Try<Ok = Acc>,
{
FuseImpl::try_fold(self, acc, fold)
}
#[inline]
fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
where
Fold: FnMut(Acc, Self::Item) -> Acc,
{
FuseImpl::fold(self, acc, fold)
}
#[inline]
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
where
P: FnMut(&Self::Item) -> bool,
{
FuseImpl::find(self, predicate)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> DoubleEndedIterator for Fuse<I>
where
I: DoubleEndedIterator,
{
#[inline]
fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
FuseImpl::next_back(self)
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
FuseImpl::nth_back(self, n)
}
#[inline]
fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
where
Self: Sized,
Fold: FnMut(Acc, Self::Item) -> R,
R: Try<Ok = Acc>,
{
FuseImpl::try_rfold(self, acc, fold)
}
#[inline]
fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
where
Fold: FnMut(Acc, Self::Item) -> Acc,
{
FuseImpl::rfold(self, acc, fold)
}
#[inline]
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
where
P: FnMut(&Self::Item) -> bool,
{
FuseImpl::rfind(self, predicate)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Fuse<I>
where
I: ExactSizeIterator,
{
fn len(&self) -> usize {
FuseImpl::len(self)
}
fn is_empty(&self) -> bool {
FuseImpl::is_empty(self)
}
}
unsafe impl<I> TrustedRandomAccess for Fuse<I>
where
I: TrustedRandomAccess,
{
unsafe fn get_unchecked(&mut self, i: usize) -> I::Item {
match self.iter {
Some(ref mut iter) => iter.get_unchecked(i),
// SAFETY: the caller asserts there is an item at `i`, so we're not exhausted.
None => intrinsics::unreachable(),
}
}
fn may_have_side_effect() -> bool {
I::may_have_side_effect()
}
}
// Fuse specialization trait
#[doc(hidden)]
trait FuseImpl<I> {
type Item;
// Functions specific to any normal Iterators
fn next(&mut self) -> Option<Self::Item>;
fn nth(&mut self, n: usize) -> Option<Self::Item>;
fn last(self) -> Option<Self::Item>;
fn count(self) -> usize;
fn size_hint(&self) -> (usize, Option<usize>);
fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
where
Self: Sized,
Fold: FnMut(Acc, Self::Item) -> R,
R: Try<Ok = Acc>;
fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
where
Fold: FnMut(Acc, Self::Item) -> Acc;
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
where
P: FnMut(&Self::Item) -> bool;
// Functions specific to DoubleEndedIterators
fn next_back(&mut self) -> Option<Self::Item>
where
I: DoubleEndedIterator;
fn nth_back(&mut self, n: usize) -> Option<Self::Item>
where
I: DoubleEndedIterator;
fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
where
Self: Sized,
Fold: FnMut(Acc, Self::Item) -> R,
R: Try<Ok = Acc>,
I: DoubleEndedIterator;
fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
where
Fold: FnMut(Acc, Self::Item) -> Acc,
I: DoubleEndedIterator;
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
where
P: FnMut(&Self::Item) -> bool,
I: DoubleEndedIterator;
// Functions specific to ExactSizeIterator
fn len(&self) -> usize
where
I: ExactSizeIterator;
fn is_empty(&self) -> bool
where
I: ExactSizeIterator;
}
// General Fuse impl
#[doc(hidden)]
impl<I> FuseImpl<I> for Fuse<I>
where
I: Iterator,
{
type Item = <I as Iterator>::Item;
#[inline]
default fn next(&mut self) -> Option<<I as Iterator>::Item> {
fuse!(self.iter.next())
@ -117,20 +317,20 @@ where
{
fuse!(self.iter.find(predicate))
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> DoubleEndedIterator for Fuse<I>
where
I: DoubleEndedIterator,
{
#[inline]
default fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
default fn next_back(&mut self) -> Option<<I as Iterator>::Item>
where
I: DoubleEndedIterator,
{
fuse!(self.iter.next_back())
}
#[inline]
default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
where
I: DoubleEndedIterator,
{
fuse!(self.iter.nth_back(n))
}
@ -140,6 +340,7 @@ where
Self: Sized,
Fold: FnMut(Acc, Self::Item) -> R,
R: Try<Ok = Acc>,
I: DoubleEndedIterator,
{
if let Some(ref mut iter) = self.iter {
acc = iter.try_rfold(acc, fold)?;
@ -152,6 +353,7 @@ where
default fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
where
Fold: FnMut(Acc, Self::Item) -> Acc,
I: DoubleEndedIterator,
{
if let Some(iter) = self.iter {
acc = iter.rfold(acc, fold);
@ -163,24 +365,27 @@ where
default fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
where
P: FnMut(&Self::Item) -> bool,
I: DoubleEndedIterator,
{
fuse!(self.iter.rfind(predicate))
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Fuse<I>
where
I: ExactSizeIterator,
{
default fn len(&self) -> usize {
#[inline]
default fn len(&self) -> usize
where
I: ExactSizeIterator,
{
match self.iter {
Some(ref iter) => iter.len(),
None => 0,
}
}
default fn is_empty(&self) -> bool {
#[inline]
default fn is_empty(&self) -> bool
where
I: ExactSizeIterator,
{
match self.iter {
Some(ref iter) => iter.is_empty(),
None => true,
@ -188,20 +393,8 @@ where
}
}
// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`.
// Implementing this as a directly-expanded macro helps codegen performance.
macro_rules! unchecked {
($self:ident) => {
match $self {
Fuse { iter: Some(iter) } => iter,
// SAFETY: the specialized iterator never sets `None`
Fuse { iter: None } => unsafe { intrinsics::unreachable() },
}
};
}
#[stable(feature = "fused", since = "1.26.0")]
impl<I> Iterator for Fuse<I>
#[doc(hidden)]
impl<I> FuseImpl<I> for Fuse<I>
where
I: FusedIterator,
{
@ -255,20 +448,20 @@ where
{
unchecked!(self).find(predicate)
}
}
#[stable(feature = "fused", since = "1.26.0")]
impl<I> DoubleEndedIterator for Fuse<I>
where
I: DoubleEndedIterator + FusedIterator,
{
#[inline]
fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
fn next_back(&mut self) -> Option<<I as Iterator>::Item>
where
I: DoubleEndedIterator,
{
unchecked!(self).next_back()
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
where
I: DoubleEndedIterator,
{
unchecked!(self).nth_back(n)
}
@ -278,6 +471,7 @@ where
Self: Sized,
Fold: FnMut(Acc, Self::Item) -> R,
R: Try<Ok = Acc>,
I: DoubleEndedIterator,
{
unchecked!(self).try_rfold(init, fold)
}
@ -286,6 +480,7 @@ where
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
where
Fold: FnMut(Acc, Self::Item) -> Acc,
I: DoubleEndedIterator,
{
unchecked!(self).rfold(init, fold)
}
@ -294,38 +489,24 @@ where
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
where
P: FnMut(&Self::Item) -> bool,
I: DoubleEndedIterator,
{
unchecked!(self).rfind(predicate)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Fuse<I>
where
I: ExactSizeIterator + FusedIterator,
{
fn len(&self) -> usize {
#[inline]
fn len(&self) -> usize
where
I: ExactSizeIterator,
{
unchecked!(self).len()
}
fn is_empty(&self) -> bool {
#[inline]
fn is_empty(&self) -> bool
where
I: ExactSizeIterator,
{
unchecked!(self).is_empty()
}
}
unsafe impl<I> TrustedRandomAccess for Fuse<I>
where
I: TrustedRandomAccess,
{
unsafe fn get_unchecked(&mut self, i: usize) -> I::Item {
match self.iter {
Some(ref mut iter) => iter.get_unchecked(i),
// SAFETY: the caller asserts there is an item at `i`, so we're not exhausted.
None => intrinsics::unreachable(),
}
}
fn may_have_side_effect() -> bool {
I::may_have_side_effect()
}
}

View File

@ -3109,7 +3109,7 @@ pub trait Iterator {
Self::Item: PartialOrd<I::Item>,
Self: Sized,
{
matches!(self.partial_cmp(other), Some(Ordering::Less) | Some(Ordering::Equal))
matches!(self.partial_cmp(other), Some(Ordering::Less | Ordering::Equal))
}
/// Determines if the elements of this `Iterator` are lexicographically
@ -3149,7 +3149,7 @@ pub trait Iterator {
Self::Item: PartialOrd<I::Item>,
Self: Sized,
{
matches!(self.partial_cmp(other), Some(Ordering::Greater) | Some(Ordering::Equal))
matches!(self.partial_cmp(other), Some(Ordering::Greater | Ordering::Equal))
}
/// Checks if the elements of this iterator are sorted.

View File

@ -105,6 +105,7 @@
#![feature(exhaustive_patterns)]
#![feature(no_core)]
#![feature(optin_builtin_traits)]
#![feature(or_patterns)]
#![feature(prelude_import)]
#![feature(repr_simd, platform_intrinsics)]
#![feature(rustc_attrs)]

View File

@ -54,7 +54,7 @@ pub fn parse_decimal(s: &str) -> ParseResult<'_> {
match s.first() {
None => Valid(Decimal::new(integral, b"", 0)),
Some(&b'e') | Some(&b'E') => {
Some(&b'e' | &b'E') => {
if integral.is_empty() {
return Invalid; // No digits before 'e'
}
@ -70,7 +70,7 @@ pub fn parse_decimal(s: &str) -> ParseResult<'_> {
match s.first() {
None => Valid(Decimal::new(integral, fractional, 0)),
Some(&b'e') | Some(&b'E') => parse_exp(integral, fractional, &s[1..]),
Some(&b'e' | &b'E') => parse_exp(integral, fractional, &s[1..]),
_ => Invalid, // Trailing junk after fractional part
}
}

View File

@ -422,14 +422,14 @@ fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static
"+"
}
}
(_, Sign::Minus) | (_, Sign::MinusRaw) => {
(_, Sign::Minus | Sign::MinusRaw) => {
if negative {
"-"
} else {
""
}
}
(_, Sign::MinusPlus) | (_, Sign::MinusPlusRaw) => {
(_, Sign::MinusPlus | Sign::MinusPlusRaw) => {
if negative {
"-"
} else {

View File

@ -366,6 +366,7 @@ E0644: include_str!("./error_codes/E0644.md"),
E0646: include_str!("./error_codes/E0646.md"),
E0647: include_str!("./error_codes/E0647.md"),
E0648: include_str!("./error_codes/E0648.md"),
E0657: include_str!("./error_codes/E0657.md"),
E0658: include_str!("./error_codes/E0658.md"),
E0659: include_str!("./error_codes/E0659.md"),
E0660: include_str!("./error_codes/E0660.md"),
@ -597,7 +598,6 @@ E0751: include_str!("./error_codes/E0751.md"),
// used in argument position
E0640, // infer outlives requirements
// E0645, // trait aliases not finished
E0657, // `impl Trait` can only capture lifetimes bound at the fn level
E0667, // `impl Trait` in projections
E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders

View File

@ -0,0 +1,57 @@
A lifetime bound on a trait implementation was captured at an incorrect place.
Erroneous code example:
```compile_fail,E0657
trait Id<T> {}
trait Lt<'a> {}
impl<'a> Lt<'a> for () {}
impl<T> Id<T> for T {}
fn free_fn_capture_hrtb_in_impl_trait()
-> Box<for<'a> Id<impl Lt<'a>>> // error!
{
Box::new(())
}
struct Foo;
impl Foo {
fn impl_fn_capture_hrtb_in_impl_trait()
-> Box<for<'a> Id<impl Lt<'a>>> // error!
{
Box::new(())
}
}
```
Here, you have used the inappropriate lifetime in the `impl Trait`,
The `impl Trait` can only capture lifetimes bound at the fn or impl
level.
To fix this we have to define the lifetime at the function or impl
level and use that lifetime in the `impl Trait`. For example you can
define the lifetime at the function:
```
trait Id<T> {}
trait Lt<'a> {}
impl<'a> Lt<'a> for () {}
impl<T> Id<T> for T {}
fn free_fn_capture_hrtb_in_impl_trait<'b>()
-> Box<for<'a> Id<impl Lt<'b>>> // ok!
{
Box::new(())
}
struct Foo;
impl Foo {
fn impl_fn_capture_hrtb_in_impl_trait<'b>()
-> Box<for<'a> Id<impl Lt<'b>>> // ok!
{
Box::new(())
}
}
```

View File

@ -305,7 +305,7 @@ impl fmt::Debug for InvalidProgramInfo<'_> {
Layout(ref err) => write!(f, "{}", err),
TransmuteSizeDiff(from_ty, to_ty) => write!(
f,
"tried to transmute from {:?} to {:?}, but their sizes differed",
"transmuting `{}` to `{}` is not possible, because these types do not have the same size",
from_ty, to_ty
),
}
@ -431,7 +431,7 @@ impl fmt::Debug for UndefinedBehaviorInfo {
"using uninitialized data, but this operation requires initialized memory"
),
DeadLocal => write!(f, "accessing a dead local variable"),
ReadFromReturnPlace => write!(f, "tried to read from the return place"),
ReadFromReturnPlace => write!(f, "reading from return place"),
}
}
}
@ -462,9 +462,9 @@ impl fmt::Debug for UnsupportedOpInfo {
match self {
Unsupported(ref msg) => write!(f, "{}", msg),
ReadForeignStatic(did) => {
write!(f, "tried to read from foreign (extern) static {:?}", did)
write!(f, "cannot read from foreign (extern) static {:?}", did)
}
NoMirFor(did) => write!(f, "could not load MIR for {:?}", did),
NoMirFor(did) => write!(f, "no MIR body is available for {:?}", did),
ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes",),
ReadBytesAsPointer => write!(f, "unable to turn bytes into a pointer"),
}

View File

@ -322,7 +322,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
let value = self.ecx.read_immediate(value)?;
// Handle wide pointers.
// Check metadata early, for better diagnostics
let place = try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path);
let place = try_validation!(
self.ecx.ref_to_mplace(value),
format_args!("uninitialized {}", kind),
self.path
);
if place.layout.is_unsized() {
self.check_wide_ptr_meta(place.meta, place.layout)?;
}
@ -334,7 +338,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
format_args!("invalid {} metadata: {}", kind, msg),
self.path
),
_ => bug!("Unexpected error during ptr size_and_align_of: {}", err),
_ => bug!("unexpected error during ptr size_and_align_of: {}", err),
},
};
let (size, align) = size_and_align
@ -477,10 +481,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
}
ty::RawPtr(..) => {
// We are conservative with undef for integers, but try to
// actually enforce our current rules for raw pointers.
// actually enforce the strict rules for raw pointers (mostly because
// that lets us re-use `ref_to_mplace`).
let place = try_validation!(
self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?),
"undefined pointer",
"uninitialized raw pointer",
self.path
);
if place.layout.is_unsized() {
@ -776,14 +781,14 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
// For some errors we might be able to provide extra information
match err.kind {
err_ub!(InvalidUndefBytes(Some(ptr))) => {
// Some byte was undefined, determine which
// Some byte was uninitialized, determine which
// element that byte belongs to so we can
// provide an index.
let i = usize::try_from(ptr.offset.bytes() / layout.size.bytes())
.unwrap();
self.path.push(PathElem::ArrayElem(i));
throw_validation_failure!("undefined bytes", self.path)
throw_validation_failure!("uninitialized bytes", self.path)
}
// Other errors shouldn't be possible
_ => return Err(err),

View File

@ -285,6 +285,7 @@
#![feature(never_type)]
#![feature(nll)]
#![feature(optin_builtin_traits)]
#![feature(or_patterns)]
#![feature(panic_info_message)]
#![feature(panic_internals)]
#![feature(panic_unwind)]

View File

@ -260,7 +260,7 @@ impl<T> Packet<T> {
let state = match self.state.load(Ordering::SeqCst) {
// Each of these states means that no further activity will happen
// with regard to abortion selection
s @ EMPTY | s @ DATA | s @ DISCONNECTED => s,
s @ (EMPTY | DATA | DISCONNECTED) => s,
// If we've got a blocked thread, then use an atomic to gain ownership
// of it (may fail)

View File

@ -205,7 +205,7 @@ impl<T> Packet<T> {
// Messages which actually popped from the queue shouldn't count as
// a steal, so offset the decrement here (we already have our
// "steal" factored into the channel count above).
data @ Ok(..) | data @ Err(Upgraded(..)) => unsafe {
data @ (Ok(..) | Err(Upgraded(..))) => unsafe {
*self.queue.consumer_addition().steals.get() -= 1;
data
},

View File

@ -0,0 +1,12 @@
// check-pass
// ignore-emscripten no llvm_asm! support
#![feature(llvm_asm)]
pub fn boot(addr: Option<u32>) {
unsafe {
llvm_asm!("mov sp, $0"::"r" (addr));
}
}
fn main() {}

View File

@ -0,0 +1,10 @@
// edition:2018
use std::sync::{Arc, Mutex};
pub async fn f(_: ()) {}
pub async fn run() {
let x: Arc<Mutex<()>> = unimplemented!();
f(*x.lock().unwrap()).await;
}

View File

@ -0,0 +1,13 @@
// aux-build: issue_67893.rs
// edition:2018
// dont-check-compiler-stderr
// FIXME(#71222): Add above flag because of the difference of stderrs on some env.
extern crate issue_67893;
fn g(_: impl Send) {}
fn main() {
g(issue_67893::run())
//~^ ERROR: `std::sync::MutexGuard<'_, ()>` cannot be sent between threads safely
}

View File

@ -0,0 +1,65 @@
#![feature(const_transmute)]
#![allow(const_err)] // make sure we cannot allow away the errors tested here
//! Test the "array of int" fast path in validity checking, and in particular whether it
//! points at the right array element.
use std::mem;
#[repr(C)]
union MaybeUninit<T: Copy> {
uninit: (),
init: T,
}
const UNINIT_INT_0: [u32; 3] = unsafe {
//~^ ERROR it is undefined behavior to use this value
//~| type validation failed: encountered uninitialized bytes at [0]
[
MaybeUninit { uninit: () }.init,
1,
2,
]
};
const UNINIT_INT_1: [u32; 3] = unsafe {
//~^ ERROR it is undefined behavior to use this value
//~| type validation failed: encountered uninitialized bytes at [1]
mem::transmute(
[
0u8,
0u8,
0u8,
0u8,
1u8,
MaybeUninit { uninit: () }.init,
1u8,
1u8,
2u8,
2u8,
MaybeUninit { uninit: () }.init,
2u8,
]
)
};
const UNINIT_INT_2: [u32; 3] = unsafe {
//~^ ERROR it is undefined behavior to use this value
//~| type validation failed: encountered uninitialized bytes at [2]
mem::transmute(
[
0u8,
0u8,
0u8,
0u8,
1u8,
1u8,
1u8,
1u8,
2u8,
2u8,
2u8,
MaybeUninit { uninit: () }.init,
]
)
};
fn main() {}

View File

@ -0,0 +1,45 @@
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-int-array.rs:15:1
|
LL | / const UNINIT_INT_0: [u32; 3] = unsafe {
LL | |
LL | |
LL | | [
... |
LL | | ]
LL | | };
| |__^ type validation failed: encountered uninitialized bytes at [0]
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-int-array.rs:24:1
|
LL | / const UNINIT_INT_1: [u32; 3] = unsafe {
LL | |
LL | |
LL | | mem::transmute(
... |
LL | | )
LL | | };
| |__^ type validation failed: encountered uninitialized bytes at [1]
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-int-array.rs:44:1
|
LL | / const UNINIT_INT_2: [u32; 3] = unsafe {
LL | |
LL | |
LL | | mem::transmute(
... |
LL | | )
LL | | };
| |__^ type validation failed: encountered uninitialized bytes at [2]
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0080`.

View File

@ -6,11 +6,11 @@ use std::mem;
const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
//~^ ERROR it is undefined behavior to use this value
//~^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1)
//~| type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1)
const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
//~^ ERROR it is undefined behavior to use this value
//~^^ type validation failed: encountered an unaligned box (required 2 byte alignment but found 1)
//~| type validation failed: encountered an unaligned box (required 2 byte alignment but found 1)
const NULL: &u16 = unsafe { mem::transmute(0usize) };
//~^ ERROR it is undefined behavior to use this value

View File

@ -62,7 +62,7 @@ LL | |
LL | | let uninit_len = MaybeUninit::<usize> { uninit: () };
LL | | mem::transmute((42, uninit_len))
LL | | };
| |__^ type validation failed: encountered undefined pointer
| |__^ type validation failed: encountered uninitialized reference
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
@ -130,7 +130,7 @@ LL | |
LL | | let uninit_len = MaybeUninit::<usize> { uninit: () };
LL | | mem::transmute((42, uninit_len))
LL | | };
| |__^ type validation failed: encountered undefined pointer
| |__^ type validation failed: encountered uninitialized raw pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.

View File

@ -27,7 +27,7 @@ LL | | unsafe { UNION.field3 },
... |
LL | | a: 42,
LL | | };
| |__^ type validation failed: encountered undefined bytes at .b[1]
| |__^ type validation failed: encountered uninitialized bytes at .b[1]
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.

View File

@ -4,7 +4,7 @@ error: any use of this value will cause an error
LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
| ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^---
| |
| tried to transmute from usize to &[u8], but their sizes differed
| transmuting `usize` to `&[u8]` is not possible, because these types do not have the same size
|
= note: `#[deny(const_err)]` on by default

View File

@ -12,3 +12,4 @@ LL | -> Box<for<'a> Id<impl Lt<'a>>>
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0657`.

View File

@ -0,0 +1,9 @@
#![feature(intrinsics)]
extern "C" {
pub static FOO: extern "rust-intrinsic" fn();
}
fn main() {
FOO() //~ ERROR: use of extern static is unsafe
}

View File

@ -0,0 +1,11 @@
error[E0133]: use of extern static is unsafe and requires unsafe function or block
--> $DIR/issue-28575.rs:8:5
|
LL | FOO()
| ^^^ use of extern static
|
= note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
error: aborting due to previous error
For more information about this error, try `rustc --explain E0133`.

View File

@ -0,0 +1 @@
pub static TEST_STR: &'static str = "Hello world";

View File

@ -0,0 +1,8 @@
// aux-build: issue_24843.rs
// check-pass
extern crate issue_24843;
static _TEST_STR_2: &'static str = &issue_24843::TEST_STR;
fn main() {}