From a35cdd4e41a2bec5d8896653f898aaff61cb0106 Mon Sep 17 00:00:00 2001 From: John Downey Date: Wed, 6 Mar 2019 12:17:26 -0600 Subject: [PATCH 01/23] Implement `iter::Sum` and `iter::Product` for `Option` This is similar to the existing implementation for `Result`. It will take each item into the accumulator unless a `None` is returned. --- src/libcore/iter/traits/accum.rs | 113 +++++++++++++++++++++++++++++++ src/libcore/tests/iter.rs | 16 +++++ 2 files changed, 129 insertions(+) diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs index dfe1d2a1006d7..b67714ca77903 100644 --- a/src/libcore/iter/traits/accum.rs +++ b/src/libcore/iter/traits/accum.rs @@ -223,3 +223,116 @@ impl Product> for Result ResultShunt::process(iter, |i| i.product()) } } + +/// An iterator adapter that produces output as long as the underlying +/// iterator produces `Option::Some` values. +struct OptionShunt { + iter: I, + exited_early: bool, +} + +impl OptionShunt +where + I: Iterator>, +{ + /// Process the given iterator as if it yielded a `T` instead of a + /// `Option`. Any `None` value will stop the inner iterator and + /// the overall result will be a `None`. + pub fn process(iter: I, mut f: F) -> Option + where + F: FnMut(&mut Self) -> U, + { + let mut shunt = OptionShunt::new(iter); + let value = f(shunt.by_ref()); + shunt.reconstruct(value) + } + + fn new(iter: I) -> Self { + OptionShunt { + iter, + exited_early: false, + } + } + + /// Consume the adapter and rebuild a `Option` value. + fn reconstruct(self, val: U) -> Option { + if self.exited_early { + None + } else { + Some(val) + } + } +} + +impl Iterator for OptionShunt +where + I: Iterator>, +{ + type Item = T; + + fn next(&mut self) -> Option { + match self.iter.next() { + Some(Some(v)) => Some(v), + Some(None) => { + self.exited_early = true; + None + } + None => None, + } + } + + fn size_hint(&self) -> (usize, Option) { + if self.exited_early { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } + } +} + +#[stable(feature = "iter_arith_traits_option", since = "1.34.0")] +impl Sum> for Option +where + T: Sum, +{ + /// Takes each element in the `Iterator`: if it is a `None`, no further + /// elements are taken, and the `None` is returned. Should no `None` occur, + /// the sum of all elements is returned. + /// + /// # Examples + /// + /// This sums up every integer in a vector, rejecting the sum if a negative + /// element is encountered: + /// + /// ``` + /// let v = vec![1, 2]; + /// let res: Option = v.iter().map(|&x: &i32| + /// if x < 0 { None } + /// else { Some(x) } + /// ).sum(); + /// assert_eq!(res, Some(3)); + /// ``` + fn sum(iter: I) -> Option + where + I: Iterator>, + { + OptionShunt::process(iter, |i| i.sum()) + } +} + +#[stable(feature = "iter_arith_traits_option", since = "1.34.0")] +impl Product> for Option +where + T: Product, +{ + /// Takes each element in the `Iterator`: if it is a `None`, no further + /// elements are taken, and the `None` is returned. Should no `None` occur, + /// the product of all elements is returned. + fn product(iter: I) -> Option + where + I: Iterator>, + { + OptionShunt::process(iter, |i| i.product()) + } +} diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index d880abb181c20..814f4ec4ca53b 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1066,6 +1066,14 @@ fn test_iterator_sum_result() { assert_eq!(v.iter().cloned().sum::>(), Err(())); } +#[test] +fn test_iterator_sum_option() { + let v: &[Option] = &[Some(1), Some(2), Some(3), Some(4)]; + assert_eq!(v.iter().cloned().sum::>(), Some(10)); + let v: &[Option] = &[Some(1), None, Some(3), Some(4)]; + assert_eq!(v.iter().cloned().sum::>(), None); +} + #[test] fn test_iterator_product() { let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; @@ -1082,6 +1090,14 @@ fn test_iterator_product_result() { assert_eq!(v.iter().cloned().product::>(), Err(())); } +#[test] +fn test_iterator_product_option() { + let v: &[Option] = &[Some(1), Some(2), Some(3), Some(4)]; + assert_eq!(v.iter().cloned().product::>(), Some(24)); + let v: &[Option] = &[Some(1), None, Some(3), Some(4)]; + assert_eq!(v.iter().cloned().product::>(), None); +} + #[test] fn test_iterator_max() { let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; From 8c698763579d5cf78094d2d4495c3d801ed0d2e7 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 19 Mar 2019 17:17:18 -0500 Subject: [PATCH 02/23] Update stable attribute to be since 1.35.0 Co-Authored-By: jtdowney --- src/libcore/iter/traits/accum.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs index b67714ca77903..ae51e1bddac0a 100644 --- a/src/libcore/iter/traits/accum.rs +++ b/src/libcore/iter/traits/accum.rs @@ -291,7 +291,7 @@ where } } -#[stable(feature = "iter_arith_traits_option", since = "1.34.0")] +#[stable(feature = "iter_arith_traits_option", since = "1.35.0")] impl Sum> for Option where T: Sum, @@ -321,7 +321,7 @@ where } } -#[stable(feature = "iter_arith_traits_option", since = "1.34.0")] +#[stable(feature = "iter_arith_traits_option", since = "1.35.0")] impl Product> for Option where T: Product, From 422a4c07c826fb007f5199031482d5b40d255899 Mon Sep 17 00:00:00 2001 From: John Downey Date: Wed, 20 Mar 2019 20:14:46 -0500 Subject: [PATCH 03/23] Add improved doc example for Sum> --- src/libcore/iter/traits/accum.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs index ae51e1bddac0a..88c4820d5839c 100644 --- a/src/libcore/iter/traits/accum.rs +++ b/src/libcore/iter/traits/accum.rs @@ -302,16 +302,13 @@ where /// /// # Examples /// - /// This sums up every integer in a vector, rejecting the sum if a negative - /// element is encountered: + /// This sums up the position of the character 'a' in a vector of strings, + /// if a word did not have the character 'a' the operation returns `None`: /// /// ``` - /// let v = vec![1, 2]; - /// let res: Option = v.iter().map(|&x: &i32| - /// if x < 0 { None } - /// else { Some(x) } - /// ).sum(); - /// assert_eq!(res, Some(3)); + /// let words = vec!["have", "a", "great", "day"]; + /// let total: Option = words.iter().map(|w| w.find('a')).sum(); + /// assert_eq!(total, Some(5)); /// ``` fn sum(iter: I) -> Option where From 4d9b9e9038102ada95d1898d303038803d752f62 Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Fri, 26 Apr 2019 19:53:18 +0530 Subject: [PATCH 04/23] wip nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 16 ++++++++++++++++ src/libcore/tests/slice.rs | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 8731f48675356..049d38c158ce5 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4152,6 +4152,22 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { Some(snd) } } + + #[inline] + fn nth_back(&mut self, n: usize) { + let (end, overflow) = self.v.len().overflowing_sub(n); + if end < self.v.len() || overflow { + self.v = &[]; + None + } else { + let start = match end.checked_sub(self.chunk_size) { + Some(sum) => cmp::min(self.v.len(), sum), + None => self.v.len(), + }; + let nth = &self.v[start..end]; + self.v = &self.v[end..]; + } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index acf6b03791f01..0233b96d3a72d 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -134,6 +134,19 @@ fn test_chunks_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_chunks_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.chunks(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.chunks(3); + assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); + assert_eq!(c2.next(), None); +} + #[test] fn test_chunks_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; From 73ca8bc140d4b0935ecb0199ea65723ec6a6791f Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Wed, 1 May 2019 23:34:07 +0530 Subject: [PATCH 05/23] hopefully working nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 17 +++++++++-------- src/libcore/tests/slice.rs | 9 ++++++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 049d38c158ce5..00dbe7104d1a4 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4154,18 +4154,19 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { } #[inline] - fn nth_back(&mut self, n: usize) { - let (end, overflow) = self.v.len().overflowing_sub(n); - if end < self.v.len() || overflow { - self.v = &[]; + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.v.len().overflowing_sub(n * self.chunk_size); + if overflow { + self.v = &mut []; None } else { let start = match end.checked_sub(self.chunk_size) { - Some(sum) => cmp::min(self.v.len(), sum), - None => self.v.len(), + Some(res) => cmp::min(self.v.len(), res), + None => 0, }; - let nth = &self.v[start..end]; - self.v = &self.v[end..]; + let nth_back = &self.v[start..end]; + self.v = &self.v[..start]; + Some(nth_back) } } } diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 0233b96d3a72d..edea405fad791 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -139,12 +139,19 @@ fn test_chunks_nth_back() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; let mut c = v.chunks(2); assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); - assert_eq!(c.next().unwrap(), &[4, 5]); + assert_eq!(c.next().unwrap(), &[0, 1]); + assert_eq!(c.next(), None); let v2: &[i32] = &[0, 1, 2, 3, 4]; let mut c2 = v2.chunks(3); assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); assert_eq!(c2.next(), None); + assert_eq!(c2.next_back(), None); + + let v3: &[i32] = &[0, 1, 2, 3, 4]; + let mut c3 = v3.chunks(10); + assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); + assert_eq!(c3.next(), None); } #[test] From 5eb0e08d0feab69f9e5f3b6881bde328a9105c96 Mon Sep 17 00:00:00 2001 From: Tim Vermeulen Date: Sun, 5 May 2019 11:21:30 +0200 Subject: [PATCH 06/23] Implement nth_back for RChunks(Exact)(Mut) --- src/libcore/slice/mod.rs | 72 ++++++++++++++++++++++++++++++++++++++ src/libcore/tests/slice.rs | 52 +++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 8731f48675356..f7a7976faecd1 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4643,6 +4643,23 @@ impl<'a, T> DoubleEndedIterator for RChunks<'a, T> { Some(fst) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &[]; + None + } else { + // can't underflow because `n < len` + let offset_from_end = (len - 1 - n) * self.chunk_size; + let end = self.v.len() - offset_from_end; + let start = end.saturating_sub(self.chunk_size); + let nth_back = &self.v[start..end]; + self.v = &self.v[end..]; + Some(nth_back) + } + } } #[stable(feature = "rchunks", since = "1.31.0")] @@ -4768,6 +4785,24 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> { Some(head) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &mut []; + None + } else { + // can't underflow because `n < len` + let offset_from_end = (len - 1 - n) * self.chunk_size; + let end = self.v.len() - offset_from_end; + let start = end.saturating_sub(self.chunk_size); + let (tmp, tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end); + let (_, nth_back) = tmp.split_at_mut(start); + self.v = tail; + Some(nth_back) + } + } } #[stable(feature = "rchunks", since = "1.31.0")] @@ -4892,6 +4927,24 @@ impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> { Some(fst) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &[]; + None + } else { + // now that we know that `n` corresponds to a chunk, + // none of these operations can underflow/overflow + let offset = (len - n) * self.chunk_size; + let start = self.v.len() - offset; + let end = start + self.chunk_size; + let nth_back = &self.v[start..end]; + self.v = &self.v[end..]; + Some(nth_back) + } + } } #[stable(feature = "rchunks", since = "1.31.0")] @@ -5010,6 +5063,25 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> { Some(head) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &mut []; + None + } else { + // now that we know that `n` corresponds to a chunk, + // none of these operations can underflow/overflow + let offset = (len - n) * self.chunk_size; + let start = self.v.len() - offset; + let end = start + self.chunk_size; + let (tmp, tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end); + let (_, nth_back) = tmp.split_at_mut(start); + self.v = tail; + Some(nth_back) + } + } } #[stable(feature = "rchunks", since = "1.31.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index acf6b03791f01..cd520a052a005 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -356,6 +356,19 @@ fn test_rchunks_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_rchunks_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.rchunks(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next_back().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.rchunks(3); + assert_eq!(c2.nth_back(1).unwrap(), &[2, 3, 4]); + assert_eq!(c2.next_back(), None); +} + #[test] fn test_rchunks_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; @@ -407,6 +420,19 @@ fn test_rchunks_mut_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_rchunks_mut_nth_back() { + let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; + let mut c = v.rchunks_mut(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next_back().unwrap(), &[4, 5]); + + let v2: &mut [i32] = &mut [0, 1, 2, 3, 4]; + let mut c2 = v2.rchunks_mut(3); + assert_eq!(c2.nth_back(1).unwrap(), &[2, 3, 4]); + assert_eq!(c2.next_back(), None); +} + #[test] fn test_rchunks_mut_last() { let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; @@ -460,6 +486,19 @@ fn test_rchunks_exact_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_rchunks_exact_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.rchunks_exact(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next_back().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4, 5, 6]; + let mut c2 = v2.rchunks_exact(3); + assert_eq!(c2.nth_back(1).unwrap(), &[4, 5, 6]); + assert_eq!(c2.next(), None); +} + #[test] fn test_rchunks_exact_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; @@ -518,6 +557,19 @@ fn test_rchunks_exact_mut_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_rchunks_exact_mut_nth_back() { + let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; + let mut c = v.rchunks_exact_mut(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next_back().unwrap(), &[4, 5]); + + let v2: &mut [i32] = &mut [0, 1, 2, 3, 4, 5, 6]; + let mut c2 = v2.rchunks_exact_mut(3); + assert_eq!(c2.nth_back(1).unwrap(), &[4, 5, 6]); + assert_eq!(c2.next(), None); +} + #[test] fn test_rchunks_exact_mut_last() { let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; From 02a148dba261439626c5020a7cbb15e690521e87 Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Fri, 26 Apr 2019 19:53:18 +0530 Subject: [PATCH 07/23] wip nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 16 ++++++++++++++++ src/libcore/tests/slice.rs | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 8731f48675356..049d38c158ce5 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4152,6 +4152,22 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { Some(snd) } } + + #[inline] + fn nth_back(&mut self, n: usize) { + let (end, overflow) = self.v.len().overflowing_sub(n); + if end < self.v.len() || overflow { + self.v = &[]; + None + } else { + let start = match end.checked_sub(self.chunk_size) { + Some(sum) => cmp::min(self.v.len(), sum), + None => self.v.len(), + }; + let nth = &self.v[start..end]; + self.v = &self.v[end..]; + } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index acf6b03791f01..0233b96d3a72d 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -134,6 +134,19 @@ fn test_chunks_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_chunks_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.chunks(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.chunks(3); + assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); + assert_eq!(c2.next(), None); +} + #[test] fn test_chunks_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; From aff83c80dd162b43a301e2bea73762cc4560f0f3 Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Wed, 1 May 2019 23:34:07 +0530 Subject: [PATCH 08/23] hopefully working nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 17 +++++++++-------- src/libcore/tests/slice.rs | 9 ++++++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 049d38c158ce5..00dbe7104d1a4 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4154,18 +4154,19 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { } #[inline] - fn nth_back(&mut self, n: usize) { - let (end, overflow) = self.v.len().overflowing_sub(n); - if end < self.v.len() || overflow { - self.v = &[]; + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.v.len().overflowing_sub(n * self.chunk_size); + if overflow { + self.v = &mut []; None } else { let start = match end.checked_sub(self.chunk_size) { - Some(sum) => cmp::min(self.v.len(), sum), - None => self.v.len(), + Some(res) => cmp::min(self.v.len(), res), + None => 0, }; - let nth = &self.v[start..end]; - self.v = &self.v[end..]; + let nth_back = &self.v[start..end]; + self.v = &self.v[..start]; + Some(nth_back) } } } diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 0233b96d3a72d..edea405fad791 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -139,12 +139,19 @@ fn test_chunks_nth_back() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; let mut c = v.chunks(2); assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); - assert_eq!(c.next().unwrap(), &[4, 5]); + assert_eq!(c.next().unwrap(), &[0, 1]); + assert_eq!(c.next(), None); let v2: &[i32] = &[0, 1, 2, 3, 4]; let mut c2 = v2.chunks(3); assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); assert_eq!(c2.next(), None); + assert_eq!(c2.next_back(), None); + + let v3: &[i32] = &[0, 1, 2, 3, 4]; + let mut c3 = v3.chunks(10); + assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); + assert_eq!(c3.next(), None); } #[test] From 16223e4bea1ecb087c60d2ac1aeb16c7b7033d52 Mon Sep 17 00:00:00 2001 From: wizAmit Date: Tue, 14 May 2019 13:28:43 +0530 Subject: [PATCH 09/23] new implementation for nth_back for chunks --- src/libcore/slice/mod.rs | 27 ++++++++++++++++++++++----- src/libcore/tests/slice.rs | 6 +++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 00dbe7104d1a4..72a54c5ce82d0 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4155,15 +4155,32 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { #[inline] fn nth_back(&mut self, n: usize) -> Option { - let (end, overflow) = self.v.len().overflowing_sub(n * self.chunk_size); + let remainder = match self.v.len().checked_rem(self.chunk_size) { + Some(res) => res, + None => 0, + }; + + let sub_chunk_size = if remainder != 0 { remainder } else { self.chunk_size }; + + let safe_sub = match n.checked_mul(sub_chunk_size) { + Some(res) => res, + None => 0, + }; + + let (end, overflow) = self.v.len().overflowing_sub(safe_sub); if overflow { - self.v = &mut []; + self.v= &[]; None } else { - let start = match end.checked_sub(self.chunk_size) { - Some(res) => cmp::min(self.v.len(), res), - None => 0, + let start = if n == 0 { + self.v.len() - sub_chunk_size + } else { + match end.checked_sub(self.chunk_size) { + Some(res) => res, + None => 0, + } }; + let nth_back = &self.v[start..end]; self.v = &self.v[..start]; Some(nth_back) diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index edea405fad791..cf2602f3210f1 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -144,7 +144,7 @@ fn test_chunks_nth_back() { let v2: &[i32] = &[0, 1, 2, 3, 4]; let mut c2 = v2.chunks(3); - assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); + assert_eq!(c2.nth_back(1).unwrap(), &[0, 1, 2]); assert_eq!(c2.next(), None); assert_eq!(c2.next_back(), None); @@ -152,6 +152,10 @@ fn test_chunks_nth_back() { let mut c3 = v3.chunks(10); assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); assert_eq!(c3.next(), None); + + let v4: &[i32] = &[0, 1, 2]; + let mut c4 = v4.chunks(10); + assert_eq!(c4.nth_back(1_000_000_000usize), None); } #[test] From dc82626262605665bbcea8f24925442e48dc897c Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Fri, 26 Apr 2019 19:53:18 +0530 Subject: [PATCH 10/23] wip nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 16 ++++++++++++++++ src/libcore/tests/slice.rs | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index d06d107d32a41..54c5285bc495c 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4178,6 +4178,22 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { Some(snd) } } + + #[inline] + fn nth_back(&mut self, n: usize) { + let (end, overflow) = self.v.len().overflowing_sub(n); + if end < self.v.len() || overflow { + self.v = &[]; + None + } else { + let start = match end.checked_sub(self.chunk_size) { + Some(sum) => cmp::min(self.v.len(), sum), + None => self.v.len(), + }; + let nth = &self.v[start..end]; + self.v = &self.v[end..]; + } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index acf6b03791f01..0233b96d3a72d 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -134,6 +134,19 @@ fn test_chunks_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_chunks_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.chunks(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.chunks(3); + assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); + assert_eq!(c2.next(), None); +} + #[test] fn test_chunks_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; From 2080b86566358dad8cb8c967e321a172a69c49f7 Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Wed, 1 May 2019 23:34:07 +0530 Subject: [PATCH 11/23] hopefully working nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 17 +++++++++-------- src/libcore/tests/slice.rs | 9 ++++++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 54c5285bc495c..b138ae3449f87 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4180,18 +4180,19 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { } #[inline] - fn nth_back(&mut self, n: usize) { - let (end, overflow) = self.v.len().overflowing_sub(n); - if end < self.v.len() || overflow { - self.v = &[]; + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.v.len().overflowing_sub(n * self.chunk_size); + if overflow { + self.v = &mut []; None } else { let start = match end.checked_sub(self.chunk_size) { - Some(sum) => cmp::min(self.v.len(), sum), - None => self.v.len(), + Some(res) => cmp::min(self.v.len(), res), + None => 0, }; - let nth = &self.v[start..end]; - self.v = &self.v[end..]; + let nth_back = &self.v[start..end]; + self.v = &self.v[..start]; + Some(nth_back) } } } diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 0233b96d3a72d..edea405fad791 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -139,12 +139,19 @@ fn test_chunks_nth_back() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; let mut c = v.chunks(2); assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); - assert_eq!(c.next().unwrap(), &[4, 5]); + assert_eq!(c.next().unwrap(), &[0, 1]); + assert_eq!(c.next(), None); let v2: &[i32] = &[0, 1, 2, 3, 4]; let mut c2 = v2.chunks(3); assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); assert_eq!(c2.next(), None); + assert_eq!(c2.next_back(), None); + + let v3: &[i32] = &[0, 1, 2, 3, 4]; + let mut c3 = v3.chunks(10); + assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); + assert_eq!(c3.next(), None); } #[test] From 29a103daa92bb3607fd4cd34169d4ff6170987fa Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Fri, 26 Apr 2019 19:53:18 +0530 Subject: [PATCH 12/23] wip nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 17 ----------------- src/libcore/tests/slice.rs | 19 ------------------- 2 files changed, 36 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index b138ae3449f87..d06d107d32a41 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4178,23 +4178,6 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { Some(snd) } } - - #[inline] - fn nth_back(&mut self, n: usize) -> Option { - let (end, overflow) = self.v.len().overflowing_sub(n * self.chunk_size); - if overflow { - self.v = &mut []; - None - } else { - let start = match end.checked_sub(self.chunk_size) { - Some(res) => cmp::min(self.v.len(), res), - None => 0, - }; - let nth_back = &self.v[start..end]; - self.v = &self.v[..start]; - Some(nth_back) - } - } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index edea405fad791..1cba4b38382a4 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -134,25 +134,6 @@ fn test_chunks_nth() { assert_eq!(c2.next(), None); } -#[test] -fn test_chunks_nth_back() { - let v: &[i32] = &[0, 1, 2, 3, 4, 5]; - let mut c = v.chunks(2); - assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); - assert_eq!(c.next().unwrap(), &[0, 1]); - assert_eq!(c.next(), None); - - let v2: &[i32] = &[0, 1, 2, 3, 4]; - let mut c2 = v2.chunks(3); - assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); - assert_eq!(c2.next(), None); - assert_eq!(c2.next_back(), None); - - let v3: &[i32] = &[0, 1, 2, 3, 4]; - let mut c3 = v3.chunks(10); - assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); - assert_eq!(c3.next(), None); -} #[test] fn test_chunks_last() { From 9309447397ffcc2f427f850c1a7df8af2c682169 Mon Sep 17 00:00:00 2001 From: wizAmit Date: Wed, 22 May 2019 22:27:30 +0530 Subject: [PATCH 13/23] succint implementation --- src/libcore/slice/mod.rs | 18 ++++++++++++++++++ src/libcore/tests/slice.rs | 24 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index d06d107d32a41..8862c0c1cefa4 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4178,6 +4178,24 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { Some(snd) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &[]; + None + } else { + let start = (len - 1 - n) * self.chunk_size; + let end = match start.checked_add(self.chunk_size) { + Some(res) => cmp::min(res, self.v.len()), + None => self.v.len(), + }; + let nth_back = &self.v[start..end]; + self.v = &self.v[..start]; + Some(nth_back) + } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 1cba4b38382a4..a4cb0c42044b0 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -134,6 +134,30 @@ fn test_chunks_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_chunks_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.chunks(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[0, 1]); + assert_eq!(c.next(), None); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.chunks(3); + assert_eq!(c2.nth_back(1).unwrap(), &[0, 1, 2]); + assert_eq!(c2.next(), None); + assert_eq!(c2.next_back(), None); + + let v3: &[i32] = &[0, 1, 2, 3, 4]; + let mut c3 = v3.chunks(10); + assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); + assert_eq!(c3.next(), None); + + let v4: &[i32] = &[0, 1, 2]; + let mut c4 = v4.chunks(10); + assert_eq!(c4.nth_back(1_000_000_000usize), None); +} + #[test] fn test_chunks_last() { From f1d0829e20e3ff3ff78a09136968612887544af2 Mon Sep 17 00:00:00 2001 From: Tim Vermeulen Date: Sat, 4 May 2019 12:04:52 +0200 Subject: [PATCH 14/23] Add Step::sub_usize --- src/libcore/iter/range.rs | 35 +++++++++++++++++++ src/librustc_data_structures/indexed_vec.rs | 5 +++ .../run-pass/impl-trait/example-calendar.rs | 4 +++ 3 files changed, 44 insertions(+) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index f8a975cc8d47f..6bbf776fb8f17 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -34,6 +34,13 @@ pub trait Step: Clone + PartialOrd + Sized { /// Adds a `usize`, returning `None` on overflow. fn add_usize(&self, n: usize) -> Option; + + /// Subtracts a `usize`, returning `None` on underflow. + fn sub_usize(&self, n: usize) -> Option { + // this default implementation makes the addition of `sub_usize` a non-breaking change + let _ = n; + unimplemented!() + } } // These are still macro-generated because the integer literals resolve to different types. @@ -85,6 +92,15 @@ macro_rules! step_impl_unsigned { } } + #[inline] + #[allow(unreachable_patterns)] + fn sub_usize(&self, n: usize) -> Option { + match <$t>::try_from(n) { + Ok(n_as_t) => self.checked_sub(n_as_t), + Err(_) => None, + } + } + step_identical_methods!(); } )*) @@ -125,6 +141,25 @@ macro_rules! step_impl_signed { } } + #[inline] + #[allow(unreachable_patterns)] + fn sub_usize(&self, n: usize) -> Option { + match <$unsigned>::try_from(n) { + Ok(n_as_unsigned) => { + // Wrapping in unsigned space handles cases like + // `80_i8.sub_usize(200) == Some(-120_i8)`, + // even though 200_usize is out of range for i8. + let wrapped = (*self as $unsigned).wrapping_sub(n_as_unsigned) as $t; + if wrapped <= *self { + Some(wrapped) + } else { + None // Subtraction underflowed + } + } + Err(_) => None, + } + } + step_identical_methods!(); } )*) diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 359b89f683dc4..c7f6e54c3d56b 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -212,6 +212,11 @@ macro_rules! newtype_index { fn add_usize(&self, u: usize) -> Option { Idx::index(*self).checked_add(u).map(Self::new) } + + #[inline] + fn sub_usize(&self, u: usize) -> Option { + Idx::index(*self).checked_sub(u).map(Self::new) + } } impl From<$type> for u32 { diff --git a/src/test/run-pass/impl-trait/example-calendar.rs b/src/test/run-pass/impl-trait/example-calendar.rs index 968e9b7d34ab7..f1b1656745e7c 100644 --- a/src/test/run-pass/impl-trait/example-calendar.rs +++ b/src/test/run-pass/impl-trait/example-calendar.rs @@ -180,6 +180,10 @@ impl std::iter::Step for NaiveDate { fn add_usize(&self, _: usize) -> Option { unimplemented!() } + + fn sub_usize(&self, _: usize) -> Option { + unimplemented!() + } } #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] From f9d328d7ffa17ab78eaa62a2976033a7176886d9 Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Sun, 12 May 2019 14:53:01 +0200 Subject: [PATCH 15/23] sync::Weak::{as,from,into}_raw Methods on the Weak to access it as raw pointer to the data. --- src/liballoc/sync.rs | 164 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 158 insertions(+), 6 deletions(-) diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 90c7859b3db9e..70865656c510e 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -13,7 +13,7 @@ use core::borrow; use core::fmt; use core::cmp::{self, Ordering}; use core::intrinsics::abort; -use core::mem::{self, align_of_val, size_of_val}; +use core::mem::{self, align_of, align_of_val, size_of_val}; use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn}; use core::pin::Pin; use core::ptr::{self, NonNull}; @@ -397,11 +397,7 @@ impl Arc { /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - // Align the unsized value to the end of the ArcInner. - // Because it is ?Sized, it will always be the last field in memory. - let align = align_of_val(&*ptr); - let layout = Layout::new::>(); - let offset = (layout.size() + layout.padding_needed_for(align)) as isize; + let offset = data_offset(ptr); // Reverse the offset to find the original ArcInner. let fake_ptr = ptr as *mut ArcInner; @@ -1071,6 +1067,144 @@ impl Weak { ptr: NonNull::new(usize::MAX as *mut ArcInner).expect("MAX is not 0"), } } + + /// Returns a raw pointer to the object `T` pointed to by this `Weak`. + /// + /// It is up to the caller to ensure that the object is still alive when accessing it through + /// the pointer. + /// + /// The pointer may be [`null`] or be dangling in case the object has already been destroyed. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::sync::{Arc, Weak}; + /// use std::ptr; + /// + /// let strong = Arc::new(42); + /// let weak = Arc::downgrade(&strong); + /// // Both point to the same object + /// assert!(ptr::eq(&*strong, Weak::as_raw(&weak))); + /// // The strong here keeps it alive, so we can still access the object. + /// assert_eq!(42, unsafe { *Weak::as_raw(&weak) }); + /// + /// drop(strong); + /// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to + /// // undefined behaviour. + /// // assert_eq!(42, unsafe { *Weak::as_raw(&weak) }); + /// ``` + /// + /// [`null`]: ../../std/ptr/fn.null.html + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub fn as_raw(this: &Self) -> *const T { + match this.inner() { + None => ptr::null(), + Some(inner) => { + let offset = data_offset_sized::(); + let ptr = inner as *const ArcInner; + // Note: while the pointer we create may already point to dropped value, the + // allocation still lives (it must hold the weak point as long as we are alive). + // Therefore, the offset is OK to do, it won't get out of the allocation. + let ptr = unsafe { (ptr as *const u8).offset(offset) }; + ptr as *const T + } + } + } + + /// Consumes the `Weak` and turns it into a raw pointer. + /// + /// This converts the weak pointer into a raw pointer, preserving the original weak count. It + /// can be turned back into the `Weak` with [`from_raw`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_raw`] apply. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new(42); + /// let weak = Arc::downgrade(&strong); + /// let raw = Weak::into_raw(weak); + /// + /// assert_eq!(1, Arc::weak_count(&strong)); + /// assert_eq!(42, unsafe { *raw }); + /// + /// drop(unsafe { Weak::from_raw(raw) }); + /// assert_eq!(0, Arc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw`]: struct.Weak.html#method.from_raw + /// [`as_raw`]: struct.Weak.html#method.as_raw + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub fn into_raw(this: Self) -> *const T { + let result = Self::as_raw(&this); + mem::forget(this); + result + } + + /// Converts a raw pointer previously created by [`into_raw`] back into + /// `Weak`. + /// + /// This can be used to safely get a strong reference (by calling [`upgrade`] + /// later) or to deallocate the weak count by dropping the `Weak`. + /// + /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is + /// returned. + /// + /// # Safety + /// + /// The pointer must represent one valid weak count. In other words, it must point to `T` which + /// is or *was* managed by an [`Arc`] and the weak count of that [`Arc`] must not have reached + /// 0. It is allowed for the strong count to be 0. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new(42); + /// + /// let raw_1 = Weak::into_raw(Arc::downgrade(&strong)); + /// let raw_2 = Weak::into_raw(Arc::downgrade(&strong)); + /// + /// assert_eq!(2, Arc::weak_count(&strong)); + /// + /// assert_eq!(42, *Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap()); + /// assert_eq!(1, Arc::weak_count(&strong)); + /// + /// drop(strong); + /// + /// // Decrement the last weak count. + /// assert!(Weak::upgrade(&unsafe { Weak::from_raw(raw_2) }).is_none()); + /// ``` + /// + /// [`null`]: ../../std/ptr/fn.null.html + /// [`into_raw`]: struct.Weak.html#method.into_raw + /// [`upgrade`]: struct.Weak.html#method.upgrade + /// [`Weak`]: struct.Weak.html + /// [`Arc`]: struct.Arc.html + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + if ptr.is_null() { + Self::new() + } else { + // See Arc::from_raw for details + let offset = data_offset(ptr); + let fake_ptr = ptr as *mut ArcInner; + let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); + Weak { + ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw"), + } + } + } } impl Weak { @@ -2150,3 +2284,21 @@ impl AsRef for Arc { #[stable(feature = "pin", since = "1.33.0")] impl Unpin for Arc { } + +/// Computes the offset of the data field within ArcInner. +unsafe fn data_offset(ptr: *const T) -> isize { + // Align the unsized value to the end of the ArcInner. + // Because it is ?Sized, it will always be the last field in memory. + let align = align_of_val(&*ptr); + let layout = Layout::new::>(); + (layout.size() + layout.padding_needed_for(align)) as isize +} + +/// Computes the offset of the data field within ArcInner. +/// +/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`. +fn data_offset_sized() -> isize { + let align = align_of::(); + let layout = Layout::new::>(); + (layout.size() + layout.padding_needed_for(align)) as isize +} From 4f1dcb34dffc26a23fa8c2cac69a31d7557fd173 Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Sun, 19 May 2019 12:46:37 +0200 Subject: [PATCH 16/23] rc::Weak::{as,from,into}_raw Methods on the Weak to access it as a raw pointer to the data. --- src/liballoc/rc.rs | 162 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 156 insertions(+), 6 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 0dffb19476f3d..1f357a719bb43 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -239,7 +239,7 @@ use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::abort; use core::marker::{self, Unpin, Unsize, PhantomData}; -use core::mem::{self, align_of_val, forget, size_of_val}; +use core::mem::{self, align_of, align_of_val, forget, size_of_val}; use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn}; use core::pin::Pin; use core::ptr::{self, NonNull}; @@ -416,11 +416,7 @@ impl Rc { /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - // Align the unsized value to the end of the RcBox. - // Because it is ?Sized, it will always be the last field in memory. - let align = align_of_val(&*ptr); - let layout = Layout::new::>(); - let offset = (layout.size() + layout.padding_needed_for(align)) as isize; + let offset = data_offset(ptr); // Reverse the offset to find the original RcBox. let fake_ptr = ptr as *mut RcBox; @@ -1262,6 +1258,143 @@ impl Weak { ptr: NonNull::new(usize::MAX as *mut RcBox).expect("MAX is not 0"), } } + + /// Returns a raw pointer to the object `T` pointed to by this `Weak`. + /// + /// It is up to the caller to ensure that the object is still alive when accessing it through + /// the pointer. + /// + /// The pointer may be [`null`] or be dangling in case the object has already been destroyed. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::rc::{Rc, Weak}; + /// use std::ptr; + /// + /// let strong = Rc::new(42); + /// let weak = Rc::downgrade(&strong); + /// // Both point to the same object + /// assert!(ptr::eq(&*strong, Weak::as_raw(&weak))); + /// // The strong here keeps it alive, so we can still access the object. + /// assert_eq!(42, unsafe { *Weak::as_raw(&weak) }); + /// + /// drop(strong); + /// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to + /// // undefined behaviour. + /// // assert_eq!(42, unsafe { *Weak::as_raw(&weak) }); + /// ``` + /// + /// [`null`]: ../../std/ptr/fn.null.html + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub fn as_raw(this: &Self) -> *const T { + match this.inner() { + None => ptr::null(), + Some(inner) => { + let offset = data_offset_sized::(); + let ptr = inner as *const RcBox; + // Note: while the pointer we create may already point to dropped value, the + // allocation still lives (it must hold the weak point as long as we are alive). + // Therefore, the offset is OK to do, it won't get out of the allocation. + let ptr = unsafe { (ptr as *const u8).offset(offset) }; + ptr as *const T + } + } + } + + /// Consumes the `Weak` and turns it into a raw pointer. + /// + /// This converts the weak pointer into a raw pointer, preserving the original weak count. It + /// can be turned back into the `Weak` with [`from_raw`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_raw`] apply. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::rc::{Rc, Weak}; + /// + /// let strong = Rc::new(42); + /// let weak = Rc::downgrade(&strong); + /// let raw = Weak::into_raw(weak); + /// + /// assert_eq!(1, Rc::weak_count(&strong)); + /// assert_eq!(42, unsafe { *raw }); + /// + /// drop(unsafe { Weak::from_raw(raw) }); + /// assert_eq!(0, Rc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw`]: struct.Weak.html#method.from_raw + /// [`as_raw`]: struct.Weak.html#method.as_raw + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub fn into_raw(this: Self) -> *const T { + let result = Self::as_raw(&this); + mem::forget(this); + result + } + + /// Converts a raw pointer previously created by [`into_raw`] back into `Weak`. + /// + /// This can be used to safely get a strong reference (by calling [`upgrade`] + /// later) or to deallocate the weak count by dropping the `Weak`. + /// + /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is + /// returned. + /// + /// # Safety + /// + /// The pointer must represent one valid weak count. In other words, it must point to `T` which + /// is or *was* managed by an [`Rc`] and the weak count of that [`Rc`] must not have reached + /// 0. It is allowed for the strong count to be 0. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::rc::{Rc, Weak}; + /// + /// let strong = Rc::new(42); + /// + /// let raw_1 = Weak::into_raw(Rc::downgrade(&strong)); + /// let raw_2 = Weak::into_raw(Rc::downgrade(&strong)); + /// + /// assert_eq!(2, Rc::weak_count(&strong)); + /// + /// assert_eq!(42, *Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap()); + /// assert_eq!(1, Rc::weak_count(&strong)); + /// + /// drop(strong); + /// + /// // Decrement the last weak count. + /// assert!(Weak::upgrade(&unsafe { Weak::from_raw(raw_2) }).is_none()); + /// ``` + /// + /// [`null`]: ../../std/ptr/fn.null.html + /// [`into_raw`]: struct.Weak.html#method.into_raw + /// [`upgrade`]: struct.Weak.html#method.upgrade + /// [`Rc`]: struct.Rc.html + /// [`Weak`]: struct.Weak.html + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + if ptr.is_null() { + Self::new() + } else { + // See Rc::from_raw for details + let offset = data_offset(ptr); + let fake_ptr = ptr as *mut RcBox; + let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); + Weak { + ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw"), + } + } + } } pub(crate) fn is_dangling(ptr: NonNull) -> bool { @@ -2007,3 +2140,20 @@ impl AsRef for Rc { #[stable(feature = "pin", since = "1.33.0")] impl Unpin for Rc { } + +unsafe fn data_offset(ptr: *const T) -> isize { + // Align the unsized value to the end of the RcBox. + // Because it is ?Sized, it will always be the last field in memory. + let align = align_of_val(&*ptr); + let layout = Layout::new::>(); + (layout.size() + layout.padding_needed_for(align)) as isize +} + +/// Computes the offset of the data field within ArcInner. +/// +/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`. +fn data_offset_sized() -> isize { + let align = align_of::(); + let layout = Layout::new::>(); + (layout.size() + layout.padding_needed_for(align)) as isize +} From 96e3fb255bfcae8ce7210985bf75e77335d22580 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 25 May 2019 21:45:51 +0200 Subject: [PATCH 17/23] librustc_errors: Move annotation collection to own impl Extracted from work on #59346. This moves the annotation collection to the `FileWithAnnotatedLines` impl to allow re-use in a separate EmitterWriter. --- src/librustc_errors/emitter.rs | 341 +++++++++++++++++---------------- 1 file changed, 174 insertions(+), 167 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 890d2c5ce0b80..e1112a1557771 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -162,6 +162,7 @@ impl ColorConfig { } } +/// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short` pub struct EmitterWriter { dst: Destination, sm: Option>, @@ -170,7 +171,8 @@ pub struct EmitterWriter { ui_testing: bool, } -struct FileWithAnnotatedLines { +#[derive(Debug)] +pub struct FileWithAnnotatedLines { file: Lrc, lines: Vec, multiline_depth: usize, @@ -221,169 +223,6 @@ impl EmitterWriter { } } - fn preprocess_annotations(&mut self, msp: &MultiSpan) -> Vec { - fn add_annotation_to_file(file_vec: &mut Vec, - file: Lrc, - line_index: usize, - ann: Annotation) { - - for slot in file_vec.iter_mut() { - // Look through each of our files for the one we're adding to - if slot.file.name == file.name { - // See if we already have a line for it - for line_slot in &mut slot.lines { - if line_slot.line_index == line_index { - line_slot.annotations.push(ann); - return; - } - } - // We don't have a line yet, create one - slot.lines.push(Line { - line_index, - annotations: vec![ann], - }); - slot.lines.sort(); - return; - } - } - // This is the first time we're seeing the file - file_vec.push(FileWithAnnotatedLines { - file, - lines: vec![Line { - line_index, - annotations: vec![ann], - }], - multiline_depth: 0, - }); - } - - let mut output = vec![]; - let mut multiline_annotations = vec![]; - - if let Some(ref sm) = self.sm { - for span_label in msp.span_labels() { - if span_label.span.is_dummy() { - continue; - } - - let lo = sm.lookup_char_pos(span_label.span.lo()); - let mut hi = sm.lookup_char_pos(span_label.span.hi()); - - // Watch out for "empty spans". If we get a span like 6..6, we - // want to just display a `^` at 6, so convert that to - // 6..7. This is degenerate input, but it's best to degrade - // gracefully -- and the parser likes to supply a span like - // that for EOF, in particular. - - if lo.col_display == hi.col_display && lo.line == hi.line { - hi.col_display += 1; - } - - let ann_type = if lo.line != hi.line { - let ml = MultilineAnnotation { - depth: 1, - line_start: lo.line, - line_end: hi.line, - start_col: lo.col_display, - end_col: hi.col_display, - is_primary: span_label.is_primary, - label: span_label.label.clone(), - overlaps_exactly: false, - }; - multiline_annotations.push((lo.file.clone(), ml.clone())); - AnnotationType::Multiline(ml) - } else { - AnnotationType::Singleline - }; - let ann = Annotation { - start_col: lo.col_display, - end_col: hi.col_display, - is_primary: span_label.is_primary, - label: span_label.label.clone(), - annotation_type: ann_type, - }; - - if !ann.is_multiline() { - add_annotation_to_file(&mut output, lo.file, lo.line, ann); - } - } - } - - // Find overlapping multiline annotations, put them at different depths - multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, ml.line_end)); - for item in multiline_annotations.clone() { - let ann = item.1; - for item in multiline_annotations.iter_mut() { - let ref mut a = item.1; - // Move all other multiline annotations overlapping with this one - // one level to the right. - if !(ann.same_span(a)) && - num_overlap(ann.line_start, ann.line_end, a.line_start, a.line_end, true) - { - a.increase_depth(); - } else if ann.same_span(a) && &ann != a { - a.overlaps_exactly = true; - } else { - break; - } - } - } - - let mut max_depth = 0; // max overlapping multiline spans - for (file, ann) in multiline_annotations { - if ann.depth > max_depth { - max_depth = ann.depth; - } - let mut end_ann = ann.as_end(); - if !ann.overlaps_exactly { - // avoid output like - // - // | foo( - // | _____^ - // | |_____| - // | || bar, - // | || ); - // | || ^ - // | ||______| - // | |______foo - // | baz - // - // and instead get - // - // | foo( - // | _____^ - // | | bar, - // | | ); - // | | ^ - // | | | - // | |______foo - // | baz - add_annotation_to_file(&mut output, file.clone(), ann.line_start, ann.as_start()); - // 4 is the minimum vertical length of a multiline span when presented: two lines - // of code and two lines of underline. This is not true for the special case where - // the beginning doesn't have an underline, but the current logic seems to be - // working correctly. - let middle = min(ann.line_start + 4, ann.line_end); - for line in ann.line_start + 1..middle { - // Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`). - add_annotation_to_file(&mut output, file.clone(), line, ann.as_line()); - } - if middle < ann.line_end - 1 { - for line in ann.line_end - 1..ann.line_end { - add_annotation_to_file(&mut output, file.clone(), line, ann.as_line()); - } - } - } else { - end_ann.annotation_type = AnnotationType::Singleline; - } - add_annotation_to_file(&mut output, file, ann.line_end, end_ann); - } - for file_vec in output.iter_mut() { - file_vec.multiline_depth = max_depth; - } - output - } - fn render_source_line(&self, buffer: &mut StyledBuffer, file: Lrc, @@ -1093,9 +932,7 @@ impl EmitterWriter { } } - // Preprocess all the annotations so that they are grouped by file and by line number - // This helps us quickly iterate over the whole message (including secondary file spans) - let mut annotated_files = self.preprocess_annotations(msp); + let mut annotated_files = FileWithAnnotatedLines::collect_annotations(msp, &self.sm); // Make sure our primary file comes first let (primary_lo, sm) = if let (Some(sm), Some(ref primary_span)) = @@ -1503,6 +1340,176 @@ impl EmitterWriter { } } +impl FileWithAnnotatedLines { + /// Preprocess all the annotations so that they are grouped by file and by line number + /// This helps us quickly iterate over the whole message (including secondary file spans) + pub fn collect_annotations( + msp: &MultiSpan, + source_map: &Option> + ) -> Vec { + fn add_annotation_to_file(file_vec: &mut Vec, + file: Lrc, + line_index: usize, + ann: Annotation) { + + for slot in file_vec.iter_mut() { + // Look through each of our files for the one we're adding to + if slot.file.name == file.name { + // See if we already have a line for it + for line_slot in &mut slot.lines { + if line_slot.line_index == line_index { + line_slot.annotations.push(ann); + return; + } + } + // We don't have a line yet, create one + slot.lines.push(Line { + line_index, + annotations: vec![ann], + }); + slot.lines.sort(); + return; + } + } + // This is the first time we're seeing the file + file_vec.push(FileWithAnnotatedLines { + file, + lines: vec![Line { + line_index, + annotations: vec![ann], + }], + multiline_depth: 0, + }); + } + + let mut output = vec![]; + let mut multiline_annotations = vec![]; + + if let Some(ref sm) = source_map { + for span_label in msp.span_labels() { + if span_label.span.is_dummy() { + continue; + } + + let lo = sm.lookup_char_pos(span_label.span.lo()); + let mut hi = sm.lookup_char_pos(span_label.span.hi()); + + // Watch out for "empty spans". If we get a span like 6..6, we + // want to just display a `^` at 6, so convert that to + // 6..7. This is degenerate input, but it's best to degrade + // gracefully -- and the parser likes to supply a span like + // that for EOF, in particular. + + if lo.col_display == hi.col_display && lo.line == hi.line { + hi.col_display += 1; + } + + let ann_type = if lo.line != hi.line { + let ml = MultilineAnnotation { + depth: 1, + line_start: lo.line, + line_end: hi.line, + start_col: lo.col_display, + end_col: hi.col_display, + is_primary: span_label.is_primary, + label: span_label.label.clone(), + overlaps_exactly: false, + }; + multiline_annotations.push((lo.file.clone(), ml.clone())); + AnnotationType::Multiline(ml) + } else { + AnnotationType::Singleline + }; + let ann = Annotation { + start_col: lo.col_display, + end_col: hi.col_display, + is_primary: span_label.is_primary, + label: span_label.label.clone(), + annotation_type: ann_type, + }; + + if !ann.is_multiline() { + add_annotation_to_file(&mut output, lo.file, lo.line, ann); + } + } + } + + // Find overlapping multiline annotations, put them at different depths + multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, ml.line_end)); + for item in multiline_annotations.clone() { + let ann = item.1; + for item in multiline_annotations.iter_mut() { + let ref mut a = item.1; + // Move all other multiline annotations overlapping with this one + // one level to the right. + if !(ann.same_span(a)) && + num_overlap(ann.line_start, ann.line_end, a.line_start, a.line_end, true) + { + a.increase_depth(); + } else if ann.same_span(a) && &ann != a { + a.overlaps_exactly = true; + } else { + break; + } + } + } + + let mut max_depth = 0; // max overlapping multiline spans + for (file, ann) in multiline_annotations { + if ann.depth > max_depth { + max_depth = ann.depth; + } + let mut end_ann = ann.as_end(); + if !ann.overlaps_exactly { + // avoid output like + // + // | foo( + // | _____^ + // | |_____| + // | || bar, + // | || ); + // | || ^ + // | ||______| + // | |______foo + // | baz + // + // and instead get + // + // | foo( + // | _____^ + // | | bar, + // | | ); + // | | ^ + // | | | + // | |______foo + // | baz + add_annotation_to_file(&mut output, file.clone(), ann.line_start, ann.as_start()); + // 4 is the minimum vertical length of a multiline span when presented: two lines + // of code and two lines of underline. This is not true for the special case where + // the beginning doesn't have an underline, but the current logic seems to be + // working correctly. + let middle = min(ann.line_start + 4, ann.line_end); + for line in ann.line_start + 1..middle { + // Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`). + add_annotation_to_file(&mut output, file.clone(), line, ann.as_line()); + } + if middle < ann.line_end - 1 { + for line in ann.line_end - 1..ann.line_end { + add_annotation_to_file(&mut output, file.clone(), line, ann.as_line()); + } + } + } else { + end_ann.annotation_type = AnnotationType::Singleline; + } + add_annotation_to_file(&mut output, file, ann.line_end, end_ann); + } + for file_vec in output.iter_mut() { + file_vec.multiline_depth = max_depth; + } + output + } +} + fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) { buffer.puts(line, col, "| ", Style::LineNumber); } From 0631d19c9a8d4b31828f0c980bec3d1699e5c10b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 28 May 2019 22:46:48 +0200 Subject: [PATCH 18/23] Avoid unneeded bug!() call --- src/librustc_codegen_ssa/mir/place.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 670b6c472698d..cd32d6f484d73 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -396,22 +396,20 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let cx = self.cx; let tcx = self.cx.tcx(); - if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place { - match self.locals[index] { - LocalRef::Place(place) => { - return place; - } - LocalRef::UnsizedPlace(place) => { - return bx.load_operand(place).deref(cx); - } - LocalRef::Operand(..) => { - bug!("using operand local {:?} as place", place); + let result = match *place { + mir::Place::Base(mir::PlaceBase::Local(index)) => { + match self.locals[index] { + LocalRef::Place(place) => { + return place; + } + LocalRef::UnsizedPlace(place) => { + return bx.load_operand(place).deref(cx); + } + LocalRef::Operand(..) => { + bug!("using operand local {:?} as place", place); + } } } - } - - let result = match *place { - mir::Place::Base(mir::PlaceBase::Local(_)) => bug!(), // handled above mir::Place::Base( mir::PlaceBase::Static( box mir::Static { ty, kind: mir::StaticKind::Promoted(promoted) } From 120ce12016005e73dfe01a67aa34c02f0eb432e2 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 29 May 2019 00:35:14 +0300 Subject: [PATCH 19/23] Rename `TraitOrImpl` to `Assoc` and `trait_or_impl` to `assoc`. --- src/librustc_privacy/lib.rs | 25 +++++++++++++++++++------ src/librustc_resolve/lib.rs | 12 ++++++------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 68930533a285c..a08c028390bf7 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1703,8 +1703,13 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { } } - fn check_trait_or_impl_item(&self, hir_id: hir::HirId, assoc_item_kind: AssocItemKind, - defaultness: hir::Defaultness, vis: ty::Visibility) { + fn check_assoc_item( + &self, + hir_id: hir::HirId, + assoc_item_kind: AssocItemKind, + defaultness: hir::Defaultness, + vis: ty::Visibility, + ) { let mut check = self.check(hir_id, vis); let (check_ty, is_assoc_ty) = match assoc_item_kind { @@ -1754,8 +1759,12 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> self.check(item.hir_id, item_visibility).generics().predicates(); for trait_item_ref in trait_item_refs { - self.check_trait_or_impl_item(trait_item_ref.id.hir_id, trait_item_ref.kind, - trait_item_ref.defaultness, item_visibility); + self.check_assoc_item( + trait_item_ref.id.hir_id, + trait_item_ref.kind, + trait_item_ref.defaultness, + item_visibility, + ); } } hir::ItemKind::TraitAlias(..) => { @@ -1803,8 +1812,12 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> } else { impl_vis }; - self.check_trait_or_impl_item(impl_item_ref.id.hir_id, impl_item_ref.kind, - impl_item_ref.defaultness, impl_item_vis); + self.check_assoc_item( + impl_item_ref.id.hir_id, + impl_item_ref.kind, + impl_item_ref.defaultness, + impl_item_vis, + ); } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c05b69ab44f42..9b7b44025c13f 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -860,7 +860,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { FnKind::ItemFn(_, ref header, ..) => (FnItemRibKind, &header.asyncness.node), FnKind::Method(_, ref sig, _, _) => - (TraitOrImplItemRibKind, &sig.header.asyncness.node), + (AssocItemRibKind, &sig.header.asyncness.node), FnKind::Closure(_) => // Async closures aren't resolved through `visit_fn`-- they're // processed separately @@ -1033,7 +1033,7 @@ enum RibKind<'a> { /// methods or associated types. Allow references to ty params that impl or trait /// binds. Disallow any other upvars (including other ty params that are /// upvars). - TraitOrImplItemRibKind, + AssocItemRibKind, /// We passed through a function definition. Disallow upvars. /// Permit only those const parameters that are specified in the function's generics. @@ -2612,7 +2612,7 @@ impl<'a> Resolver<'a> { for trait_item in trait_items { let generic_params = HasGenericParams(&trait_item.generics, - TraitOrImplItemRibKind); + AssocItemRibKind); this.with_generic_param_rib(generic_params, |this| { match trait_item.node { TraitItemKind::Const(ref ty, ref default) => { @@ -2899,7 +2899,7 @@ impl<'a> Resolver<'a> { // We also need a new scope for the impl item type parameters. let generic_params = HasGenericParams(&impl_item.generics, - TraitOrImplItemRibKind); + AssocItemRibKind); this.with_generic_param_rib(generic_params, |this| { use self::ResolutionError::*; match impl_item.node { @@ -4074,7 +4074,7 @@ impl<'a> Resolver<'a> { seen.insert(node_id, depth); } } - ItemRibKind | FnItemRibKind | TraitOrImplItemRibKind => { + ItemRibKind | FnItemRibKind | AssocItemRibKind => { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. @@ -4103,7 +4103,7 @@ impl<'a> Resolver<'a> { Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => { for rib in ribs { match rib.kind { - NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) | + NormalRibKind | AssocItemRibKind | ClosureRibKind(..) | ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind | ConstantItemRibKind | TyParamAsConstParamTy => { // Nothing to do. Continue. From 03d32905e7312b0179103e8cc338876c81098da4 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 29 May 2019 01:01:32 +0300 Subject: [PATCH 20/23] rustc_codegen_ssa: remove obsolete codegen stats. --- src/librustc/mir/mono.rs | 18 ------------------ src/librustc_codegen_ssa/base.rs | 10 ---------- 2 files changed, 28 deletions(-) diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index a26468b0fb6ce..eeefaa4dd492c 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -190,12 +190,6 @@ impl<'a, 'tcx> HashStable> for CodegenUnit<'tcx> { #[derive(Clone, Default)] pub struct Stats { - pub n_glues_created: usize, - pub n_null_glues: usize, - pub n_real_glues: usize, - pub n_fns: usize, - pub n_inlines: usize, - pub n_closures: usize, pub n_llvm_insns: usize, pub llvm_insns: FxHashMap, // (ident, llvm-instructions) @@ -203,12 +197,6 @@ pub struct Stats { } impl_stable_hash_for!(struct self::Stats { - n_glues_created, - n_null_glues, - n_real_glues, - n_fns, - n_inlines, - n_closures, n_llvm_insns, llvm_insns, fn_stats @@ -216,12 +204,6 @@ impl_stable_hash_for!(struct self::Stats { impl Stats { pub fn extend(&mut self, stats: Stats) { - self.n_glues_created += stats.n_glues_created; - self.n_null_glues += stats.n_null_glues; - self.n_real_glues += stats.n_real_glues; - self.n_fns += stats.n_fns; - self.n_inlines += stats.n_inlines; - self.n_closures += stats.n_closures; self.n_llvm_insns += stats.n_llvm_insns; for (k, v) in stats.llvm_insns { diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 0b037f872475d..67d3a2113067c 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -85,7 +85,6 @@ impl<'a, 'tcx, Cx: CodegenMethods<'tcx>> Drop for StatRecorder<'a, 'tcx, Cx> { let mut stats = self.cx.stats().borrow_mut(); let iend = stats.n_llvm_insns; stats.fn_stats.push((self.name.take().unwrap(), iend - self.istart)); - stats.n_fns += 1; // Reset LLVM insn count to avoid compound costs. stats.n_llvm_insns = self.istart; } @@ -428,8 +427,6 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( let lldecl = cx.instances().borrow().get(&instance).cloned().unwrap_or_else(|| bug!("Instance `{:?}` not already declared", instance)); - cx.stats().borrow_mut().n_closures += 1; - let mir = cx.tcx().instance_mir(instance.def); mir::codegen_mir::(cx, lldecl, &mir, instance, sig); } @@ -703,13 +700,6 @@ pub fn codegen_crate( if tcx.sess.codegen_stats() { println!("--- codegen stats ---"); - println!("n_glues_created: {}", all_stats.n_glues_created); - println!("n_null_glues: {}", all_stats.n_null_glues); - println!("n_real_glues: {}", all_stats.n_real_glues); - - println!("n_fns: {}", all_stats.n_fns); - println!("n_inlines: {}", all_stats.n_inlines); - println!("n_closures: {}", all_stats.n_closures); println!("fn stats:"); all_stats.fn_stats.sort_by_key(|&(_, insns)| insns); for &(ref name, insns) in all_stats.fn_stats.iter() { From 29b7c0687e4408fcd94bad8bf7c25142573c5065 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 29 May 2019 01:21:27 +0300 Subject: [PATCH 21/23] rustc_codegen_llvm: remove LLVM instruction count stats. --- src/librustc/mir/mono.rs | 25 ----- src/librustc/session/config.rs | 13 --- src/librustc/session/mod.rs | 6 -- src/librustc_codegen_llvm/base.rs | 34 +++---- src/librustc_codegen_llvm/builder.rs | 107 --------------------- src/librustc_codegen_llvm/context.rs | 11 --- src/librustc_codegen_llvm/lib.rs | 5 +- src/librustc_codegen_ssa/base.rs | 64 +----------- src/librustc_codegen_ssa/traits/backend.rs | 3 +- src/librustc_codegen_ssa/traits/misc.rs | 3 - 10 files changed, 20 insertions(+), 251 deletions(-) diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index eeefaa4dd492c..ca79bc15358c5 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -188,31 +188,6 @@ impl<'a, 'tcx> HashStable> for CodegenUnit<'tcx> { } } -#[derive(Clone, Default)] -pub struct Stats { - pub n_llvm_insns: usize, - pub llvm_insns: FxHashMap, - // (ident, llvm-instructions) - pub fn_stats: Vec<(String, usize)>, -} - -impl_stable_hash_for!(struct self::Stats { - n_llvm_insns, - llvm_insns, - fn_stats -}); - -impl Stats { - pub fn extend(&mut self, stats: Stats) { - self.n_llvm_insns += stats.n_llvm_insns; - - for (k, v) in stats.llvm_insns { - *self.llvm_insns.entry(k).or_insert(0) += v; - } - self.fn_stats.extend(stats.fn_stats); - } -} - pub struct CodegenUnitNameBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, cache: FxHashMap, diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index f4ee39d69883c..300d0cbfba55b 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1216,21 +1216,12 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "measure time of each rustc pass"), time: bool = (false, parse_bool, [UNTRACKED], "measure time of rustc processes"), - count_llvm_insns: bool = (false, parse_bool, - [UNTRACKED_WITH_WARNING(true, - "The output generated by `-Z count_llvm_insns` might not be reliable \ - when used with incremental compilation")], - "count where LLVM instrs originate"), time_llvm_passes: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true, "The output of `-Z time-llvm-passes` will only reflect timings of \ re-codegened modules when used with incremental compilation" )], "measure time of each LLVM pass"), input_stats: bool = (false, parse_bool, [UNTRACKED], "gather statistics about the input"), - codegen_stats: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true, - "The output of `-Z codegen-stats` might not be accurate when incremental \ - compilation is enabled")], - "gather codegen statistics"), asm_comments: bool = (false, parse_bool, [TRACKED], "generate comments into the assembly (may change behavior)"), verify_llvm_ir: bool = (false, parse_bool, [TRACKED], @@ -3259,14 +3250,10 @@ mod tests { assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.time_passes = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.count_llvm_insns = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.time_llvm_passes = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.input_stats = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.codegen_stats = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.borrowck_stats = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.meta_stats = true; diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 974a5bb70e653..2726a4770c860 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -519,15 +519,9 @@ impl Session { pub fn instrument_mcount(&self) -> bool { self.opts.debugging_opts.instrument_mcount } - pub fn count_llvm_insns(&self) -> bool { - self.opts.debugging_opts.count_llvm_insns - } pub fn time_llvm_passes(&self) -> bool { self.opts.debugging_opts.time_llvm_passes } - pub fn codegen_stats(&self) -> bool { - self.opts.debugging_opts.codegen_stats - } pub fn meta_stats(&self) -> bool { self.opts.debugging_opts.meta_stats } diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 9077e89a4020e..f8c6087373f1e 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -24,7 +24,7 @@ use crate::common; use crate::context::CodegenCx; use crate::monomorphize::partitioning::CodegenUnitExt; use rustc::dep_graph; -use rustc::mir::mono::{Linkage, Visibility, Stats}; +use rustc::mir::mono::{Linkage, Visibility}; use rustc::middle::cstore::{EncodedMetadata}; use rustc::ty::TyCtxt; use rustc::middle::exported_symbols; @@ -104,17 +104,17 @@ pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> { } } -pub fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - cgu_name: InternedString) - -> Stats { +pub fn compile_codegen_unit(tcx: TyCtxt<'a, 'tcx, 'tcx>, cgu_name: InternedString) { let start_time = Instant::now(); let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx); - let ((stats, module), _) = tcx.dep_graph.with_task(dep_node, - tcx, - cgu_name, - module_codegen, - dep_graph::hash_result); + let (module, _) = tcx.dep_graph.with_task( + dep_node, + tcx, + cgu_name, + module_codegen, + dep_graph::hash_result, + ); let time_to_codegen = start_time.elapsed(); // We assume that the cost to run LLVM on a CGU is proportional to @@ -123,17 +123,15 @@ pub fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, time_to_codegen.subsec_nanos() as u64; submit_codegened_module_to_llvm(&LlvmCodegenBackend(()), tcx, module, cost); - return stats; fn module_codegen<'ll, 'tcx>( tcx: TyCtxt<'ll, 'tcx, 'tcx>, - cgu_name: InternedString) - -> (Stats, ModuleCodegen) - { + cgu_name: InternedString, + ) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str()); - let stats = { + { let cx = CodegenCx::new(tcx, cgu, &llvm_module); let mono_items = cx.codegen_unit .items_in_deterministic_order(cx.tcx); @@ -169,15 +167,13 @@ pub fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if cx.sess().opts.debuginfo != DebugInfo::None { cx.debuginfo_finalize(); } + } - cx.consume_stats().into_inner() - }; - - (stats, ModuleCodegen { + ModuleCodegen { name: cgu_name.to_string(), module_llvm: llvm_module, kind: ModuleKind::Regular, - }) + } } } diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 48808eea3045e..79c58fbf6e465 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -147,21 +147,18 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn ret_void(&mut self) { - self.count_insn("retvoid"); unsafe { llvm::LLVMBuildRetVoid(self.llbuilder); } } fn ret(&mut self, v: &'ll Value) { - self.count_insn("ret"); unsafe { llvm::LLVMBuildRet(self.llbuilder, v); } } fn br(&mut self, dest: &'ll BasicBlock) { - self.count_insn("br"); unsafe { llvm::LLVMBuildBr(self.llbuilder, dest); } @@ -173,7 +170,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { then_llbb: &'ll BasicBlock, else_llbb: &'ll BasicBlock, ) { - self.count_insn("condbr"); unsafe { llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb); } @@ -204,7 +200,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { catch: &'ll BasicBlock, funclet: Option<&Funclet<'ll>>, ) -> &'ll Value { - self.count_insn("invoke"); debug!("Invoke {:?} with args ({:?})", llfn, @@ -227,7 +222,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn unreachable(&mut self) { - self.count_insn("unreachable"); unsafe { llvm::LLVMBuildUnreachable(self.llbuilder); } @@ -235,21 +229,18 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { /* Arithmetic */ fn add(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("add"); unsafe { llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname()) } } fn fadd(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("fadd"); unsafe { llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname()) } } fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("fadd"); unsafe { let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname()); llvm::LLVMRustSetHasUnsafeAlgebra(instr); @@ -258,21 +249,18 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn sub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("sub"); unsafe { llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname()) } } fn fsub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("fsub"); unsafe { llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname()) } } fn fsub_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("fsub"); unsafe { let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname()); llvm::LLVMRustSetHasUnsafeAlgebra(instr); @@ -281,21 +269,18 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn mul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("mul"); unsafe { llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname()) } } fn fmul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("fmul"); unsafe { llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname()) } } fn fmul_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("fmul"); unsafe { let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname()); llvm::LLVMRustSetHasUnsafeAlgebra(instr); @@ -305,42 +290,36 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn udiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("udiv"); unsafe { llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname()) } } fn exactudiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("exactudiv"); unsafe { llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname()) } } fn sdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("sdiv"); unsafe { llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname()) } } fn exactsdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("exactsdiv"); unsafe { llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname()) } } fn fdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("fdiv"); unsafe { llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname()) } } fn fdiv_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("fdiv"); unsafe { let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname()); llvm::LLVMRustSetHasUnsafeAlgebra(instr); @@ -349,28 +328,24 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn urem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("urem"); unsafe { llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname()) } } fn srem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("srem"); unsafe { llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname()) } } fn frem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("frem"); unsafe { llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname()) } } fn frem_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("frem"); unsafe { let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname()); llvm::LLVMRustSetHasUnsafeAlgebra(instr); @@ -379,63 +354,54 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn shl(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("shl"); unsafe { llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname()) } } fn lshr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("lshr"); unsafe { llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname()) } } fn ashr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("ashr"); unsafe { llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname()) } } fn and(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("and"); unsafe { llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname()) } } fn or(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("or"); unsafe { llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname()) } } fn xor(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("xor"); unsafe { llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname()) } } fn neg(&mut self, v: &'ll Value) -> &'ll Value { - self.count_insn("neg"); unsafe { llvm::LLVMBuildNeg(self.llbuilder, v, noname()) } } fn fneg(&mut self, v: &'ll Value) -> &'ll Value { - self.count_insn("fneg"); unsafe { llvm::LLVMBuildFNeg(self.llbuilder, v, noname()) } } fn not(&mut self, v: &'ll Value) -> &'ll Value { - self.count_insn("not"); unsafe { llvm::LLVMBuildNot(self.llbuilder, v, noname()) } @@ -524,7 +490,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { - self.count_insn("alloca"); unsafe { let alloca = if name.is_empty() { llvm::LLVMBuildAlloca(self.llbuilder, ty, noname()) @@ -543,7 +508,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { len: &'ll Value, name: &str, align: Align) -> &'ll Value { - self.count_insn("alloca"); unsafe { let alloca = if name.is_empty() { llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, noname()) @@ -558,7 +522,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value { - self.count_insn("load"); unsafe { let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); llvm::LLVMSetAlignment(load, align.bytes() as c_uint); @@ -567,7 +530,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value { - self.count_insn("load.volatile"); unsafe { let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); llvm::LLVMSetVolatile(insn, llvm::True); @@ -581,7 +543,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { order: rustc_codegen_ssa::common::AtomicOrdering, size: Size, ) -> &'ll Value { - self.count_insn("load.atomic"); unsafe { let load = llvm::LLVMRustBuildAtomicLoad( self.llbuilder, @@ -745,7 +706,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { flags: MemFlags, ) -> &'ll Value { debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags); - self.count_insn("store"); let ptr = self.check_store(val, ptr); unsafe { let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr); @@ -774,7 +734,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn atomic_store(&mut self, val: &'ll Value, ptr: &'ll Value, order: rustc_codegen_ssa::common::AtomicOrdering, size: Size) { debug!("Store {:?} -> {:?}", val, ptr); - self.count_insn("store.atomic"); let ptr = self.check_store(val, ptr); unsafe { let store = llvm::LLVMRustBuildAtomicStore( @@ -789,7 +748,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value { - self.count_insn("gep"); unsafe { llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, noname()) @@ -797,7 +755,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn inbounds_gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value { - self.count_insn("inboundsgep"); unsafe { llvm::LLVMBuildInBoundsGEP( self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, noname()) @@ -805,7 +762,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn struct_gep(&mut self, ptr: &'ll Value, idx: u64) -> &'ll Value { - self.count_insn("structgep"); assert_eq!(idx as c_uint as u64, idx); unsafe { llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname()) @@ -814,77 +770,66 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { /* Casts */ fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - self.count_insn("trunc"); unsafe { llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname()) } } fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - self.count_insn("sext"); unsafe { llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname()) } } fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - self.count_insn("fptoui"); unsafe { llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname()) } } fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - self.count_insn("fptosi"); unsafe { llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname()) } } fn uitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - self.count_insn("uitofp"); unsafe { llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname()) } } fn sitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - self.count_insn("sitofp"); unsafe { llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname()) } } fn fptrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - self.count_insn("fptrunc"); unsafe { llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname()) } } fn fpext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - self.count_insn("fpext"); unsafe { llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname()) } } fn ptrtoint(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - self.count_insn("ptrtoint"); unsafe { llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname()) } } fn inttoptr(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - self.count_insn("inttoptr"); unsafe { llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname()) } } fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - self.count_insn("bitcast"); unsafe { llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname()) } @@ -892,14 +837,12 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value { - self.count_insn("intcast"); unsafe { llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed) } } fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - self.count_insn("pointercast"); unsafe { llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname()) } @@ -907,7 +850,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { /* Comparisons */ fn icmp(&mut self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("icmp"); let op = llvm::IntPredicate::from_generic(op); unsafe { llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname()) @@ -915,7 +857,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn fcmp(&mut self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("fcmp"); unsafe { llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname()) } @@ -984,7 +925,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { then_val: &'ll Value, else_val: &'ll Value, ) -> &'ll Value { - self.count_insn("select"); unsafe { llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname()) } @@ -992,14 +932,12 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { #[allow(dead_code)] fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { - self.count_insn("vaarg"); unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname()) } } fn extract_element(&mut self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value { - self.count_insn("extractelement"); unsafe { llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname()) } @@ -1016,7 +954,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn extract_value(&mut self, agg_val: &'ll Value, idx: u64) -> &'ll Value { - self.count_insn("extractvalue"); assert_eq!(idx as c_uint as u64, idx); unsafe { llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname()) @@ -1025,7 +962,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn insert_value(&mut self, agg_val: &'ll Value, elt: &'ll Value, idx: u64) -> &'ll Value { - self.count_insn("insertvalue"); assert_eq!(idx as c_uint as u64, idx); unsafe { llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint, @@ -1035,7 +971,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn landing_pad(&mut self, ty: &'ll Type, pers_fn: &'ll Value, num_clauses: usize) -> &'ll Value { - self.count_insn("landingpad"); unsafe { llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn, num_clauses as c_uint, noname()) @@ -1043,14 +978,12 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn set_cleanup(&mut self, landing_pad: &'ll Value) { - self.count_insn("setcleanup"); unsafe { llvm::LLVMSetCleanup(landing_pad, llvm::True); } } fn resume(&mut self, exn: &'ll Value) -> &'ll Value { - self.count_insn("resume"); unsafe { llvm::LLVMBuildResume(self.llbuilder, exn) } @@ -1059,7 +992,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Funclet<'ll> { - self.count_insn("cleanuppad"); let name = const_cstr!("cleanuppad"); let ret = unsafe { llvm::LLVMRustBuildCleanupPad(self.llbuilder, @@ -1075,7 +1007,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { &mut self, funclet: &Funclet<'ll>, unwind: Option<&'ll BasicBlock>, ) -> &'ll Value { - self.count_insn("cleanupret"); let ret = unsafe { llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind) }; @@ -1085,7 +1016,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn catch_pad(&mut self, parent: &'ll Value, args: &[&'ll Value]) -> Funclet<'ll> { - self.count_insn("catchpad"); let name = const_cstr!("catchpad"); let ret = unsafe { llvm::LLVMRustBuildCatchPad(self.llbuilder, parent, @@ -1101,7 +1031,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unwind: Option<&'ll BasicBlock>, num_handlers: usize, ) -> &'ll Value { - self.count_insn("catchswitch"); let name = const_cstr!("catchswitch"); let ret = unsafe { llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind, @@ -1199,7 +1128,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { args: &[&'ll Value], funclet: Option<&Funclet<'ll>>, ) -> &'ll Value { - self.count_insn("call"); debug!("Call {:?} with args ({:?})", llfn, @@ -1221,7 +1149,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn zext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - self.count_insn("zext"); unsafe { llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname()) } @@ -1285,19 +1212,6 @@ impl Builder<'a, 'll, 'tcx> { } } - fn count_insn(&self, category: &str) { - if self.sess().codegen_stats() { - self.stats.borrow_mut().n_llvm_insns += 1; - } - if self.sess().count_llvm_insns() { - *self.stats - .borrow_mut() - .llvm_insns - .entry(category.to_string()) - .or_insert(0) += 1; - } - } - fn position_at_start(&mut self, llbb: &'ll BasicBlock) { unsafe { llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb); @@ -1305,12 +1219,10 @@ impl Builder<'a, 'll, 'tcx> { } pub fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("minnum"); unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) } } pub fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.count_insn("maxnum"); unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) } } @@ -1319,7 +1231,6 @@ impl Builder<'a, 'll, 'tcx> { elt: &'ll Value, idx: &'ll Value, ) -> &'ll Value { - self.count_insn("insertelement"); unsafe { llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname()) } @@ -1331,14 +1242,12 @@ impl Builder<'a, 'll, 'tcx> { v2: &'ll Value, mask: &'ll Value, ) -> &'ll Value { - self.count_insn("shufflevector"); unsafe { llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname()) } } pub fn vector_reduce_fadd_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { - self.count_insn("vector.reduce.fadd_fast"); unsafe { // FIXME: add a non-fast math version once // https://bugs.llvm.org/show_bug.cgi?id=36732 @@ -1349,7 +1258,6 @@ impl Builder<'a, 'll, 'tcx> { } } pub fn vector_reduce_fmul_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { - self.count_insn("vector.reduce.fmul_fast"); unsafe { // FIXME: add a non-fast math version once // https://bugs.llvm.org/show_bug.cgi?id=36732 @@ -1360,35 +1268,27 @@ impl Builder<'a, 'll, 'tcx> { } } pub fn vector_reduce_add(&mut self, src: &'ll Value) -> &'ll Value { - self.count_insn("vector.reduce.add"); unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) } } pub fn vector_reduce_mul(&mut self, src: &'ll Value) -> &'ll Value { - self.count_insn("vector.reduce.mul"); unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) } } pub fn vector_reduce_and(&mut self, src: &'ll Value) -> &'ll Value { - self.count_insn("vector.reduce.and"); unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) } } pub fn vector_reduce_or(&mut self, src: &'ll Value) -> &'ll Value { - self.count_insn("vector.reduce.or"); unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) } } pub fn vector_reduce_xor(&mut self, src: &'ll Value) -> &'ll Value { - self.count_insn("vector.reduce.xor"); unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) } } pub fn vector_reduce_fmin(&mut self, src: &'ll Value) -> &'ll Value { - self.count_insn("vector.reduce.fmin"); unsafe { llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false) } } pub fn vector_reduce_fmax(&mut self, src: &'ll Value) -> &'ll Value { - self.count_insn("vector.reduce.fmax"); unsafe { llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false) } } pub fn vector_reduce_fmin_fast(&mut self, src: &'ll Value) -> &'ll Value { - self.count_insn("vector.reduce.fmin_fast"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true); llvm::LLVMRustSetHasUnsafeAlgebra(instr); @@ -1396,7 +1296,6 @@ impl Builder<'a, 'll, 'tcx> { } } pub fn vector_reduce_fmax_fast(&mut self, src: &'ll Value) -> &'ll Value { - self.count_insn("vector.reduce.fmax_fast"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true); llvm::LLVMRustSetHasUnsafeAlgebra(instr); @@ -1404,11 +1303,9 @@ impl Builder<'a, 'll, 'tcx> { } } pub fn vector_reduce_min(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value { - self.count_insn("vector.reduce.min"); unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) } } pub fn vector_reduce_max(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value { - self.count_insn("vector.reduce.max"); unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) } } @@ -1419,7 +1316,6 @@ impl Builder<'a, 'll, 'tcx> { } pub fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value { - self.count_insn("catchret"); let ret = unsafe { llvm::LLVMRustBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) }; @@ -1488,7 +1384,6 @@ impl Builder<'a, 'll, 'tcx> { } pub fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { - self.count_insn("vaarg"); unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname()) } @@ -1511,7 +1406,6 @@ impl Builder<'a, 'll, 'tcx> { } fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value { - self.count_insn("addincoming"); assert_eq!(vals.len(), bbs.len()); let phi = unsafe { llvm::LLVMBuildPhi(self.llbuilder, ty, noname()) @@ -1525,7 +1419,6 @@ impl Builder<'a, 'll, 'tcx> { } fn add_incoming_to_phi(&mut self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) { - self.count_insn("addincoming"); unsafe { llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint); } diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 7bf8f705ea8ad..b6b47d047c8b1 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -12,7 +12,6 @@ use rustc_codegen_ssa::traits::*; use rustc_data_structures::base_n; use rustc_data_structures::small_c_str::SmallCStr; -use rustc::mir::mono::Stats; use rustc::session::config::{self, DebugInfo}; use rustc::session::Session; use rustc::ty::layout::{ @@ -44,7 +43,6 @@ pub struct CodegenCx<'ll, 'tcx: 'll> { pub llmod: &'ll llvm::Module, pub llcx: &'ll llvm::Context, - pub stats: RefCell, pub codegen_unit: Arc>, /// Cache instances of monomorphic and polymorphic items @@ -284,7 +282,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { tls_model, llmod, llcx, - stats: RefCell::new(Stats::default()), codegen_unit, instances: Default::default(), vtables: Default::default(), @@ -408,14 +405,6 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { self.check_overflow } - fn stats(&self) -> &RefCell { - &self.stats - } - - fn consume_stats(self) -> RefCell { - self.stats - } - fn codegen_unit(&self) -> &Arc> { &self.codegen_unit } diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 09b284052b3c4..57cffa48163e1 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -52,7 +52,6 @@ use rustc_codegen_ssa::CompiledModule; use errors::{FatalError, Handler}; use rustc::dep_graph::WorkProduct; use syntax_pos::symbol::InternedString; -use rustc::mir::mono::Stats; pub use llvm_util::target_features; use std::any::Any; use std::sync::{mpsc, Arc}; @@ -130,8 +129,8 @@ impl ExtraBackendMethods for LlvmCodegenBackend { &self, tcx: TyCtxt<'a, 'tcx, 'tcx>, cgu_name: InternedString, - ) -> Stats { - base::compile_codegen_unit(tcx, cgu_name) + ) { + base::compile_codegen_unit(tcx, cgu_name); } fn target_machine_factory( &self, diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 67d3a2113067c..172b5b39987d4 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -20,7 +20,7 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::middle::cstore::EncodedMetadata; use rustc::middle::lang_items::StartFnLangItem; use rustc::middle::weak_lang_items; -use rustc::mir::mono::{Stats, CodegenUnitNameBuilder}; +use rustc::mir::mono::CodegenUnitNameBuilder; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::ty::query::Providers; @@ -28,7 +28,6 @@ use rustc::middle::cstore::{self, LinkagePreference}; use rustc::util::common::{time, print_time_passes_entry}; use rustc::session::config::{self, EntryFnType, Lto}; use rustc::session::Session; -use rustc_mir::monomorphize::item::DefPathBasedNames; use rustc_mir::monomorphize::Instance; use rustc_mir::monomorphize::partitioning::{CodegenUnit, CodegenUnitExt}; use rustc::util::nodemap::FxHashMap; @@ -58,39 +57,6 @@ use rustc::hir; use crate::mir::operand::OperandValue; -use std::marker::PhantomData; - -pub struct StatRecorder<'a, 'tcx, Cx: 'a + CodegenMethods<'tcx>> { - cx: &'a Cx, - name: Option, - istart: usize, - _marker: PhantomData<&'tcx ()>, -} - -impl<'a, 'tcx, Cx: CodegenMethods<'tcx>> StatRecorder<'a, 'tcx, Cx> { - pub fn new(cx: &'a Cx, name: String) -> Self { - let istart = cx.stats().borrow().n_llvm_insns; - StatRecorder { - cx, - name: Some(name), - istart, - _marker: PhantomData, - } - } -} - -impl<'a, 'tcx, Cx: CodegenMethods<'tcx>> Drop for StatRecorder<'a, 'tcx, Cx> { - fn drop(&mut self) { - if self.cx.sess().codegen_stats() { - let mut stats = self.cx.stats().borrow_mut(); - let iend = stats.n_llvm_insns; - stats.fn_stats.push((self.name.take().unwrap(), iend - self.istart)); - // Reset LLVM insn count to avoid compound costs. - stats.n_llvm_insns = self.istart; - } - } -} - pub fn bin_op_to_icmp_predicate(op: hir::BinOpKind, signed: bool) -> IntPredicate { @@ -407,15 +373,6 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, instance: Instance<'tcx>, ) { - let _s = if cx.sess().codegen_stats() { - let mut instance_name = String::new(); - DefPathBasedNames::new(cx.tcx(), true, true) - .push_def_path(instance.def_id(), &mut instance_name); - Some(StatRecorder::new(cx, instance_name)) - } else { - None - }; - // this is an info! to allow collecting monomorphization statistics // and to allow finding the last function before LLVM aborts from // release builds. @@ -650,7 +607,6 @@ pub fn codegen_crate( }; let mut total_codegen_time = Duration::new(0, 0); - let mut all_stats = Stats::default(); for cgu in codegen_units.into_iter() { ongoing_codegen.wait_for_signal_to_codegen_item(); @@ -663,8 +619,7 @@ pub fn codegen_crate( CguReuse::No => { tcx.sess.profiler(|p| p.start_activity(format!("codegen {}", cgu.name()))); let start_time = Instant::now(); - let stats = backend.compile_codegen_unit(tcx, *cgu.name()); - all_stats.extend(stats); + backend.compile_codegen_unit(tcx, *cgu.name()); total_codegen_time += start_time.elapsed(); tcx.sess.profiler(|p| p.end_activity(format!("codegen {}", cgu.name()))); false @@ -698,21 +653,6 @@ pub fn codegen_crate( symbol_names_test::report_symbol_names(tcx); - if tcx.sess.codegen_stats() { - println!("--- codegen stats ---"); - println!("fn stats:"); - all_stats.fn_stats.sort_by_key(|&(_, insns)| insns); - for &(ref name, insns) in all_stats.fn_stats.iter() { - println!("{} insns, {}", insns, *name); - } - } - - if tcx.sess.count_llvm_insns() { - for (k, v) in all_stats.llvm_insns.iter() { - println!("{:7} {}", *v, *k); - } - } - ongoing_codegen.check_for_errors(tcx.sess); assert_and_save_dep_graph(tcx); diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index 530eba516a6c0..0466b47cf148f 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -5,7 +5,6 @@ use super::write::WriteBackendMethods; use super::CodegenObject; use rustc::middle::allocator::AllocatorKind; use rustc::middle::cstore::EncodedMetadata; -use rustc::mir::mono::Stats; use rustc::session::{Session, config}; use rustc::ty::TyCtxt; use rustc_codegen_utils::codegen_backend::CodegenBackend; @@ -49,7 +48,7 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se &self, tcx: TyCtxt<'a, 'tcx, 'tcx>, cgu_name: InternedString, - ) -> Stats; + ); // If find_features is true this won't access `sess.crate_types` by assuming // that `is_pie_binary` is false. When we discover LLVM target features // `sess.crate_types` is uninitialized so we cannot access it. diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs index 2797dd89f5b15..5ea86df6e9459 100644 --- a/src/librustc_codegen_ssa/traits/misc.rs +++ b/src/librustc_codegen_ssa/traits/misc.rs @@ -1,5 +1,4 @@ use super::BackendTypes; -use rustc::mir::mono::Stats; use rustc::session::Session; use rustc::ty::{self, Instance, Ty}; use rustc::util::nodemap::FxHashMap; @@ -17,8 +16,6 @@ pub trait MiscMethods<'tcx>: BackendTypes { fn eh_personality(&self) -> Self::Value; fn eh_unwind_resume(&self) -> Self::Value; fn sess(&self) -> &Session; - fn stats(&self) -> &RefCell; - fn consume_stats(self) -> RefCell; fn codegen_unit(&self) -> &Arc>; fn used_statics(&self) -> &RefCell>; fn set_frame_pointer_elimination(&self, llfn: Self::Value); From 7fa97c08508057b29142211fc45b3e282f194a7b Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 29 May 2019 01:22:37 +0300 Subject: [PATCH 22/23] rustc_codegen_llvm: rename away the last occurrence of `insn`. --- src/librustc_codegen_llvm/builder.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 79c58fbf6e465..42e7a72c43b21 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -531,9 +531,9 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value { unsafe { - let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); - llvm::LLVMSetVolatile(insn, llvm::True); - insn + let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); + llvm::LLVMSetVolatile(load, llvm::True); + load } } From 9f8d934f271fcaf9c34aefa8062b7563cfd34721 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 28 May 2019 16:00:39 -0700 Subject: [PATCH 23/23] Bump Sum and Product for Option to 1.37 --- src/libcore/iter/traits/accum.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs index 88c4820d5839c..f9e86be3721a5 100644 --- a/src/libcore/iter/traits/accum.rs +++ b/src/libcore/iter/traits/accum.rs @@ -291,7 +291,7 @@ where } } -#[stable(feature = "iter_arith_traits_option", since = "1.35.0")] +#[stable(feature = "iter_arith_traits_option", since = "1.37.0")] impl Sum> for Option where T: Sum, @@ -318,7 +318,7 @@ where } } -#[stable(feature = "iter_arith_traits_option", since = "1.35.0")] +#[stable(feature = "iter_arith_traits_option", since = "1.37.0")] impl Product> for Option where T: Product,