Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove problematic specialization from RangeInclusive #68835

Merged
merged 2 commits into from
Feb 10, 2020

Conversation

CAD97
Copy link
Contributor

@CAD97 CAD97 commented Feb 4, 2020

Fixes #67194 using the approach outlined by Mark-Simulacrum.

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.

@rust-highfive
Copy link
Collaborator

r? @alexcrichton

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 4, 2020
@Mark-Simulacrum
Copy link
Member

Can you run benchmarks locally as well? We should try to make sure this is not regressing performance (or at least be aware if it is). We could also verify that the codegen is nice (particularly that it still unrolls nicely).

I'm not running compiler perf tests here since that seems super unlikely to actually be influenced by this.

cc @kennytm

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-7 of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
2020-02-04T23:01:42.4840484Z ========================== Starting Command Output ===========================
2020-02-04T23:01:42.4846492Z [command]/bin/bash --noprofile --norc /home/vsts/work/_temp/6d97dde7-9732-4d5d-9b59-b2b9c80dc7b3.sh
2020-02-04T23:01:42.4846529Z 
2020-02-04T23:01:42.4849086Z ##[section]Finishing: Disable git automatic line ending conversion
2020-02-04T23:01:42.4856415Z ##[section]Starting: Checkout rust-lang/rust@refs/pull/68835/merge to s
2020-02-04T23:01:42.4857895Z Task         : Get sources
2020-02-04T23:01:42.4857959Z Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
2020-02-04T23:01:42.4857987Z Version      : 1.0.0
2020-02-04T23:01:42.4858015Z Author       : Microsoft
---
2020-02-04T23:01:43.3055830Z ##[command]git remote add origin https://github.com/rust-lang/rust
2020-02-04T23:01:43.3135555Z ##[command]git config gc.auto 0
2020-02-04T23:01:43.3216461Z ##[command]git config --get-all http.https://github.com/rust-lang/rust.extraheader
2020-02-04T23:01:43.3272127Z ##[command]git config --get-all http.proxy
2020-02-04T23:01:43.3403890Z ##[command]git -c http.extraheader="AUTHORIZATION: basic ***" fetch --force --tags --prune --progress --no-recurse-submodules --depth=2 origin +refs/heads/*:refs/remotes/origin/* +refs/pull/68835/merge:refs/remotes/pull/68835/merge
---
2020-02-04T23:53:56.9010727Z .................................................................................................... 1700/9585
2020-02-04T23:54:01.1522601Z .................................................................................................... 1800/9585
2020-02-04T23:54:11.4197815Z ............................i....................................................................... 1900/9585
2020-02-04T23:54:17.5110911Z .................................................................................................... 2000/9585
2020-02-04T23:54:29.4527792Z ..................iiiii............................................................................. 2100/9585
2020-02-04T23:54:37.6981191Z .................................................................................................... 2300/9585
2020-02-04T23:54:39.6873233Z .................................................................................................... 2400/9585
2020-02-04T23:54:43.7559066Z .................................................................................................... 2500/9585
2020-02-04T23:55:01.3064118Z .................................................................................................... 2600/9585
---
2020-02-04T23:57:13.0606480Z .............................................................i...............i...................... 4900/9585
2020-02-04T23:57:19.4924018Z .................................................................................................... 5000/9585
2020-02-04T23:57:26.2223529Z .................................................................................................... 5100/9585
2020-02-04T23:57:30.1006504Z ....i............................................................................................... 5200/9585
2020-02-04T23:57:39.3874894Z ..............................................................................ii.ii........i...i.... 5300/9585
2020-02-04T23:57:46.7198661Z ................i................................................................................... 5500/9585
2020-02-04T23:57:54.6089864Z .................................................................................................... 5600/9585
2020-02-04T23:58:00.3435966Z .................................................................i.................................. 5700/9585
2020-02-04T23:58:06.3787638Z .................................................................................................... 5800/9585
2020-02-04T23:58:06.3787638Z .................................................................................................... 5800/9585
2020-02-04T23:58:12.6418300Z .................................................................................................... 5900/9585
2020-02-04T23:58:20.3014767Z ........................................................ii...i..ii...........i...................... 6000/9585
2020-02-04T23:58:38.4524998Z .................................................................................................... 6200/9585
2020-02-04T23:58:44.9345511Z .................................................................................................... 6300/9585
2020-02-04T23:58:44.9345511Z .................................................................................................... 6300/9585
2020-02-04T23:58:51.7444854Z ....................................................................................i..ii........... 6400/9585
2020-02-04T23:59:13.4286518Z .................................................................................................... 6600/9585
2020-02-04T23:59:21.4871101Z .......................................................................i............................ 6700/9585
2020-02-04T23:59:23.4372638Z .................................................................................................... 6800/9585
2020-02-04T23:59:25.4203543Z .........................................................................i.......................... 6900/9585
---
2020-02-05T00:00:52.3506966Z .................................................................................................... 7600/9585
2020-02-05T00:00:56.6669633Z .................................................................................................... 7700/9585
2020-02-05T00:01:02.6598847Z .................................................................................................... 7800/9585
2020-02-05T00:01:10.1756342Z .................................................................................................... 7900/9585
2020-02-05T00:01:16.8008544Z ..................................iiiiiii.i......................................................... 8000/9585
2020-02-05T00:01:30.0810743Z .................................................................................................... 8200/9585
2020-02-05T00:01:37.7721289Z .................................................................................................... 8300/9585
2020-02-05T00:01:50.2160563Z .................................................................................................... 8400/9585
2020-02-05T00:01:56.8159041Z .................................................................................................... 8500/9585
---
2020-02-05T00:04:00.4518602Z  finished in 6.816
2020-02-05T00:04:00.4678096Z Check compiletest suite=codegen mode=codegen (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
2020-02-05T00:04:00.6578159Z 
2020-02-05T00:04:00.6578334Z running 172 tests
2020-02-05T00:04:03.3357736Z iiii......i...........ii..iiii...i....i...........i............i..i..F...............i....i......... 100/172
2020-02-05T00:04:05.3931246Z ...i.i.i...iii..iiiiiiiiii.......................iii............ii......
2020-02-05T00:04:05.3931644Z 
2020-02-05T00:04:05.3932183Z ---- [codegen] codegen/issue-45222.rs stdout ----
2020-02-05T00:04:05.3932217Z 
2020-02-05T00:04:05.3932217Z 
2020-02-05T00:04:05.3932425Z error: verification with 'FileCheck' failed
2020-02-05T00:04:05.3932693Z status: exit code: 1
2020-02-05T00:04:05.3933538Z command: "/usr/lib/llvm-7/bin/FileCheck" "--input-file" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/codegen/issue-45222/issue-45222.ll" "/checkout/src/test/codegen/issue-45222.rs"
2020-02-05T00:04:05.3934095Z ------------------------------------------
2020-02-05T00:04:05.3934128Z 
2020-02-05T00:04:05.3934292Z ------------------------------------------
2020-02-05T00:04:05.3934507Z stderr:
2020-02-05T00:04:05.3934507Z stderr:
2020-02-05T00:04:05.3934818Z ------------------------------------------
2020-02-05T00:04:05.3935386Z /checkout/src/test/codegen/issue-45222.rs:40:12: error: CHECK: expected string not found in input
2020-02-05T00:04:05.3935485Z  // CHECK: ret i64 5000050000
2020-02-05T00:04:05.3936312Z            ^
2020-02-05T00:04:05.3936988Z /checkout/obj/build/x86_64-unknown-linux-gnu/test/codegen/issue-45222/issue-45222.ll:16:31: note: scanning from here
2020-02-05T00:04:05.3937076Z define i64 @check_triangle_inc() unnamed_addr #0 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
2020-02-05T00:04:05.3937254Z                               ^
2020-02-05T00:04:05.3939831Z /checkout/obj/build/x86_64-unknown-linux-gnu/test/codegen/issue-45222/issue-45222.ll:25:48: note: possible intended match here
2020-02-05T00:04:05.3939928Z  %spec.select.i = select i1 %0, i64 %_5.0.i.i.i.i, i64 100000
2020-02-05T00:04:05.3939992Z 
2020-02-05T00:04:05.3940429Z ------------------------------------------
2020-02-05T00:04:05.3940474Z 
2020-02-05T00:04:05.3940496Z 
---
2020-02-05T00:04:05.3941302Z thread 'main' panicked at 'Some tests failed', src/tools/compiletest/src/main.rs:348:22
2020-02-05T00:04:05.3941358Z note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
2020-02-05T00:04:05.3946861Z 
2020-02-05T00:04:05.3946915Z 
2020-02-05T00:04:05.3948196Z command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/codegen" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/codegen" "--stage-id" "stage2-x86_64-unknown-linux-gnu" "--mode" "codegen" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-7/bin/FileCheck" "--host-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--target-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--docck-python" "/usr/bin/python2.7" "--lldb-python" "/usr/bin/python2.7" "--gdb" "/usr/bin/gdb" "--quiet" "--llvm-version" "7.0.0\n" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--llvm-components" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"
2020-02-05T00:04:05.3948386Z 
2020-02-05T00:04:05.3948424Z 
2020-02-05T00:04:05.3960632Z failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
2020-02-05T00:04:05.3960691Z Build completed unsuccessfully in 0:55:40
2020-02-05T00:04:05.3960691Z Build completed unsuccessfully in 0:55:40
2020-02-05T00:04:05.4002014Z == clock drift check ==
2020-02-05T00:04:05.4017370Z   local time: Wed Feb  5 00:04:05 UTC 2020
2020-02-05T00:04:05.4263576Z   network time: Wed, 05 Feb 2020 00:04:05 GMT
2020-02-05T00:04:05.4265320Z == end clock drift check ==
2020-02-05T00:04:07.6659887Z 
2020-02-05T00:04:07.6735773Z ##[error]Bash exited with code '1'.
2020-02-05T00:04:07.6759043Z ##[section]Finishing: Run build
2020-02-05T00:04:07.6785700Z ##[section]Starting: Checkout rust-lang/rust@refs/pull/68835/merge to s
2020-02-05T00:04:07.6787620Z Task         : Get sources
2020-02-05T00:04:07.6787656Z Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
2020-02-05T00:04:07.6787691Z Version      : 1.0.0
2020-02-05T00:04:07.6787739Z Author       : Microsoft
2020-02-05T00:04:07.6787739Z Author       : Microsoft
2020-02-05T00:04:07.6787774Z Help         : [More Information](https://go.microsoft.com/fwlink/?LinkId=798199)
2020-02-05T00:04:07.6787811Z ==============================================================================
2020-02-05T00:04:08.0150912Z Cleaning any cached credential from repository: rust-lang/rust (GitHub)
2020-02-05T00:04:08.0185500Z ##[section]Finishing: Checkout rust-lang/rust@refs/pull/68835/merge to s
2020-02-05T00:04:08.0281553Z Cleaning up task key
2020-02-05T00:04:08.0282197Z Start cleaning up orphan processes.
2020-02-05T00:04:08.0374321Z Terminate orphan process: pid (7159) (python)
2020-02-05T00:04:08.1501194Z ##[section]Finishing: Finalize Job

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@CAD97
Copy link
Contributor Author

CAD97 commented Feb 5, 2020

Speaking of codegen issues...

I'll play with this locally now that I know what test to run. I ran libcore tests locally but apparently not the other relevant ones.

@CAD97
Copy link
Contributor Author

CAD97 commented Feb 5, 2020

I was unable to tweak the implementation to allow that codegen pass to pass. The other, smaller change approach I suggested trying leads to an ICE, so I can't test if it breaks the codegen test.

@alexcrichton
Copy link
Member

r? @Mark-Simulacrum

@Mark-Simulacrum
Copy link
Member

Can you update the codegen tests (possibly just commenting out the broken tests for now)? I personally think we should land the soundness fix and then take another look at fixing the codegen. These codegen tests were always pretty brittle I think anyway.

@CAD97
Copy link
Contributor Author

CAD97 commented Feb 5, 2020

I disabled the failing codegen test.

Interestingly, of the three checks in the file, only one actually started failing. The internal iteration version obviously still works, as that was adjusted in #48012 to be more optimizable.

The interesting part is that the original example from #45222 continues to be optimized down to a ret while the simplified example isn't being optimized down.

// verify that LLVM recognizes a loop involving 0..=n and will const-fold it.

// Example from original issue #45222

fn foo2(n: u64) -> u64 {
    let mut count = 0;
    for _ in 0..n {
        for j in (0..=n).rev() {
            count += j;
        }
    }
    count
}

// CHECK-LABEL: @check_foo2
#[no_mangle]
pub fn check_foo2() -> u64 {
    // CHECK: ret i64 500005000000000
    foo2(100000)
}

// 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 {
    // NO-CHECK: 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| {
            count += j;
        })
    });
    count
}

// CHECK-LABEL: @check_foo3r
#[no_mangle]
pub fn check_foo3r() -> u64 {
    // CHECK: ret i64 500050000000
    foo3r(10000)
}

So... next_back is optimizing but next isn't? Changing the failing test to for j in (0 ..= n).rev() does indeed allow it to pass. If someone better at teasing out optimizations wants to look at it, here are those functions:

    #[inline]
    fn next(&mut self) -> Option<A> {
        if self.is_empty() {
            return None;
        }
        let is_iterating = self.start < self.end;
        Some(if is_iterating {
            let n = self.start.add_one();
            mem::replace(&mut self.start, n)
        } else {
            self.exhausted = true;
            self.start.clone()
        })
    }

    #[inline]
    fn next_back(&mut self) -> Option<A> {
        if self.is_empty() {
            return None;
        }
        let is_iterating = self.start < self.end;
        Some(if is_iterating {
            let n = self.end.sub_one();
            mem::replace(&mut self.end, n)
        } else {
            self.exhausted = true;
            self.end.clone()
        })
    }

Here's a link to the playground and to the compiler explorer that shows this mismatch with minimal code.

@CAD97
Copy link
Contributor Author

CAD97 commented Feb 5, 2020

So as it turns out, codegen is bizarre, and flipping the check in next from start < end to end >= start causes it to get optimized properly https://twitter.com/CAD97_/status/1225167483264475136?s=20

@Mark-Simulacrum
Copy link
Member

Those are also different conditions; I think we don't care in practice because is_empty would've already returned false if we were done, though, right?

@CAD97
Copy link
Contributor Author

CAD97 commented Feb 5, 2020

Whoops, that messes up a test

    r = RangeInclusive::new(127i8, 127);
    assert_eq!(r.next(), Some(127));
    assert_eq!(r.next(), None);
---- ops::test_range_inclusive stdout ----
thread 'ops::test_range_inclusive' panicked at 'assertion failed: `(left == right)`
  left: `Some(-128)`,
 right: `None`', src\libcore\../libcore/tests\ops.rs:50:5

Reverting for now, whoops

@CAD97 CAD97 force-pushed the sound-range-inclusive branch from 2a009de to 90645ea Compare February 5, 2020 21:31
@CAD97
Copy link
Contributor Author

CAD97 commented Feb 6, 2020

I realized a potential reason why LLVM would do better optimizing the downward direction.

And the reason is that downward-inclusive iteration is a lot more common (in C/C++ code) than upward inclusive. Even a top-half-open range backwards is end-inclusive.

And while iterate up will typically be written in exclusive style (for(i=0; i<count; i++)), downwards iteration is still somewhat commonly used (for(i=count; i-->0;)) and sometimes in an inclusive style.

Because the reverse iterator is optimized here, I suspect LLVM can be taught to recognize the positive direction as well, though doing so might not be trivial nor reach us quickly.

@Mark-Simulacrum
Copy link
Member

Okay, pushed up an update (just some changes to the comments) since I want to get this landed quickly.

@bors r+ rollup=never

Marking as non-rollup to make it easy to bisect regressions to this.

@bors
Copy link
Contributor

bors commented Feb 6, 2020

📌 Commit 5f0d830a46ebb217aab8dc9e118788b0fc91f712 has been approved by Mark-Simulacrum

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 6, 2020
@Mark-Simulacrum
Copy link
Member

Oh, also, I am not filing a new issue for the codegen regression as #45222 is still open anyway...

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-7 of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
2020-02-06T21:16:11.5670559Z ========================== Starting Command Output ===========================
2020-02-06T21:16:11.5674524Z [command]/bin/bash --noprofile --norc /home/vsts/work/_temp/35103085-bc61-4722-9676-a30650115329.sh
2020-02-06T21:16:11.5674770Z 
2020-02-06T21:16:11.5678401Z ##[section]Finishing: Disable git automatic line ending conversion
2020-02-06T21:16:11.5686030Z ##[section]Starting: Checkout rust-lang/rust@refs/pull/68835/merge to s
2020-02-06T21:16:11.5687796Z Task         : Get sources
2020-02-06T21:16:11.5687831Z Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
2020-02-06T21:16:11.5687916Z Version      : 1.0.0
2020-02-06T21:16:11.5687950Z Author       : Microsoft
---
2020-02-06T21:16:12.5661512Z ##[command]git remote add origin https://github.com/rust-lang/rust
2020-02-06T21:16:12.5671489Z ##[command]git config gc.auto 0
2020-02-06T21:16:12.5677716Z ##[command]git config --get-all http.https://github.com/rust-lang/rust.extraheader
2020-02-06T21:16:12.5679973Z ##[command]git config --get-all http.proxy
2020-02-06T21:16:12.5685989Z ##[command]git -c http.extraheader="AUTHORIZATION: basic ***" fetch --force --tags --prune --progress --no-recurse-submodules --depth=2 origin +refs/heads/*:refs/remotes/origin/* +refs/pull/68835/merge:refs/remotes/pull/68835/merge
---
2020-02-06T22:13:44.1438557Z .................................................................................................... 1700/9595
2020-02-06T22:13:48.8250259Z .................................................................................................... 1800/9595
2020-02-06T22:14:00.9711710Z .............................i...................................................................... 1900/9595
2020-02-06T22:14:07.7805249Z .................................................................................................... 2000/9595
2020-02-06T22:14:21.7001998Z ...................iiiii............................................................................ 2100/9595
2020-02-06T22:14:31.2293039Z .................................................................................................... 2300/9595
2020-02-06T22:14:33.5846298Z .................................................................................................... 2400/9595
2020-02-06T22:14:38.2318549Z .................................................................................................... 2500/9595
2020-02-06T22:14:58.9388064Z .................................................................................................... 2600/9595
---
2020-02-06T22:17:31.6780067Z ..............................................................i...............i..................... 4900/9595
2020-02-06T22:17:38.8653396Z .................................................................................................... 5000/9595
2020-02-06T22:17:46.8035714Z .................................................................................................... 5100/9595
2020-02-06T22:17:51.2799027Z .....i.............................................................................................. 5200/9595
2020-02-06T22:18:01.9224711Z ...............................................................................ii.ii........i...i... 5300/9595
2020-02-06T22:18:10.0998741Z .................i.................................................................................. 5500/9595
2020-02-06T22:18:19.0990084Z .................................................................................................... 5600/9595
2020-02-06T22:18:25.6540729Z ..................................................................i................................. 5700/9595
2020-02-06T22:18:32.7782150Z .................................................................................................... 5800/9595
2020-02-06T22:18:32.7782150Z .................................................................................................... 5800/9595
2020-02-06T22:18:39.7885027Z .................................................................................................... 5900/9595
2020-02-06T22:18:48.9286193Z .........................................................ii...i..ii...........i..................... 6000/9595
2020-02-06T22:19:09.7587538Z .................................................................................................... 6200/9595
2020-02-06T22:19:17.1850609Z .................................................................................................... 6300/9595
2020-02-06T22:19:17.1850609Z .................................................................................................... 6300/9595
2020-02-06T22:19:25.0094715Z .....................................................................................i..ii.......... 6400/9595
2020-02-06T22:19:49.8688200Z .................................................................................................... 6600/9595
2020-02-06T22:19:58.9954141Z ........................................................................i........................... 6700/9595
2020-02-06T22:20:01.1765810Z .................................................................................................... 6800/9595
2020-02-06T22:20:03.4012081Z ...............................................................................i.................... 6900/9595
---
2020-02-06T22:21:41.0997657Z .................................................................................................... 7600/9595
2020-02-06T22:21:45.7249374Z .................................................................................................... 7700/9595
2020-02-06T22:21:52.6029364Z .................................................................................................... 7800/9595
2020-02-06T22:22:00.6642917Z .................................................................................................... 7900/9595
2020-02-06T22:22:08.1517538Z ...........................................iiiiiiii................................................. 8000/9595
2020-02-06T22:22:22.5184061Z .................................................................................................... 8200/9595
2020-02-06T22:22:28.5285531Z .................................................................................................... 8300/9595
2020-02-06T22:22:43.8846784Z .................................................................................................... 8400/9595
2020-02-06T22:22:51.1353438Z .................................................................................................... 8500/9595
---
2020-02-06T22:25:14.5798819Z  finished in 7.105
2020-02-06T22:25:14.5974911Z Check compiletest suite=codegen mode=codegen (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
2020-02-06T22:25:14.7949477Z 
2020-02-06T22:25:14.7949937Z running 172 tests
2020-02-06T22:25:17.7456413Z iiii......i...........ii..iiii...i....i...........i............i..i..F...............i....i......... 100/172
2020-02-06T22:25:20.1008501Z ...i.i.i...iii..iiiiiiiiii.......................iii............ii......
2020-02-06T22:25:20.1009931Z 
2020-02-06T22:25:20.1013720Z ---- [codegen] codegen/issue-45222.rs stdout ----
2020-02-06T22:25:20.1014084Z 
2020-02-06T22:25:20.1014084Z 
2020-02-06T22:25:20.1014505Z error: verification with 'FileCheck' failed
2020-02-06T22:25:20.1014567Z status: exit code: 1
2020-02-06T22:25:20.1015278Z command: "/usr/lib/llvm-7/bin/FileCheck" "--input-file" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/codegen/issue-45222/issue-45222.ll" "/checkout/src/test/codegen/issue-45222.rs"
2020-02-06T22:25:20.1015966Z ------------------------------------------
2020-02-06T22:25:20.1016007Z 
2020-02-06T22:25:20.1016503Z ------------------------------------------
2020-02-06T22:25:20.1016794Z stderr:
2020-02-06T22:25:20.1016794Z stderr:
2020-02-06T22:25:20.1017147Z ------------------------------------------
2020-02-06T22:25:20.1017476Z /checkout/src/test/codegen/issue-45222.rs:39:20: error: CHECK-LABEL: expected string not found in input
2020-02-06T22:25:20.1017994Z // // CHECK-LABEL: @check_triangle_inc
2020-02-06T22:25:20.1018279Z                    ^
2020-02-06T22:25:20.1018728Z /checkout/obj/build/x86_64-unknown-linux-gnu/test/codegen/issue-45222/issue-45222.ll:10:23: note: scanning from here
2020-02-06T22:25:20.1018837Z define i64 @check_foo2() unnamed_addr #0 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
2020-02-06T22:25:20.1019091Z                       ^
2020-02-06T22:25:20.1019571Z /checkout/obj/build/x86_64-unknown-linux-gnu/test/codegen/issue-45222/issue-45222.ll:16:12: note: possible intended match here
2020-02-06T22:25:20.1019656Z define i64 @check_foo3r() unnamed_addr #0 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
2020-02-06T22:25:20.1020015Z 
2020-02-06T22:25:20.1020356Z ------------------------------------------
2020-02-06T22:25:20.1020569Z 
2020-02-06T22:25:20.1020647Z 
---
2020-02-06T22:25:20.1026726Z thread 'main' panicked at 'Some tests failed', src/tools/compiletest/src/main.rs:348:22
2020-02-06T22:25:20.1027041Z note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
2020-02-06T22:25:20.1030979Z 
2020-02-06T22:25:20.1031051Z 
2020-02-06T22:25:20.1032774Z command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/codegen" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/codegen" "--stage-id" "stage2-x86_64-unknown-linux-gnu" "--mode" "codegen" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-7/bin/FileCheck" "--host-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--target-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--docck-python" "/usr/bin/python2.7" "--lldb-python" "/usr/bin/python2.7" "--gdb" "/usr/bin/gdb" "--quiet" "--llvm-version" "7.0.0\n" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--llvm-components" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"
2020-02-06T22:25:20.1033201Z 
2020-02-06T22:25:20.1033233Z 
2020-02-06T22:25:20.1042705Z failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
2020-02-06T22:25:20.1042832Z Build completed unsuccessfully in 1:03:02
2020-02-06T22:25:20.1042832Z Build completed unsuccessfully in 1:03:02
2020-02-06T22:25:20.1097760Z == clock drift check ==
2020-02-06T22:25:20.1116539Z   local time: Thu Feb  6 22:25:20 UTC 2020
2020-02-06T22:25:21.2542647Z   network time: Thu, 06 Feb 2020 22:25:20 GMT
2020-02-06T22:25:21.2543299Z == end clock drift check ==
2020-02-06T22:25:22.7581683Z 
2020-02-06T22:25:22.7668670Z ##[error]Bash exited with code '1'.
2020-02-06T22:25:22.7692770Z ##[section]Finishing: Run build
2020-02-06T22:25:22.7715099Z ##[section]Starting: Checkout rust-lang/rust@refs/pull/68835/merge to s
2020-02-06T22:25:22.7717044Z Task         : Get sources
2020-02-06T22:25:22.7717092Z Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
2020-02-06T22:25:22.7717154Z Version      : 1.0.0
2020-02-06T22:25:22.7717196Z Author       : Microsoft
2020-02-06T22:25:22.7717196Z Author       : Microsoft
2020-02-06T22:25:22.7717243Z Help         : [More Information](https://go.microsoft.com/fwlink/?LinkId=798199)
2020-02-06T22:25:22.7717310Z ==============================================================================
2020-02-06T22:25:23.1866389Z Cleaning any cached credential from repository: rust-lang/rust (GitHub)
2020-02-06T22:25:23.1909639Z ##[section]Finishing: Checkout rust-lang/rust@refs/pull/68835/merge to s
2020-02-06T22:25:23.2024958Z Cleaning up task key
2020-02-06T22:25:23.2025741Z Start cleaning up orphan processes.
2020-02-06T22:25:23.2131600Z Terminate orphan process: pid (4604) (python)
2020-02-06T22:25:23.2355445Z ##[section]Finishing: Finalize Job

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@CAD97
Copy link
Contributor Author

CAD97 commented Feb 7, 2020

Just FYI I've currently got a tree in my roof and no power, so I won't be able to touch this for a bit, at least until the power comes back on.

The comment annotations need to be hidden from the codegen test harness by removing them or adding characters, just commenting out the area isn't enough. That's why I used NO-CHECK in the version I pushed.

@Mark-Simulacrum
Copy link
Member

❤️ No worries! I can definitely patch this up.

As to the NO-CHECK, makes sense. I guess we can't check if it's in a comment because it's always in a comment... Will fix that shortly.

@Mark-Simulacrum
Copy link
Member

@bors r+ rollup=never

@bors
Copy link
Contributor

bors commented Feb 7, 2020

📌 Commit cfb5d8dce9769a66d3849adaa17a36a6f125af68 has been approved by Mark-Simulacrum

@bors
Copy link
Contributor

bors commented Feb 8, 2020

☔ The latest upstream changes (presumably #68358) made this pull request unmergeable. Please resolve the merge conflicts.

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Feb 8, 2020
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-7 of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
2020-02-08T20:56:34.9823237Z ========================== Starting Command Output ===========================
2020-02-08T20:56:34.9841813Z [command]/bin/bash --noprofile --norc /home/vsts/work/_temp/2b8b7097-2d97-4e39-affd-51d8cbebc8ad.sh
2020-02-08T20:56:35.3768955Z 
2020-02-08T20:56:35.3832414Z ##[section]Finishing: Disable git automatic line ending conversion
2020-02-08T20:56:35.3838685Z ##[section]Starting: Checkout rust-lang/rust@refs/pull/68835/merge to s
2020-02-08T20:56:35.3840627Z Task         : Get sources
2020-02-08T20:56:35.3840742Z Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
2020-02-08T20:56:35.3840777Z Version      : 1.0.0
2020-02-08T20:56:35.3840810Z Author       : Microsoft
---
2020-02-08T20:56:41.4492359Z ##[command]git remote add origin https://github.com/rust-lang/rust
2020-02-08T20:56:41.4705220Z ##[command]git config gc.auto 0
2020-02-08T20:56:41.5373203Z ##[command]git config --get-all http.https://github.com/rust-lang/rust.extraheader
2020-02-08T20:56:41.5425610Z ##[command]git config --get-all http.proxy
2020-02-08T20:56:41.5579645Z ##[command]git -c http.extraheader="AUTHORIZATION: basic ***" fetch --force --tags --prune --progress --no-recurse-submodules --depth=2 origin +refs/heads/*:refs/remotes/origin/* +refs/pull/68835/merge:refs/remotes/pull/68835/merge
---
2020-02-08T21:59:04.2150343Z .................................................................................................... 1700/9611
2020-02-08T21:59:09.3739351Z .................................................................................................... 1800/9611
2020-02-08T21:59:21.6434647Z ...............................i.................................................................... 1900/9611
2020-02-08T21:59:29.4713749Z .................................................................................................... 2000/9611
2020-02-08T21:59:44.2094202Z .....................iiiii.......................................................................... 2100/9611
2020-02-08T21:59:54.2094861Z .................................................................................................... 2300/9611
2020-02-08T21:59:56.7446547Z .................................................................................................... 2400/9611
2020-02-08T22:00:01.5943936Z .................................................................................................... 2500/9611
2020-02-08T22:00:23.6863661Z .................................................................................................... 2600/9611
---
2020-02-08T22:03:06.3984893Z .........................................................................i...............i.......... 4900/9611
2020-02-08T22:03:14.2744933Z .................................................................................................... 5000/9611
2020-02-08T22:03:22.9990665Z .................................................................................................... 5100/9611
2020-02-08T22:03:27.7282639Z ................i................................................................................... 5200/9611
2020-02-08T22:03:38.8195848Z ..........................................................................................ii.ii..... 5300/9611
2020-02-08T22:03:43.1955345Z ...i...i............................................................................................ 5400/9611
2020-02-08T22:03:53.2787350Z .................................................................................................... 5600/9611
2020-02-08T22:04:04.2653730Z ..............................................................................i..................... 5700/9611
2020-02-08T22:04:12.0466107Z .................................................................................................... 5800/9611
2020-02-08T22:04:18.4417208Z .................................................................................................... 5900/9611
2020-02-08T22:04:18.4417208Z .................................................................................................... 5900/9611
2020-02-08T22:04:29.1383855Z .....................................................................ii...i..ii...........i......... 6000/9611
2020-02-08T22:04:51.7048248Z .................................................................................................... 6200/9611
2020-02-08T22:04:59.8668570Z .................................................................................................... 6300/9611
2020-02-08T22:05:06.7751935Z .................................................................................................i.. 6400/9611
2020-02-08T22:05:20.7513376Z ii.................................................................................................. 6500/9611
---
2020-02-08T22:07:29.6928534Z .................................................................................................... 7600/9611
2020-02-08T22:07:34.9048892Z .................................................................................................... 7700/9611
2020-02-08T22:07:40.2215029Z .................................................................................................... 7800/9611
2020-02-08T22:07:49.7897382Z .................................................................................................... 7900/9611
2020-02-08T22:07:58.7878516Z .......................................................iiiiiii.i.................................... 8000/9611
2020-02-08T22:08:14.1412105Z ..i................................................................................................. 8200/9611
2020-02-08T22:08:19.8423720Z .................................................................................................... 8300/9611
2020-02-08T22:08:35.8833023Z .................................................................................................... 8400/9611
2020-02-08T22:08:44.4418657Z .................................................................................................... 8500/9611
---
2020-02-08T22:11:16.0298597Z  finished in 7.470
2020-02-08T22:11:16.0516748Z Check compiletest suite=codegen mode=codegen (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
2020-02-08T22:11:16.2605067Z 
2020-02-08T22:11:16.2605413Z running 175 tests
2020-02-08T22:11:19.3483137Z iiii......i...........ii..iiii...i....i...........i............i..i..................i....i......... 100/175
2020-02-08T22:11:21.8760055Z ...i.i.i...iii..iiiiiii.iiiiii......................iii............ii......
2020-02-08T22:11:21.8761638Z 
2020-02-08T22:11:21.8767594Z  finished in 5.825
2020-02-08T22:11:21.8953046Z Check compiletest suite=codegen-units mode=codegen-units (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
2020-02-08T22:11:22.0765835Z 
---
2020-02-08T22:11:24.1106317Z  finished in 2.215
2020-02-08T22:11:24.1293095Z Check compiletest suite=assembly mode=assembly (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
2020-02-08T22:11:24.2896236Z 
2020-02-08T22:11:24.2896725Z running 9 tests
2020-02-08T22:11:24.2898826Z iiiiiiiii
2020-02-08T22:11:24.2899324Z 
2020-02-08T22:11:24.2899367Z  finished in 0.160
2020-02-08T22:11:24.3074946Z Check compiletest suite=incremental mode=incremental (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
2020-02-08T22:11:24.5053549Z 
---
2020-02-08T22:11:45.0655588Z  finished in 20.755
2020-02-08T22:11:45.0860176Z Check compiletest suite=debuginfo mode=debuginfo (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
2020-02-08T22:11:45.2870961Z 
2020-02-08T22:11:45.2871495Z running 116 tests
2020-02-08T22:11:58.6317828Z iiiii..i.....i..i...i..i.i.i..i..i..ii....i.i....ii..........iiii..........i.....i..i.......ii.i.ii. 100/116
2020-02-08T22:12:00.5239559Z ....iiii.....ii.
2020-02-08T22:12:00.5244501Z 
2020-02-08T22:12:00.5244553Z  finished in 15.438
2020-02-08T22:12:00.5244867Z Uplifting stage1 rustc (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
2020-02-08T22:12:00.5245173Z Copying stage2 rustc from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
---
2020-02-08T22:26:18.8890498Z .................................................................................................... 1000/1010
2020-02-08T22:26:19.9944851Z ..........
2020-02-08T22:26:19.9945001Z failures:
2020-02-08T22:26:19.9945032Z 
2020-02-08T22:26:19.9945727Z ---- iter::test_range_inclusive_nth stdout ----
2020-02-08T22:26:19.9946188Z thread 'iter::test_range_inclusive_nth' panicked at 'assertion failed: `(left == right)`
2020-02-08T22:26:19.9946291Z   left: `16..=20 (exhausted)`,
2020-02-08T22:26:19.9946559Z  right: `20..=20 (exhausted)`', src/libcore/../libcore/tests/iter.rs:2101:5
2020-02-08T22:26:19.9946826Z ---- iter::test_range_inclusive_nth_back stdout ----
2020-02-08T22:26:19.9947103Z thread 'iter::test_range_inclusive_nth_back' panicked at 'assertion failed: `(left == right)`
2020-02-08T22:26:19.9947103Z thread 'iter::test_range_inclusive_nth_back' panicked at 'assertion failed: `(left == right)`
2020-02-08T22:26:19.9947155Z   left: `10..=14 (exhausted)`,
2020-02-08T22:26:19.9947416Z  right: `10..=10 (exhausted)`', src/libcore/../libcore/tests/iter.rs:2125:5
2020-02-08T22:26:19.9947476Z 
2020-02-08T22:26:19.9947517Z failures:
2020-02-08T22:26:19.9947559Z     iter::test_range_inclusive_nth
2020-02-08T22:26:19.9947624Z     iter::test_range_inclusive_nth_back
---
2020-02-08T22:26:20.0047646Z   local time: Sat Feb  8 22:26:20 UTC 2020
2020-02-08T22:26:20.5519617Z   network time: Sat, 08 Feb 2020 22:26:20 GMT
2020-02-08T22:26:20.5526494Z == end clock drift check ==
2020-02-08T22:26:21.0308658Z 
2020-02-08T22:26:21.0425402Z ##[error]Bash exited with code '1'.
2020-02-08T22:26:21.0437981Z ##[section]Finishing: Run build
2020-02-08T22:26:21.0457549Z ##[section]Starting: Checkout rust-lang/rust@refs/pull/68835/merge to s
2020-02-08T22:26:21.0462262Z Task         : Get sources
2020-02-08T22:26:21.0462312Z Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
2020-02-08T22:26:21.0462379Z Version      : 1.0.0
2020-02-08T22:26:21.0462423Z Author       : Microsoft
2020-02-08T22:26:21.0462423Z Author       : Microsoft
2020-02-08T22:26:21.0462472Z Help         : [More Information](https://go.microsoft.com/fwlink/?LinkId=798199)
2020-02-08T22:26:21.0462524Z ==============================================================================
2020-02-08T22:26:21.5062433Z Cleaning any cached credential from repository: rust-lang/rust (GitHub)
2020-02-08T22:26:21.5115687Z ##[section]Finishing: Checkout rust-lang/rust@refs/pull/68835/merge to s
2020-02-08T22:26:21.5240889Z Cleaning up task key
2020-02-08T22:26:21.5242222Z Start cleaning up orphan processes.
2020-02-08T22:26:21.5596780Z Terminate orphan process: pid (4032) (python)
2020-02-08T22:26:21.5638225Z ##[section]Finishing: Finalize Job

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@Mark-Simulacrum
Copy link
Member

@bors r-

@CAD97
Copy link
Contributor Author

CAD97 commented Feb 8, 2020

The failure previously was a rebase error.

Wait, I thought I tested this before the previous message... I re-implemented with this version of next and it doesn't pass all of the libcore tests after all. iter::test_range_inclusive_exhaustion tests the specific results of exhausting RangeInclusive (which is documented as unspecified), and iter::test_range_inclusive_nth revealed a disconnect between ending states (and thus equivalence) from different ways of exhaustion (next, nth, next_back, nth_back).

@Mark-Simulacrum
Copy link
Member

Let's leave restoring the performance/codegen test to a future PR; I don't want to get bogged down in figuring it out exactly here, we should fix the Hash/Eq bug at least (which this is doing).

I'll wait till PR CI is passing before re-approving.

@Mark-Simulacrum
Copy link
Member

@bors r+

@bors
Copy link
Contributor

bors commented Feb 9, 2020

📌 Commit 136008c has been approved by Mark-Simulacrum

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 9, 2020
@bors
Copy link
Contributor

bors commented Feb 10, 2020

⌛ Testing commit 136008c with merge e6ec0d1...

bors added a commit that referenced this pull request Feb 10, 2020
Remove problematic specialization from RangeInclusive

Fixes #67194 using the approach [outlined by Mark-Simulacrum](#67194 (comment)).

> 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.
@bors
Copy link
Contributor

bors commented Feb 10, 2020

☀️ Test successful - checks-azure
Approved by: Mark-Simulacrum
Pushing e6ec0d1 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Feb 10, 2020
@bors bors merged commit 136008c into rust-lang:master Feb 10, 2020
@nikic nikic mentioned this pull request Feb 10, 2020
8 tasks
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Mar 20, 2020
…ramertj

Derive PartialEq, Eq and Hash for RangeInclusive

The manual implementation of `PartialEq`, `Eq` and `Hash` for `RangeInclusive` was functionally equivalent to a derived implementation.

This change removes the manual implementation and adds the respective derives.
A side effect of this change is that the derives also add implementations for `StructuralPartialEq` and `StructuralEq`, which enables `RangeInclusive` to be used in const generics, closing rust-lang#70155.

This change is enabled by rust-lang#68835, which changed the field `is_empty: Option<bool>` to `exhausted: bool` removing the need for *semantic* equality instead of *structural* equality.

## PartialEq
original [`PartialEq`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L353-L359) implementation:
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: PartialEq> PartialEq for RangeInclusive<Idx> {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.start == other.start && self.end == other.end && self.exhausted == other.exhausted
    }
}
```
expanded derive implementation (using `cargo expand ops::range`):
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx> crate::marker::StructuralPartialEq for RangeInclusive<Idx> {}

#[automatically_derived]
#[allow(unused_qualifications)]
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: crate::cmp::PartialEq> crate::cmp::PartialEq for RangeInclusive<Idx> {
    #[inline]
    fn eq(&self, other: &RangeInclusive<Idx>) -> bool {
        match *other {
            RangeInclusive { start: ref __self_1_0,end: ref __self_1_1, exhausted: ref __self_1_2 } => match *self {
                RangeInclusive { start: ref __self_0_0, end: ref __self_0_1, exhausted: ref __self_0_2 } => {
                    (*__self_0_0) == (*__self_1_0) && (*__self_0_1) == (*__self_1_1) && (*__self_0_2) == (*__self_1_2)
                }
            },
        }
    }
    #[inline]
    fn ne(&self, other: &RangeInclusive<Idx>) -> bool {
        match *other {
            RangeInclusive { start: ref __self_1_0, end: ref __self_1_1, exhausted: ref __self_1_2 } => match *self {
                RangeInclusive { start: ref __self_0_0, end: ref __self_0_1exhausted: ref __self_0_2 } => {
                    (*__self_0_0) != (*__self_1_0) || (*__self_0_1) != (*__self_1_1) || (*__self_0_2) != (*__self_1_2)
                }
            },
        }
    }
}
```

These implementations both test for *structural* equality, with the same order of field comparisons, and the bound `Idx: PartialEq` is the same.
## Eq
original [`Eq`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L361-L362) implementation:
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: Eq> Eq for RangeInclusive<Idx> {}
```
expanded derive implementation (using `cargo expand ops::range`):
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx> crate::marker::StructuralEq for RangeInclusive<Idx> {}

#[automatically_derived]
#[allow(unused_qualifications)]
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: crate::cmp::Eq> crate::cmp::Eq for RangeInclusive<Idx> {
    #[inline]
    #[doc(hidden)]
    fn assert_receiver_is_total_eq(&self) -> () {
        {
            let _: crate::cmp::AssertParamIsEq<Idx>;
            let _: crate::cmp::AssertParamIsEq<Idx>;
            let _: crate::cmp::AssertParamIsEq<bool>;
        }
    }
}
```
These implementations are equivalent since `Eq` is just a marker trait and the bound `Idx: Eq` is the same.

## Hash
original [`Hash`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L364-L371) implementation:
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: Hash> Hash for RangeInclusive<Idx> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.start.hash(state);
        self.end.hash(state);
        self.exhausted.hash(state);
    }
}
```
expanded derive implementation (using `cargo expand ops::range`):
```rust
#[automatically_derived]
#[allow(unused_qualifications)]
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: crate::hash::Hash> crate::hash::Hash for RangeInclusive<Idx> {
    fn hash<__H: crate::hash::Hasher>(&self, state: &mut __H) -> () {
        match *self { RangeInclusive { start: ref __self_0_0, end: ref __self_0_1, exhausted: ref __self_0_2 } => {
                crate::hash::Hash::hash(&(*__self_0_0), state);
                crate::hash::Hash::hash(&(*__self_0_1), state);
                crate::hash::Hash::hash(&(*__self_0_2), state)
            }
        }
    }
}
```
These implementations are functionally equivalent, with the same order of field hashing, and the bound `Idx: Hash` is the same.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Mar 21, 2020
…ramertj

Derive PartialEq, Eq and Hash for RangeInclusive

The manual implementation of `PartialEq`, `Eq` and `Hash` for `RangeInclusive` was functionally equivalent to a derived implementation.

This change removes the manual implementation and adds the respective derives.
A side effect of this change is that the derives also add implementations for `StructuralPartialEq` and `StructuralEq`, which enables `RangeInclusive` to be used in const generics, closing rust-lang#70155.

This change is enabled by rust-lang#68835, which changed the field `is_empty: Option<bool>` to `exhausted: bool` removing the need for *semantic* equality instead of *structural* equality.

## PartialEq
original [`PartialEq`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L353-L359) implementation:
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: PartialEq> PartialEq for RangeInclusive<Idx> {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.start == other.start && self.end == other.end && self.exhausted == other.exhausted
    }
}
```
expanded derive implementation (using `cargo expand ops::range`):
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx> crate::marker::StructuralPartialEq for RangeInclusive<Idx> {}

#[automatically_derived]
#[allow(unused_qualifications)]
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: crate::cmp::PartialEq> crate::cmp::PartialEq for RangeInclusive<Idx> {
    #[inline]
    fn eq(&self, other: &RangeInclusive<Idx>) -> bool {
        match *other {
            RangeInclusive { start: ref __self_1_0,end: ref __self_1_1, exhausted: ref __self_1_2 } => match *self {
                RangeInclusive { start: ref __self_0_0, end: ref __self_0_1, exhausted: ref __self_0_2 } => {
                    (*__self_0_0) == (*__self_1_0) && (*__self_0_1) == (*__self_1_1) && (*__self_0_2) == (*__self_1_2)
                }
            },
        }
    }
    #[inline]
    fn ne(&self, other: &RangeInclusive<Idx>) -> bool {
        match *other {
            RangeInclusive { start: ref __self_1_0, end: ref __self_1_1, exhausted: ref __self_1_2 } => match *self {
                RangeInclusive { start: ref __self_0_0, end: ref __self_0_1exhausted: ref __self_0_2 } => {
                    (*__self_0_0) != (*__self_1_0) || (*__self_0_1) != (*__self_1_1) || (*__self_0_2) != (*__self_1_2)
                }
            },
        }
    }
}
```

These implementations both test for *structural* equality, with the same order of field comparisons, and the bound `Idx: PartialEq` is the same.
## Eq
original [`Eq`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L361-L362) implementation:
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: Eq> Eq for RangeInclusive<Idx> {}
```
expanded derive implementation (using `cargo expand ops::range`):
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx> crate::marker::StructuralEq for RangeInclusive<Idx> {}

#[automatically_derived]
#[allow(unused_qualifications)]
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: crate::cmp::Eq> crate::cmp::Eq for RangeInclusive<Idx> {
    #[inline]
    #[doc(hidden)]
    fn assert_receiver_is_total_eq(&self) -> () {
        {
            let _: crate::cmp::AssertParamIsEq<Idx>;
            let _: crate::cmp::AssertParamIsEq<Idx>;
            let _: crate::cmp::AssertParamIsEq<bool>;
        }
    }
}
```
These implementations are equivalent since `Eq` is just a marker trait and the bound `Idx: Eq` is the same.

## Hash
original [`Hash`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L364-L371) implementation:
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: Hash> Hash for RangeInclusive<Idx> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.start.hash(state);
        self.end.hash(state);
        self.exhausted.hash(state);
    }
}
```
expanded derive implementation (using `cargo expand ops::range`):
```rust
#[automatically_derived]
#[allow(unused_qualifications)]
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: crate::hash::Hash> crate::hash::Hash for RangeInclusive<Idx> {
    fn hash<__H: crate::hash::Hasher>(&self, state: &mut __H) -> () {
        match *self { RangeInclusive { start: ref __self_0_0, end: ref __self_0_1, exhausted: ref __self_0_2 } => {
                crate::hash::Hash::hash(&(*__self_0_0), state);
                crate::hash::Hash::hash(&(*__self_0_1), state);
                crate::hash::Hash::hash(&(*__self_0_2), state)
            }
        }
    }
}
```
These implementations are functionally equivalent, with the same order of field hashing, and the bound `Idx: Hash` is the same.
Centril added a commit to Centril/rust that referenced this pull request Mar 21, 2020
…ramertj

Derive PartialEq, Eq and Hash for RangeInclusive

The manual implementation of `PartialEq`, `Eq` and `Hash` for `RangeInclusive` was functionally equivalent to a derived implementation.

This change removes the manual implementation and adds the respective derives.
A side effect of this change is that the derives also add implementations for `StructuralPartialEq` and `StructuralEq`, which enables `RangeInclusive` to be used in const generics, closing rust-lang#70155.

This change is enabled by rust-lang#68835, which changed the field `is_empty: Option<bool>` to `exhausted: bool` removing the need for *semantic* equality instead of *structural* equality.

## PartialEq
original [`PartialEq`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L353-L359) implementation:
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: PartialEq> PartialEq for RangeInclusive<Idx> {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.start == other.start && self.end == other.end && self.exhausted == other.exhausted
    }
}
```
expanded derive implementation (using `cargo expand ops::range`):
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx> crate::marker::StructuralPartialEq for RangeInclusive<Idx> {}

#[automatically_derived]
#[allow(unused_qualifications)]
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: crate::cmp::PartialEq> crate::cmp::PartialEq for RangeInclusive<Idx> {
    #[inline]
    fn eq(&self, other: &RangeInclusive<Idx>) -> bool {
        match *other {
            RangeInclusive { start: ref __self_1_0,end: ref __self_1_1, exhausted: ref __self_1_2 } => match *self {
                RangeInclusive { start: ref __self_0_0, end: ref __self_0_1, exhausted: ref __self_0_2 } => {
                    (*__self_0_0) == (*__self_1_0) && (*__self_0_1) == (*__self_1_1) && (*__self_0_2) == (*__self_1_2)
                }
            },
        }
    }
    #[inline]
    fn ne(&self, other: &RangeInclusive<Idx>) -> bool {
        match *other {
            RangeInclusive { start: ref __self_1_0, end: ref __self_1_1, exhausted: ref __self_1_2 } => match *self {
                RangeInclusive { start: ref __self_0_0, end: ref __self_0_1exhausted: ref __self_0_2 } => {
                    (*__self_0_0) != (*__self_1_0) || (*__self_0_1) != (*__self_1_1) || (*__self_0_2) != (*__self_1_2)
                }
            },
        }
    }
}
```

These implementations both test for *structural* equality, with the same order of field comparisons, and the bound `Idx: PartialEq` is the same.
## Eq
original [`Eq`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L361-L362) implementation:
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: Eq> Eq for RangeInclusive<Idx> {}
```
expanded derive implementation (using `cargo expand ops::range`):
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx> crate::marker::StructuralEq for RangeInclusive<Idx> {}

#[automatically_derived]
#[allow(unused_qualifications)]
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: crate::cmp::Eq> crate::cmp::Eq for RangeInclusive<Idx> {
    #[inline]
    #[doc(hidden)]
    fn assert_receiver_is_total_eq(&self) -> () {
        {
            let _: crate::cmp::AssertParamIsEq<Idx>;
            let _: crate::cmp::AssertParamIsEq<Idx>;
            let _: crate::cmp::AssertParamIsEq<bool>;
        }
    }
}
```
These implementations are equivalent since `Eq` is just a marker trait and the bound `Idx: Eq` is the same.

## Hash
original [`Hash`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L364-L371) implementation:
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: Hash> Hash for RangeInclusive<Idx> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.start.hash(state);
        self.end.hash(state);
        self.exhausted.hash(state);
    }
}
```
expanded derive implementation (using `cargo expand ops::range`):
```rust
#[automatically_derived]
#[allow(unused_qualifications)]
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: crate::hash::Hash> crate::hash::Hash for RangeInclusive<Idx> {
    fn hash<__H: crate::hash::Hasher>(&self, state: &mut __H) -> () {
        match *self { RangeInclusive { start: ref __self_0_0, end: ref __self_0_1, exhausted: ref __self_0_2 } => {
                crate::hash::Hash::hash(&(*__self_0_0), state);
                crate::hash::Hash::hash(&(*__self_0_1), state);
                crate::hash::Hash::hash(&(*__self_0_2), state)
            }
        }
    }
}
```
These implementations are functionally equivalent, with the same order of field hashing, and the bound `Idx: Hash` is the same.
Centril added a commit to Centril/rust that referenced this pull request Mar 21, 2020
…ramertj

Derive PartialEq, Eq and Hash for RangeInclusive

The manual implementation of `PartialEq`, `Eq` and `Hash` for `RangeInclusive` was functionally equivalent to a derived implementation.

This change removes the manual implementation and adds the respective derives.
A side effect of this change is that the derives also add implementations for `StructuralPartialEq` and `StructuralEq`, which enables `RangeInclusive` to be used in const generics, closing rust-lang#70155.

This change is enabled by rust-lang#68835, which changed the field `is_empty: Option<bool>` to `exhausted: bool` removing the need for *semantic* equality instead of *structural* equality.

## PartialEq
original [`PartialEq`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L353-L359) implementation:
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: PartialEq> PartialEq for RangeInclusive<Idx> {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.start == other.start && self.end == other.end && self.exhausted == other.exhausted
    }
}
```
expanded derive implementation (using `cargo expand ops::range`):
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx> crate::marker::StructuralPartialEq for RangeInclusive<Idx> {}

#[automatically_derived]
#[allow(unused_qualifications)]
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: crate::cmp::PartialEq> crate::cmp::PartialEq for RangeInclusive<Idx> {
    #[inline]
    fn eq(&self, other: &RangeInclusive<Idx>) -> bool {
        match *other {
            RangeInclusive { start: ref __self_1_0,end: ref __self_1_1, exhausted: ref __self_1_2 } => match *self {
                RangeInclusive { start: ref __self_0_0, end: ref __self_0_1, exhausted: ref __self_0_2 } => {
                    (*__self_0_0) == (*__self_1_0) && (*__self_0_1) == (*__self_1_1) && (*__self_0_2) == (*__self_1_2)
                }
            },
        }
    }
    #[inline]
    fn ne(&self, other: &RangeInclusive<Idx>) -> bool {
        match *other {
            RangeInclusive { start: ref __self_1_0, end: ref __self_1_1, exhausted: ref __self_1_2 } => match *self {
                RangeInclusive { start: ref __self_0_0, end: ref __self_0_1exhausted: ref __self_0_2 } => {
                    (*__self_0_0) != (*__self_1_0) || (*__self_0_1) != (*__self_1_1) || (*__self_0_2) != (*__self_1_2)
                }
            },
        }
    }
}
```

These implementations both test for *structural* equality, with the same order of field comparisons, and the bound `Idx: PartialEq` is the same.
## Eq
original [`Eq`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L361-L362) implementation:
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: Eq> Eq for RangeInclusive<Idx> {}
```
expanded derive implementation (using `cargo expand ops::range`):
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx> crate::marker::StructuralEq for RangeInclusive<Idx> {}

#[automatically_derived]
#[allow(unused_qualifications)]
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: crate::cmp::Eq> crate::cmp::Eq for RangeInclusive<Idx> {
    #[inline]
    #[doc(hidden)]
    fn assert_receiver_is_total_eq(&self) -> () {
        {
            let _: crate::cmp::AssertParamIsEq<Idx>;
            let _: crate::cmp::AssertParamIsEq<Idx>;
            let _: crate::cmp::AssertParamIsEq<bool>;
        }
    }
}
```
These implementations are equivalent since `Eq` is just a marker trait and the bound `Idx: Eq` is the same.

## Hash
original [`Hash`](https://github.com/rust-lang/rust/blob/f4c675c476c18b1a11041193f2f59d695b126bc8/src/libcore/ops/range.rs#L364-L371) implementation:
```rust
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: Hash> Hash for RangeInclusive<Idx> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.start.hash(state);
        self.end.hash(state);
        self.exhausted.hash(state);
    }
}
```
expanded derive implementation (using `cargo expand ops::range`):
```rust
#[automatically_derived]
#[allow(unused_qualifications)]
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: crate::hash::Hash> crate::hash::Hash for RangeInclusive<Idx> {
    fn hash<__H: crate::hash::Hasher>(&self, state: &mut __H) -> () {
        match *self { RangeInclusive { start: ref __self_0_0, end: ref __self_0_1, exhausted: ref __self_0_2 } => {
                crate::hash::Hash::hash(&(*__self_0_0), state);
                crate::hash::Hash::hash(&(*__self_0_1), state);
                crate::hash::Hash::hash(&(*__self_0_2), state)
            }
        }
    }
}
```
These implementations are functionally equivalent, with the same order of field hashing, and the bound `Idx: Hash` is the same.
@CAD97 CAD97 deleted the sound-range-inclusive branch April 12, 2020 00:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

PartialEq implementation for RangeInclusive is unsound
5 participants