Skip to content

Conversation

cuviper
Copy link
Member

@cuviper cuviper commented Oct 19, 2020

When a range has finished iteration, is_empty returns true, so it
should also be the case that contains returns false.

Fixes #77941.

When a range has finished iteration, `is_empty` returns true, so it
should also be the case that `contains` returns false.
@rust-highfive
Copy link
Contributor

r? @shepmaster

(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 Oct 19, 2020
@cuviper
Copy link
Member Author

cuviper commented Oct 19, 2020

This might want @rust-lang/libs FCP per #77941 (comment).

@cuviper
Copy link
Member Author

cuviper commented Oct 19, 2020

I've moved the exhausted check to RangeBounds::end_bound, per @SkiFire13's observation in #77941 (comment).

@jyn514
Copy link
Member

jyn514 commented Oct 19, 2020

I don't know why the end should be treated specially. If you think this is useful, shouldn't it apply to all parts of iteration equally, and let mut iter = 0..5; iter.next(); iter.contains(0) return false?

@jyn514 jyn514 added A-iterators Area: Iterators T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Oct 19, 2020
@cuviper
Copy link
Member Author

cuviper commented Oct 19, 2020

This is about RangeInclusive, so your example should be 0..=5, but otherwise yes! Once you advance the iterator, contains(&0) will be false, and this is already the case. Well, except if you advance in reverse to exhaustion, then it would be "empty" but still "contain" start==end==0, until this PR.

The inclusive end is special by nature, that's the whole point. Once the iterator reaches start == end, we have two possible states: !exhausted where the next value is that start/end value, then exhausted where we are empty. But contains didn't consider the latter state, which is what I'm addressing now.

@jyn514
Copy link
Member

jyn514 commented Oct 19, 2020

Got it, thanks, I didn't realize this was fixing an omission. Looks good to me then :)

Also, wow, Range being an Iterator is very confusing.

@SkiFire13
Copy link
Contributor

It would also be nice to have some tests that check this behaviour

@dtolnay
Copy link
Member

dtolnay commented Oct 20, 2020

@rust-lang/libs: this PR changes the implementation of RangeBounds for RangeInclusive in such a way that the following assertions succeed. Previously range.contains(end) continued returning true even after range.is_empty() was true.

fn main() {
    let mut range = 0..=0;
    assert!(!range.is_empty());
    assert!(range.contains(&0));

    range.next();
    assert!(range.is_empty());
    assert!(!range.contains(&0));
}

Another example of the behavior change:

fn main() {
    let array = ['w', 'x', 'y', 'z'];
    let mut range = 0..=3;
    while let Some(i) = range.next() {
        println!(
            "after i={}, the remaining elements are {:?}",
            i, &array[range.clone()],
        );
    }
}

Old behavior:

after i=0, the remaining elements are ['x', 'y', 'z']
after i=1, the remaining elements are ['y', 'z']
after i=2, the remaining elements are ['z']
after i=3, the remaining elements are ['z']

New behavior:

after i=0, the remaining elements are ['x', 'y', 'z']
after i=1, the remaining elements are ['y', 'z']
after i=2, the remaining elements are ['z']
after i=3, the remaining elements are []

@rfcbot fcp merge

@rfcbot
Copy link

rfcbot commented Oct 20, 2020

Team member @dtolnay has proposed to merge this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rfcbot rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Oct 20, 2020
@dtolnay dtolnay assigned dtolnay and unassigned shepmaster Oct 20, 2020
@cuviper
Copy link
Member Author

cuviper commented Oct 20, 2020

@SkiFire13 I figured the doc-test was sufficient -- I don't see any other existing tests of ranged contains.

@dtolnay this doesn't actually affect slicing (yet) because SliceIndex is a separate thing. I was going to followup separately, but I can add that change to this PR if you'd prefer to do it all at once.

@dtolnay
Copy link
Member

dtolnay commented Oct 20, 2020

Let's consider both as part of this FCP. I imagine we'd not want to do one without the other. But the code change for SliceIndex can go in either this PR or separate PR if easier.

@Mark-Simulacrum Mark-Simulacrum added the relnotes Marks issues that should be documented in the release notes of the next release. label Oct 20, 2020
@cuviper
Copy link
Member Author

cuviper commented Oct 21, 2020

Preserving bounds checking for exhausted SliceIndex was tricky to think about, but I think I've got it working now.

@cuviper cuviper changed the title Check for exhaustion in RangeInclusive::contains Check for exhaustion in RangeInclusive::contains and slicing Oct 21, 2020
Copy link
Member

@dtolnay dtolnay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation looks good to me. Thank you @cuviper.

@rfcbot rfcbot added final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. and removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. labels Oct 23, 2020
@rfcbot
Copy link

rfcbot commented Oct 23, 2020

🔔 This is now entering its final comment period, as per the review above. 🔔

@dtolnay
Copy link
Member

dtolnay commented Oct 23, 2020

@bors r+

@bors
Copy link
Collaborator

bors commented Oct 23, 2020

📌 Commit 9202fbd has been approved by dtolnay

@bors
Copy link
Collaborator

bors commented Oct 23, 2020

🌲 The tree is currently closed for pull requests below priority 1000, this pull request will be tested once the tree is reopened

@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 Oct 23, 2020
bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 24, 2020
…as-schievink

Rollup of 15 pull requests

Successful merges:

 - rust-lang#76649 (Add a spin loop hint for Arc::downgrade)
 - rust-lang#77392 (add `insert` to `Option`)
 - rust-lang#77716 (Revert "Allow dynamic linking for iOS/tvOS targets.")
 - rust-lang#78109 (Check for exhaustion in RangeInclusive::contains and slicing)
 - rust-lang#78198 (Simplify assert terminator only if condition evaluates to expected value)
 - rust-lang#78243 (--test-args flag description)
 - rust-lang#78249 (improve const infer error)
 - rust-lang#78250 (Document inline-const)
 - rust-lang#78264 (Add regression test for issue-77475)
 - rust-lang#78274 (Update description of Empty Enum for accuracy)
 - rust-lang#78278 (move `visit_predicate` into `TypeVisitor`)
 - rust-lang#78292 (Loop instead of recursion)
 - rust-lang#78293 (Always store Rustdoc theme when it's changed)
 - rust-lang#78300 (Make codegen coverage_context optional, and check)
 - rust-lang#78307 (Revert "Set .llvmbc and .llvmcmd sections as allocatable")

Failed merges:

r? `@ghost`
@bors bors merged commit d9acd7d into rust-lang:master Oct 24, 2020
@rustbot rustbot added this to the 1.49.0 milestone Oct 24, 2020
@rfcbot rfcbot added finished-final-comment-period The final comment period is finished for this PR / Issue. to-announce Announce this issue on triage meeting and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels Nov 2, 2020
@spastorino spastorino removed the to-announce Announce this issue on triage meeting label Nov 5, 2020
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Feb 14, 2021
Pkgsrc changes:
 * Adjust patches, convert tabs to spaces so that tests pass.
 * Remove patches which are no longer needed (upstream changed)
 * Minor adjustments for SunOS, e.g. disable stack probes.
 * Adjust cargo checksum patching accordingly.
 * Remove commented-out use of PATCHELF on NetBSD, which doesn't work anyway...

Upstream changes:

Version 1.49.0 (2020-12-31)
============================

Language
-----------------------

- [Unions can now implement `Drop`, and you can now have a field in a union
  with `ManuallyDrop<T>`.][77547]
- [You can now cast uninhabited enums to integers.][76199]
- [You can now bind by reference and by move in patterns.][76119] This
  allows you to selectively borrow individual components of a type. E.g.
  ```rust
  #[derive(Debug)]
  struct Person {
      name: String,
      age: u8,
  }

  let person = Person {
      name: String::from("Alice"),
      age: 20,
  };

  // `name` is moved out of person, but `age` is referenced.
  let Person { name, ref age } = person;
  println!("{} {}", name, age);
  ```

Compiler
-----------------------

- [Added tier 1\* support for `aarch64-unknown-linux-gnu`.][78228]
- [Added tier 2 support for `aarch64-apple-darwin`.][75991]
- [Added tier 2 support for `aarch64-pc-windows-msvc`.][75914]
- [Added tier 3 support for `mipsel-unknown-none`.][78676]
- [Raised the minimum supported LLVM version to LLVM 9.][78848]
- [Output from threads spawned in tests is now captured.][78227]
- [Change os and vendor values to "none" and "unknown" for some targets][78951]

\* Refer to Rust's [platform support page][forge-platform-support] for more
information on Rust's tiered platform support.

Libraries
-----------------------

- [`RangeInclusive` now checks for exhaustion when calling `contains`
  and indexing.][78109]
- [`ToString::to_string` now no longer shrinks the internal buffer
  in the default implementation.][77997]
- [`ops::{Index, IndexMut}` are now implemented for fixed sized
  arrays of any length.][74989]

Stabilized APIs
---------------

- [`slice::select_nth_unstable`]
- [`slice::select_nth_unstable_by`]
- [`slice::select_nth_unstable_by_key`]

The following previously stable methods are now `const`.

- [`Poll::is_ready`]
- [`Poll::is_pending`]

Cargo
-----------------------
- [Building a crate with `cargo-package` should now be independently
  reproducible.][cargo/8864]
- [`cargo-tree` now marks proc-macro crates.][cargo/8765]
- [Added `CARGO_PRIMARY_PACKAGE` build-time environment
  variable.]  [cargo/8758] This variable will be set if the crate
  being built is one the user selected to build, either with `-p`
  or through defaults.
- [You can now use glob patterns when specifying packages &
  targets.][cargo/8752]


Compatibility Notes
-------------------
- [Demoted `i686-unknown-freebsd` from host tier 2 to target tier
  2 support.][78746]
- [Macros that end with a semi-colon are now treated as statements
  even if they expand to nothing.][78376]
- [Rustc will now check for the validity of some built-in attributes
  on enum variants.][77015] Previously such invalid or unused
  attributes could be ignored.
- Leading whitespace is stripped more uniformly in documentation
  comments, which may change behavior. You read [this post about
  the changes][rustdoc-ws-post] for more details.
- [Trait bounds are no longer inferred for associated types.][79904]

Internal Only
-------------
These changes provide no direct user facing benefits, but represent
significant improvements to the internals and overall performance
of rustc and related tools.

- [rustc's internal crates are now compiled using the `initial-exec` Thread
  Local Storage model.][78201]
- [Calculate visibilities once in resolve.][78077]
- [Added `system` to the `llvm-libunwind` bootstrap config option.][77703]
- [Added `--color` for configuring terminal color support to bootstrap.][79004]


[75991]: rust-lang/rust#75991
[78951]: rust-lang/rust#78951
[78848]: rust-lang/rust#78848
[78746]: rust-lang/rust#78746
[78376]: rust-lang/rust#78376
[78228]: rust-lang/rust#78228
[78227]: rust-lang/rust#78227
[78201]: rust-lang/rust#78201
[78109]: rust-lang/rust#78109
[78077]: rust-lang/rust#78077
[77997]: rust-lang/rust#77997
[77703]: rust-lang/rust#77703
[77547]: rust-lang/rust#77547
[77015]: rust-lang/rust#77015
[76199]: rust-lang/rust#76199
[76119]: rust-lang/rust#76119
[75914]: rust-lang/rust#75914
[74989]: rust-lang/rust#74989
[79004]: rust-lang/rust#79004
[78676]: rust-lang/rust#78676
[79904]: rust-lang/rust#79904
[cargo/8864]: rust-lang/cargo#8864
[cargo/8765]: rust-lang/cargo#8765
[cargo/8758]: rust-lang/cargo#8758
[cargo/8752]: rust-lang/cargo#8752
[`slice::select_nth_unstable`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.select_nth_unstable
[`slice::select_nth_unstable_by`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.select_nth_unstable_by
[`slice::select_nth_unstable_by_key`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.select_nth_unstable_by_key
[`hint::spin_loop`]: https://doc.rust-lang.org/stable/std/hint/fn.spin_loop.html
[`Poll::is_ready`]: https://doc.rust-lang.org/stable/std/task/enum.Poll.html#method.is_ready
[`Poll::is_pending`]: https://doc.rust-lang.org/stable/std/task/enum.Poll.html#method.is_pending
[rustdoc-ws-post]: https://blog.guillaume-gomez.fr/articles/2020-11-11+New+doc+comment+handling+in+rustdoc
@cuviper cuviper deleted the exhausted-rangeinc branch September 21, 2021 16:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-iterators Area: Iterators disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. relnotes Marks issues that should be documented in the release notes of the next release. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RangeInclusive::contains doesn't consider exhaustion