From 56ebfb185b2e144d5404eda1fc40b0070a3122f3 Mon Sep 17 00:00:00 2001 From: Tim Vermeulen Date: Sun, 2 Jun 2019 13:31:49 +0200 Subject: [PATCH 01/21] Implement DoubleEndedIterator for iter::{StepBy, Peekable, Take} --- src/libcore/iter/adapters/mod.rs | 117 +++++++++++++++++++ src/libcore/tests/iter.rs | 192 ++++++++++++++++++++++++++++--- 2 files changed, 296 insertions(+), 13 deletions(-) diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 518442efe7417..00053d9da84e0 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -485,6 +485,39 @@ impl Iterator for StepBy where I: Iterator { } } +impl StepBy where I: ExactSizeIterator { + // The zero-based index starting from the end of the iterator of the + // last element. Used in the `DoubleEndedIterator` implementation. + fn next_back_index(&self) -> usize { + let rem = self.iter.len() % (self.step + 1); + if self.first_take { + if rem == 0 { self.step } else { rem - 1 } + } else { + rem + } + } +} + +#[stable(feature = "double_ended_step_by_iterator", since = "1.38.0")] +impl DoubleEndedIterator for StepBy where I: DoubleEndedIterator + ExactSizeIterator { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.nth_back(self.next_back_index()) + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + // `self.iter.nth_back(usize::MAX)` does the right thing here when `n` + // is out of bounds because the length of `self.iter` does not exceed + // `usize::MAX` (because `I: ExactSizeIterator`) and `nth_back` is + // zero-indexed + let n = n + .saturating_mul(self.step + 1) + .saturating_add(self.next_back_index()); + self.iter.nth_back(n) + } +} + // StepBy can only make the iterator shorter, so the len will still fit. #[stable(feature = "iterator_step_by", since = "1.28.0")] impl ExactSizeIterator for StepBy where I: ExactSizeIterator {} @@ -1158,6 +1191,45 @@ impl Iterator for Peekable { } } +#[stable(feature = "double_ended_peek_iterator", since = "1.38.0")] +impl DoubleEndedIterator for Peekable where I: DoubleEndedIterator { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back().or_else(|| self.peeked.take().and_then(|x| x)) + } + + #[inline] + fn try_rfold(&mut self, init: B, mut f: F) -> R where + Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try + { + match self.peeked.take() { + Some(None) => return Try::from_ok(init), + Some(Some(v)) => match self.iter.try_rfold(init, &mut f).into_result() { + Ok(acc) => f(acc, v), + Err(e) => { + self.peeked = Some(Some(v)); + Try::from_error(e) + } + }, + None => self.iter.try_rfold(init, f), + } + } + + #[inline] + fn rfold(self, init: Acc, mut fold: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + match self.peeked { + Some(None) => return init, + Some(Some(v)) => { + let acc = self.iter.rfold(init, &mut fold); + fold(acc, v) + } + None => self.iter.rfold(init, fold), + } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Peekable {} @@ -1613,6 +1685,51 @@ impl Iterator for Take where I: Iterator{ } } +#[stable(feature = "double_ended_take_iterator", since = "1.38.0")] +impl DoubleEndedIterator for Take where I: DoubleEndedIterator + ExactSizeIterator { + #[inline] + fn next_back(&mut self) -> Option { + if self.n == 0 { + None + } else { + let n = self.n; + self.n -= 1; + self.iter.nth_back(self.iter.len().saturating_sub(n)) + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.iter.len(); + if self.n > n { + let m = len.saturating_sub(self.n) + n; + self.n -= n + 1; + self.iter.nth_back(m) + } else { + if len > 0 { + self.iter.nth_back(len - 1); + } + None + } + } + + #[inline] + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R where + Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try + { + if self.n == 0 { + Try::from_ok(init) + } else { + let len = self.iter.len(); + if len > self.n && self.iter.nth_back(len - self.n - 1).is_none() { + Try::from_ok(init) + } else { + self.iter.try_rfold(init, fold) + } + } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Take where I: ExactSizeIterator {} diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index bedb9e756129c..60efeda3a40ec 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -188,6 +188,19 @@ fn test_iterator_step_by() { assert_eq!(it.next(), Some(6)); assert_eq!(it.next(), Some(9)); assert_eq!(it.next(), None); + + let mut it = (0..3).step_by(1); + assert_eq!(it.next_back(), Some(2)); + assert_eq!(it.next_back(), Some(1)); + assert_eq!(it.next_back(), Some(0)); + assert_eq!(it.next_back(), None); + + let mut it = (0..11).step_by(3); + assert_eq!(it.next_back(), Some(9)); + assert_eq!(it.next_back(), Some(6)); + assert_eq!(it.next_back(), Some(3)); + assert_eq!(it.next_back(), Some(0)); + assert_eq!(it.next_back(), None); } #[test] @@ -252,6 +265,31 @@ fn test_iterator_step_by_nth_overflow() { assert_eq!(it.0, (usize::MAX as Bigger) * 1); } +#[test] +fn test_iterator_step_by_nth_back() { + let mut it = (0..16).step_by(5); + assert_eq!(it.nth_back(0), Some(15)); + assert_eq!(it.nth_back(0), Some(10)); + assert_eq!(it.nth_back(0), Some(5)); + assert_eq!(it.nth_back(0), Some(0)); + assert_eq!(it.nth_back(0), None); + + let mut it = (0..16).step_by(5); + assert_eq!(it.next(), Some(0)); // to set `first_take` to `false` + assert_eq!(it.nth_back(0), Some(15)); + assert_eq!(it.nth_back(0), Some(10)); + assert_eq!(it.nth_back(0), Some(5)); + assert_eq!(it.nth_back(0), None); + + let it = || (0..18).step_by(5); + assert_eq!(it().nth_back(0), Some(15)); + assert_eq!(it().nth_back(1), Some(10)); + assert_eq!(it().nth_back(2), Some(5)); + assert_eq!(it().nth_back(3), Some(0)); + assert_eq!(it().nth_back(4), None); + assert_eq!(it().nth_back(42), None); +} + #[test] #[should_panic] fn test_iterator_step_by_zero() { @@ -465,8 +503,8 @@ fn test_iterator_filter_fold() { #[test] fn test_iterator_peekable() { let xs = vec![0, 1, 2, 3, 4, 5]; - let mut it = xs.iter().cloned().peekable(); + let mut it = xs.iter().cloned().peekable(); assert_eq!(it.len(), 6); assert_eq!(it.peek().unwrap(), &0); assert_eq!(it.len(), 6); @@ -492,6 +530,33 @@ fn test_iterator_peekable() { assert_eq!(it.len(), 0); assert!(it.next().is_none()); assert_eq!(it.len(), 0); + + let mut it = xs.iter().cloned().peekable(); + assert_eq!(it.len(), 6); + assert_eq!(it.peek().unwrap(), &0); + assert_eq!(it.len(), 6); + assert_eq!(it.next_back().unwrap(), 5); + assert_eq!(it.len(), 5); + assert_eq!(it.next_back().unwrap(), 4); + assert_eq!(it.len(), 4); + assert_eq!(it.next_back().unwrap(), 3); + assert_eq!(it.len(), 3); + assert_eq!(it.peek().unwrap(), &0); + assert_eq!(it.len(), 3); + assert_eq!(it.peek().unwrap(), &0); + assert_eq!(it.len(), 3); + assert_eq!(it.next_back().unwrap(), 2); + assert_eq!(it.len(), 2); + assert_eq!(it.next_back().unwrap(), 1); + assert_eq!(it.len(), 1); + assert_eq!(it.peek().unwrap(), &0); + assert_eq!(it.len(), 1); + assert_eq!(it.next_back().unwrap(), 0); + assert_eq!(it.len(), 0); + assert!(it.peek().is_none()); + assert_eq!(it.len(), 0); + assert!(it.next_back().is_none()); + assert_eq!(it.len(), 0); } #[test] @@ -564,6 +629,18 @@ fn test_iterator_peekable_fold() { assert_eq!(i, xs.len()); } +#[test] +fn test_iterator_peekable_rfold() { + let xs = [0, 1, 2, 3, 4, 5]; + let mut it = xs.iter().peekable(); + assert_eq!(it.peek(), Some(&&0)); + let i = it.rfold(0, |i, &x| { + assert_eq!(x, xs[xs.len() - 1 - i]); + i + 1 + }); + assert_eq!(i, xs.len()); +} + /// This is an iterator that follows the Iterator contract, /// but it is not fused. After having returned None once, it will start /// producing elements if .next() is called again. @@ -812,13 +889,25 @@ fn test_iterator_skip_fold() { fn test_iterator_take() { let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19]; let ys = [0, 1, 2, 3, 5]; - let mut it = xs.iter().take(5); + + let mut it = xs.iter().take(ys.len()); let mut i = 0; - assert_eq!(it.len(), 5); + assert_eq!(it.len(), ys.len()); while let Some(&x) = it.next() { assert_eq!(x, ys[i]); i += 1; - assert_eq!(it.len(), 5-i); + assert_eq!(it.len(), ys.len() - i); + } + assert_eq!(i, ys.len()); + assert_eq!(it.len(), 0); + + let mut it = xs.iter().take(ys.len()); + let mut i = 0; + assert_eq!(it.len(), ys.len()); + while let Some(&x) = it.next_back() { + i += 1; + assert_eq!(x, ys[ys.len() - i]); + assert_eq!(it.len(), ys.len() - i); } assert_eq!(i, ys.len()); assert_eq!(it.len(), 0); @@ -848,19 +937,51 @@ fn test_iterator_take_nth() { } } +#[test] +fn test_iterator_take_nth_back() { + let xs = [0, 1, 2, 4, 5]; + let mut it = xs.iter(); + { + let mut take = it.by_ref().take(3); + let mut i = 0; + while let Some(&x) = take.nth_back(0) { + i += 1; + assert_eq!(x, 3 - i); + } + } + assert_eq!(it.nth_back(0), None); + + let xs = [0, 1, 2, 3, 4]; + let mut it = xs.iter().take(7); + assert_eq!(it.nth_back(1), Some(&3)); + assert_eq!(it.nth_back(1), Some(&1)); + assert_eq!(it.nth_back(1), None); +} + #[test] fn test_iterator_take_short() { let xs = [0, 1, 2, 3]; - let ys = [0, 1, 2, 3]; + let mut it = xs.iter().take(5); let mut i = 0; - assert_eq!(it.len(), 4); + assert_eq!(it.len(), xs.len()); while let Some(&x) = it.next() { - assert_eq!(x, ys[i]); + assert_eq!(x, xs[i]); i += 1; - assert_eq!(it.len(), 4-i); + assert_eq!(it.len(), xs.len() - i); } - assert_eq!(i, ys.len()); + assert_eq!(i, xs.len()); + assert_eq!(it.len(), 0); + + let mut it = xs.iter().take(5); + let mut i = 0; + assert_eq!(it.len(), xs.len()); + while let Some(&x) = it.next_back() { + i += 1; + assert_eq!(x, xs[xs.len() - i]); + assert_eq!(it.len(), xs.len() - i); + } + assert_eq!(i, xs.len()); assert_eq!(it.len(), 0); } @@ -2241,17 +2362,50 @@ fn test_enumerate_try_folds() { } #[test] -fn test_peek_try_fold() { +fn test_peek_try_folds() { let f = &|acc, x| i32::checked_add(2*acc, x); + assert_eq!((1..20).peekable().try_fold(7, f), (1..20).try_fold(7, f)); + assert_eq!((1..20).peekable().try_rfold(7, f), (1..20).try_rfold(7, f)); + let mut iter = (1..20).peekable(); assert_eq!(iter.peek(), Some(&1)); assert_eq!(iter.try_fold(7, f), (1..20).try_fold(7, f)); + let mut iter = (1..20).peekable(); + assert_eq!(iter.peek(), Some(&1)); + assert_eq!(iter.try_rfold(7, f), (1..20).try_rfold(7, f)); + let mut iter = [100, 20, 30, 40, 50, 60, 70].iter().cloned().peekable(); assert_eq!(iter.peek(), Some(&100)); assert_eq!(iter.try_fold(0, i8::checked_add), None); assert_eq!(iter.peek(), Some(&40)); + + let mut iter = [100, 20, 30, 40, 50, 60, 70].iter().cloned().peekable(); + assert_eq!(iter.peek(), Some(&100)); + assert_eq!(iter.try_rfold(0, i8::checked_add), None); + assert_eq!(iter.peek(), Some(&100)); + assert_eq!(iter.next_back(), Some(50)); + + let mut iter = (2..5).peekable(); + assert_eq!(iter.peek(), Some(&2)); + assert_eq!(iter.try_for_each(Err), Err(2)); + assert_eq!(iter.peek(), Some(&3)); + assert_eq!(iter.try_for_each(Err), Err(3)); + assert_eq!(iter.peek(), Some(&4)); + assert_eq!(iter.try_for_each(Err), Err(4)); + assert_eq!(iter.peek(), None); + assert_eq!(iter.try_for_each(Err), Ok(())); + + let mut iter = (2..5).peekable(); + assert_eq!(iter.peek(), Some(&2)); + assert_eq!(iter.try_rfold((), |(), x| Err(x)), Err(4)); + assert_eq!(iter.peek(), Some(&2)); + assert_eq!(iter.try_rfold((), |(), x| Err(x)), Err(3)); + assert_eq!(iter.peek(), Some(&2)); + assert_eq!(iter.try_rfold((), |(), x| Err(x)), Err(2)); + assert_eq!(iter.peek(), None); + assert_eq!(iter.try_rfold((), |(), x| Err(x)), Ok(())); } #[test] @@ -2300,13 +2454,25 @@ fn test_skip_try_folds() { fn test_take_try_folds() { let f = &|acc, x| i32::checked_add(2*acc, x); assert_eq!((10..30).take(10).try_fold(7, f), (10..20).try_fold(7, f)); - //assert_eq!((10..30).take(10).try_rfold(7, f), (10..20).try_rfold(7, f)); + assert_eq!((10..30).take(10).try_rfold(7, f), (10..20).try_rfold(7, f)); let mut iter = (10..30).take(20); assert_eq!(iter.try_fold(0, i8::checked_add), None); assert_eq!(iter.next(), Some(20)); - //assert_eq!(iter.try_rfold(0, i8::checked_add), None); - //assert_eq!(iter.next_back(), Some(24)); + assert_eq!(iter.try_rfold(0, i8::checked_add), None); + assert_eq!(iter.next_back(), Some(24)); + + let mut iter = (2..20).take(3); + assert_eq!(iter.try_for_each(Err), Err(2)); + assert_eq!(iter.try_for_each(Err), Err(3)); + assert_eq!(iter.try_for_each(Err), Err(4)); + assert_eq!(iter.try_for_each(Err), Ok(())); + + let mut iter = (2..20).take(3).rev(); + assert_eq!(iter.try_for_each(Err), Err(4)); + assert_eq!(iter.try_for_each(Err), Err(3)); + assert_eq!(iter.try_for_each(Err), Err(2)); + assert_eq!(iter.try_for_each(Err), Ok(())); } #[test] From 3b15b1664e2856a2a7cf430676355c82f2aac65b Mon Sep 17 00:00:00 2001 From: Jason Shin Date: Thu, 1 Aug 2019 12:42:52 +1000 Subject: [PATCH 02/21] Explaining the reason why validation is performed in to_str of path.rs --- src/libstd/path.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 126bc3754dabc..21c4968bfbe8b 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1819,6 +1819,8 @@ impl Path { /// Yields a [`&str`] slice if the `Path` is valid unicode. /// /// This conversion may entail doing a check for UTF-8 validity. + /// Also it it worthwhile noting that validation is performed because Non-UTF-8 strings are + /// perfectly valid for some OS. /// /// [`&str`]: ../primitive.str.html /// From 1aa4a578276b2a3f7c47dcea7ad75786982550d4 Mon Sep 17 00:00:00 2001 From: Jason Shin Date: Thu, 1 Aug 2019 13:55:01 +1000 Subject: [PATCH 03/21] Update src/libstd/path.rs to shorten the explanation for .to_str validation step Co-Authored-By: Mazdak Farrokhzad --- src/libstd/path.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 21c4968bfbe8b..56fde77daac58 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1819,7 +1819,7 @@ impl Path { /// Yields a [`&str`] slice if the `Path` is valid unicode. /// /// This conversion may entail doing a check for UTF-8 validity. - /// Also it it worthwhile noting that validation is performed because Non-UTF-8 strings are + /// Note that validation is performed because non-UTF-8 strings are /// perfectly valid for some OS. /// /// [`&str`]: ../primitive.str.html From 0d1584507ba540becb6fc78dfc2d1f8d1fc60cc1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 4 Aug 2019 14:12:11 +0200 Subject: [PATCH 04/21] fix UB in a test --- src/libcore/tests/ptr.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs index 569b3197d09bd..df5f4faa60e67 100644 --- a/src/libcore/tests/ptr.rs +++ b/src/libcore/tests/ptr.rs @@ -145,7 +145,6 @@ fn test_as_ref() { } #[test] -#[cfg(not(miri))] // This test is UB according to Stacked Borrows fn test_as_mut() { unsafe { let p: *mut isize = null_mut(); @@ -164,7 +163,7 @@ fn test_as_mut() { // Pointers to unsized types -- slices let s: &mut [u8] = &mut [1, 2, 3]; let ms: *mut [u8] = s; - assert_eq!(ms.as_mut(), Some(s)); + assert_eq!(ms.as_mut().unwrap() as *mut _, s as *mut _); let mz: *mut [u8] = &mut []; assert_eq!(mz.as_mut(), Some(&mut [][..])); From 95f29aa81bb0839f7cdedf267ac2a711d3301aae Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 4 Aug 2019 19:52:43 +0300 Subject: [PATCH 05/21] Revert "Rollup merge of #62696 - chocol4te:fix_#62194, r=estebank" This reverts commit df21a6f040a7011d509769a61ac7af9502636b33, reversing changes made to cc16d0486933e02237190366de2eb43df2215c11. --- src/librustc/traits/specialize/mod.rs | 9 ++------- .../ui/coherence/coherence-overlap-upstream.old.stderr | 2 ++ .../ui/coherence/coherence-overlap-upstream.re.stderr | 2 ++ ...nce_copy_like_err_fundamental_struct_tuple.old.stderr | 2 ++ ...ence_copy_like_err_fundamental_struct_tuple.re.stderr | 2 ++ .../coherence/coherence_copy_like_err_struct.old.stderr | 2 ++ .../coherence/coherence_copy_like_err_struct.re.stderr | 2 ++ .../coherence/coherence_copy_like_err_tuple.old.stderr | 2 ++ .../ui/coherence/coherence_copy_like_err_tuple.re.stderr | 2 ++ src/test/ui/issues/issue-48728.stderr | 2 ++ src/test/ui/specialization/issue-52050.stderr | 2 ++ 11 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 8a84fca143809..f0389bb037ac5 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -366,13 +366,8 @@ pub(super) fn specialization_graph_provider( } } - let access_levels = tcx.privacy_access_levels(impl_def_id.krate); - if let Some(id) = tcx.hir().as_local_hir_id(impl_def_id) { - if access_levels.is_exported(id) || access_levels.is_public(id) { - for cause in &overlap.intercrate_ambiguity_causes { - cause.add_intercrate_ambiguity_hint(&mut err); - } - } + for cause in &overlap.intercrate_ambiguity_causes { + cause.add_intercrate_ambiguity_hint(&mut err); } if overlap.involves_placeholder { diff --git a/src/test/ui/coherence/coherence-overlap-upstream.old.stderr b/src/test/ui/coherence/coherence-overlap-upstream.old.stderr index dea948ff8abbb..6c3484c2d8c4d 100644 --- a/src/test/ui/coherence/coherence-overlap-upstream.old.stderr +++ b/src/test/ui/coherence/coherence-overlap-upstream.old.stderr @@ -5,6 +5,8 @@ LL | impl Foo for T where T: Remote {} | --------------------------------- first implementation here LL | impl Foo for i16 {} | ^^^^^^^^^^^^^^^^ conflicting implementation for `i16` + | + = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-overlap-upstream.re.stderr b/src/test/ui/coherence/coherence-overlap-upstream.re.stderr index dea948ff8abbb..6c3484c2d8c4d 100644 --- a/src/test/ui/coherence/coherence-overlap-upstream.re.stderr +++ b/src/test/ui/coherence/coherence-overlap-upstream.re.stderr @@ -5,6 +5,8 @@ LL | impl Foo for T where T: Remote {} | --------------------------------- first implementation here LL | impl Foo for i16 {} | ^^^^^^^^^^^^^^^^ conflicting implementation for `i16` + | + = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr index 0ec4f0bb8e74d..12c7a1f977c3f 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr @@ -6,6 +6,8 @@ LL | impl MyTrait for T { } ... LL | impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyFundamentalStruct<(MyType,)>` + | + = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr index 0ec4f0bb8e74d..12c7a1f977c3f 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr @@ -6,6 +6,8 @@ LL | impl MyTrait for T { } ... LL | impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyFundamentalStruct<(MyType,)>` + | + = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr index e5862fdda7c58..1b6c62e9bf3a8 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr @@ -6,6 +6,8 @@ LL | impl MyTrait for T { } ... LL | impl MyTrait for lib::MyStruct { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyStruct` + | + = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyStruct` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr index e5862fdda7c58..1b6c62e9bf3a8 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr @@ -6,6 +6,8 @@ LL | impl MyTrait for T { } ... LL | impl MyTrait for lib::MyStruct { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyStruct` + | + = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyStruct` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr index a3c4ef8e105a2..11bd788c76153 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr @@ -6,6 +6,8 @@ LL | impl MyTrait for T { } ... LL | impl MyTrait for (MyType,) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(MyType,)` + | + = note: upstream crates may add new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr index a3c4ef8e105a2..11bd788c76153 100644 --- a/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr +++ b/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr @@ -6,6 +6,8 @@ LL | impl MyTrait for T { } ... LL | impl MyTrait for (MyType,) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(MyType,)` + | + = note: upstream crates may add new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions error: aborting due to previous error diff --git a/src/test/ui/issues/issue-48728.stderr b/src/test/ui/issues/issue-48728.stderr index 777e1fc9c27ea..99a9bf9903e25 100644 --- a/src/test/ui/issues/issue-48728.stderr +++ b/src/test/ui/issues/issue-48728.stderr @@ -6,6 +6,8 @@ LL | #[derive(Clone)] ... LL | impl Clone for Node<[T]> { | ------------------------------------------- first implementation here + | + = note: upstream crates may add new impl of trait `std::clone::Clone` for type `[_]` in future versions error: aborting due to previous error diff --git a/src/test/ui/specialization/issue-52050.stderr b/src/test/ui/specialization/issue-52050.stderr index 583c580d341ba..dcb34f3ad4836 100644 --- a/src/test/ui/specialization/issue-52050.stderr +++ b/src/test/ui/specialization/issue-52050.stderr @@ -10,6 +10,8 @@ LL | | } LL | LL | impl IntoPyDictPointer for () | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: upstream crates may add new impl of trait `std::iter::Iterator` for type `()` in future versions error: aborting due to previous error From 4e51ef7ccd9729b1f9074a44ef49778a3c53c3d4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Aug 2019 11:21:15 +0200 Subject: [PATCH 06/21] Test content, not value Co-Authored-By: Aleksey Kladov --- src/libcore/tests/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs index df5f4faa60e67..d5a079da989e2 100644 --- a/src/libcore/tests/ptr.rs +++ b/src/libcore/tests/ptr.rs @@ -163,7 +163,7 @@ fn test_as_mut() { // Pointers to unsized types -- slices let s: &mut [u8] = &mut [1, 2, 3]; let ms: *mut [u8] = s; - assert_eq!(ms.as_mut().unwrap() as *mut _, s as *mut _); + assert_eq!(ms.as_mut(), Some(&mut [1, 2, 3])); let mz: *mut [u8] = &mut []; assert_eq!(mz.as_mut(), Some(&mut [][..])); From b5e35b128efeed4bfdb4b1ee9d0697389ec9f164 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 30 Jul 2019 12:33:32 +0300 Subject: [PATCH 07/21] remove special code path for unknown tokens --- src/libsyntax/parse/lexer/mod.rs | 73 ++++--------------- src/test/ui/parser/lex-bad-token.rs | 2 + src/test/ui/parser/lex-stray-backslash.rs | 2 + src/test/ui/parser/unicode-quote-chars.rs | 3 + src/test/ui/parser/unicode-quote-chars.stderr | 18 ++++- 5 files changed, 37 insertions(+), 61 deletions(-) diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 950b1b2ff5340..c209ae1cb9f1f 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -3,7 +3,7 @@ use crate::parse::token::{self, Token, TokenKind}; use crate::symbol::{sym, Symbol}; use crate::parse::unescape_error_reporting::{emit_unescape_error, push_escaped_char}; -use errors::{FatalError, Diagnostic, DiagnosticBuilder}; +use errors::{FatalError, DiagnosticBuilder}; use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION}; use rustc_lexer::Base; use rustc_lexer::unescape; @@ -39,7 +39,6 @@ pub struct StringReader<'a> { pos: BytePos, /// Stop reading src at this index. end_src_index: usize, - fatal_errs: Vec>, /// Source text to tokenize. src: Lrc, override_span: Option, @@ -62,7 +61,6 @@ impl<'a> StringReader<'a> { pos: source_file.start_pos, end_src_index: src.len(), src, - fatal_errs: Vec::new(), override_span, } } @@ -89,29 +87,17 @@ impl<'a> StringReader<'a> { self.override_span.unwrap_or_else(|| Span::new(lo, hi, NO_EXPANSION)) } - fn unwrap_or_abort(&mut self, res: Result) -> Token { - match res { - Ok(tok) => tok, - Err(_) => { - self.emit_fatal_errors(); - FatalError.raise(); - } - } - } - /// Returns the next token, including trivia like whitespace or comments. /// /// `Err(())` means that some errors were encountered, which can be /// retrieved using `buffer_fatal_errors`. - pub fn try_next_token(&mut self) -> Result { - assert!(self.fatal_errs.is_empty()); - + pub fn next_token(&mut self) -> Token { let start_src_index = self.src_index(self.pos); let text: &str = &self.src[start_src_index..self.end_src_index]; if text.is_empty() { let span = self.mk_sp(self.pos, self.pos); - return Ok(Token::new(token::Eof, span)); + return Token::new(token::Eof, span); } { @@ -125,7 +111,7 @@ impl<'a> StringReader<'a> { let kind = token::Shebang(sym); let span = self.mk_sp(start, self.pos); - return Ok(Token::new(kind, span)); + return Token::new(kind, span); } } } @@ -139,39 +125,10 @@ impl<'a> StringReader<'a> { // This could use `?`, but that makes code significantly (10-20%) slower. // https://github.com/rust-lang/rust/issues/37939 - let kind = match self.cook_lexer_token(token.kind, start) { - Ok(it) => it, - Err(err) => return Err(self.fatal_errs.push(err)), - }; + let kind = self.cook_lexer_token(token.kind, start); let span = self.mk_sp(start, self.pos); - Ok(Token::new(kind, span)) - } - - /// Returns the next token, including trivia like whitespace or comments. - /// - /// Aborts in case of an error. - pub fn next_token(&mut self) -> Token { - let res = self.try_next_token(); - self.unwrap_or_abort(res) - } - - fn emit_fatal_errors(&mut self) { - for err in &mut self.fatal_errs { - err.emit(); - } - - self.fatal_errs.clear(); - } - - pub fn buffer_fatal_errors(&mut self) -> Vec { - let mut buffer = Vec::new(); - - for err in self.fatal_errs.drain(..) { - err.buffer(&mut buffer); - } - - buffer + Token::new(kind, span) } /// Report a fatal lexical error with a given span. @@ -218,8 +175,8 @@ impl<'a> StringReader<'a> { &self, token: rustc_lexer::TokenKind, start: BytePos, - ) -> Result> { - let kind = match token { + ) -> TokenKind { + match token { rustc_lexer::TokenKind::LineComment => { let string = self.str_from(start); // comments with only more "/"s are not doc comments @@ -396,16 +353,12 @@ impl<'a> StringReader<'a> { // this should be inside `rustc_lexer`. However, we should first remove compound // tokens like `<<` from `rustc_lexer`, and then add fancier error recovery to it, // as there will be less overall work to do this way. - return match unicode_chars::check_for_substitution(self, start, c, &mut err) { - Some(token) => { - err.emit(); - Ok(token) - } - None => Err(err), - } + let token = unicode_chars::check_for_substitution(self, start, c, &mut err) + .unwrap_or(token::Whitespace); + err.emit(); + token } - }; - Ok(kind) + } } fn cook_lexer_literal( diff --git a/src/test/ui/parser/lex-bad-token.rs b/src/test/ui/parser/lex-bad-token.rs index feb670c3d3dd0..9e4824611128d 100644 --- a/src/test/ui/parser/lex-bad-token.rs +++ b/src/test/ui/parser/lex-bad-token.rs @@ -1 +1,3 @@ ● //~ ERROR: unknown start of token + +fn main() {} diff --git a/src/test/ui/parser/lex-stray-backslash.rs b/src/test/ui/parser/lex-stray-backslash.rs index 90d359231a6e7..bb27f44c279f7 100644 --- a/src/test/ui/parser/lex-stray-backslash.rs +++ b/src/test/ui/parser/lex-stray-backslash.rs @@ -1 +1,3 @@ \ //~ ERROR: unknown start of token: \ + +fn main() {} diff --git a/src/test/ui/parser/unicode-quote-chars.rs b/src/test/ui/parser/unicode-quote-chars.rs index 69644211b8a11..1812dad81afc3 100644 --- a/src/test/ui/parser/unicode-quote-chars.rs +++ b/src/test/ui/parser/unicode-quote-chars.rs @@ -4,4 +4,7 @@ fn main() { println!(“hello world”); //~^ ERROR unknown start of token: \u{201c} //~^^ HELP Unicode characters '“' (Left Double Quotation Mark) and '”' (Right Double Quotation Mark) look like '"' (Quotation Mark), but are not + //~^^^ ERROR unknown start of token: \u{201d} + //~^^^^ HELP Unicode character '”' (Right Double Quotation Mark) looks like '"' (Quotation Mark), but it is not + //~^^^^^ ERROR expected token: `,` } diff --git a/src/test/ui/parser/unicode-quote-chars.stderr b/src/test/ui/parser/unicode-quote-chars.stderr index 4a09ed75605e4..84e45ecd873a4 100644 --- a/src/test/ui/parser/unicode-quote-chars.stderr +++ b/src/test/ui/parser/unicode-quote-chars.stderr @@ -8,5 +8,21 @@ help: Unicode characters '“' (Left Double Quotation Mark) and '”' (Right Dou LL | println!("hello world"); | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: unknown start of token: \u{201d} + --> $DIR/unicode-quote-chars.rs:4:26 + | +LL | println!(“hello world”); + | ^ +help: Unicode character '”' (Right Double Quotation Mark) looks like '"' (Quotation Mark), but it is not + | +LL | println!(“hello world"); + | ^ + +error: expected token: `,` + --> $DIR/unicode-quote-chars.rs:4:21 + | +LL | println!(“hello world”); + | ^^^^^ expected `,` + +error: aborting due to 3 previous errors From 58ac81a60fe11868b0748a406d8e0b97efa4e8c5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 30 Jul 2019 12:31:41 +0300 Subject: [PATCH 08/21] add unknown token --- src/librustc/ich/impls_syntax.rs | 3 ++- src/librustdoc/html/highlight.rs | 2 +- src/libsyntax/ext/proc_macro_server.rs | 2 +- src/libsyntax/parse/lexer/mod.rs | 2 +- src/libsyntax/parse/lexer/tokentrees.rs | 2 +- src/libsyntax/parse/token.rs | 4 +++- src/libsyntax/print/pprust.rs | 1 + 7 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 0c9c9adcf9da6..5cc8324b31606 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -363,7 +363,8 @@ impl<'a> HashStable> for token::TokenKind { } token::DocComment(val) | - token::Shebang(val) => val.hash_stable(hcx, hasher), + token::Shebang(val) | + token::Unknown(val) => val.hash_stable(hcx, hasher), } } } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 8132074d6e0e7..92d85ef9cacc5 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -237,7 +237,7 @@ impl<'a> Classifier<'a> { return Ok(()); }, - token::Whitespace => Class::None, + token::Whitespace | token::Unknown(..) => Class::None, token::Comment => Class::Comment, token::DocComment(..) => Class::DocComment, diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs index 8d0023c9ab1eb..36621ce777510 100644 --- a/src/libsyntax/ext/proc_macro_server.rs +++ b/src/libsyntax/ext/proc_macro_server.rs @@ -184,7 +184,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec)> } OpenDelim(..) | CloseDelim(..) => unreachable!(), - Whitespace | Comment | Shebang(..) | Eof => unreachable!(), + Whitespace | Comment | Shebang(..) | Unknown(..) | Eof => unreachable!(), } } } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index c209ae1cb9f1f..e86d4c7fde683 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -354,7 +354,7 @@ impl<'a> StringReader<'a> { // tokens like `<<` from `rustc_lexer`, and then add fancier error recovery to it, // as there will be less overall work to do this way. let token = unicode_chars::check_for_substitution(self, start, c, &mut err) - .unwrap_or(token::Whitespace); + .unwrap_or_else(|| token::Unknown(self.symbol_from(start))); err.emit(); token } diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index 830fbec58ded9..37e67a2729e6d 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -217,7 +217,7 @@ impl<'a> TokenTreesReader<'a> { loop { let token = self.string_reader.next_token(); match token.kind { - token::Whitespace | token::Comment | token::Shebang(_) => { + token::Whitespace | token::Comment | token::Shebang(_) | token::Unknown(_) => { self.joint_to_prev = NonJoint; } _ => { diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 73adb5c947c0b..be800b4de66af 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -255,6 +255,8 @@ pub enum TokenKind { /// A comment. Comment, Shebang(ast::Name), + /// A completely invalid token which should be skipped. + Unknown(ast::Name), Eof, } @@ -603,7 +605,7 @@ impl Token { DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) | - Whitespace | Comment | Shebang(..) | Eof => return None, + Whitespace | Comment | Shebang(..) | Unknown(..) | Eof => return None, }; Some(Token::new(kind, self.span.to(joint.span))) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 2ef8a919b9c56..378ba1e4107a4 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -288,6 +288,7 @@ fn token_kind_to_string_ext(tok: &TokenKind, convert_dollar_crate: Option) token::Whitespace => " ".to_string(), token::Comment => "/* */".to_string(), token::Shebang(s) => format!("/* shebang: {}*/", s), + token::Unknown(s) => s.to_string(), token::Interpolated(ref nt) => nonterminal_to_string(nt), } From b3e8c8bbe27e21a2e67039d9fb9ea41cb83b1499 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 30 Jul 2019 13:45:08 +0300 Subject: [PATCH 09/21] adapt rustdoc to infailable lexer --- src/librustdoc/html/highlight.rs | 27 +-- .../passes/check_code_block_syntax.rs | 32 +--- src/test/rustdoc-ui/invalid-syntax.stderr | 168 ++++++++++++++++-- 3 files changed, 177 insertions(+), 50 deletions(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 92d85ef9cacc5..5d86ee9721b75 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -44,7 +44,7 @@ pub fn render_with_highlighting( let mut highlighted_source = vec![]; if classifier.write_source(&mut highlighted_source).is_err() { - Err(classifier.lexer.buffer_fatal_errors()) + Err(()) } else { Ok(String::from_utf8_lossy(&highlighted_source).into_owned()) } @@ -59,14 +59,9 @@ pub fn render_with_highlighting( } write_footer(&mut out).unwrap(); } - Err(errors) => { - // If errors are encountered while trying to highlight, cancel the errors and just emit - // the unhighlighted source. The errors will have already been reported in the - // `check-code-block-syntax` pass. - for mut error in errors { - error.cancel(); - } - + Err(()) => { + // If errors are encountered while trying to highlight, just emit + // the unhighlighted source. write!(out, "
{}
", src).unwrap(); } } @@ -192,14 +187,20 @@ impl<'a> Classifier<'a> { if let Some(token) = self.peek_token.take() { return Ok(token); } - self.lexer.try_next_token().map_err(|()| HighlightError::LexError) + let token = self.lexer.next_token(); + if let token::Unknown(..) = &token.kind { + return Err(HighlightError::LexError); + } + Ok(token) } fn peek(&mut self) -> Result<&Token, HighlightError> { if self.peek_token.is_none() { - self.peek_token = Some( - self.lexer.try_next_token().map_err(|()| HighlightError::LexError)? - ); + let token = self.lexer.next_token(); + if let token::Unknown(..) = &token.kind { + return Err(HighlightError::LexError); + } + self.peek_token = Some(token); } Ok(self.peek_token.as_ref().unwrap()) } diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 0488153e7cb73..357e17d2d1bc4 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -32,24 +32,20 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { dox[code_block.code].to_owned(), ); - let errors = { + let has_errors = { + let mut has_errors = false; let mut lexer = Lexer::new(&sess, source_file, None); - while let Ok(token::Token { kind, .. }) = lexer.try_next_token() { - if kind == token::Eof { - break; + loop { + match lexer.next_token().kind { + token::Eof => break, + token::Unknown(..) => has_errors = true, + _ => (), } } - - let errors = lexer.buffer_fatal_errors(); - - if !errors.is_empty() { - Err(errors) - } else { - Ok(()) - } + has_errors }; - if let Err(errors) = errors { + if has_errors { let mut diag = if let Some(sp) = super::source_span_for_markdown_range(self.cx, &dox, &code_block.range, &item.attrs) { @@ -58,11 +54,6 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { .sess() .struct_span_warn(sp, "could not parse code block as Rust code"); - for mut err in errors { - diag.note(&format!("error from rustc: {}", err.message())); - err.cancel(); - } - if code_block.syntax.is_none() && code_block.is_fenced { let sp = sp.from_inner(InnerSpan::new(0, 3)); diag.span_suggestion( @@ -82,11 +73,6 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { "doc comment contains an invalid Rust code block", ); - for mut err in errors { - // Don't bother reporting the error, because we can't show where it happened. - err.cancel(); - } - if code_block.syntax.is_none() && code_block.is_fenced { diag.help("mark blocks that do not contain Rust code as text: ```text"); } diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr index b4ed747b44c81..3bebbecb9dfcf 100644 --- a/src/test/rustdoc-ui/invalid-syntax.stderr +++ b/src/test/rustdoc-ui/invalid-syntax.stderr @@ -1,3 +1,21 @@ +error: unknown start of token: \ + --> :1:1 + | +1 | \__________pkt->size___________/ \_result->size_/ \__pkt->size__/ + | ^ + +error: unknown start of token: \ + --> :1:43 + | +1 | \__________pkt->size___________/ \_result->size_/ \__pkt->size__/ + | ^ + +error: unknown start of token: \ + --> :1:60 + | +1 | \__________pkt->size___________/ \_result->size_/ \__pkt->size__/ + | ^ + warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:3:5 | @@ -6,13 +24,31 @@ LL | /// ``` LL | | /// \__________pkt->size___________/ \_result->size_/ \__pkt->size__/ LL | | /// ``` | |_______^ - | - = note: error from rustc: unknown start of token: \ help: mark blocks that do not contain Rust code as text | LL | /// ```text | ^^^^^^^ +error: unknown start of token: ` + --> :3:30 + | +3 | | ^^^^^^ did you mean `baz::foobar`? + | ^ +help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not + | +3 | | ^^^^^^ did you mean 'baz::foobar`? + | ^ + +error: unknown start of token: ` + --> :3:42 + | +3 | | ^^^^^^ did you mean `baz::foobar`? + | ^ +help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not + | +3 | | ^^^^^^ did you mean `baz::foobar'? + | ^ + warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:8:5 | @@ -23,13 +59,17 @@ LL | | /// LL | use foobar::Baz; LL | | /// | ^^^^^^ did you mean `baz::foobar`? LL | | /// ``` | |_______^ - | - = note: error from rustc: unknown start of token: ` help: mark blocks that do not contain Rust code as text | LL | /// ```text | ^^^^^^^ +error: unknown start of token: \ + --> :1:1 + | +1 | \_ + | ^ + warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:19:5 | @@ -38,13 +78,17 @@ LL | /// ``` LL | | /// \_ LL | | /// ``` | |_______^ - | - = note: error from rustc: unknown start of token: \ help: mark blocks that do not contain Rust code as text | LL | /// ```text | ^^^^^^^ +error: unknown start of token: \ + --> :1:1 + | +1 | \_ + | ^ + warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:32:5 | @@ -53,8 +97,12 @@ LL | /// ```rust LL | | /// \_ LL | | /// ``` | |_______^ - | - = note: error from rustc: unknown start of token: \ + +error: unknown start of token: \ + --> :2:5 + | +2 | \_ + | ^ warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:41:9 @@ -63,16 +111,48 @@ LL | /// code with bad syntax | _________^ LL | | /// \_ | |__________^ - | - = note: error from rustc: unknown start of token: \ + +error: unknown start of token: ` + --> :1:1 + | +1 | ``` + | ^ +help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not + | +1 | '`` + | ^ + +error: unknown start of token: ` + --> :1:2 + | +1 | ``` + | ^ +help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not + | +1 | `'` + | ^ + +error: unknown start of token: ` + --> :1:3 + | +1 | ``` + | ^ +help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not + | +1 | ``' + | ^ warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:55:9 | LL | /// ``` | ^^^ - | - = note: error from rustc: unknown start of token: ` + +error: unknown start of token: \ + --> :1:1 + | +1 | \_ + | ^ warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:58:5 @@ -82,8 +162,12 @@ LL | /// ```edition2018 LL | | /// \_ LL | | /// ``` | |_______^ - | - = note: error from rustc: unknown start of token: \ + +error: unknown start of token: \ + --> :1:1 + | +1 | \_ + | ^ warning: doc comment contains an invalid Rust code block --> $DIR/invalid-syntax.rs:63:1 @@ -95,3 +179,59 @@ LL | | #[doc = "```"] | = help: mark blocks that do not contain Rust code as text: ```text +error: unknown start of token: \ + --> :1:1 + | +1 | \_ + | ^ + +error: unknown start of token: \ + --> :1:1 + | +1 | \_ + | ^ + +error: unknown start of token: ` + --> :1:1 + | +1 | ``` + | ^ +help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not + | +1 | '`` + | ^ + +error: unknown start of token: \ + --> :2:1 + | +2 | \_ + | ^ + +error: unknown start of token: \ + --> :1:1 + | +1 | \_ + | ^ + +error: unknown start of token: \ + --> :1:1 + | +1 | \_ + | ^ + +error: unknown start of token: ` + --> :3:30 + | +3 | | ^^^^^^ did you mean `baz::foobar`? + | ^ +help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not + | +3 | | ^^^^^^ did you mean 'baz::foobar`? + | ^ + +error: unknown start of token: \ + --> :1:1 + | +1 | \__________pkt->size___________/ \_result->size_/ \__pkt->size__/ + | ^ + From ab3fb1e775ff20f80096953080dfc650950041b0 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 4 Aug 2019 17:59:06 -0400 Subject: [PATCH 10/21] Drop span argument from mk_list_item --- src/librustc/hir/lowering.rs | 7 +++---- src/libsyntax/attr/mod.rs | 4 ++-- src/libsyntax/ext/build.rs | 2 +- src/libsyntax/ext/expand.rs | 4 ++-- src/libsyntax/print/pprust.rs | 5 ++--- src/libsyntax_ext/test_harness.rs | 3 +-- 6 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5031e6dbd87d2..493083c680aad 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -5176,11 +5176,10 @@ impl<'a> LoweringContext<'a> { let attr = { // `allow(unreachable_code)` let allow = { - let allow_ident = Ident::with_empty_ctxt(sym::allow).with_span_pos(e.span); - let uc_ident = Ident::with_empty_ctxt(sym::unreachable_code) - .with_span_pos(e.span); + let allow_ident = Ident::new(sym::allow, e.span); + let uc_ident = Ident::new(sym::unreachable_code, e.span); let uc_nested = attr::mk_nested_word_item(uc_ident); - attr::mk_list_item(e.span, allow_ident, vec![uc_nested]) + attr::mk_list_item(allow_ident, vec![uc_nested]) }; attr::mk_attr_outer(allow) }; diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 3e56136b17108..7eea1aad8eadf 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -355,8 +355,8 @@ pub fn mk_name_value_item(span: Span, ident: Ident, lit_kind: LitKind, lit_span: MetaItem { path: Path::from_ident(ident), span, node: MetaItemKind::NameValue(lit) } } -pub fn mk_list_item(span: Span, ident: Ident, items: Vec) -> MetaItem { - MetaItem { path: Path::from_ident(ident), span, node: MetaItemKind::List(items) } +pub fn mk_list_item(ident: Ident, items: Vec) -> MetaItem { + MetaItem { path: Path::from_ident(ident), span: ident.span, node: MetaItemKind::List(items) } } pub fn mk_word_item(ident: Ident) -> MetaItem { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 59e13fdc8f163..83d9521685096 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -879,7 +879,7 @@ impl<'a> ExtCtxt<'a> { pub fn meta_list(&self, sp: Span, name: ast::Name, mis: Vec) -> ast::MetaItem { - attr::mk_list_item(sp, Ident::new(name, sp), mis) + attr::mk_list_item(Ident::new(name, sp), mis) } pub fn meta_name_value(&self, span: Span, name: ast::Name, lit_kind: ast::LitKind) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d2807e4a4b5fa..964c81dd46641 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1272,7 +1272,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { ]; let include_ident = Ident::with_empty_ctxt(sym::include); - let item = attr::mk_list_item(DUMMY_SP, include_ident, include_info); + let item = attr::mk_list_item(include_ident, include_info); items.push(ast::NestedMetaItem::MetaItem(item)); } Err(e) => { @@ -1333,7 +1333,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } } - let meta = attr::mk_list_item(DUMMY_SP, Ident::with_empty_ctxt(sym::doc), items); + let meta = attr::mk_list_item(Ident::with_empty_ctxt(sym::doc), items); *at = attr::Attribute { span: at.span, id: at.id, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 2ef8a919b9c56..803426877335e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -15,7 +15,7 @@ use crate::tokenstream::{self, TokenStream, TokenTree}; use rustc_target::spec::abi::{self, Abi}; use syntax_pos::{self, BytePos}; -use syntax_pos::{DUMMY_SP, FileName, Span}; +use syntax_pos::{FileName, Span}; use std::borrow::Cow; @@ -124,8 +124,7 @@ pub fn print_crate<'a>(cm: &'a SourceMap, // #![feature(prelude_import)] let pi_nested = attr::mk_nested_word_item(ast::Ident::with_empty_ctxt(sym::prelude_import)); - let list = attr::mk_list_item( - DUMMY_SP, ast::Ident::with_empty_ctxt(sym::feature), vec![pi_nested]); + let list = attr::mk_list_item(ast::Ident::with_empty_ctxt(sym::feature), vec![pi_nested]); let fake_attr = attr::mk_attr_inner(list); s.print_attribute(&fake_attr); diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs index 4b3903c7ad7d3..eec8a3f802343 100644 --- a/src/libsyntax_ext/test_harness.rs +++ b/src/libsyntax_ext/test_harness.rs @@ -157,8 +157,7 @@ impl MutVisitor for EntryPointCleaner { item.map(|ast::Item {id, ident, attrs, node, vis, span, tokens}| { let allow_ident = Ident::with_empty_ctxt(sym::allow); let dc_nested = attr::mk_nested_word_item(Ident::from_str("dead_code")); - let allow_dead_code_item = attr::mk_list_item(DUMMY_SP, allow_ident, - vec![dc_nested]); + let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]); let allow_dead_code = attr::mk_attr_outer(allow_dead_code_item); ast::Item { From 24a491f40c891e06dce930081d5e5228232f7a18 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 4 Aug 2019 18:03:34 -0400 Subject: [PATCH 11/21] Drop explicit span argument from mk_name_value_item --- src/librustdoc/clean/cfg/tests.rs | 1 - src/libsyntax/attr/mod.rs | 5 +++-- src/libsyntax/ext/build.rs | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs index d0df9f8f7e410..405144b444f09 100644 --- a/src/librustdoc/clean/cfg/tests.rs +++ b/src/librustdoc/clean/cfg/tests.rs @@ -211,7 +211,6 @@ fn test_parse_ok() { fn test_parse_err() { with_default_globals(|| { let mi = attr::mk_name_value_item( - DUMMY_SP, Ident::from_str("foo"), LitKind::Bool(false), DUMMY_SP, diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 7eea1aad8eadf..28391aa0dec80 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -347,11 +347,12 @@ impl Attribute { pub fn mk_name_value_item_str(ident: Ident, value: Spanned) -> MetaItem { let lit_kind = LitKind::Str(value.node, ast::StrStyle::Cooked); - mk_name_value_item(ident.span.to(value.span), ident, lit_kind, value.span) + mk_name_value_item(ident, lit_kind, value.span) } -pub fn mk_name_value_item(span: Span, ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem { +pub fn mk_name_value_item(ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem { let lit = Lit::from_lit_kind(lit_kind, lit_span); + let span = ident.span.to(lit_span); MetaItem { path: Path::from_ident(ident), span, node: MetaItemKind::NameValue(lit) } } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 83d9521685096..db562840e8d3b 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -884,8 +884,7 @@ impl<'a> ExtCtxt<'a> { pub fn meta_name_value(&self, span: Span, name: ast::Name, lit_kind: ast::LitKind) -> ast::MetaItem { - attr::mk_name_value_item(span, Ident::new(name, span), - lit_kind, span) + attr::mk_name_value_item(Ident::new(name, span), lit_kind, span) } pub fn item_use(&self, sp: Span, From 88491497456e485b0171d6791bd81f52170fbc09 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 4 Aug 2019 19:35:29 -0400 Subject: [PATCH 12/21] Make mk_attr_id private to libsyntax --- src/libsyntax/attr/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 28391aa0dec80..a9d3227b3a8f4 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -368,7 +368,7 @@ pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem { NestedMetaItem::MetaItem(mk_word_item(ident)) } -pub fn mk_attr_id() -> AttrId { +crate fn mk_attr_id() -> AttrId { use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; From fbf93d4931ac9878943cb644d9c1b993b1d20a80 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 5 Aug 2019 09:14:51 -0400 Subject: [PATCH 13/21] Remove leftover AwaitOrigin This was missed in PR #62293. --- src/libsyntax/ast.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 849e77c4f3112..052eb55b40811 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1284,15 +1284,6 @@ pub enum Movability { Movable, } -/// Whether an `await` comes from `await!` or `.await` syntax. -/// FIXME: this should be removed when support for legacy `await!` is removed. -/// https://github.com/rust-lang/rust/issues/60610 -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] -pub enum AwaitOrigin { - FieldLike, - MacroLike, -} - pub type Mac = Spanned; /// Represents a macro invocation. The `Path` indicates which macro From 90b95cf53f68888812cd5683cf44161e070e7dbd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Aug 2019 15:30:08 +0200 Subject: [PATCH 14/21] fix slice comparison Co-Authored-By: Aleksey Kladov --- src/libcore/tests/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs index d5a079da989e2..1a6be3a9bbd03 100644 --- a/src/libcore/tests/ptr.rs +++ b/src/libcore/tests/ptr.rs @@ -163,7 +163,7 @@ fn test_as_mut() { // Pointers to unsized types -- slices let s: &mut [u8] = &mut [1, 2, 3]; let ms: *mut [u8] = s; - assert_eq!(ms.as_mut(), Some(&mut [1, 2, 3])); + assert_eq!(ms.as_mut(), Some(&mut [1, 2, 3][..])); let mz: *mut [u8] = &mut []; assert_eq!(mz.as_mut(), Some(&mut [][..])); From 288b4e90780d827b0bca2b63b25b4a3056986111 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 5 Aug 2019 10:28:23 -0400 Subject: [PATCH 15/21] Don't store &Span This is just needless indirection. --- src/librustc_mir/interpret/snapshot.rs | 4 ++-- src/librustc_resolve/lib.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs index 70a297c866280..fad9fafbb0803 100644 --- a/src/librustc_mir/interpret/snapshot.rs +++ b/src/librustc_mir/interpret/snapshot.rs @@ -305,7 +305,7 @@ impl_stable_hash_for!(enum crate::interpret::eval_context::StackPopCleanup { #[derive(Eq, PartialEq)] struct FrameSnapshot<'a, 'tcx> { instance: &'a ty::Instance<'tcx>, - span: &'a Span, + span: Span, return_to_block: &'a StackPopCleanup, return_place: Option>>, locals: IndexVec>>, @@ -345,7 +345,7 @@ impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx> FrameSnapshot { instance, - span, + span: *span, return_to_block, block, stmt: *stmt, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 1a203e73f0a86..1908d85e4ff2a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -171,7 +171,7 @@ enum ResolutionError<'a> { GenericParamsFromOuterFunction(Res), /// Error E0403: the name is already used for a type or const parameter in this generic /// parameter list. - NameAlreadyUsedInParameterList(Name, &'a Span), + NameAlreadyUsedInParameterList(Name, Span), /// Error E0407: method is not a member of trait. MethodNotMemberOfTrait(Name, &'a str), /// Error E0437: type is not a member of trait. @@ -297,7 +297,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>, parameter in this list of generic parameters", name); err.span_label(span, "already used"); - err.span_label(first_use_span.clone(), format!("first use of `{}`", name)); + err.span_label(first_use_span, format!("first use of `{}`", name)); err } ResolutionError::MethodNotMemberOfTrait(method, trait_) => { @@ -2853,7 +2853,7 @@ impl<'a> Resolver<'a> { let span = seen_bindings.get(&ident).unwrap(); let err = ResolutionError::NameAlreadyUsedInParameterList( ident.name, - span, + *span, ); resolve_error(self, param.ident.span, err); } @@ -2875,7 +2875,7 @@ impl<'a> Resolver<'a> { let span = seen_bindings.get(&ident).unwrap(); let err = ResolutionError::NameAlreadyUsedInParameterList( ident.name, - span, + *span, ); resolve_error(self, param.ident.span, err); } From 1f018636e35018bbd3f83de8da68ec50669cd646 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Aug 2019 18:38:10 +0200 Subject: [PATCH 16/21] improve align_offset docs --- src/libcore/ptr/mod.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 0ec4dd47b1ff0..fa55bbf9c1650 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -1606,10 +1606,12 @@ impl *const T { /// `align`. /// /// If it is not possible to align the pointer, the implementation returns - /// `usize::max_value()`. + /// `usize::max_value()`. It is permissible for the implementation to *always* + /// return `usize::max_value()`. Only your algorithm's performance can depend + /// on getting a usable offset here, not its correctness. /// /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be - /// used with the `add` method. + /// used with the `wrapping_add` method. /// /// There are no guarantees whatsoever that offsetting the pointer will not overflow or go /// beyond the allocation that the pointer points into. It is up to the caller to ensure that @@ -2407,10 +2409,12 @@ impl *mut T { /// `align`. /// /// If it is not possible to align the pointer, the implementation returns - /// `usize::max_value()`. + /// `usize::max_value()`. It is permissible for the implementation to *always* + /// return `usize::max_value()`. Only your algorithm's performance can depend + /// on getting a usable offset here, not its correctness. /// /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be - /// used with the `add` method. + /// used with the `wrapping_add` method. /// /// There are no guarantees whatsoever that offsetting the pointer will not overflow or go /// beyond the allocation that the pointer points into. It is up to the caller to ensure that From 30910eef367fb305615597885242045e6c9949ba Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 5 Aug 2019 20:58:07 +0200 Subject: [PATCH 17/21] Make qualify consts in_projection use PlaceRef --- src/librustc_mir/transform/qualify_consts.rs | 29 ++++++++++---------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index ffeaf4e19c22a..15f27d4e0c514 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -182,16 +182,17 @@ trait Qualif { fn in_projection_structurally( cx: &ConstCx<'_, 'tcx>, - base: &PlaceBase<'tcx>, - proj: &Projection<'tcx>, + place: PlaceRef<'_, 'tcx>, ) -> bool { + let proj = place.projection.as_ref().unwrap(); + let base_qualif = Self::in_place(cx, PlaceRef { - base, + base: place.base, projection: &proj.base, }); let qualif = base_qualif && Self::mask_for_ty( cx, - Place::ty_from(&base, &proj.base, cx.body, cx.tcx) + Place::ty_from(place.base, &proj.base, cx.body, cx.tcx) .projection_ty(cx.tcx, &proj.elem) .ty, ); @@ -208,10 +209,9 @@ trait Qualif { fn in_projection( cx: &ConstCx<'_, 'tcx>, - base: &PlaceBase<'tcx>, - proj: &Projection<'tcx>, + place: PlaceRef<'_, 'tcx>, ) -> bool { - Self::in_projection_structurally(cx, base, proj) + Self::in_projection_structurally(cx, place) } fn in_place(cx: &ConstCx<'_, 'tcx>, place: PlaceRef<'_, 'tcx>) -> bool { @@ -234,9 +234,9 @@ trait Qualif { Self::in_static(cx, static_) }, PlaceRef { - base, - projection: Some(proj), - } => Self::in_projection(cx, base, proj), + base: _, + projection: Some(_), + } => Self::in_projection(cx, place), } } @@ -448,9 +448,10 @@ impl Qualif for IsNotPromotable { fn in_projection( cx: &ConstCx<'_, 'tcx>, - base: &PlaceBase<'tcx>, - proj: &Projection<'tcx>, + place: PlaceRef<'_, 'tcx>, ) -> bool { + let proj = place.projection.as_ref().unwrap(); + match proj.elem { ProjectionElem::Deref | ProjectionElem::Downcast(..) => return true, @@ -461,7 +462,7 @@ impl Qualif for IsNotPromotable { ProjectionElem::Field(..) => { if cx.mode == Mode::NonConstFn { - let base_ty = Place::ty_from(base, &proj.base, cx.body, cx.tcx).ty; + let base_ty = Place::ty_from(place.base, &proj.base, cx.body, cx.tcx).ty; if let Some(def) = base_ty.ty_adt_def() { // No promotion of union field accesses. if def.is_union() { @@ -472,7 +473,7 @@ impl Qualif for IsNotPromotable { } } - Self::in_projection_structurally(cx, base, proj) + Self::in_projection_structurally(cx, place) } fn in_rvalue(cx: &ConstCx<'_, 'tcx>, rvalue: &Rvalue<'tcx>) -> bool { From 9058bf2100499649a285e49555e42fbe8fa3556d Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 2 Aug 2019 17:08:16 -0700 Subject: [PATCH 18/21] Make use of possibly uninitialized data a hard error This is one of the behaviors we no longer allow in NLL. Since it can lead to undefined behavior, I think it's definitely worth making it a hard error without waiting to turn off migration mode (#58781). Closes #60450. My ulterior motive here is making it impossible to leave variables partially initialized across a yield (see discussion at #63035), so tests are included for that. --- .../borrow_check/conflict_errors.rs | 3 ++ src/librustc_mir/borrow_check/mod.rs | 12 ++++- .../partial-initialization-across-await.rs | 44 ++++++++++++++++++ ...partial-initialization-across-await.stderr | 21 +++++++++ .../disallow-possibly-uninitialized.rs | 22 +++++++++ .../disallow-possibly-uninitialized.stderr | 27 +++++++++++ .../ui/consts/const_let_refutable.nll.stderr | 31 ------------- src/test/ui/consts/const_let_refutable.rs | 8 +--- src/test/ui/consts/const_let_refutable.stderr | 14 ++---- .../ui/empty/empty-never-array.nll.stderr | 23 ---------- src/test/ui/empty/empty-never-array.rs | 4 +- src/test/ui/empty/empty-never-array.stderr | 8 +--- .../partial-initialization-across-yield.rs | 46 +++++++++++++++++++ ...partial-initialization-across-yield.stderr | 21 +++++++++ src/test/ui/issues/issue-15381.nll.stderr | 16 ------- src/test/ui/issues/issue-15381.rs | 4 +- src/test/ui/issues/issue-15381.stderr | 8 +--- ...rsive-types-are-not-uninhabited.nll.stderr | 16 ------- .../recursive-types-are-not-uninhabited.rs | 4 +- ...recursive-types-are-not-uninhabited.stderr | 8 +--- 20 files changed, 209 insertions(+), 131 deletions(-) create mode 100644 src/test/ui/async-await/partial-initialization-across-await.rs create mode 100644 src/test/ui/async-await/partial-initialization-across-await.stderr create mode 100644 src/test/ui/borrowck/disallow-possibly-uninitialized.rs create mode 100644 src/test/ui/borrowck/disallow-possibly-uninitialized.stderr delete mode 100644 src/test/ui/consts/const_let_refutable.nll.stderr delete mode 100644 src/test/ui/empty/empty-never-array.nll.stderr create mode 100644 src/test/ui/generator/partial-initialization-across-yield.rs create mode 100644 src/test/ui/generator/partial-initialization-across-yield.stderr delete mode 100644 src/test/ui/issues/issue-15381.nll.stderr delete mode 100644 src/test/ui/recursion/recursive-types-are-not-uninhabited.nll.stderr diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 5d0e490ebea5a..b7e15bd8f7423 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -105,6 +105,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), ); + // This error should not be downgraded to a warning, + // even in migrate mode. + self.disable_error_downgrading(); err.buffer(&mut self.errors_buffer); } else { if let Some((reported_place, _)) = self.move_error_reported.get(&move_out_indices) { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 92774bbb7a6b4..548514081d6bf 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -252,6 +252,7 @@ fn do_mir_borrowck<'a, 'tcx>( move_error_reported: BTreeMap::new(), uninitialized_error_reported: Default::default(), errors_buffer, + disable_error_downgrading: false, nonlexical_regioncx: regioncx, used_mut: Default::default(), used_mut_upvars: SmallVec::new(), @@ -363,7 +364,7 @@ fn do_mir_borrowck<'a, 'tcx>( if !mbcx.errors_buffer.is_empty() { mbcx.errors_buffer.sort_by_key(|diag| diag.span.primary_span()); - if tcx.migrate_borrowck() { + if !mbcx.disable_error_downgrading && tcx.migrate_borrowck() { // When borrowck=migrate, check if AST-borrowck would // error on the given code. @@ -479,6 +480,9 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> { uninitialized_error_reported: FxHashSet>, /// Errors to be reported buffer errors_buffer: Vec, + /// If there are no errors reported by the HIR borrow checker, we downgrade + /// all NLL errors to warnings. Setting this flag disables downgrading. + disable_error_downgrading: bool, /// This field keeps track of all the local variables that are declared mut and are mutated. /// Used for the warning issued by an unused mutable local variable. used_mut: FxHashSet, @@ -919,6 +923,12 @@ impl InitializationRequiringAction { } impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { + /// If there are no errors reported by the HIR borrow checker, we downgrade + /// all NLL errors to warnings. Calling this disables downgrading. + crate fn disable_error_downgrading(&mut self) { + self.disable_error_downgrading = true; + } + /// Checks an access to the given place to see if it is allowed. Examines the set of borrows /// that are in scope, as well as which paths have been initialized, to ensure that (a) the /// place is initialized and (b) it is not borrowed in some way that would prevent this diff --git a/src/test/ui/async-await/partial-initialization-across-await.rs b/src/test/ui/async-await/partial-initialization-across-await.rs new file mode 100644 index 0000000000000..40f9f5202e77c --- /dev/null +++ b/src/test/ui/async-await/partial-initialization-across-await.rs @@ -0,0 +1,44 @@ +// Test that we don't allow awaiting from an async fn while a local is partially +// initialized. + +// edition:2018 + +#![feature(async_await)] + +struct S { x: i32, y: i32 } +struct T(i32, i32); + +async fn noop() {} + +async fn test_tuple() { + let mut t: (i32, i32); + t.0 = 42; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + noop().await; + t.1 = 88; + let _ = t; +} + +async fn test_tuple_struct() { + let mut t: T; + t.0 = 42; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + noop().await; + t.1 = 88; + let _ = t; +} + +async fn test_struct() { + let mut t: S; + t.x = 42; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + noop().await; + t.y = 88; + let _ = t; +} + +fn main() { + let _ = test_tuple(); + let _ = test_tuple_struct(); + let _ = test_struct(); +} diff --git a/src/test/ui/async-await/partial-initialization-across-await.stderr b/src/test/ui/async-await/partial-initialization-across-await.stderr new file mode 100644 index 0000000000000..fe79eb08befaa --- /dev/null +++ b/src/test/ui/async-await/partial-initialization-across-await.stderr @@ -0,0 +1,21 @@ +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/partial-initialization-across-await.rs:15:5 + | +LL | t.0 = 42; + | ^^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/partial-initialization-across-await.rs:24:5 + | +LL | t.0 = 42; + | ^^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/partial-initialization-across-await.rs:33:5 + | +LL | t.x = 42; + | ^^^^^^^^ use of possibly uninitialized `t` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.rs b/src/test/ui/borrowck/disallow-possibly-uninitialized.rs new file mode 100644 index 0000000000000..a987c00b09191 --- /dev/null +++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.rs @@ -0,0 +1,22 @@ +// Test that we don't allow partial initialization. +// This may be relaxed in the future (see #54987). + +fn main() { + let mut t: (u64, u64); + t.0 = 1; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + t.1 = 1; + + let mut t: (u64, u64); + t.1 = 1; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + t.0 = 1; + + let mut t: (u64, u64); + t.0 = 1; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + + let mut t: (u64,); + t.0 = 1; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] +} diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr new file mode 100644 index 0000000000000..a32b17b165934 --- /dev/null +++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr @@ -0,0 +1,27 @@ +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/disallow-possibly-uninitialized.rs:6:5 + | +LL | t.0 = 1; + | ^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/disallow-possibly-uninitialized.rs:11:5 + | +LL | t.1 = 1; + | ^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/disallow-possibly-uninitialized.rs:16:5 + | +LL | t.0 = 1; + | ^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/disallow-possibly-uninitialized.rs:20:5 + | +LL | t.0 = 1; + | ^^^^^^^ use of possibly uninitialized `t` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/consts/const_let_refutable.nll.stderr b/src/test/ui/consts/const_let_refutable.nll.stderr deleted file mode 100644 index a61c9b0c9fef9..0000000000000 --- a/src/test/ui/consts/const_let_refutable.nll.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0005]: refutable pattern in function argument: `&[]` not covered - --> $DIR/const_let_refutable.rs:3:16 - | -LL | const fn slice([a, b]: &[i32]) -> i32 { - | ^^^^^^ pattern `&[]` not covered - -error[E0723]: can only call other `const fn` within a `const fn`, but `const <&i32 as std::ops::Add>::add` is not stable as `const fn` - --> $DIR/const_let_refutable.rs:4:5 - | -LL | a + b - | ^^^^^ - | - = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563 - = help: add `#![feature(const_fn)]` to the crate attributes to enable - -error[E0381]: use of possibly uninitialized variable: `a` - --> $DIR/const_let_refutable.rs:4:5 - | -LL | a + b - | ^ use of possibly uninitialized `a` - -error[E0381]: use of possibly uninitialized variable: `b` - --> $DIR/const_let_refutable.rs:4:9 - | -LL | a + b - | ^ use of possibly uninitialized `b` - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0005, E0381, E0723. -For more information about an error, try `rustc --explain E0005`. diff --git a/src/test/ui/consts/const_let_refutable.rs b/src/test/ui/consts/const_let_refutable.rs index 322048c7fbf3f..7b3a591223025 100644 --- a/src/test/ui/consts/const_let_refutable.rs +++ b/src/test/ui/consts/const_let_refutable.rs @@ -2,10 +2,6 @@ fn main() {} const fn slice([a, b]: &[i32]) -> i32 { //~ ERROR refutable pattern in function argument a + b //~ ERROR can only call other `const fn` within a `const fn` - //~^ WARN use of possibly uninitialized variable: `a` - //~| WARN this error has been downgraded to a warning for backwards compatibility - //~| WARN this represents potential undefined behavior in your code and this warning will - //~| WARN use of possibly uninitialized variable: `b` - //~| WARN this error has been downgraded to a warning for backwards compatibility - //~| WARN this represents potential undefined behavior in your code and this warning will + //~^ ERROR use of possibly uninitialized variable: `a` + //~| ERROR use of possibly uninitialized variable: `b` } diff --git a/src/test/ui/consts/const_let_refutable.stderr b/src/test/ui/consts/const_let_refutable.stderr index a848b20ed98f5..a61c9b0c9fef9 100644 --- a/src/test/ui/consts/const_let_refutable.stderr +++ b/src/test/ui/consts/const_let_refutable.stderr @@ -13,27 +13,19 @@ LL | a + b = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563 = help: add `#![feature(const_fn)]` to the crate attributes to enable -warning[E0381]: use of possibly uninitialized variable: `a` +error[E0381]: use of possibly uninitialized variable: `a` --> $DIR/const_let_refutable.rs:4:5 | LL | a + b | ^ use of possibly uninitialized `a` - | - = warning: this error has been downgraded to a warning for backwards compatibility with previous releases - = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future - = note: for more information, try `rustc --explain E0729` -warning[E0381]: use of possibly uninitialized variable: `b` +error[E0381]: use of possibly uninitialized variable: `b` --> $DIR/const_let_refutable.rs:4:9 | LL | a + b | ^ use of possibly uninitialized `b` - | - = warning: this error has been downgraded to a warning for backwards compatibility with previous releases - = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future - = note: for more information, try `rustc --explain E0729` -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0005, E0381, E0723. For more information about an error, try `rustc --explain E0005`. diff --git a/src/test/ui/empty/empty-never-array.nll.stderr b/src/test/ui/empty/empty-never-array.nll.stderr deleted file mode 100644 index 01ee1c3a4d7fa..0000000000000 --- a/src/test/ui/empty/empty-never-array.nll.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0005]: refutable pattern in local binding: `T(_, _)` not covered - --> $DIR/empty-never-array.rs:10:9 - | -LL | / enum Helper { -LL | | T(T, [!; 0]), -LL | | #[allow(dead_code)] -LL | | U(U), -LL | | } - | |_- `Helper` defined here -... -LL | let Helper::U(u) = Helper::T(t, []); - | ^^^^^^^^^^^^ pattern `T(_, _)` not covered - -error[E0381]: use of possibly uninitialized variable: `u` - --> $DIR/empty-never-array.rs:12:5 - | -LL | u - | ^ use of possibly uninitialized `u` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0005, E0381. -For more information about an error, try `rustc --explain E0005`. diff --git a/src/test/ui/empty/empty-never-array.rs b/src/test/ui/empty/empty-never-array.rs index ce781da7d47e1..ffd2545b291e2 100644 --- a/src/test/ui/empty/empty-never-array.rs +++ b/src/test/ui/empty/empty-never-array.rs @@ -10,9 +10,7 @@ fn transmute(t: T) -> U { let Helper::U(u) = Helper::T(t, []); //~^ ERROR refutable pattern in local binding: `T(_, _)` not covered u - //~^ WARN use of possibly uninitialized variable: `u` - //~| WARN this error has been downgraded to a warning for backwards compatibility - //~| WARN this represents potential undefined behavior in your code and this warning will + //~^ ERROR use of possibly uninitialized variable: `u` } fn main() { diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr index 9911dd4683b66..01ee1c3a4d7fa 100644 --- a/src/test/ui/empty/empty-never-array.stderr +++ b/src/test/ui/empty/empty-never-array.stderr @@ -11,17 +11,13 @@ LL | | } LL | let Helper::U(u) = Helper::T(t, []); | ^^^^^^^^^^^^ pattern `T(_, _)` not covered -warning[E0381]: use of possibly uninitialized variable: `u` +error[E0381]: use of possibly uninitialized variable: `u` --> $DIR/empty-never-array.rs:12:5 | LL | u | ^ use of possibly uninitialized `u` - | - = warning: this error has been downgraded to a warning for backwards compatibility with previous releases - = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future - = note: for more information, try `rustc --explain E0729` -error: aborting due to previous error +error: aborting due to 2 previous errors Some errors have detailed explanations: E0005, E0381. For more information about an error, try `rustc --explain E0005`. diff --git a/src/test/ui/generator/partial-initialization-across-yield.rs b/src/test/ui/generator/partial-initialization-across-yield.rs new file mode 100644 index 0000000000000..1e4593002cb9a --- /dev/null +++ b/src/test/ui/generator/partial-initialization-across-yield.rs @@ -0,0 +1,46 @@ +// Test that we don't allow yielding from a generator while a local is partially +// initialized. + +#![feature(generators)] + +struct S { x: i32, y: i32 } +struct T(i32, i32); + +fn test_tuple() { + let _ = || { + let mut t: (i32, i32); + t.0 = 42; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + yield; + t.1 = 88; + let _ = t; + }; +} + +fn test_tuple_struct() { + let _ = || { + let mut t: T; + t.0 = 42; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + yield; + t.1 = 88; + let _ = t; + }; +} + +fn test_struct() { + let _ = || { + let mut t: S; + t.x = 42; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + yield; + t.y = 88; + let _ = t; + }; +} + +fn main() { + test_tuple(); + test_tuple_struct(); + test_struct(); +} diff --git a/src/test/ui/generator/partial-initialization-across-yield.stderr b/src/test/ui/generator/partial-initialization-across-yield.stderr new file mode 100644 index 0000000000000..8bf0037e07009 --- /dev/null +++ b/src/test/ui/generator/partial-initialization-across-yield.stderr @@ -0,0 +1,21 @@ +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/partial-initialization-across-yield.rs:12:9 + | +LL | t.0 = 42; + | ^^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/partial-initialization-across-yield.rs:23:9 + | +LL | t.0 = 42; + | ^^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/partial-initialization-across-yield.rs:34:9 + | +LL | t.x = 42; + | ^^^^^^^^ use of possibly uninitialized `t` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/issues/issue-15381.nll.stderr b/src/test/ui/issues/issue-15381.nll.stderr deleted file mode 100644 index a8495846b3610..0000000000000 --- a/src/test/ui/issues/issue-15381.nll.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0005]: refutable pattern in `for` loop binding: `&[]` not covered - --> $DIR/issue-15381.rs:4:9 - | -LL | for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { - | ^^^^^^^^ pattern `&[]` not covered - -error[E0381]: borrow of possibly uninitialized variable: `y` - --> $DIR/issue-15381.rs:6:26 - | -LL | println!("y={}", y); - | ^ use of possibly uninitialized `y` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0005, E0381. -For more information about an error, try `rustc --explain E0005`. diff --git a/src/test/ui/issues/issue-15381.rs b/src/test/ui/issues/issue-15381.rs index 3dbd4e717a0db..d21c321b09399 100644 --- a/src/test/ui/issues/issue-15381.rs +++ b/src/test/ui/issues/issue-15381.rs @@ -4,8 +4,6 @@ fn main() { for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { //~^ ERROR refutable pattern in `for` loop binding: `&[]` not covered println!("y={}", y); - //~^ WARN borrow of possibly uninitialized variable: `y` - //~| WARN this error has been downgraded to a warning for backwards compatibility - //~| WARN this represents potential undefined behavior in your code and this warning will + //~^ ERROR borrow of possibly uninitialized variable: `y` } } diff --git a/src/test/ui/issues/issue-15381.stderr b/src/test/ui/issues/issue-15381.stderr index 7b11d85ead874..a8495846b3610 100644 --- a/src/test/ui/issues/issue-15381.stderr +++ b/src/test/ui/issues/issue-15381.stderr @@ -4,17 +4,13 @@ error[E0005]: refutable pattern in `for` loop binding: `&[]` not covered LL | for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { | ^^^^^^^^ pattern `&[]` not covered -warning[E0381]: borrow of possibly uninitialized variable: `y` +error[E0381]: borrow of possibly uninitialized variable: `y` --> $DIR/issue-15381.rs:6:26 | LL | println!("y={}", y); | ^ use of possibly uninitialized `y` - | - = warning: this error has been downgraded to a warning for backwards compatibility with previous releases - = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future - = note: for more information, try `rustc --explain E0729` -error: aborting due to previous error +error: aborting due to 2 previous errors Some errors have detailed explanations: E0005, E0381. For more information about an error, try `rustc --explain E0005`. diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.nll.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.nll.stderr deleted file mode 100644 index eee331d95b9bc..0000000000000 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.nll.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0005]: refutable pattern in local binding: `Err(_)` not covered - --> $DIR/recursive-types-are-not-uninhabited.rs:6:9 - | -LL | let Ok(x) = res; - | ^^^^^ pattern `Err(_)` not covered - -error[E0381]: use of possibly uninitialized variable: `x` - --> $DIR/recursive-types-are-not-uninhabited.rs:8:5 - | -LL | x - | ^ use of possibly uninitialized `x` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0005, E0381. -For more information about an error, try `rustc --explain E0005`. diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs b/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs index a618aba9413f0..45910c3c3a8c6 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs @@ -6,9 +6,7 @@ fn foo(res: Result) -> u32 { let Ok(x) = res; //~^ ERROR refutable pattern x - //~^ WARN use of possibly uninitialized variable: `x` - //~| WARN this error has been downgraded to a warning for backwards compatibility - //~| WARN this represents potential undefined behavior in your code and this warning will + //~^ ERROR use of possibly uninitialized variable: `x` } fn main() { diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr index 9203f893fdbf7..eee331d95b9bc 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -4,17 +4,13 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered LL | let Ok(x) = res; | ^^^^^ pattern `Err(_)` not covered -warning[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly uninitialized variable: `x` --> $DIR/recursive-types-are-not-uninhabited.rs:8:5 | LL | x | ^ use of possibly uninitialized `x` - | - = warning: this error has been downgraded to a warning for backwards compatibility with previous releases - = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future - = note: for more information, try `rustc --explain E0729` -error: aborting due to previous error +error: aborting due to 2 previous errors Some errors have detailed explanations: E0005, E0381. For more information about an error, try `rustc --explain E0005`. From 571e22d7e82d471a38ebba1e6fdeed635b2a9953 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Mon, 5 Aug 2019 11:57:55 -0400 Subject: [PATCH 19/21] Clarify align_to's requirements and obligations --- src/libcore/slice/mod.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index c8257d30488a9..d5a34ea2bd5a1 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -2308,9 +2308,10 @@ impl [T] { /// maintained. /// /// This method splits the slice into three distinct slices: prefix, correctly aligned middle - /// slice of a new type, and the suffix slice. The method does a best effort to make the - /// middle slice the greatest length possible for a given type and input slice, but only - /// your algorithm's performance should depend on that, not its correctness. + /// slice of a new type, and the suffix slice. The method may make the middle slice the greatest + /// length possible for a given type and input slice, but only your algorithm's performance + /// should depend on that, not its correctness. It is permissible for all of the input data to + /// be returned as the prefix or suffix slice. /// /// This method has no purpose when either input element `T` or output element `U` are /// zero-sized and will return the original slice without splitting anything. @@ -2361,9 +2362,10 @@ impl [T] { /// maintained. /// /// This method splits the slice into three distinct slices: prefix, correctly aligned middle - /// slice of a new type, and the suffix slice. The method does a best effort to make the - /// middle slice the greatest length possible for a given type and input slice, but only - /// your algorithm's performance should depend on that, not its correctness. + /// slice of a new type, and the suffix slice. The method may make the middle slice the greatest + /// length possible for a given type and input slice, but only your algorithm's performance + /// should depend on that, not its correctness. It is permissible for all of the input data to + /// be returned as the prefix or suffix slice. /// /// This method has no purpose when either input element `T` or output element `U` are /// zero-sized and will return the original slice without splitting anything. From 175eb9ca93cf9dbf841d70a6845f820e73180b2d Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Tue, 6 Aug 2019 02:36:59 +0200 Subject: [PATCH 20/21] doc: fix broken sentence Also, the move was done nearly a year ago --- src/test/COMPILER_TESTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/COMPILER_TESTS.md b/src/test/COMPILER_TESTS.md index c4ca478134399..3f47ca834cda6 100644 --- a/src/test/COMPILER_TESTS.md +++ b/src/test/COMPILER_TESTS.md @@ -1,4 +1,4 @@ # Compiler Test Documentation -Documentation the compiler testing framework has moved to +Documentation for the compiler testing framework can be found in [the rustc guide](https://rust-lang.github.io/rustc-guide/tests/intro.html). From ee48f820bf00f6555d96cd3972a28486d6b34b78 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 6 Aug 2019 04:01:55 +0200 Subject: [PATCH 21/21] Update README.md --- src/librustc/infer/lexical_region_resolve/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/infer/lexical_region_resolve/README.md b/src/librustc/infer/lexical_region_resolve/README.md index 56320636a6743..7eb4da86ec081 100644 --- a/src/librustc/infer/lexical_region_resolve/README.md +++ b/src/librustc/infer/lexical_region_resolve/README.md @@ -6,7 +6,7 @@ > As of edition 2018, region inference is done using Non-lexical lifetimes, > which is described in the guide and [this RFC]. -[rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html +[rustc guide]: https://rust-lang.github.io/rustc-guide/borrow_check/region_inference.html [this RFC]: https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md ## Terminology