about summary refs log tree commit diff
path: root/src/test/codegen
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-02-10 15:24:59 +0000
committerbors <bors@rust-lang.org>2020-02-10 15:24:59 +0000
commite6ec0d125eba4074122b187032474b4174fb9d31 (patch)
tree6068680ebdd11e46ff0e16cf29872db95469f4a9 /src/test/codegen
parent4d1241f5158ffd66730e094d8f199ed654ed52ae (diff)
parent136008c15bbd2f9517dab54b87cddf2023df38a3 (diff)
downloadrust-e6ec0d125eba4074122b187032474b4174fb9d31.tar.gz
rust-e6ec0d125eba4074122b187032474b4174fb9d31.zip
Auto merge of #68835 - CAD97:sound-range-inclusive, r=Mark-Simulacrum
Remove problematic specialization from RangeInclusive

Fixes #67194 using the approach [outlined by Mark-Simulacrum](https://github.com/rust-lang/rust/issues/67194#issuecomment-581669549).

> I believe the property we want is that if `PartialEq(&self, &other) == true`, then `self.next() == other.next()`. It is true that this is satisfied by removing the specialization and always doing `is_empty.unwrap_or_default()`; the "wrong" behavior there arises from calling `next()` having an effect on initially empty ranges, as we should be in `is_empty = true` but are not (yet) there. It might be possible to detect that the current state is always empty (i.e., `start > end`) and then not fill in the empty slot. I think this might solve the problem without regressing tests; however, this could have performance implications.

> That approach essentially states that we only use the `is_empty` slot for cases where `start <= end`. That means that `Idx: !Step` and `start > end` would both behave the same, and correctly -- we do not need the boolean if we're not ever going to emit any values from the iterator.

This is implemented here by replacing the `is_empty: Option<bool>` slot with an `exhausted: bool` slot. This flag is

- `false` upon construction,
- `false` when iteration has not yielded an element -- importantly, this means it is always `false` for an iterator empty by construction,
- `false` when iteration has yielded an element and the iterator is not exhausted, and
- only `true` when iteration has been used to exhaust the iterator.

For completeness, this also adds a note to the `Debug` representation to note when the range is exhausted.
Diffstat (limited to 'src/test/codegen')
-rw-r--r--src/test/codegen/issue-45222.rs34
1 files changed, 18 insertions, 16 deletions
diff --git a/src/test/codegen/issue-45222.rs b/src/test/codegen/issue-45222.rs
index 7aadc8a0954..e9b05e648b4 100644
--- a/src/test/codegen/issue-45222.rs
+++ b/src/test/codegen/issue-45222.rs
@@ -25,28 +25,30 @@ pub fn check_foo2() -> u64 {
 }
 
 // Simplified example of #45222
-
-fn triangle_inc(n: u64) -> u64 {
-    let mut count = 0;
-    for j in 0 ..= n {
-        count += j;
-    }
-    count
-}
-
-// CHECK-LABEL: @check_triangle_inc
-#[no_mangle]
-pub fn check_triangle_inc() -> u64 {
-    // CHECK: ret i64 5000050000
-    triangle_inc(100000)
-}
+//
+// Temporarily disabled in #68835 to fix a soundness hole.
+//
+// fn triangle_inc(n: u64) -> u64 {
+//     let mut count = 0;
+//     for j in 0 ..= n {
+//         count += j;
+//     }
+//     count
+// }
+//
+// // COMMENTEDCHECK-LABEL: @check_triangle_inc
+// #[no_mangle]
+// pub fn check_triangle_inc() -> u64 {
+//     // COMMENTEDCHECK: ret i64 5000050000
+//     triangle_inc(100000)
+// }
 
 // Demo in #48012
 
 fn foo3r(n: u64) -> u64 {
     let mut count = 0;
     (0..n).for_each(|_| {
-        (0 ..= n).rev().for_each(|j| {
+        (0..=n).rev().for_each(|j| {
             count += j;
         })
     });