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

Add ?Sized bounds to all the RangeBounds impls #61584

Closed
wants to merge 1 commit into from
Closed

Add ?Sized bounds to all the RangeBounds impls #61584

wants to merge 1 commit into from

Conversation

Kerollmops
Copy link
Contributor

@Kerollmops Kerollmops commented Jun 6, 2019

We found that all the RangeBounds implementations on the real range types (i.e. RangeFull, RangeFrom...) should have some size relaxation. Therefore I added the ?Sized trait bound to all the implementations of the RangeBounds trait.

This pull request emerged after having seen the problem on one of my reddit post.

@rust-highfive
Copy link
Collaborator

r? @TimNN

(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 Jun 6, 2019
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-6.0 of your PR failed on Travis (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.
travis_time:end:24647297:start=1559823304760332092,finish=1559823308249546529,duration=3489214437
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
$ export GCP_CACHE_BUCKET=rust-lang-ci-cache
$ export AWS_ACCESS_KEY_ID=AKIA46X5W6CZEJZ6XT55
---
[00:05:01]    Compiling backtrace-sys v0.1.27
[00:05:02] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:02]    --> src/libcore/ops/range.rs:784:17
[00:05:02]     |
[00:05:02] 784 | impl<T: ?Sized> RangeBounds<T> for RangeFrom<T> {
[00:05:02]     |
[00:05:02]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:02]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:02]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:02]     = help: consider adding a `where T: marker::Sized` bound
[00:05:02] note: required by `ops::range::RangeFrom`
[00:05:02]    --> src/libcore/ops/range.rs:181:1
[00:05:02] 181 | pub struct RangeFrom<Idx> {
[00:05:02]     | ^^^^^^^^^^^^^^^^^^^^^^^^^
[00:05:02] 
[00:05:02] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:02] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:02]    --> src/libcore/ops/range.rs:794:17
[00:05:02]     |
[00:05:02] 794 | impl<T: ?Sized> RangeBounds<T> for RangeTo<T> {
[00:05:02]     |
[00:05:02]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:02]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:02]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:02]     = help: consider adding a `where T: marker::Sized` bound
[00:05:02] note: required by `ops::range::RangeTo`
[00:05:02]    --> src/libcore/ops/range.rs:265:1
[00:05:02] 265 | pub struct RangeTo<Idx> {
[00:05:02]     | ^^^^^^^^^^^^^^^^^^^^^^^
[00:05:02] 
[00:05:02] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:02] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:02]    --> src/libcore/ops/range.rs:804:17
[00:05:02]     |
[00:05:02] 804 | impl<T: ?Sized> RangeBounds<T> for Range<T> {
[00:05:02]     |
[00:05:02]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:02]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:02]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:02]     = help: consider adding a `where T: marker::Sized` bound
[00:05:02] note: required by `ops::range::Range`
[00:05:02]    --> src/libcore/ops/range.rs:76:1
[00:05:02] 76  | pub struct Range<Idx> {
[00:05:02]     | ^^^^^^^^^^^^^^^^^^^^^
[00:05:02] 
[00:05:02] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:02] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:02]    --> src/libcore/ops/range.rs:814:17
[00:05:02]     |
[00:05:02] 814 | impl<T: ?Sized> RangeBounds<T> for RangeInclusive<T> {
[00:05:02]     |
[00:05:02]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:02]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:02]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:02]     = help: consider adding a `where T: marker::Sized` bound
[00:05:02] note: required by `ops::range::RangeInclusive`
[00:05:02]    --> src/libcore/ops/range.rs:335:1
[00:05:02] 335 | pub struct RangeInclusive<Idx> {
[00:05:02]     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[00:05:02] 
[00:05:02] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:02] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:02]    --> src/libcore/ops/range.rs:824:17
[00:05:02]     |
[00:05:02] 824 | impl<T: ?Sized> RangeBounds<T> for RangeToInclusive<T> {
[00:05:02]     |
[00:05:02]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:02]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:02]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:02]     = help: consider adding a `where T: marker::Sized` bound
[00:05:02] note: required by `ops::range::RangeToInclusive`
[00:05:02]    --> src/libcore/ops/range.rs:606:1
[00:05:02] 606 | pub struct RangeToInclusive<Idx> {
[00:05:02]     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[00:05:02] 
[00:05:02] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:02] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:02]    --> src/libcore/ops/range.rs:834:17
[00:05:02]     |
[00:05:02] 834 | impl<T: ?Sized> RangeBounds<T> for (Bound<T>, Bound<T>) {
[00:05:02]     |
[00:05:02]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:02]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:02]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:02]     = help: consider adding a `where T: marker::Sized` bound
[00:05:02] note: required by `ops::range::Bound`
[00:05:02]    --> src/libcore/ops/range.rs:687:1
[00:05:02]     |
[00:05:02] 687 | pub enum Bound<T> {
[00:05:02] 
[00:05:03]    Compiling std v0.0.0 (/checkout/src/libstd)
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03]    --> src/libcore/ops/range.rs:785:5
[00:05:03]    --> src/libcore/ops/range.rs:785:5
[00:05:03]     |
[00:05:03] 785 | /     fn start_bound(&self) -> Bound<&T> {
[00:05:03] 786 | |         Included(&self.start)
[00:05:03]     | |_____^ doesn't have a size known at compile-time
[00:05:03]     |
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = help: consider adding a `where T: marker::Sized` bound
[00:05:03] note: required by `ops::range::RangeFrom`
[00:05:03]    --> src/libcore/ops/range.rs:181:1
[00:05:03] 181 | pub struct RangeFrom<Idx> {
[00:05:03]     | ^^^^^^^^^^^^^^^^^^^^^^^^^
[00:05:03] 
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03]    --> src/libcore/ops/range.rs:788:5
[00:05:03]     |
[00:05:03] 788 | /     fn end_bound(&self) -> Bound<&T> {
[00:05:03] 790 | |     }
[00:05:03]     | |_____^ doesn't have a size known at compile-time
[00:05:03]     |
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = help: consider adding a `where T: marker::Sized` bound
[00:05:03] note: required by `ops::range::RangeFrom`
[00:05:03]    --> src/libcore/ops/range.rs:181:1
[00:05:03] 181 | pub struct RangeFrom<Idx> {
[00:05:03]     | ^^^^^^^^^^^^^^^^^^^^^^^^^
[00:05:03] 
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03]    --> src/libcore/ops/range.rs:795:5
[00:05:03]     |
[00:05:03] 795 | /     fn start_bound(&self) -> Bound<&T> {
[00:05:03] 797 | |     }
[00:05:03]     | |_____^ doesn't have a size known at compile-time
[00:05:03]     |
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = help: consider adding a `where T: marker::Sized` bound
[00:05:03] note: required by `ops::range::RangeTo`
[00:05:03]    --> src/libcore/ops/range.rs:265:1
[00:05:03] 265 | pub struct RangeTo<Idx> {
[00:05:03]     | ^^^^^^^^^^^^^^^^^^^^^^^
[00:05:03] 
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03]    --> src/libcore/ops/range.rs:798:5
[00:05:03]     |
[00:05:03] 798 | /     fn end_bound(&self) -> Bound<&T> {
[00:05:03] 799 | |         Excluded(&self.end)
[00:05:03]     | |_____^ doesn't have a size known at compile-time
[00:05:03]     |
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = help: consider adding a `where T: marker::Sized` bound
[00:05:03] note: required by `ops::range::RangeTo`
[00:05:03]    --> src/libcore/ops/range.rs:265:1
[00:05:03] 265 | pub struct RangeTo<Idx> {
[00:05:03]     | ^^^^^^^^^^^^^^^^^^^^^^^
[00:05:03] 
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03]    --> src/libcore/ops/range.rs:805:5
[00:05:03]     |
[00:05:03] 805 | /     fn start_bound(&self) -> Bound<&T> {
[00:05:03] 806 | |         Included(&self.start)
[00:05:03]     | |_____^ doesn't have a size known at compile-time
[00:05:03]     |
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = help: consider adding a `where T: marker::Sized` bound
[00:05:03] note: required by `ops::range::Range`
[00:05:03]    --> src/libcore/ops/range.rs:76:1
[00:05:03] 76  | pub struct Range<Idx> {
[00:05:03]     | ^^^^^^^^^^^^^^^^^^^^^
[00:05:03] 
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03]    --> src/libcore/ops/range.rs:808:5
[00:05:03]     |
[00:05:03] 808 | /     fn end_bound(&self) -> Bound<&T> {
[00:05:03] 809 | |         Excluded(&self.end)
[00:05:03]     | |_____^ doesn't have a size known at compile-time
[00:05:03]     |
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = help: consider adding a `where T: marker::Sized` bound
[00:05:03] note: required by `ops::range::Range`
[00:05:03]    --> src/libcore/ops/range.rs:76:1
[00:05:03] 76  | pub struct Range<Idx> {
[00:05:03]     | ^^^^^^^^^^^^^^^^^^^^^
[00:05:03] 
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03]    --> src/libcore/ops/range.rs:815:5
[00:05:03]     |
[00:05:03] 815 | /     fn start_bound(&self) -> Bound<&T> {
[00:05:03] 816 | |         Included(&self.start)
[00:05:03]     | |_____^ doesn't have a size known at compile-time
[00:05:03]     |
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = help: consider adding a `where T: marker::Sized` bound
[00:05:03] note: required by `ops::range::RangeInclusive`
[00:05:03]    --> src/libcore/ops/range.rs:335:1
[00:05:03] 335 | pub struct RangeInclusive<Idx> {
[00:05:03]     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[00:05:03] 
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03]    --> src/libcore/ops/range.rs:818:5
[00:05:03]     |
[00:05:03] 818 | /     fn end_bound(&self) -> Bound<&T> {
[00:05:03] 819 | |         Included(&self.end)
[00:05:03]     | |_____^ doesn't have a size known at compile-time
[00:05:03]     |
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = help: consider adding a `where T: marker::Sized` bound
[00:05:03] note: required by `ops::range::RangeInclusive`
[00:05:03]    --> src/libcore/ops/range.rs:335:1
[00:05:03] 335 | pub struct RangeInclusive<Idx> {
[00:05:03]     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[00:05:03] 
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03]    --> src/libcore/ops/range.rs:825:5
[00:05:03]     |
[00:05:03] 825 | /     fn start_bound(&self) -> Bound<&T> {
[00:05:03] 827 | |     }
[00:05:03]     | |_____^ doesn't have a size known at compile-time
[00:05:03]     |
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = help: consider adding a `where T: marker::Sized` bound
[00:05:03] note: required by `ops::range::RangeToInclusive`
[00:05:03]    --> src/libcore/ops/range.rs:606:1
[00:05:03] 606 | pub struct RangeToInclusive<Idx> {
[00:05:03]     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[00:05:03] 
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03]    --> src/libcore/ops/range.rs:828:5
[00:05:03]     |
[00:05:03] 828 | /     fn end_bound(&self) -> Bound<&T> {
[00:05:03] 829 | |         Included(&self.end)
[00:05:03]     | |_____^ doesn't have a size known at compile-time
[00:05:03]     |
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = help: consider adding a `where T: marker::Sized` bound
[00:05:03] note: required by `ops::range::RangeToInclusive`
[00:05:03]    --> src/libcore/ops/range.rs:606:1
[00:05:03] 606 | pub struct RangeToInclusive<Idx> {
[00:05:03]     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[00:05:03] 
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03]    --> src/libcore/ops/range.rs:835:5
[00:05:03]     |
[00:05:03] 835 | /     fn start_bound(&self) -> Bound<&T> {
[00:05:03] 836 | |         match *self {
[00:05:03] 837 | |             (Included(ref start), _) => Included(start),
[00:05:03] 838 | |             (Excluded(ref start), _) => Excluded(start),
[00:05:03] 839 | |             (Unbounded, _) => Unbounded,
[00:05:03] 841 | |     }
[00:05:03]     | |_____^ doesn't have a size known at compile-time
[00:05:03]     |
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = help: consider adding a `where T: marker::Sized` bound
[00:05:03] note: required by `ops::range::Bound`
[00:05:03]    --> src/libcore/ops/range.rs:687:1
[00:05:03]     |
[00:05:03] 687 | pub enum Bound<T> {
[00:05:03] 
[00:05:03] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:05:03]    --> src/libcore/ops/range.rs:843:5
[00:05:03]     |
[00:05:03]     |
[00:05:03] 843 | /     fn end_bound(&self) -> Bound<&T> {
[00:05:03] 844 | |         match *self {
[00:05:03] 845 | |             (_, Included(ref end)) => Included(end),
[00:05:03] 846 | |             (_, Excluded(ref end)) => Excluded(end),
[00:05:03] 847 | |             (_, Unbounded) => Unbounded,
[00:05:03] 849 | |     }
[00:05:03]     | |_____^ doesn't have a size known at compile-time
[00:05:03]     |
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = help: the trait `marker::Sized` is not implemented for `T`
[00:05:03]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:05:03]     = help: consider adding a `where T: marker::Sized` bound
[00:05:03] note: required by `ops::range::Bound`
[00:05:03]    --> src/libcore/ops/range.rs:687:1
[00:05:03]     |
[00:05:03] 687 | pub enum Bound<T> {
[00:05:03] 
[00:05:04] error: aborting due to 18 previous errors
[00:05:04] 
[00:05:04] For more information about this error, try `rustc --explain E0277`.

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)

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-6.0 of your PR failed on Travis (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.
travis_time:end:2a0d9a64:start=1559824974243927155,finish=1559824975034404963,duration=790477808
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
$ export GCP_CACHE_BUCKET=rust-lang-ci-cache
$ export AWS_ACCESS_KEY_ID=AKIA46X5W6CZEJZ6XT55
---
[00:04:55]    Compiling backtrace-sys v0.1.27
[00:04:55] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:04:55]    --> src/libcore/ops/range.rs:834:17
[00:04:55]     |
[00:04:55] 834 | impl<T: ?Sized> RangeBounds<T> for (Bound<T>, Bound<T>) {
[00:04:55]     |
[00:04:55]     = help: the trait `marker::Sized` is not implemented for `T`
[00:04:55]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:55]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:55]     = help: consider adding a `where T: marker::Sized` bound
[00:04:55] note: required by `ops::range::Bound`
[00:04:55]    --> src/libcore/ops/range.rs:687:1
[00:04:55]     |
[00:04:55] 687 | pub enum Bound<T> {
[00:04:55] 
[00:04:55] 
[00:04:56] error[E0277]: the size for values of type `Idx` cannot be known at compilation time
[00:04:56]   --> src/libcore/ops/range.rs:79:5
[00:04:56] 79 |     pub start: Idx,
[00:04:56]    |     ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
[00:04:56]    |
[00:04:56]    = help: the trait `marker::Sized` is not implemented for `Idx`
[00:04:56]    = help: the trait `marker::Sized` is not implemented for `Idx`
[00:04:56]    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:56]    = help: consider adding a `where Idx: marker::Sized` bound
[00:04:56]    = note: only the last field of a struct may have a dynamically sized type
[00:04:56] 
[00:04:56] error[E0277]: the size for values of type `Idx` cannot be known at compilation time
[00:04:56]    --> src/libcore/ops/range.rs:336:5
[00:04:56]     |
[00:04:56] 336 |     pub(crate) start: Idx,
[00:04:56]     |
[00:04:56]     = help: the trait `marker::Sized` is not implemented for `Idx`
[00:04:56]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:56]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:56]     = help: consider adding a `where Idx: marker::Sized` bound
[00:04:56]     = note: only the last field of a struct may have a dynamically sized type
[00:04:57]    Compiling std v0.0.0 (/checkout/src/libstd)
[00:04:57]    Compiling std v0.0.0 (/checkout/src/libstd)
[00:04:57] error[E0277]: the size for values of type `Idx` cannot be known at compilation time
[00:04:57]    --> src/libcore/ops/range.rs:469:5
[00:04:57] 469 | /     pub fn into_inner(self) -> (Idx, Idx) {
[00:04:57] 470 | |         (self.start, self.end)
[00:04:57] 471 | |     }
[00:04:57]     | |_____^ doesn't have a size known at compile-time
[00:04:57]     | |_____^ doesn't have a size known at compile-time
[00:04:57]     |
[00:04:57]     = help: the trait `marker::Sized` is not implemented for `Idx`
[00:04:57]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:57]     = help: consider adding a `where Idx: marker::Sized` bound
[00:04:57]     = note: only the last element of a tuple may have a dynamically sized type
[00:04:57] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:04:57]    --> src/libcore/ops/range.rs:835:5
[00:04:57]     |
[00:04:57]     |
[00:04:57] 835 | /     fn start_bound(&self) -> Bound<&T> {
[00:04:57] 836 | |         match *self {
[00:04:57] 837 | |             (Included(ref start), _) => Included(start),
[00:04:57] 838 | |             (Excluded(ref start), _) => Excluded(start),
[00:04:57] 839 | |             (Unbounded, _) => Unbounded,
[00:04:57] 841 | |     }
[00:04:57]     | |_____^ doesn't have a size known at compile-time
[00:04:57]     |
[00:04:57]     = help: the trait `marker::Sized` is not implemented for `T`
[00:04:57]     = help: the trait `marker::Sized` is not implemented for `T`
[00:04:57]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:57]     = help: consider adding a `where T: marker::Sized` bound
[00:04:57] note: required by `ops::range::Bound`
[00:04:57]    --> src/libcore/ops/range.rs:687:1
[00:04:57]     |
[00:04:57] 687 | pub enum Bound<T> {
[00:04:57] 
[00:04:57] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:04:57]    --> src/libcore/ops/range.rs:843:5
[00:04:57]     |
[00:04:57]     |
[00:04:57] 843 | /     fn end_bound(&self) -> Bound<&T> {
[00:04:57] 844 | |         match *self {
[00:04:57] 845 | |             (_, Included(ref end)) => Included(end),
[00:04:57] 846 | |             (_, Excluded(ref end)) => Excluded(end),
[00:04:57] 847 | |             (_, Unbounded) => Unbounded,
[00:04:57] 849 | |     }
[00:04:57]     | |_____^ doesn't have a size known at compile-time
[00:04:57]     |
[00:04:57]     = help: the trait `marker::Sized` is not implemented for `T`
[00:04:57]     = help: the trait `marker::Sized` is not implemented for `T`
[00:04:57]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:57]     = help: consider adding a `where T: marker::Sized` bound
[00:04:57] note: required by `ops::range::Bound`
[00:04:57]    --> src/libcore/ops/range.rs:687:1
[00:04:57]     |
[00:04:57] 687 | pub enum Bound<T> {
[00:04:57] 
[00:04:58] error: aborting due to 6 previous errors
[00:04:58] 
[00:04:58] For more information about this error, try `rustc --explain E0277`.

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)

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-6.0 of your PR failed on Travis (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.
travis_time:end:1fa28a86:start=1559830134917475271,finish=1559830135730407821,duration=812932550
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
$ export GCP_CACHE_BUCKET=rust-lang-ci-cache
$ export AWS_ACCESS_KEY_ID=AKIA46X5W6CZEJZ6XT55
---
[00:04:50]    Compiling cmake v0.1.38
[00:04:51] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:04:51]    --> src/libcore/ops/range.rs:834:17
[00:04:51]     |
[00:04:51] 834 | impl<T: ?Sized> RangeBounds<T> for (Bound<T>, Bound<T>) {
[00:04:51]     |
[00:04:51]     |
[00:04:51]     = help: within `ops::range::Bound<T>`, the trait `marker::Sized` is not implemented for `T`
[00:04:51]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:51]     = help: consider adding a `where T: marker::Sized` bound
[00:04:51]     = note: required because it appears within the type `ops::range::Bound<T>`
[00:04:51]     = note: only the last element of a tuple may have a dynamically sized type
[00:04:51] 
[00:04:51] error[E0277]: the size for values of type `Idx` cannot be known at compilation time
[00:04:51]   --> src/libcore/ops/range.rs:79:5
[00:04:51] 79 |     pub start: Idx,
[00:04:51]    |     ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
[00:04:51]    |
[00:04:51]    = help: the trait `marker::Sized` is not implemented for `Idx`
[00:04:51]    = help: the trait `marker::Sized` is not implemented for `Idx`
[00:04:51]    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:51]    = help: consider adding a `where Idx: marker::Sized` bound
[00:04:51]    = note: only the last field of a struct may have a dynamically sized type
[00:04:51] 
[00:04:51] error[E0277]: the size for values of type `Idx` cannot be known at compilation time
[00:04:51]    --> src/libcore/ops/range.rs:336:5
[00:04:51]     |
[00:04:51] 336 |     pub(crate) start: Idx,
[00:04:51]     |
[00:04:51]     = help: the trait `marker::Sized` is not implemented for `Idx`
[00:04:51]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:51]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:51]     = help: consider adding a `where Idx: marker::Sized` bound
[00:04:51]     = note: only the last field of a struct may have a dynamically sized type
[00:04:51] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:04:51]    --> src/libcore/ops/range.rs:690:73
[00:04:51]     |
[00:04:51]     |
[00:04:51] 690 |     Included(#[stable(feature = "collections_bound", since = "1.17.0")] T),
[00:04:51]     |                                                                         ^ doesn't have a size known at compile-time
[00:04:51]     = help: the trait `marker::Sized` is not implemented for `T`
[00:04:51]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:51]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:51]     = help: consider adding a `where T: marker::Sized` bound
[00:04:51]     = note: no field of an enum variant may have a dynamically sized type
[00:04:52]    Compiling std v0.0.0 (/checkout/src/libstd)
[00:04:52]    Compiling std v0.0.0 (/checkout/src/libstd)
[00:04:52] error[E0277]: the size for values of type `Idx` cannot be known at compilation time
[00:04:52]    --> src/libcore/ops/range.rs:469:5
[00:04:52] 469 | /     pub fn into_inner(self) -> (Idx, Idx) {
[00:04:52] 470 | |         (self.start, self.end)
[00:04:52] 471 | |     }
[00:04:52]     | |_____^ doesn't have a size known at compile-time
[00:04:52]     | |_____^ doesn't have a size known at compile-time
[00:04:52]     |
[00:04:52]     = help: the trait `marker::Sized` is not implemented for `Idx`
[00:04:52]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:52]     = help: consider adding a `where Idx: marker::Sized` bound
[00:04:52]     = note: only the last element of a tuple may have a dynamically sized type
[00:04:52] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:04:52]    --> src/libcore/ops/range.rs:835:5
[00:04:52]     |
[00:04:52]     |
[00:04:52] 835 | /     fn start_bound(&self) -> Bound<&T> {
[00:04:52] 836 | |         match *self {
[00:04:52] 837 | |             (Included(ref start), _) => Included(start),
[00:04:52] 838 | |             (Excluded(ref start), _) => Excluded(start),
[00:04:52] 839 | |             (Unbounded, _) => Unbounded,
[00:04:52] 841 | |     }
[00:04:52]     | |_____^ doesn't have a size known at compile-time
[00:04:52]     |
[00:04:52]     |
[00:04:52]     = help: within `ops::range::Bound<T>`, the trait `marker::Sized` is not implemented for `T`
[00:04:52]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:52]     = help: consider adding a `where T: marker::Sized` bound
[00:04:52]     = note: required because it appears within the type `ops::range::Bound<T>`
[00:04:52]     = note: only the last element of a tuple may have a dynamically sized type
[00:04:52] error[E0277]: the size for values of type `T` cannot be known at compilation time
[00:04:52]    --> src/libcore/ops/range.rs:843:5
[00:04:52]     |
[00:04:52]     |
[00:04:52] 843 | /     fn end_bound(&self) -> Bound<&T> {
[00:04:52] 844 | |         match *self {
[00:04:52] 845 | |             (_, Included(ref end)) => Included(end),
[00:04:52] 846 | |             (_, Excluded(ref end)) => Excluded(end),
[00:04:52] 847 | |             (_, Unbounded) => Unbounded,
[00:04:52] 849 | |     }
[00:04:52]     | |_____^ doesn't have a size known at compile-time
[00:04:52]     |
[00:04:52]     |
[00:04:52]     = help: within `ops::range::Bound<T>`, the trait `marker::Sized` is not implemented for `T`
[00:04:52]     = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
[00:04:52]     = help: consider adding a `where T: marker::Sized` bound
[00:04:52]     = note: required because it appears within the type `ops::range::Bound<T>`
[00:04:52]     = note: only the last element of a tuple may have a dynamically sized type
[00:04:53] error: aborting due to 7 previous errors
[00:04:53] 
[00:04:53] For more information about this error, try `rustc --explain E0277`.
[00:04:53] error: Could not compile `core`.
---
travis_time:end:0025c63c:start=1559830446491539029,finish=1559830446496666209,duration=5127180
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:2267a507
$ ln -s . checkout && for CORE in obj/cores/core.*; do EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|'); if [ -f "$EXE" ]; then printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE"; gdb --batch -q -c "$CORE" "$EXE" -iex 'set auto-load off' -iex 'dir src/' -iex 'set sysroot .' -ex bt -ex q; echo travis_fold":"end:crashlog; fi; done || true
travis_fold:end:after_failure.4
travis_fold:start:after_failure.5
travis_time:start:10f9a140
travis_time:start:10f9a140
$ cat ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers || true
cat: ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers: No such file or directory
travis_fold:end:after_failure.5
travis_fold:

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)

@SimonSapin
Copy link
Contributor

On a closer look I think most of these changes do not make much changes. Sorry for my misleading comment on Reddit.

For example, only the last field of a struct can be !Sized but Range<Idx> contains two fields of type Idx which cannot both be last. So Idx cannot be ?Sized in Range.

This immediate problem does not apply when there is only one field, but then that limits how the type can be used. For example, Bound<T> can exist where T: !Sized, but in that case Bound<T>: !Sized and so (Bound<T>, Bound<T>) cannot exist. Similarly, BTreeMap::range takes a R: RangeBounds parameter but implicitly requires R: Sized so while RangeTo<str> could exist (with a T: ?Sized added to the struct definition) it cannot be passed to BTreeMap::range. With unsized locals (#48055) it might be technically possible in the future to let range accept R: ?Sized, but it’s unclear that we’d want to. Passing RangeTo<str> by value involves copying the entire string.

And this is perhaps the important point here: dynamically-sized types (at least for now) need to live behind some kind of pointer indirection. Rather than have dynamically-sized range types, we can have ranges of (statically double-pointer-sized) references to dynamically sized values.

We already have impls for ranges of references: https://doc.rust-lang.org/1.35.0/std/ops/trait.RangeBounds.html#implementors but indeed some of them are missing T: ?Sized.

src/libcore/ops/range.rs Outdated Show resolved Hide resolved
@Kerollmops
Copy link
Contributor Author

Kerollmops commented Jun 6, 2019

Yeah, you are right, I was asking myself if it was possible to have two unsized types in the same struct. My computer and my internet connection are not really helping me and doesn't let me iterate fast enough so I decided to run it on the rust CI :)

I will revert all of my changes but the part about RangeBounds on references, though.

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-6.0 of your PR failed on Travis (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.
travis_time:end:014e60e2:start=1559831420945941179,finish=1559831421903615115,duration=957673936
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
$ export GCP_CACHE_BUCKET=rust-lang-ci-cache
$ export AWS_ACCESS_KEY_ID=AKIA46X5W6CZEJZ6XT55
---
travis_time:start:test_codegen
Check compiletest suite=codegen mode=codegen (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[01:02:47] 
[01:02:47] running 144 tests
[01:02:49] i..iii.....iii..iiii.....i......................i..i.................i.....i..........ii.i..i..i.ii. 100/144
[01:02:51] test result: ok. 114 passed; 0 failed; 30 ignored; 0 measured; 0 filtered out
[01:02:51] 
[01:02:51]  finished in 4.499
[01:02:51] travis_fold:end:test_codegen
---
travis_time:start:test_assembly
Check compiletest suite=assembly mode=assembly (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[01:02:53] 
[01:02:53] running 9 tests
[01:02:53] iiiiiiiii
[01:02:53] 
[01:02:53]  finished in 0.150
[01:02:53] travis_fold:end:test_assembly

---
travis_time:start:test_debuginfo
Check compiletest suite=debuginfo mode=debuginfo-gdb+lldb (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[01:03:09] 
[01:03:09] running 122 tests
[01:03:33] .iiiii...i.....i..i...i..i.i.i..i.ii..i.i.....i..i....i..........iiii..........i...ii...i.......ii.i 100/122
[01:03:38] .i.i......iii.i.....ii
[01:03:38] 
[01:03:38]  finished in 29.673
[01:03:38] travis_fold:end:test_debuginfo

---
[01:17:00] 
[01:17:00]    Doc-tests alloc
[01:17:00] 
[01:17:00] running 388 tests
[01:17:19] ...............................................F.................................................... 100/388
[01:17:44] .................................................................................................... 300/388
[01:17:54] ........................................................................................
[01:17:54] failures:
[01:17:54] 
[01:17:54] 
[01:17:54] ---- collections/btree/map.rs - collections::btree::map::BTreeMap<K, V>::range_mut (line 841) stdout ----
[01:17:54] error[E0283]: type annotations required: cannot resolve `_: std::cmp::Ord`
[01:17:54]   --> collections/btree/map.rs:848:25
[01:17:54]    |
[01:17:54] 10 | for (_, balance) in map.range_mut("B".."Cheryl") {
[01:17:54] 
[01:17:54] error: aborting due to previous error
[01:17:54] 
[01:17:54] For more information about this error, try `rustc --explain E0283`.
---
[01:17:54] 
[01:17:54] error: test failed, to rerun pass '--doc'
[01:17:54] 
[01:17:54] 
[01:17:54] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "test" "--target" "x86_64-unknown-linux-gnu" "-j" "4" "--release" "--locked" "--color" "always" "--features" "panic-unwind backtrace compiler-builtins-c" "--manifest-path" "/checkout/src/libstd/Cargo.toml" "-p" "alloc" "--" "--quiet"
[01:17:54] 
[01:17:54] 
[01:17:54] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[01:17:54] Build completed unsuccessfully in 1:13:19
---
travis_time:end:067d2620:start=1559836109091911892,finish=1559836109143247983,duration=51336091
travis_fold:end:after_failure.4
travis_fold:start:after_failure.5
travis_time:start:1394d64b
$ cat ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers || true
cat: ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers: No such file or directory
travis_fold:end:after_failure.5
travis_fold:start:after_failure.6
travis_time:start:16c8e7df
$ dmesg | grep -i kill

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)

@Kerollmops
Copy link
Contributor Author

Kerollmops commented Jun 6, 2019

Do I need to understand that by adding the T: ?Sized bound to the impl RangeBounds for Range<&T>, Rust does not know what to choose between Range<&T> where T: !Sized and T = str or Range<T> where T: Sized and T = &str?

@SimonSapin Do you think that this dilemma could be fixed by using any specialization?
I don't think so.

@Kerollmops
Copy link
Contributor Author

I read the signature of the HashMap::get to understand how it worked and found that it ask directly for a reference on a Q type where K: Borrow<Q>.

Would it make any sense to ask for a RangeBounds<&T> in the BTreeMap::range signature?

I know that it will be an hard breaking change and it is absolutely not feasible, but I just want to understand if this fix could be valid.

@SimonSapin
Copy link
Contributor

Do I need to understand that […] Rust does not know what to choose between

Is this in response to the latest CI failure?

[01:17:54] error[E0283]: type annotations required: cannot resolve `_: std::cmp::Ord`
[01:17:54]   --> collections/btree/map.rs:848:25
[01:17:54]    |
[01:17:54] 10 | for (_, balance) in map.range_mut("B".."Cheryl") {

Let’s work through it.

We have this signature:

impl<K: Ord, V> BTreeMap<K, V> {
    pub fn range_mut<T: ?Sized, R>(&mut self, range: R) -> RangeMut<'_, K, V>
        where T: Ord, K: Borrow<T>, R: RangeBounds<T>
}

Earlier in the test case there’s let mut map: BTreeMap<&str, i32>, so K = &str and V = i32. The value passed to range_mut is "B".."Cheryl" which is a range literal with type Range<&str>. So R = Range<&str>.

The remaining type variable is T. The compiler’s type inference needs to find a T type such as T: Ord, &str: Borrow<T> and Range<&str>: RangeBounds<T>. Relevant impls are:

impl Ord for str {}
impl<T: ?Sized> Borrow<T> for T {}
impl<T> RangeBounds<T> for Range<T> {}

impl<A: ?Sized> Ord for &A where A: Ord {}
impl<T: ?Sized> Borrow<T> for &T {}
impl<T /* this part is new: */  : ?Sized> RangeBounds<T> for Range<&T> {}

T = &str is a valid solution, based on the latter three impls (and the first). With this PR as-is, T = str is also a valid solution, with the former three impls. Previously it was not a valid solution because the last impl implicitly required T: Sized, but str: !Sized. Since there is more than one valid solution, type inference fails and suggests adding a type annotation like map.range_mut<&str, _>("B".."Cheryl").

This kind of type inference regression when adding or generalizing impls in the standard library is not usual. Sometimes we call it a minor breaking change and move on. But since BTreeMap::range is also in the standard library, and this such a typical example of intended use case that it’s an example in the doc-comment, maybe the impact is significant enough that we shouldn’t land this particular change.

Now that I’ve typed all this I wonder if we haven’t tried exactly this before and hit the same problem. @rust-lang/libs, does this ring a bell?

HashMap::get is less sensitive to this kind of type inference regression because it has one fewer type parameters. If the type of its k: &Q parameter is known (based on the context of where the value being passed comes from), then Q is fully known. Compare this with the relationship between T and R in BTreeMap::range.

In hindsight I think that range and range_mut are almost “too generic” and we should have considered not stabilizing them as-is. But we’re stuck with them now.

I think changing the bound from R: RangeBounds<T> to R: RangeBounds<&T> would fix this particular test case, but break plenty of other cases.

@@ -861,7 +861,7 @@ impl<'a, T: ?Sized + 'a> RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
}

#[stable(feature = "collections_range", since = "1.28.0")]
impl<T> RangeBounds<T> for RangeFrom<&T> {
impl<T: ?Sized> RangeBounds<T> for RangeFrom<&T> {
Copy link
Member

Choose a reason for hiding this comment

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

Isn't it technically a breaking change to expand the scope of a blanket impl? e.g. if someone had already implemented this for their own unsized Foo, that would now conflict.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes. We usually categorize it as a so-called “minor” breaking change: https://rust-lang.github.io/rfcs/1105-api-evolution.html#minor-change-implementing-any-non-fundamental-trait

Copy link
Member

@cuviper cuviper Jun 6, 2019

Choose a reason for hiding this comment

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

That's minor regarding dispatch ambiguity, but blanket impls cause actual conflicts.

https://rust-lang.github.io/rfcs/1023-rebalancing-coherence.html
https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html

As such, RFC #1105 is amended to remove the statement that implementing a non-fundamental trait is a minor breaking change, and states that adding any blanket impl for an existing trait is a major breaking change, using the definition of blanket impl given above.

That doesn't address expanding a blanket impl by relaxing constraints, as here, but I think the problem is the same and should be considered a major breaking change. It's particularly relevant that Sized is a fundamental trait, so coherence allows child crates to assume that their unsized type will never overlap with this current Sized impl. (Hmm, well, maybe that's beside the point for a crate's local types.)

The reason I said "technically" before was that I doubt anyone would actually have a conflicting impl in this specific case, but it's possible.

Copy link
Contributor

Choose a reason for hiding this comment

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

(Getting more and more off-topic, but: I think we should not have RFCs that say “RFC X is amended to…” without actually applying the change to the other file. More generally, “facts” that are out of date should not be found on https://rust-lang.github.io/rfcs/.)

@Kerollmops
Copy link
Contributor Author

What is a problem is that even by adding these bounds to relax the RangeBounds implemenations doesn't seems to fix the original problem: being able to BTreeMap::range in a BTreeMap of Vec<T> using bytes slices (&[T]).

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c8007603f0810978259def81997e7331

@SimonSapin
Copy link
Contributor

Isn’t it? When running this test with a rustc/std that have this PR applied, do you see the same error message as on the playground?

Anyway, because of the inference regression in range we likely land this PR. As mentioned in a Reddit comment, this compiles:

    use std::ops::Bound::*;
    let mut iter = map.range::<[_], _>((Included(key), Unbounded));

@Kerollmops
Copy link
Contributor Author

Kerollmops commented Jun 9, 2019

No, it doesn't fixed the original issue. You are right, this pull request would break too much compilations and there already is a work around using raw Include/Excluded bounds types.

The only thing is that it is sad to keep this issue and make people face it again, as it is some kind of mistake in the std library.

@SimonSapin
Copy link
Contributor

Closing since it looks like there’s no subset or variation of this we can land without breaking range, and a work-around exists.

Still, thanks for working on this!

@SimonSapin SimonSapin closed this Jun 12, 2019
@Kerollmops Kerollmops deleted the sized-relax-rangebound-impls branch June 12, 2019 18:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants