-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Expand upper bounds on RangeBounds impls #64327
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
Conversation
r? @kennytm (rust_highfive has picked a reviewer for you, use r? to override) |
The job Click to expand the log.
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 |
This has broken type-inference of some existing tests.
|
Yup I'm looking into it. Is there an easy way to run that test case? Edit: Nevermind, I found what I need. |
I think we need a crater run but the queue is super long for now 😕 |
Hm, yeah, inference breakage here is concerning. @bors try to get a build for crater |
⌛ Trying commit c1539ab with merge b19afc12c4f781e95f168f2fdea339c972f14ae2... |
☀️ Try build successful - checks-azure |
@craterbot run mode=check-only |
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
How long do crater runs typically take? I'm curious as to how much longer this PR may be in the queue. I see it's second to the top. |
I think the current average for a check run is around 4 days, but I'm not sure. |
🚧 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
🎉 Experiment
|
cc #61584, an earlier attempt at this |
Seems like acceptable breakage to me (a single crates.io regression which will probably be fixed soon...). r? @dtolnay to assess this. |
@@ -904,7 +904,7 @@ impl<T> RangeBounds<T> for RangeTo<&T> { | |||
} | |||
|
|||
#[stable(feature = "collections_range", since = "1.28.0")] | |||
impl<T> RangeBounds<T> for Range<&T> { | |||
impl<T: ?Sized> RangeBounds<T> for Range<&T> { | |||
fn start_bound(&self) -> Bound<&T> { | |||
Included(self.start) | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this change supposed to apply to the RangeBounds<T> impls for RangeInclusive<&T> and RangeToInclusive<&T> (below) as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that the T: ?Sized
impls are more correct and it would be great to have that, but I am not thrilled about introducing even more need for turbofish on range and range_mut.
Some questions to dig into what is going on here:
-
Is there any defensible language change that might allow us to eliminate the ambiguity when using
"from".."to"
as a range into a BTreeMap<&str, _> or (separately) a BTreeMap<String, _>? Possibly some way to guide the inference ofT
when the other type parameters are known, or some way to say that any choice ofT
that satisfies the bounds is fine even if it's not known to be the unique possible choice. -
If range and range_mut didn't exist yet, is there a better less generic signature for them that wouldn't be ambiguous in common cases?
I don't know who these questions are directed to but I am hesitant to merge this change as currently implemented. The amount of breakage is small and would probably be justifiable for a change that made "from".."to"
"just work" without turbofishes, but as it is, I don't think landing this is the right tradeoff.
The workaround is to use map.range::<str, _>((Bound::Included("from"), Bound::Excluded("to")))
which has the right performance characteristics, or map.range("from".to_owned().."to".to_owned())
which is more concise.
Ping from triage: @kennethbgoodin any updates on this? |
It sounds like the consensus is that this change isn't the best approach -- should I close this PR? |
…ason, r=tgross35 Document why `Range*<&T> as RangeBounds<T>` impls are not `T: ?Sized`, and give an alternative. `Range*<&T> as RangeBounds<T>` impls have been tried to be relaxed to `T: ?Sized` at least twice: * rust-lang#61584 * rust-lang#64327 I also was just about to make another PR to do it again until I `./x.py test library/alloc` and rediscovered the type inference regression, then searched around and found the previous PRs. Hence this PR instead so hopefully that doesn't keep happening 😛. These impls cannot be relaxed for two reasons: 1. Type inference regressions: See `@SimonSapin's` explanation from a previous PR: rust-lang#61584 (comment) 2. It's a breaking change: `impl RangeBounds<MyUnsizedType> for std::ops::Range<&MyUnsizedType>` is allowed after the coherence rebalance ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=f704a6fe53bfc33e55b2fc246d895ec2)), and relaxing these impls would conflict with that downstream impl. This PR adds doc-comments explaining that not having `T: ?Sized` is intentional[^1], and gives an explicit alternative: `(Bound<&T>, Bound<&T>)`. Technically, the impls for the unstable new `std::range` types could be relaxed, as they are still unstable so the change would not be breaking, but having them be different in this regard seems worse (and the non-iterable `RangeTo/RangeToInclusive` range types are shared between the "new" and "old" so cannot be changed anyway), and then the type inference regression would pop up in whatever edition the new range types stabilize in. The "see \<link\> for discussion of those issues" is intentionally left as a non-doc comment just for whoever may try to relax these impls again in the future, but if it is preferred to have the link in the docs I can add that. Closes rust-lang#107196 (as wontfix) CC rust-lang#64027 [^1]: "intentional" is maybe a bit of strong wording, should it instead say something like "was stabilized without it and it would be breaking to change it now"?
…ason, r=tgross35 Document why `Range*<&T> as RangeBounds<T>` impls are not `T: ?Sized`, and give an alternative. `Range*<&T> as RangeBounds<T>` impls have been tried to be relaxed to `T: ?Sized` at least twice: * rust-lang#61584 * rust-lang#64327 I also was just about to make another PR to do it again until I `./x.py test library/alloc` and rediscovered the type inference regression, then searched around and found the previous PRs. Hence this PR instead so hopefully that doesn't keep happening 😛. These impls cannot be relaxed for two reasons: 1. Type inference regressions: See ``@SimonSapin's`` explanation from a previous PR: rust-lang#61584 (comment) 2. It's a breaking change: `impl RangeBounds<MyUnsizedType> for std::ops::Range<&MyUnsizedType>` is allowed after the coherence rebalance ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=f704a6fe53bfc33e55b2fc246d895ec2)), and relaxing these impls would conflict with that downstream impl. This PR adds doc-comments explaining that not having `T: ?Sized` is intentional[^1], and gives an explicit alternative: `(Bound<&T>, Bound<&T>)`. Technically, the impls for the unstable new `std::range` types could be relaxed, as they are still unstable so the change would not be breaking, but having them be different in this regard seems worse (and the non-iterable `RangeTo/RangeToInclusive` range types are shared between the "new" and "old" so cannot be changed anyway), and then the type inference regression would pop up in whatever edition the new range types stabilize in. The "see \<link\> for discussion of those issues" is intentionally left as a non-doc comment just for whoever may try to relax these impls again in the future, but if it is preferred to have the link in the docs I can add that. Closes rust-lang#107196 (as wontfix) CC rust-lang#64027 [^1]: "intentional" is maybe a bit of strong wording, should it instead say something like "was stabilized without it and it would be breaking to change it now"?
Rollup merge of #144167 - zachs18:rangebounds-not-unsized-reason, r=tgross35 Document why `Range*<&T> as RangeBounds<T>` impls are not `T: ?Sized`, and give an alternative. `Range*<&T> as RangeBounds<T>` impls have been tried to be relaxed to `T: ?Sized` at least twice: * #61584 * #64327 I also was just about to make another PR to do it again until I `./x.py test library/alloc` and rediscovered the type inference regression, then searched around and found the previous PRs. Hence this PR instead so hopefully that doesn't keep happening 😛. These impls cannot be relaxed for two reasons: 1. Type inference regressions: See ``@SimonSapin's`` explanation from a previous PR: #61584 (comment) 2. It's a breaking change: `impl RangeBounds<MyUnsizedType> for std::ops::Range<&MyUnsizedType>` is allowed after the coherence rebalance ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=f704a6fe53bfc33e55b2fc246d895ec2)), and relaxing these impls would conflict with that downstream impl. This PR adds doc-comments explaining that not having `T: ?Sized` is intentional[^1], and gives an explicit alternative: `(Bound<&T>, Bound<&T>)`. Technically, the impls for the unstable new `std::range` types could be relaxed, as they are still unstable so the change would not be breaking, but having them be different in this regard seems worse (and the non-iterable `RangeTo/RangeToInclusive` range types are shared between the "new" and "old" so cannot be changed anyway), and then the type inference regression would pop up in whatever edition the new range types stabilize in. The "see \<link\> for discussion of those issues" is intentionally left as a non-doc comment just for whoever may try to relax these impls again in the future, but if it is preferred to have the link in the docs I can add that. Closes #107196 (as wontfix) CC #64027 [^1]: "intentional" is maybe a bit of strong wording, should it instead say something like "was stabilized without it and it would be breaking to change it now"?
…ason, r=tgross35 Document why `Range*<&T> as RangeBounds<T>` impls are not `T: ?Sized`, and give an alternative. `Range*<&T> as RangeBounds<T>` impls have been tried to be relaxed to `T: ?Sized` at least twice: * rust-lang#61584 * rust-lang#64327 I also was just about to make another PR to do it again until I `./x.py test library/alloc` and rediscovered the type inference regression, then searched around and found the previous PRs. Hence this PR instead so hopefully that doesn't keep happening 😛. These impls cannot be relaxed for two reasons: 1. Type inference regressions: See ``@SimonSapin's`` explanation from a previous PR: rust-lang#61584 (comment) 2. It's a breaking change: `impl RangeBounds<MyUnsizedType> for std::ops::Range<&MyUnsizedType>` is allowed after the coherence rebalance ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=f704a6fe53bfc33e55b2fc246d895ec2)), and relaxing these impls would conflict with that downstream impl. This PR adds doc-comments explaining that not having `T: ?Sized` is intentional[^1], and gives an explicit alternative: `(Bound<&T>, Bound<&T>)`. Technically, the impls for the unstable new `std::range` types could be relaxed, as they are still unstable so the change would not be breaking, but having them be different in this regard seems worse (and the non-iterable `RangeTo/RangeToInclusive` range types are shared between the "new" and "old" so cannot be changed anyway), and then the type inference regression would pop up in whatever edition the new range types stabilize in. The "see \<link\> for discussion of those issues" is intentionally left as a non-doc comment just for whoever may try to relax these impls again in the future, but if it is preferred to have the link in the docs I can add that. Closes rust-lang#107196 (as wontfix) CC rust-lang#64027 [^1]: "intentional" is maybe a bit of strong wording, should it instead say something like "was stabilized without it and it would be breaking to change it now"?
…gross35 Document why `Range*<&T> as RangeBounds<T>` impls are not `T: ?Sized`, and give an alternative. `Range*<&T> as RangeBounds<T>` impls have been tried to be relaxed to `T: ?Sized` at least twice: * rust-lang/rust#61584 * rust-lang/rust#64327 I also was just about to make another PR to do it again until I `./x.py test library/alloc` and rediscovered the type inference regression, then searched around and found the previous PRs. Hence this PR instead so hopefully that doesn't keep happening 😛. These impls cannot be relaxed for two reasons: 1. Type inference regressions: See ``@SimonSapin's`` explanation from a previous PR: rust-lang/rust#61584 (comment) 2. It's a breaking change: `impl RangeBounds<MyUnsizedType> for std::ops::Range<&MyUnsizedType>` is allowed after the coherence rebalance ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=f704a6fe53bfc33e55b2fc246d895ec2)), and relaxing these impls would conflict with that downstream impl. This PR adds doc-comments explaining that not having `T: ?Sized` is intentional[^1], and gives an explicit alternative: `(Bound<&T>, Bound<&T>)`. Technically, the impls for the unstable new `std::range` types could be relaxed, as they are still unstable so the change would not be breaking, but having them be different in this regard seems worse (and the non-iterable `RangeTo/RangeToInclusive` range types are shared between the "new" and "old" so cannot be changed anyway), and then the type inference regression would pop up in whatever edition the new range types stabilize in. The "see \<link\> for discussion of those issues" is intentionally left as a non-doc comment just for whoever may try to relax these impls again in the future, but if it is preferred to have the link in the docs I can add that. Closes rust-lang/rust#107196 (as wontfix) CC rust-lang/rust#64027 [^1]: "intentional" is maybe a bit of strong wording, should it instead say something like "was stabilized without it and it would be breaking to change it now"?
Per issue #64027 adds
?Sized
to allRangeBounds<&T>
impls.