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

Tracking issue for start, end and new methods of RangeInclusive #49022

Closed
2 of 3 tasks
kennytm opened this issue Mar 14, 2018 · 21 comments
Closed
2 of 3 tasks

Tracking issue for start, end and new methods of RangeInclusive #49022

kennytm opened this issue Mar 14, 2018 · 21 comments
Assignees
Labels
B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@kennytm
Copy link
Member

kennytm commented Mar 14, 2018

Tracking issue for the start, end and new methods of RangeInclusive.

(Originally the tracking issue for rust-lang/rfcs#1980 the start and end fields, but we decided to make the representation private in #49022 (comment))

Steps:

Unresolved questions:

  • Should we want to expose the fields as public (stabilize as is), or simply provide getter methods and don't show the implementation detail (redesign from scratch)?

This issue is separated from #28237 since there were vocal oppositions from the community (see #47813) due to performance loss if we commit to the two-field design.

If you want start and end, please use these for now:

  • x.start()x.next().unwrap()
  • x.end()x.next_back().unwrap()
@kennytm kennytm added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. labels Mar 14, 2018
@kennytm kennytm self-assigned this Mar 14, 2018
@scottmcm
Copy link
Member

Two important points here:

  • There's no performance loss if you use internal iteration (fold & friends), just like other types (such as Chain) that can be faster if you use internal iteration instead of a for loop.
  • There is core additional complexity to iterating RangeInclusive compared to a Range, since the loop body fundamentally must do something different in the last iteration in the interesting case

As I've said before, the optimal choice here would be to only have the range types be IntoIterator (not Iterator), but that change requires a time machine, so I think being like Range is best.

bors added a commit that referenced this issue Mar 15, 2018
Stabilize inclusive range (`..=`)

Stabilize the followings:

* `inclusive_range` — The `std::ops::RangeInclusive` and `std::ops::RangeInclusiveTo` types, except its fields (tracked by #49022 separately).
* `inclusive_range_syntax` — The `a..=b` and `..=b` expression syntax
* `dotdoteq_in_patterns` — Using `a..=b` in a pattern

cc #28237
r? @rust-lang/lang
@SimonSapin
Copy link
Contributor

The libs team discussed this and the consensus was to make all fields private, provide accessor methods, and add a boolean field to implement iteration in a way that hopefully optimizes better.

impl<Idx> RangeInclusive<Idx> {
    pub fn start(&self) -> &Idx {}
    pub fn end(&self) -> &Idx {}
}

If someone has a use case for moving bounds out, they should request something like pub fn into_inner(self) -> (Idx, Idx) to be added. The methods of the RangeBounds trait (formerly RangeArgument) are to be renamed start_bound and end_bound to avoid name collision.

@rfcbot fcp merge

@rfcbot
Copy link

rfcbot commented Mar 30, 2018

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

No concerns currently listed.

Once a majority of reviewers approve (and none object), 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 the proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. label Mar 30, 2018
@scottmcm
Copy link
Member

What exact this this FCPing? It feels odd that the last two times the class was modified it was via RFC, but this time it's just a "hopefully", not even a PR.

@SimonSapin
Copy link
Contributor

This is not making again deep changes to the data structure or syntax, only picking one of two already-proposed alternatives. And the more conservative one, since methods can keep working even if the internal structure changes.

@kennytm
Copy link
Member Author

kennytm commented Apr 5, 2018

Simply making the fields private will break lowering of ..= 😒

error[E0451]: field `start` of struct `std::ops::RangeInclusive` is private
   --> librustc/ty/layout.rs:646:34
    |
646 |             self.valid_range == (0..=1)
    |                                  ^ field `start` is private

error[E0451]: field `end` of struct `std::ops::RangeInclusive` is private
   --> librustc/ty/layout.rs:646:38
    |
646 |             self.valid_range == (0..=1)
    |                                      ^ field `end` is private

Therefore x..=y will need to lower to something like RangeInclusive::new(x, y). Should the constructor be exposed or #[doc(hidden)]? Or we keep the fields public and perma-unstable them?

@SimonSapin
Copy link
Contributor

I’d be fine with #[doc(hidden)] perma-unstable public fields, but we might want an constructor function anyway if the fields are "effectively private". Is lowering to a call difficult or inconvenient?

@kennytm
Copy link
Member Author

kennytm commented Apr 5, 2018

It needs a special case in https://github.com/rust-lang/rust/blob/56714acc5eb0687ed9a7566fdebe5528657fc5b/src/librustc/hir/lowering.rs#L3082 for the ExprKind::Range(Some(..), Some(..), Closed) case. Not very difficult, just different.

@scottmcm
Copy link
Member

scottmcm commented Apr 5, 2018

I'm not sure that a doc(hidden) perma-unstable function is better than doc(hidden) perma-unstable fields.

@SimonSapin
Copy link
Contributor

Why not stabilize that function? Other range types can be created as struct literals in addition to the dedicated syntax.

@sfackler
Copy link
Member

sfackler commented Apr 5, 2018

I agree with @SimonSapin, it seems reasonable to have a stable constructor for the type.

@kennytm kennytm changed the title Tracking issue for RFC 1980, start and end fields of RangeInclusive Tracking issue for start, end and new methods of RangeInclusive Apr 5, 2018
@crlf0710
Copy link
Member

crlf0710 commented Apr 7, 2018

While i think those methods are fine, i believe (at least) the constructor should be const fn...

@scottmcm
Copy link
Member

scottmcm commented Apr 7, 2018

What advantage does the RangeInclusive::new have over just using ..=? And if there is something, wouldn't it also apply to having a Range::new in addition to ..? (I don't consider the compiler initializing unstable fields to be a problem.)

@kennytm
Copy link
Member Author

kennytm commented Apr 7, 2018

@scottmcm There is no advantage using the method.

..= and .. are simply syntactic sugar, a..b will be lowered as Range { start: a, end: b } before type-checking. The stability of the fields are irrelevant; the problem with ..= is that the compiler cannot initialize private fields (unless we use some hygiene hack to put the span inside std::ops which I think is even worse). Therefore a public method RangeInclusive::new() needs to be introduced as the lowering of a..=b.

The question is only whether we want to eventually stabilize RangeInclusive::new(), or keep it #[doc(hidden)] #[unstable] forever.

@scottmcm
Copy link
Member

scottmcm commented Apr 7, 2018

@kennytm Fair enough, makes sense if the goal is private fields.

A thought, since I don't know what was discussed: could the struct be #[non_exhaustive] so start and end are pub (and thus matchable, move-from-able, etc), but the struct can still be changed if needed? (That of course still needs the constructor, but might avoid future asks for into_inner, start_mut, etc.)

@kennytm
Copy link
Member Author

kennytm commented Apr 7, 2018

@scottmcm This will allow mutating start and end without touching the hidden field, potentially breaking some invariants for RangeInclusive.

@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 Apr 10, 2018
@rfcbot
Copy link

rfcbot commented Apr 10, 2018

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

@rfcbot
Copy link

rfcbot commented Apr 20, 2018

The final comment period is now complete.

bors added a commit that referenced this issue May 1, 2018
Introduce RangeInclusive::{new, start, end} methods and make the fields private.

cc #49022
@ghost
Copy link

ghost commented May 9, 2018

This makes it very difficult/impossible when start and end are non-Copy types.
(It has broken my math_traits crate, which relied on destructing RangeInclusive.)

If someone has a use case for moving bounds out, they should request something like pub fn into_inner(self) -> (Idx, Idx) to be added.

I hereby request pub fn into_inner(self) -> (Idx, Idx).

@SimonSapin
Copy link
Contributor

Adding into_inner sounds good to me. Wanna send a PR?

@ghost
Copy link

ghost commented May 9, 2018

@SimonSapin done! #50574

alexcrichton added a commit to alexcrichton/rust that referenced this issue May 10, 2018
…SimonSapin

add fn `into_inner(self) -> (Idx, Idx)` to RangeInclusive (rust-lang#49022)

adds `into_inner(self) -> (Idx, Idx)` to RangeInclusive
rust-lang#49022 (comment)
alexcrichton added a commit to alexcrichton/rust that referenced this issue May 10, 2018
…SimonSapin

add fn `into_inner(self) -> (Idx, Idx)` to RangeInclusive (rust-lang#49022)

adds `into_inner(self) -> (Idx, Idx)` to RangeInclusive
rust-lang#49022 (comment)
bors added a commit that referenced this issue May 10, 2018
Rollup of 18 pull requests

Successful merges:

 - #49423 (Extend tests for RFC1598 (GAT))
 - #50010 (Give SliceIndex impls a test suite of girth befitting the implementation (and fix a UTF8 boundary check))
 - #50447 (Fix update-references for tests within subdirectories.)
 - #50514 (Pull in a wasm fix from LLVM upstream)
 - #50524 (Make DepGraph::previous_work_products immutable)
 - #50532 (Don't use Lock for heavily accessed CrateMetadata::cnum_map.)
 - #50538 ( Make CrateNum allocation more thread-safe. )
 - #50564 (Inline `Span` methods.)
 - #50565 (Use SmallVec for DepNodeIndex within dep_graph.)
 - #50569 (Allow for specifying a linker plugin for cross-language LTO)
 - #50572 (Clarify in the docs that `mul_add` is not always faster.)
 - #50574 (add fn `into_inner(self) -> (Idx, Idx)` to RangeInclusive (#49022))
 - #50575 (std: Avoid `ptr::copy` if unnecessary in `vec::Drain`)
 - #50588 (Move "See also" disambiguation links for primitive types to top)
 - #50590 (Fix tuple struct field spans)
 - #50591 (Restore RawVec::reserve* documentation)
 - #50598 (Remove unnecessary mutable borrow and resizing in DepGraph::serialize)
 - #50606 (Retry when downloading the Docker cache.)

Failed merges:

 - #50161 (added missing implementation hint)
 - #50558 (Remove all reference to DepGraph::work_products)
bors added a commit that referenced this issue May 18, 2018
…monSapin

Stabilise inclusive_range_methods

r? @SimonSapin

Closes #49022.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants