From 0a54a9403ddc41d13633c17a8d24c218dc563268 Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Wed, 8 Apr 2020 05:39:00 +0530 Subject: [PATCH 01/16] Added FuseIteratorImpl, FustDoubleEndedIteratorImpl and FuseExactSizeIteratorImpl to avoid exposing default functions outside of the current crate. --- src/libcore/iter/adapters/fuse.rs | 329 +++++++++++++++++++++++------- 1 file changed, 250 insertions(+), 79 deletions(-) diff --git a/src/libcore/iter/adapters/fuse.rs b/src/libcore/iter/adapters/fuse.rs index 23bc215aa779d..946cd47536307 100644 --- a/src/libcore/iter/adapters/fuse.rs +++ b/src/libcore/iter/adapters/fuse.rs @@ -52,70 +52,54 @@ where type Item = ::Item; #[inline] - default fn next(&mut self) -> Option<::Item> { - fuse!(self.iter.next()) + fn next(&mut self) -> Option { + FuseIteratorImpl::next(self) } #[inline] - default fn nth(&mut self, n: usize) -> Option { - fuse!(self.iter.nth(n)) + fn nth(&mut self, n: usize) -> Option { + FuseIteratorImpl::nth(self, n) } #[inline] - default fn last(self) -> Option { - match self.iter { - Some(iter) => iter.last(), - None => None, - } + fn last(self) -> Option { + FuseIteratorImpl::last(self) } #[inline] - default fn count(self) -> usize { - match self.iter { - Some(iter) => iter.count(), - None => 0, - } + fn count(self) -> usize { + FuseIteratorImpl::count(self) } #[inline] - default fn size_hint(&self) -> (usize, Option) { - match self.iter { - Some(ref iter) => iter.size_hint(), - None => (0, Some(0)), - } + fn size_hint(&self) -> (usize, Option) { + FuseIteratorImpl::size_hint(self) } #[inline] - default fn try_fold(&mut self, mut acc: Acc, fold: Fold) -> R + fn try_fold(&mut self, acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { - if let Some(ref mut iter) = self.iter { - acc = iter.try_fold(acc, fold)?; - self.iter = None; - } - Try::from_ok(acc) + FuseIteratorImpl::try_fold(self, acc, fold) } #[inline] - default fn fold(self, mut acc: Acc, fold: Fold) -> Acc + fn fold(self, acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - if let Some(iter) = self.iter { - acc = iter.fold(acc, fold); - } - acc + FuseIteratorImpl::fold(self, acc, fold) } #[inline] - default fn find

(&mut self, predicate: P) -> Option + fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, { - fuse!(self.iter.find(predicate)) + FuseIteratorImpl::find(self, predicate) } } @@ -125,46 +109,39 @@ where I: DoubleEndedIterator, { #[inline] - default fn next_back(&mut self) -> Option<::Item> { - fuse!(self.iter.next_back()) + fn next_back(&mut self) -> Option<::Item> { + FuseDoubleEndedIteratorImpl::next_back(self) } #[inline] - default fn nth_back(&mut self, n: usize) -> Option<::Item> { - fuse!(self.iter.nth_back(n)) + fn nth_back(&mut self, n: usize) -> Option<::Item> { + FuseDoubleEndedIteratorImpl::nth_back(self, n) } #[inline] - default fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R + fn try_rfold(&mut self, acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { - if let Some(ref mut iter) = self.iter { - acc = iter.try_rfold(acc, fold)?; - self.iter = None; - } - Try::from_ok(acc) + FuseDoubleEndedIteratorImpl::try_rfold(self, acc, fold) } #[inline] - default fn rfold(self, mut acc: Acc, fold: Fold) -> Acc + fn rfold(self, acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - if let Some(iter) = self.iter { - acc = iter.rfold(acc, fold); - } - acc + FuseDoubleEndedIteratorImpl::rfold(self, acc, fold) } #[inline] - default fn rfind

(&mut self, predicate: P) -> Option + fn rfind

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, { - fuse!(self.iter.rfind(predicate)) + FuseDoubleEndedIteratorImpl::rfind(self, predicate) } } @@ -173,18 +150,12 @@ impl ExactSizeIterator for Fuse where I: ExactSizeIterator, { - default fn len(&self) -> usize { - match self.iter { - Some(ref iter) => iter.len(), - None => 0, - } + fn len(&self) -> usize { + FuseExactSizeIteratorImpl::len(self) } - default fn is_empty(&self) -> bool { - match self.iter { - Some(ref iter) => iter.is_empty(), - None => true, - } + fn is_empty(&self) -> bool { + FuseExactSizeIteratorImpl::is_empty(self) } } @@ -201,7 +172,131 @@ macro_rules! unchecked { } #[stable(feature = "fused", since = "1.26.0")] -impl Iterator for Fuse +impl Iterator for Fuse where I: FusedIterator {} + +#[stable(feature = "fused", since = "1.26.0")] +impl DoubleEndedIterator for Fuse where I: DoubleEndedIterator + FusedIterator {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Fuse where I: ExactSizeIterator + FusedIterator {} + +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 FuseIteratorImpl { + type Item; + 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; +} + +// General Fuse impl +#[doc(hidden)] +impl FuseIteratorImpl for Fuse +where + I: Iterator, +{ + type Item = ::Item; + + #[inline] + default fn next(&mut self) -> Option<::Item> { + fuse!(self.iter.next()) + } + + #[inline] + default fn nth(&mut self, n: usize) -> Option { + fuse!(self.iter.nth(n)) + } + + #[inline] + default fn last(self) -> Option { + match self.iter { + Some(iter) => iter.last(), + None => None, + } + } + + #[inline] + default fn count(self) -> usize { + match self.iter { + Some(iter) => iter.count(), + None => 0, + } + } + + #[inline] + default fn size_hint(&self) -> (usize, Option) { + match self.iter { + Some(ref iter) => iter.size_hint(), + None => (0, Some(0)), + } + } + + #[inline] + default fn try_fold(&mut self, mut acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + if let Some(ref mut iter) = self.iter { + acc = iter.try_fold(acc, fold)?; + self.iter = None; + } + Try::from_ok(acc) + } + + #[inline] + default fn fold(self, mut acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + if let Some(iter) = self.iter { + acc = iter.fold(acc, fold); + } + acc + } + + #[inline] + default fn find

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + fuse!(self.iter.find(predicate)) + } +} + +#[doc(hidden)] +impl FuseIteratorImpl for Fuse where I: FusedIterator, { @@ -257,8 +352,77 @@ where } } -#[stable(feature = "fused", since = "1.26.0")] -impl DoubleEndedIterator for Fuse +#[doc(hidden)] +trait FuseDoubleEndedIteratorImpl { + type Item; + fn next_back(&mut self) -> Option; + fn nth_back(&mut self, n: usize) -> Option; + fn try_rfold(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try; + fn rfold(self, acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc; + fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool; +} + +#[doc(hidden)] +impl FuseDoubleEndedIteratorImpl for Fuse +where + I: DoubleEndedIterator, +{ + type Item = ::Item; + + #[inline] + default fn next_back(&mut self) -> Option<::Item> { + fuse!(self.iter.next_back()) + } + + #[inline] + default fn nth_back(&mut self, n: usize) -> Option<::Item> { + fuse!(self.iter.nth_back(n)) + } + + #[inline] + default fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + if let Some(ref mut iter) = self.iter { + acc = iter.try_rfold(acc, fold)?; + self.iter = None; + } + Try::from_ok(acc) + } + + #[inline] + default fn rfold(self, mut acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + if let Some(iter) = self.iter { + acc = iter.rfold(acc, fold); + } + acc + } + + #[inline] + default fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + fuse!(self.iter.rfind(predicate)) + } +} + +#[doc(hidden)] +impl FuseDoubleEndedIteratorImpl for Fuse where I: DoubleEndedIterator + FusedIterator, { @@ -299,33 +463,40 @@ where } } -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Fuse +#[doc(hidden)] +trait FuseExactSizeIteratorImpl { + fn len(&self) -> usize; + fn is_empty(&self) -> bool; +} + +impl FuseExactSizeIteratorImpl for Fuse where - I: ExactSizeIterator + FusedIterator, + I: ExactSizeIterator, { - fn len(&self) -> usize { - unchecked!(self).len() + default fn len(&self) -> usize { + match self.iter { + Some(ref iter) => iter.len(), + None => 0, + } } - fn is_empty(&self) -> bool { - unchecked!(self).is_empty() + default fn is_empty(&self) -> bool { + match self.iter { + Some(ref iter) => iter.is_empty(), + None => true, + } } } -unsafe impl TrustedRandomAccess for Fuse +impl FuseExactSizeIteratorImpl for Fuse where - I: TrustedRandomAccess, + I: ExactSizeIterator + FusedIterator, { - 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 len(&self) -> usize { + unchecked!(self).len() } - fn may_have_side_effect() -> bool { - I::may_have_side_effect() + fn is_empty(&self) -> bool { + unchecked!(self).is_empty() } } From 51cd29cf6cb4bd4ec025ae436f5d8ae6260335a2 Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Fri, 10 Apr 2020 10:32:23 +0530 Subject: [PATCH 02/16] Added comments. Removed unnecessarry empty impls. Moved code to organise it better --- src/libcore/iter/adapters/fuse.rs | 37 +++++++++++++------------------ 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/libcore/iter/adapters/fuse.rs b/src/libcore/iter/adapters/fuse.rs index 946cd47536307..c3968b101e504 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 @@ -159,27 +172,6 @@ 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 where I: FusedIterator {} - -#[stable(feature = "fused", since = "1.26.0")] -impl DoubleEndedIterator for Fuse where I: DoubleEndedIterator + FusedIterator {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Fuse where I: ExactSizeIterator + FusedIterator {} - unsafe impl TrustedRandomAccess for Fuse where I: TrustedRandomAccess, @@ -198,6 +190,9 @@ where } // Fuse specialization trait +// Iterators and DoubleEndedIterators cannot be overlapped successfully +// So, they're separated into each it's own trait to provide internal implementations +// Similarly, ExactSizeIterators cannot be overlapped, so requires its own trait #[doc(hidden)] trait FuseIteratorImpl { type Item; From 908436f3bb9e41721f01099baecd68a48b8cf933 Mon Sep 17 00:00:00 2001 From: PankajChaudhary5 Date: Mon, 30 Mar 2020 23:16:44 +0530 Subject: [PATCH 03/16] Add proper explanation of error code E0657 --- src/librustc_error_codes/error_codes.rs | 2 +- src/librustc_error_codes/error_codes/E0657.md | 57 +++++++++++++++++++ src/test/ui/error-codes/E0657.stderr | 1 + 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/librustc_error_codes/error_codes/E0657.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 2f0a3fc1d1c38..6d87627ce3498 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -365,6 +365,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 0000000000000..7fe48c5114790 --- /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/test/ui/error-codes/E0657.stderr b/src/test/ui/error-codes/E0657.stderr index b24b413600c6c..df76b45a5891f 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`. From 9ee4d1aadc7f4151193a7f53d1fcbb4fddf40ece Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 15 Apr 2020 12:18:20 +0200 Subject: [PATCH 04/16] reword Miri validity errors: undefined -> uninitialized --- src/librustc_mir/interpret/validity.rs | 17 +++++++++++------ .../ui/consts/const-eval/ub-wide-ptr.stderr | 4 ++-- src/test/ui/consts/const-eval/union-ice.stderr | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 701e394415bbd..d60f6f38d07f2 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 value", self.path) } // Other errors shouldn't be possible _ => return Err(err), 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 80e60dbb58a5d..f12753e5dcacc 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 476f3651740ab..946c375ced701 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 value 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. From abe5973b9d1202f1a6460c0116f22fc33c9506c5 Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Thu, 16 Apr 2020 01:19:51 +0530 Subject: [PATCH 05/16] Inlined everything into a single trait and trait impl --- src/libcore/iter/adapters/fuse.rs | 267 ++++++++++++++++-------------- 1 file changed, 141 insertions(+), 126 deletions(-) diff --git a/src/libcore/iter/adapters/fuse.rs b/src/libcore/iter/adapters/fuse.rs index c3968b101e504..502fc2e631502 100644 --- a/src/libcore/iter/adapters/fuse.rs +++ b/src/libcore/iter/adapters/fuse.rs @@ -66,27 +66,27 @@ where #[inline] fn next(&mut self) -> Option { - FuseIteratorImpl::next(self) + FuseImpl::next(self) } #[inline] fn nth(&mut self, n: usize) -> Option { - FuseIteratorImpl::nth(self, n) + FuseImpl::nth(self, n) } #[inline] fn last(self) -> Option { - FuseIteratorImpl::last(self) + FuseImpl::last(self) } #[inline] fn count(self) -> usize { - FuseIteratorImpl::count(self) + FuseImpl::count(self) } #[inline] fn size_hint(&self) -> (usize, Option) { - FuseIteratorImpl::size_hint(self) + FuseImpl::size_hint(self) } #[inline] @@ -96,7 +96,7 @@ where Fold: FnMut(Acc, Self::Item) -> R, R: Try, { - FuseIteratorImpl::try_fold(self, acc, fold) + FuseImpl::try_fold(self, acc, fold) } #[inline] @@ -104,7 +104,7 @@ where where Fold: FnMut(Acc, Self::Item) -> Acc, { - FuseIteratorImpl::fold(self, acc, fold) + FuseImpl::fold(self, acc, fold) } #[inline] @@ -112,7 +112,7 @@ where where P: FnMut(&Self::Item) -> bool, { - FuseIteratorImpl::find(self, predicate) + FuseImpl::find(self, predicate) } } @@ -123,12 +123,12 @@ where { #[inline] fn next_back(&mut self) -> Option<::Item> { - FuseDoubleEndedIteratorImpl::next_back(self) + FuseImpl::next_back(self) } #[inline] fn nth_back(&mut self, n: usize) -> Option<::Item> { - FuseDoubleEndedIteratorImpl::nth_back(self, n) + FuseImpl::nth_back(self, n) } #[inline] @@ -138,7 +138,7 @@ where Fold: FnMut(Acc, Self::Item) -> R, R: Try, { - FuseDoubleEndedIteratorImpl::try_rfold(self, acc, fold) + FuseImpl::try_rfold(self, acc, fold) } #[inline] @@ -146,7 +146,7 @@ where where Fold: FnMut(Acc, Self::Item) -> Acc, { - FuseDoubleEndedIteratorImpl::rfold(self, acc, fold) + FuseImpl::rfold(self, acc, fold) } #[inline] @@ -154,7 +154,7 @@ where where P: FnMut(&Self::Item) -> bool, { - FuseDoubleEndedIteratorImpl::rfind(self, predicate) + FuseImpl::rfind(self, predicate) } } @@ -164,11 +164,11 @@ where I: ExactSizeIterator, { fn len(&self) -> usize { - FuseExactSizeIteratorImpl::len(self) + FuseImpl::len(self) } fn is_empty(&self) -> bool { - FuseExactSizeIteratorImpl::is_empty(self) + FuseImpl::is_empty(self) } } @@ -190,12 +190,11 @@ where } // Fuse specialization trait -// Iterators and DoubleEndedIterators cannot be overlapped successfully -// So, they're separated into each it's own trait to provide internal implementations -// Similarly, ExactSizeIterators cannot be overlapped, so requires its own trait #[doc(hidden)] -trait FuseIteratorImpl { +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; @@ -212,11 +211,41 @@ trait FuseIteratorImpl { 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 FuseIteratorImpl for Fuse +impl FuseImpl for Fuse where I: Iterator, { @@ -288,146 +317,151 @@ where { fuse!(self.iter.find(predicate)) } -} - -#[doc(hidden)] -impl FuseIteratorImpl for Fuse -where - I: FusedIterator, -{ - #[inline] - fn next(&mut self) -> Option<::Item> { - unchecked!(self).next() - } - - #[inline] - fn nth(&mut self, n: usize) -> Option { - unchecked!(self).nth(n) - } #[inline] - fn last(self) -> Option { - unchecked!(self).last() - } - - #[inline] - fn count(self) -> usize { - unchecked!(self).count() + default fn next_back(&mut self) -> Option<::Item> + where + I: DoubleEndedIterator, + { + fuse!(self.iter.next_back()) } #[inline] - fn size_hint(&self) -> (usize, Option) { - unchecked!(self).size_hint() + default fn nth_back(&mut self, n: usize) -> Option<::Item> + where + I: DoubleEndedIterator, + { + fuse!(self.iter.nth_back(n)) } #[inline] - fn try_fold(&mut self, init: Acc, fold: Fold) -> R + default fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, + I: DoubleEndedIterator, { - unchecked!(self).try_fold(init, fold) + if let Some(ref mut iter) = self.iter { + acc = iter.try_rfold(acc, fold)?; + self.iter = None; + } + Try::from_ok(acc) } #[inline] - fn fold(self, init: Acc, fold: Fold) -> Acc + default fn rfold(self, mut acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, + I: DoubleEndedIterator, { - unchecked!(self).fold(init, fold) + if let Some(iter) = self.iter { + acc = iter.rfold(acc, fold); + } + acc } #[inline] - fn find

(&mut self, predicate: P) -> Option + default fn rfind

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, + I: DoubleEndedIterator, { - unchecked!(self).find(predicate) + fuse!(self.iter.rfind(predicate)) } -} -#[doc(hidden)] -trait FuseDoubleEndedIteratorImpl { - type Item; - fn next_back(&mut self) -> Option; - fn nth_back(&mut self, n: usize) -> Option; - fn try_rfold(&mut self, acc: Acc, fold: Fold) -> R - where - Self: Sized, - Fold: FnMut(Acc, Self::Item) -> R, - R: Try; - fn rfold(self, acc: Acc, fold: Fold) -> Acc + #[inline] + default fn len(&self) -> usize where - Fold: FnMut(Acc, Self::Item) -> Acc; - fn rfind

(&mut self, predicate: P) -> Option + I: ExactSizeIterator, + { + match self.iter { + Some(ref iter) => iter.len(), + None => 0, + } + } + + #[inline] + default fn is_empty(&self) -> bool where - P: FnMut(&Self::Item) -> bool; + I: ExactSizeIterator, + { + match self.iter { + Some(ref iter) => iter.is_empty(), + None => true, + } + } } #[doc(hidden)] -impl FuseDoubleEndedIteratorImpl for Fuse +impl FuseImpl for Fuse where - I: DoubleEndedIterator, + I: FusedIterator, { - type Item = ::Item; + #[inline] + fn next(&mut self) -> Option<::Item> { + unchecked!(self).next() + } #[inline] - default fn next_back(&mut self) -> Option<::Item> { - fuse!(self.iter.next_back()) + fn nth(&mut self, n: usize) -> Option { + unchecked!(self).nth(n) } #[inline] - default fn nth_back(&mut self, n: usize) -> Option<::Item> { - fuse!(self.iter.nth_back(n)) + fn last(self) -> Option { + unchecked!(self).last() } #[inline] - default fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R + fn count(self) -> usize { + unchecked!(self).count() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + unchecked!(self).size_hint() + } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { - if let Some(ref mut iter) = self.iter { - acc = iter.try_rfold(acc, fold)?; - self.iter = None; - } - Try::from_ok(acc) + unchecked!(self).try_fold(init, fold) } #[inline] - default fn rfold(self, mut acc: Acc, fold: Fold) -> Acc + fn fold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - if let Some(iter) = self.iter { - acc = iter.rfold(acc, fold); - } - acc + unchecked!(self).fold(init, fold) } #[inline] - default fn rfind

(&mut self, predicate: P) -> Option + fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, { - fuse!(self.iter.rfind(predicate)) + unchecked!(self).find(predicate) } -} -#[doc(hidden)] -impl FuseDoubleEndedIteratorImpl 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) } @@ -437,6 +471,7 @@ where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, + I: DoubleEndedIterator, { unchecked!(self).try_rfold(init, fold) } @@ -445,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) } @@ -453,45 +489,24 @@ where fn rfind

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, + I: DoubleEndedIterator, { unchecked!(self).rfind(predicate) } -} - -#[doc(hidden)] -trait FuseExactSizeIteratorImpl { - fn len(&self) -> usize; - fn is_empty(&self) -> bool; -} - -impl FuseExactSizeIteratorImpl for Fuse -where - I: ExactSizeIterator, -{ - default fn len(&self) -> usize { - match self.iter { - Some(ref iter) => iter.len(), - None => 0, - } - } - - default fn is_empty(&self) -> bool { - match self.iter { - Some(ref iter) => iter.is_empty(), - None => true, - } - } -} -impl FuseExactSizeIteratorImpl 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() } } From 0d01ce6a1bf1d4b097fd1ef09daac974f38933f2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 16 Apr 2020 13:19:51 +0200 Subject: [PATCH 06/16] switch back to 'bytes' --- src/librustc_mir/interpret/validity.rs | 2 +- src/test/ui/consts/const-eval/union-ice.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index d60f6f38d07f2..83b8d58e0befc 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -788,7 +788,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> .unwrap(); self.path.push(PathElem::ArrayElem(i)); - throw_validation_failure!("uninitialized value", self.path) + throw_validation_failure!("uninitialized bytes", self.path) } // Other errors shouldn't be possible _ => return Err(err), diff --git a/src/test/ui/consts/const-eval/union-ice.stderr b/src/test/ui/consts/const-eval/union-ice.stderr index 946c375ced701..2545167aa02f7 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 uninitialized value 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. From 69423bf0493441de320ee58c6ac05b7011655710 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 16 Apr 2020 13:21:23 +0200 Subject: [PATCH 07/16] test fast path offset reporting --- src/test/ui/consts/const-eval/ub-int-array.rs | 65 +++++++++++++++++++ .../ui/consts/const-eval/ub-int-array.stderr | 45 +++++++++++++ src/test/ui/consts/const-eval/ub-ref.rs | 4 +- 3 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/consts/const-eval/ub-int-array.rs create mode 100644 src/test/ui/consts/const-eval/ub-int-array.stderr 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 0000000000000..8907b0c160f88 --- /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 0000000000000..b4a3c63b5a103 --- /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 562ec99111b69..10f4c8c03330e 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 From 18d0907dcc8ca5b71e6a70ff7eaed30c3e883d84 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 16 Apr 2020 17:41:28 +0200 Subject: [PATCH 08/16] Miri error messages: avoid try terminology --- src/librustc_middle/mir/interpret/error.rs | 8 ++++---- .../consts/transmute-size-mismatch-before-typeck.stderr | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_middle/mir/interpret/error.rs b/src/librustc_middle/mir/interpret/error.rs index 7844fb108406d..ddff9a57818c7 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 from {:?} to {:?}, which 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, "cannot load MIR 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/test/ui/consts/transmute-size-mismatch-before-typeck.stderr b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr index 5a47771459625..0e55d299c40ed 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 from usize to &[u8], which do not have the same size | = note: `#[deny(const_err)]` on by default From 250b27d996af6df25065756814188236ef6b0e01 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 16 Apr 2020 18:47:05 +0200 Subject: [PATCH 09/16] bikeshed --- src/librustc_middle/mir/interpret/error.rs | 4 ++-- .../ui/consts/transmute-size-mismatch-before-typeck.stderr | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_middle/mir/interpret/error.rs b/src/librustc_middle/mir/interpret/error.rs index ddff9a57818c7..f058d17a9bf28 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, - "transmuting from {:?} to {:?}, which do not have the same size", + "transmuting `{}` to `{}` is not possible, because these types do not have the same size", from_ty, to_ty ), } @@ -464,7 +464,7 @@ impl fmt::Debug for UnsupportedOpInfo { ReadForeignStatic(did) => { write!(f, "cannot read from foreign (extern) static {:?}", did) } - NoMirFor(did) => write!(f, "cannot 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/test/ui/consts/transmute-size-mismatch-before-typeck.stderr b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr index 0e55d299c40ed..b4970c82adb3e 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) }; | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | transmuting from usize to &[u8], which do not have the same size + | transmuting `usize` to `&[u8]` is not possible, because these types do not have the same size | = note: `#[deny(const_err)]` on by default From 2edd123a233fff2fbccd17299e0c14d2203e1acc Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 16 Apr 2020 12:44:57 -0700 Subject: [PATCH 10/16] Dogfood or_patterns in the standard library --- src/liballoc/collections/btree/map.rs | 7 +------ src/liballoc/lib.rs | 1 + src/libcore/cmp.rs | 4 ++-- src/libcore/iter/traits/iterator.rs | 4 ++-- src/libcore/lib.rs | 1 + src/libcore/num/dec2flt/parse.rs | 4 ++-- src/libcore/num/flt2dec/mod.rs | 4 ++-- src/libstd/lib.rs | 1 + src/libstd/sync/mpsc/oneshot.rs | 2 +- src/libstd/sync/mpsc/stream.rs | 2 +- 10 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 3fc1b5e16b372..38196b2d4b4c5 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 121c1cde548cb..a2071844d5dac 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 8c542136a7fa6..335969b3ef04e 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/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index c8829817e190c..34ca79154b68f 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 a04b7162c922b..1c7bce3fac583 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 93b08bce853c7..2766843155a0e 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 f5cd26a1852d6..9adea94e87d10 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/libstd/lib.rs b/src/libstd/lib.rs index a9a519f0a3a71..59d845c619b84 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 5b41525e06aaa..75f5621fa127e 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 f33493ee0c9c9..26b4faebd8614 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 }, From 9fb3f552114cb61cc7070af1f02a1b65226d3b3d Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 16 Apr 2020 10:09:16 +0900 Subject: [PATCH 11/16] Add test for issue-24843 --- src/test/ui/static/auxiliary/issue_24843.rs | 1 + src/test/ui/static/issue-24843.rs | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 src/test/ui/static/auxiliary/issue_24843.rs create mode 100644 src/test/ui/static/issue-24843.rs 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 0000000000000..6ca04f8606038 --- /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 0000000000000..0b3397e210d70 --- /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() {} From 077a7f741fcc1c2f9ea31dbc23b8fee5820c3cb5 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 16 Apr 2020 10:09:34 +0900 Subject: [PATCH 12/16] Add test for issue-28575 --- src/test/ui/intrinsics/issue-28575.rs | 9 +++++++++ src/test/ui/intrinsics/issue-28575.stderr | 11 +++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/test/ui/intrinsics/issue-28575.rs create mode 100644 src/test/ui/intrinsics/issue-28575.stderr diff --git a/src/test/ui/intrinsics/issue-28575.rs b/src/test/ui/intrinsics/issue-28575.rs new file mode 100644 index 0000000000000..141136d25b215 --- /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 0000000000000..66369decf4224 --- /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`. From 119bbbe31a2101d6d6b457b7814a12fcc39f1934 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 16 Apr 2020 10:09:47 +0900 Subject: [PATCH 13/16] Add test for issue-54067 --- src/test/ui/asm/issue-54067.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/test/ui/asm/issue-54067.rs diff --git a/src/test/ui/asm/issue-54067.rs b/src/test/ui/asm/issue-54067.rs new file mode 100644 index 0000000000000..f2e097222bd7d --- /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() {} From 0b85356387876b2482e3161bc4e8797193bec669 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 16 Apr 2020 10:09:59 +0900 Subject: [PATCH 14/16] Add test for issue-67893 --- .../issues/auxiliary/issue_67893.rs | 10 ++++++++ src/test/ui/async-await/issues/issue-67893.rs | 11 +++++++++ .../ui/async-await/issues/issue-67893.stderr | 24 +++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 src/test/ui/async-await/issues/auxiliary/issue_67893.rs create mode 100644 src/test/ui/async-await/issues/issue-67893.rs create mode 100644 src/test/ui/async-await/issues/issue-67893.stderr 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 0000000000000..387966a5064fa --- /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 0000000000000..9679e3807b629 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-67893.rs @@ -0,0 +1,11 @@ +// aux-build: issue_67893.rs +// edition:2018 + +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/async-await/issues/issue-67893.stderr b/src/test/ui/async-await/issues/issue-67893.stderr new file mode 100644 index 0000000000000..567a4c91b5570 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-67893.stderr @@ -0,0 +1,24 @@ +error[E0277]: `std::sync::MutexGuard<'_, ()>` cannot be sent between threads safely + --> $DIR/issue-67893.rs:9:5 + | +LL | fn g(_: impl Send) {} + | ---- required by this bound in `g` +... +LL | g(issue_67893::run()) + | ^ `std::sync::MutexGuard<'_, ()>` cannot be sent between threads safely + | + ::: $DIR/auxiliary/issue_67893.rs:7:20 + | +LL | pub async fn run() { + | - within this `impl std::future::Future` + | + = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, ()>` + = note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3> {std::future::ResumeTy, std::sync::Arc>, &'r std::sync::Mutex<()>, std::result::Result, std::sync::PoisonError>>, &'t1 std::sync::MutexGuard<'t2, ()>, std::sync::MutexGuard<'t3, ()>, (), impl std::future::Future}` + = note: required because it appears within the type `[static generator@DefId(15:11 ~ issue_67893[8787]::run[0]::{{closure}}[0]) for<'r, 's, 't0, 't1, 't2, 't3> {std::future::ResumeTy, std::sync::Arc>, &'r std::sync::Mutex<()>, std::result::Result, std::sync::PoisonError>>, &'t1 std::sync::MutexGuard<'t2, ()>, std::sync::MutexGuard<'t3, ()>, (), impl std::future::Future}]` + = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@DefId(15:11 ~ issue_67893[8787]::run[0]::{{closure}}[0]) for<'r, 's, 't0, 't1, 't2, 't3> {std::future::ResumeTy, std::sync::Arc>, &'r std::sync::Mutex<()>, std::result::Result, std::sync::PoisonError>>, &'t1 std::sync::MutexGuard<'t2, ()>, std::sync::MutexGuard<'t3, ()>, (), impl std::future::Future}]>` + = note: required because it appears within the type `impl std::future::Future` + = note: required because it appears within the type `impl std::future::Future` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From a6855b918b249751436d737d3f8bd2af23613101 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 17 Apr 2020 00:14:52 +0900 Subject: [PATCH 15/16] Avoid emitting stderr for now --- src/test/ui/async-await/issues/issue-67893.rs | 2 ++ .../ui/async-await/issues/issue-67893.stderr | 24 ------------------- 2 files changed, 2 insertions(+), 24 deletions(-) delete mode 100644 src/test/ui/async-await/issues/issue-67893.stderr diff --git a/src/test/ui/async-await/issues/issue-67893.rs b/src/test/ui/async-await/issues/issue-67893.rs index 9679e3807b629..d52303ac1cec6 100644 --- a/src/test/ui/async-await/issues/issue-67893.rs +++ b/src/test/ui/async-await/issues/issue-67893.rs @@ -1,5 +1,7 @@ // 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; diff --git a/src/test/ui/async-await/issues/issue-67893.stderr b/src/test/ui/async-await/issues/issue-67893.stderr deleted file mode 100644 index 567a4c91b5570..0000000000000 --- a/src/test/ui/async-await/issues/issue-67893.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error[E0277]: `std::sync::MutexGuard<'_, ()>` cannot be sent between threads safely - --> $DIR/issue-67893.rs:9:5 - | -LL | fn g(_: impl Send) {} - | ---- required by this bound in `g` -... -LL | g(issue_67893::run()) - | ^ `std::sync::MutexGuard<'_, ()>` cannot be sent between threads safely - | - ::: $DIR/auxiliary/issue_67893.rs:7:20 - | -LL | pub async fn run() { - | - within this `impl std::future::Future` - | - = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, ()>` - = note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3> {std::future::ResumeTy, std::sync::Arc>, &'r std::sync::Mutex<()>, std::result::Result, std::sync::PoisonError>>, &'t1 std::sync::MutexGuard<'t2, ()>, std::sync::MutexGuard<'t3, ()>, (), impl std::future::Future}` - = note: required because it appears within the type `[static generator@DefId(15:11 ~ issue_67893[8787]::run[0]::{{closure}}[0]) for<'r, 's, 't0, 't1, 't2, 't3> {std::future::ResumeTy, std::sync::Arc>, &'r std::sync::Mutex<()>, std::result::Result, std::sync::PoisonError>>, &'t1 std::sync::MutexGuard<'t2, ()>, std::sync::MutexGuard<'t3, ()>, (), impl std::future::Future}]` - = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@DefId(15:11 ~ issue_67893[8787]::run[0]::{{closure}}[0]) for<'r, 's, 't0, 't1, 't2, 't3> {std::future::ResumeTy, std::sync::Arc>, &'r std::sync::Mutex<()>, std::result::Result, std::sync::PoisonError>>, &'t1 std::sync::MutexGuard<'t2, ()>, std::sync::MutexGuard<'t3, ()>, (), impl std::future::Future}]>` - = note: required because it appears within the type `impl std::future::Future` - = note: required because it appears within the type `impl std::future::Future` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. From da48550b330d95ac92ae6a65901b10ba3ccc130c Mon Sep 17 00:00:00 2001 From: Leo Cassarani Date: Thu, 16 Apr 2020 22:30:53 +0100 Subject: [PATCH 16/16] Fix typo in Default trait docs: Provides -> Provide An earlier commit (99ed06e) accidentally changed this paragraph from the original, imperative "Provide" to the present tense "Provides". The latter is indeed the standard for Rustdoc comments relating to a function or method, but this snippet is introducing the Default trait in general terms and not talking about any particular function. I believe this change was likely made in error and should be reverted. --- src/libcore/default.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 15ac3aea8b7ba..06402a05d2687 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: /// /// ```