diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 3fc1b5e16b3..38196b2d4b4 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -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") } _ => {} diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 121c1cde548..a2071844d5d 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -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)] diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 8c542136a7f..335969b3ef0 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -858,7 +858,7 @@ pub trait PartialOrd: PartialEq { #[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: PartialEq { #[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)) } } diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 15ac3aea8b7..06402a05d26 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -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: /// /// ``` diff --git a/src/libcore/iter/adapters/fuse.rs b/src/libcore/iter/adapters/fuse.rs index 23bc215aa77..502fc2e6315 100644 --- a/src/libcore/iter/adapters/fuse.rs +++ b/src/libcore/iter/adapters/fuse.rs @@ -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 Iterator for Fuse where @@ -51,6 +64,193 @@ where { type Item = ::Item; + #[inline] + fn next(&mut self) -> Option { + FuseImpl::next(self) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + FuseImpl::nth(self, n) + } + + #[inline] + fn last(self) -> Option { + FuseImpl::last(self) + } + + #[inline] + fn count(self) -> usize { + FuseImpl::count(self) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + FuseImpl::size_hint(self) + } + + #[inline] + fn try_fold(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + FuseImpl::try_fold(self, acc, fold) + } + + #[inline] + fn fold(self, acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + FuseImpl::fold(self, acc, fold) + } + + #[inline] + fn find

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + FuseImpl::find(self, predicate) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Fuse +where + I: DoubleEndedIterator, +{ + #[inline] + fn next_back(&mut self) -> Option<::Item> { + FuseImpl::next_back(self) + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option<::Item> { + FuseImpl::nth_back(self, n) + } + + #[inline] + fn try_rfold(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + FuseImpl::try_rfold(self, acc, fold) + } + + #[inline] + fn rfold(self, acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + FuseImpl::rfold(self, acc, fold) + } + + #[inline] + fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + FuseImpl::rfind(self, predicate) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Fuse +where + I: ExactSizeIterator, +{ + fn len(&self) -> usize { + FuseImpl::len(self) + } + + fn is_empty(&self) -> bool { + FuseImpl::is_empty(self) + } +} + +unsafe impl TrustedRandomAccess for Fuse +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 { + type Item; + + // Functions specific to any normal Iterators + fn next(&mut self) -> Option; + fn nth(&mut self, n: usize) -> Option; + fn last(self) -> Option; + fn count(self) -> usize; + fn size_hint(&self) -> (usize, Option); + fn try_fold(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try; + fn fold(self, acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc; + fn find

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool; + + // Functions specific to DoubleEndedIterators + fn next_back(&mut self) -> Option + where + I: DoubleEndedIterator; + fn nth_back(&mut self, n: usize) -> Option + where + I: DoubleEndedIterator; + fn try_rfold(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + I: DoubleEndedIterator; + fn rfold(self, acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + I: DoubleEndedIterator; + fn rfind

(&mut self, predicate: P) -> Option + 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 FuseImpl for Fuse +where + I: Iterator, +{ + type Item = ::Item; + #[inline] default fn next(&mut self) -> Option<::Item> { fuse!(self.iter.next()) @@ -117,20 +317,20 @@ where { fuse!(self.iter.find(predicate)) } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Fuse -where - I: DoubleEndedIterator, -{ #[inline] - default fn next_back(&mut self) -> Option<::Item> { + default fn next_back(&mut self) -> Option<::Item> + where + I: DoubleEndedIterator, + { fuse!(self.iter.next_back()) } #[inline] - default fn nth_back(&mut self, n: usize) -> Option<::Item> { + default fn nth_back(&mut self, n: usize) -> Option<::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, + I: DoubleEndedIterator, { if let Some(ref mut iter) = self.iter { acc = iter.try_rfold(acc, fold)?; @@ -152,6 +353,7 @@ where default fn rfold(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

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, + I: DoubleEndedIterator, { fuse!(self.iter.rfind(predicate)) } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Fuse -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 Iterator for Fuse +#[doc(hidden)] +impl FuseImpl for Fuse where I: FusedIterator, { @@ -255,20 +448,20 @@ where { unchecked!(self).find(predicate) } -} -#[stable(feature = "fused", since = "1.26.0")] -impl DoubleEndedIterator for Fuse -where - I: DoubleEndedIterator + FusedIterator, -{ #[inline] - fn next_back(&mut self) -> Option<::Item> { + fn next_back(&mut self) -> Option<::Item> + where + I: DoubleEndedIterator, + { unchecked!(self).next_back() } #[inline] - fn nth_back(&mut self, n: usize) -> Option<::Item> { + fn nth_back(&mut self, n: usize) -> Option<::Item> + where + I: DoubleEndedIterator, + { unchecked!(self).nth_back(n) } @@ -278,6 +471,7 @@ where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, + I: DoubleEndedIterator, { unchecked!(self).try_rfold(init, fold) } @@ -286,6 +480,7 @@ where fn rfold(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

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, + I: DoubleEndedIterator, { unchecked!(self).rfind(predicate) } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Fuse -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 TrustedRandomAccess for Fuse -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() - } -} diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index c8829817e19..34ca79154b6 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -3109,7 +3109,7 @@ pub trait Iterator { Self::Item: PartialOrd, 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, 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. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a04b7162c92..1c7bce3fac5 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -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)] diff --git a/src/libcore/num/dec2flt/parse.rs b/src/libcore/num/dec2flt/parse.rs index 93b08bce853..2766843155a 100644 --- a/src/libcore/num/dec2flt/parse.rs +++ b/src/libcore/num/dec2flt/parse.rs @@ -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 } } diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs index f5cd26a1852..9adea94e87d 100644 --- a/src/libcore/num/flt2dec/mod.rs +++ b/src/libcore/num/flt2dec/mod.rs @@ -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 { diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 57f13d0cb38..225ede851b4 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -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 diff --git a/src/librustc_error_codes/error_codes/E0657.md b/src/librustc_error_codes/error_codes/E0657.md new file mode 100644 index 00000000000..7fe48c51147 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0657.md @@ -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 {} +trait Lt<'a> {} + +impl<'a> Lt<'a> for () {} +impl Id for T {} + +fn free_fn_capture_hrtb_in_impl_trait() + -> Box Id>> // error! +{ + Box::new(()) +} + +struct Foo; +impl Foo { + fn impl_fn_capture_hrtb_in_impl_trait() + -> Box Id>> // 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 {} +trait Lt<'a> {} + +impl<'a> Lt<'a> for () {} +impl Id for T {} + +fn free_fn_capture_hrtb_in_impl_trait<'b>() + -> Box Id>> // ok! +{ + Box::new(()) +} + +struct Foo; +impl Foo { + fn impl_fn_capture_hrtb_in_impl_trait<'b>() + -> Box Id>> // ok! + { + Box::new(()) + } +} +``` diff --git a/src/librustc_middle/mir/interpret/error.rs b/src/librustc_middle/mir/interpret/error.rs index 7844fb10840..f058d17a9bf 100644 --- a/src/librustc_middle/mir/interpret/error.rs +++ b/src/librustc_middle/mir/interpret/error.rs @@ -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"), } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 701e394415b..83b8d58e0be 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -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), diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index a9a519f0a3a..59d845c619b 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -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)] diff --git a/src/libstd/sync/mpsc/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs index 5b41525e06a..75f5621fa12 100644 --- a/src/libstd/sync/mpsc/oneshot.rs +++ b/src/libstd/sync/mpsc/oneshot.rs @@ -260,7 +260,7 @@ impl Packet { 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) diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs index f33493ee0c9..26b4faebd86 100644 --- a/src/libstd/sync/mpsc/stream.rs +++ b/src/libstd/sync/mpsc/stream.rs @@ -205,7 +205,7 @@ impl Packet { // 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 }, diff --git a/src/test/ui/asm/issue-54067.rs b/src/test/ui/asm/issue-54067.rs new file mode 100644 index 00000000000..f2e097222bd --- /dev/null +++ b/src/test/ui/asm/issue-54067.rs @@ -0,0 +1,12 @@ +// check-pass +// ignore-emscripten no llvm_asm! support + +#![feature(llvm_asm)] + +pub fn boot(addr: Option) { + unsafe { + llvm_asm!("mov sp, $0"::"r" (addr)); + } +} + +fn main() {} diff --git a/src/test/ui/async-await/issues/auxiliary/issue_67893.rs b/src/test/ui/async-await/issues/auxiliary/issue_67893.rs new file mode 100644 index 00000000000..387966a5064 --- /dev/null +++ b/src/test/ui/async-await/issues/auxiliary/issue_67893.rs @@ -0,0 +1,10 @@ +// edition:2018 + +use std::sync::{Arc, Mutex}; + +pub async fn f(_: ()) {} + +pub async fn run() { + let x: Arc> = unimplemented!(); + f(*x.lock().unwrap()).await; +} diff --git a/src/test/ui/async-await/issues/issue-67893.rs b/src/test/ui/async-await/issues/issue-67893.rs new file mode 100644 index 00000000000..d52303ac1ce --- /dev/null +++ b/src/test/ui/async-await/issues/issue-67893.rs @@ -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 +} diff --git a/src/test/ui/consts/const-eval/ub-int-array.rs b/src/test/ui/consts/const-eval/ub-int-array.rs new file mode 100644 index 00000000000..8907b0c160f --- /dev/null +++ b/src/test/ui/consts/const-eval/ub-int-array.rs @@ -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 { + 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() {} diff --git a/src/test/ui/consts/const-eval/ub-int-array.stderr b/src/test/ui/consts/const-eval/ub-int-array.stderr new file mode 100644 index 00000000000..b4a3c63b5a1 --- /dev/null +++ b/src/test/ui/consts/const-eval/ub-int-array.stderr @@ -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`. diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs index 562ec99111b..10f4c8c0333 100644 --- a/src/test/ui/consts/const-eval/ub-ref.rs +++ b/src/test/ui/consts/const-eval/ub-ref.rs @@ -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 = 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 diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 80e60dbb58a..f12753e5dca 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -62,7 +62,7 @@ LL | | LL | | let uninit_len = MaybeUninit:: { 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:: { 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. diff --git a/src/test/ui/consts/const-eval/union-ice.stderr b/src/test/ui/consts/const-eval/union-ice.stderr index 476f3651740..2545167aa02 100644 --- a/src/test/ui/consts/const-eval/union-ice.stderr +++ b/src/test/ui/consts/const-eval/union-ice.stderr @@ -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. diff --git a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr index 5a477714596..b4970c82adb 100644 --- a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr +++ b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr @@ -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 diff --git a/src/test/ui/error-codes/E0657.stderr b/src/test/ui/error-codes/E0657.stderr index b24b413600c..df76b45a589 100644 --- a/src/test/ui/error-codes/E0657.stderr +++ b/src/test/ui/error-codes/E0657.stderr @@ -12,3 +12,4 @@ LL | -> Box Id>> error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0657`. diff --git a/src/test/ui/intrinsics/issue-28575.rs b/src/test/ui/intrinsics/issue-28575.rs new file mode 100644 index 00000000000..141136d25b2 --- /dev/null +++ b/src/test/ui/intrinsics/issue-28575.rs @@ -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 +} diff --git a/src/test/ui/intrinsics/issue-28575.stderr b/src/test/ui/intrinsics/issue-28575.stderr new file mode 100644 index 00000000000..66369decf42 --- /dev/null +++ b/src/test/ui/intrinsics/issue-28575.stderr @@ -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`. diff --git a/src/test/ui/static/auxiliary/issue_24843.rs b/src/test/ui/static/auxiliary/issue_24843.rs new file mode 100644 index 00000000000..6ca04f86060 --- /dev/null +++ b/src/test/ui/static/auxiliary/issue_24843.rs @@ -0,0 +1 @@ +pub static TEST_STR: &'static str = "Hello world"; diff --git a/src/test/ui/static/issue-24843.rs b/src/test/ui/static/issue-24843.rs new file mode 100644 index 00000000000..0b3397e210d --- /dev/null +++ b/src/test/ui/static/issue-24843.rs @@ -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() {}