-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Impl Default for ranges #73197
Impl Default for ranges #73197
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
Although empty makes sense, how could we be sure that starting and ending at zero is the best choice? |
In this PR's implementation, it seems that the defaults of I'm not sure if it makes sense to implement default on ranges that have bounds only at either the start or end. EDIT: fixed wrong comment, defaults of EDIT2: this is only for unsigned integer (#73197 (comment)) |
Not sure if it is possible to have optioned implementations because the implications and semantics will vary depending on the |
r? @Amanieu |
I don't think |
There are four listed use-cases and I personally have a trait IMHO, these implementations have no side-effects. |
The listed use cases don't suggest obvious defaults (at least to me). Do you have a case that's less cut down (i.e., a real world example)? I don't think empty ranges are obviously "default" to me. |
ImplementationA default instance is, in my option, an independent constant value and if the listed examples are starting and ending as zero, it is because their // For whatever reason, <Range<u32> as Default>::default() = 0..u32::MAX is a good default
impl Default for Range<u32> { fn default() -> Self { 0..u32::MAX } }
// Problem: There isn't a Range implementation for arbitrary types
#[derive(Default)]
struct FancyDecimalType;
#[derive(Default)]
struct UserTypeWithRange(Range<FancyDecimalType>); // error!
// Because: Generic implementation will conflict with <Range<u32> as Default>
impl<T: Default> Default for Range<T> { fn default() -> Self { Default::default()..Default::default() } } // error! // Bound constraints suffer the same problem, suppose an imaginary std Number trait that has `min()` and `max()`
impl<T: Number> Default for Range<T> { fn default() -> Self { T::min()..T::max() } }
// As a consequence, it also won't be possible to have a generic implementation for Range<T> As previously said, a generic Use-caseIf all given explanations weren't enough, then I will try to explain a hopefully "real-world" use-case: I have a project that solves nondeterministic polynomial problems which is basically composed of // Just a simplification. The real code were made using declarative macros and num
impl Solution for [f64; 1] { ... }
impl Domain<[f64; 1]> for [core::ops::Range<f64>; 1] { ... } All posterior operations don't known what pub struct RangeWrapperBecauseOfDefaultDomain<T>(pub core::ops::Range<T>);
impl<T> Default for RangeWrapperBecauseOfDefaultDomain<T>
where
T: Default
{
fn default() -> Self {
Self(T::default()..T::default())
} This effect can be minimized by other means but like the subtitle says, it is just an additional use-case that hopefully can be interpreted as a more "real-world" example. |
I can see the reasoning behind this and tentatively agree that we should add @rfcbot fcp merge |
Team member @Amanieu has proposed to merge this. The next step is review by the rest of the tagged team members: Concerns:
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. |
The fact that I'll note that, for example, |
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 am skeptical of some of these too. I am definitely on board with the impl for RangeFull. I am also on board with an impl for Range, which does the equivalent of default()..default()
. I think I would prefer to leave out the rest of the impls: RangeFrom, RangeTo, RangeInclusive, RangeToInclusive.
As previously said, "empty" ranges are just a consequence of a generic Regarding on what is a "good" default, I can say IMHO that it will vary from person to person. |
@rfcbot concern let's not do for RangeFrom, RangeTo, RangeInclusive, RangeToInclusive Per #73197 (review). |
Only for unsigned integer |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
Since Vec defaults to an empty Vec, isn't it only logical that Range would default to en empty Range? I personally think it is often convenient to have default implemented for as many types as possible. For instance, it allows resize on a Vec. Default is needed even if the vector is only ever shrunk in practice. |
Let say it is: then wouldn't it also be "only logical" that the other kinds of And the other kind of
|
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. The RFC will be merged soon. |
@bors r+ |
📌 Commit c375692 has been approved by |
All good points! I think I overstated things when I said "only logical". I think it's not "obvious" that the Range types should implement Default. But I still think it would be useful, and not that much more surprising than Vec or u32 implementing Default.
Ah, I didn't know about truncate! My use case was I had a program which processed lots of data in parallel in many threads. It could use a thread pool of N threads. The program had a Vec<T> of length N for scratch data. Each worker thread needed to use some memory for its processing, and this scratch data was stored in the Vec. If the number of worker threads was changed, the Vec needed to be resized. I wanted to automatically resize the Vec to the correct number, and required T:Default so there was value to use for any new elements. If type T anywhere contained a Range, it would be inconvenient because it couldn't as easily implement Default in that case. Reading what I wrote I realize that my argument isn't super-convincing, but I at least wished that Default was implemented for all types where it can be argued that one value is more default than any other value. Such as the u32 0, the empty Vec, and conceivably, the range 0..0 . |
…arth Rollup of 13 pull requests Successful merges: - rust-lang#72714 (Fix debug assertion in typeck) - rust-lang#73197 (Impl Default for ranges) - rust-lang#73323 (wf: check foreign fn decls for well-formedness) - rust-lang#74051 (disallow non-static lifetimes in const generics) - rust-lang#74376 (test caching opt_const_param_of on disc) - rust-lang#74501 (Ayu theme: Use different background color for Run button) - rust-lang#74505 (Fix search input focus in ayu theme) - rust-lang#74522 (Update sanitizer docs) - rust-lang#74546 (Fix duplicate maybe_uninit_extra attribute) - rust-lang#74552 (Stabilize TAU constant.) - rust-lang#74555 (Improve "important traits" popup display on mobile) - rust-lang#74557 (Fix an ICE on an invalid `binding @ ...` in a tuple struct pattern) - rust-lang#74561 (update backtrace-rs) Failed merges: r? @ghost
Pkgsrc changes: * Remove patches now integrated upstream, many related to SunOS / Illumos. * The LLVM fix for powerpc is also now integrated upstream. * Adapt those patches where the source has moved or parts are integrated. * The randomness patches no longer applies, and I could not find where those files went... * Provide a separate bootstrap for NetBSD/powerpc 9.0, since apparently the C++ ABI is different from 8.0. Yes, this appears to be specific to the NetBSD powerpc ports. Upstream changes: Version 1.47.0 (2020-10-08) ========================== Language -------- - [Closures will now warn when not used.][74869] Compiler -------- - [Stabilized the `-C control-flow-guard` codegen option][73893], which enables [Control Flow Guard][1.47.0-cfg] for Windows platforms, and is ignored on other platforms. - [Upgraded to LLVM 11.][73526] - [Added tier 3\* support for the `thumbv4t-none-eabi` target.][74419] - [Upgrade the FreeBSD toolchain to version 11.4][75204] - [`RUST_BACKTRACE`'s output is now more compact.][75048] \* Refer to Rust's [platform support page][forge-platform-support] for more information on Rust's tiered platform support. Libraries --------- - [`CStr` now implements `Index<RangeFrom<usize>>`.][74021] - [Traits in `std`/`core` are now implemented for arrays of any length, not just those of length less than 33.][74060] - [`ops::RangeFull` and `ops::Range` now implement Default.][73197] - [`panic::Location` now implements `Copy`, `Clone`, `Eq`, `Hash`, `Ord`, `PartialEq`, and `PartialOrd`.][73583] Stabilized APIs --------------- - [`Ident::new_raw`] - [`Range::is_empty`] - [`RangeInclusive::is_empty`] - [`Result::as_deref`] - [`Result::as_deref_mut`] - [`Vec::leak`] - [`pointer::offset_from`] - [`f32::TAU`] - [`f64::TAU`] The following previously stable APIs have now been made const. - [The `new` method for all `NonZero` integers.][73858] - [The `checked_add`,`checked_sub`,`checked_mul`,`checked_neg`, `checked_shl`, `checked_shr`, `saturating_add`, `saturating_sub`, and `saturating_mul` methods for all integers.][73858] - [The `checked_abs`, `saturating_abs`, `saturating_neg`, and `signum` for all signed integers.][73858] - [The `is_ascii_alphabetic`, `is_ascii_uppercase`, `is_ascii_lowercase`, `is_ascii_alphanumeric`, `is_ascii_digit`, `is_ascii_hexdigit`, `is_ascii_punctuation`, `is_ascii_graphic`, `is_ascii_whitespace`, and `is_ascii_control` methods for `char` and `u8`.][73858] Cargo ----- - [`build-dependencies` are now built with opt-level 0 by default.][cargo/8500] You can override this by setting the following in your `Cargo.toml`. ```toml [profile.release.build-override] opt-level = 3 ``` - [`cargo-help` will now display man pages for commands rather just the `--help` text.][cargo/8456] - [`cargo-metadata` now emits a `test` field indicating if a target has tests enabled.][cargo/8478] - [`workspace.default-members` now respects `workspace.exclude`.][cargo/8485] - [`cargo-publish` will now use an alternative registry by default if it's the only registry specified in `package.publish`.][cargo/8571] Misc ---- - [Added a help button beside Rustdoc's searchbar that explains rustdoc's type based search.][75366] - [Added the Ayu theme to rustdoc.][71237] Compatibility Notes ------------------- - [Bumped the minimum supported Emscripten version to 1.39.20.][75716] - [Fixed a regression parsing `{} && false` in tail expressions.][74650] - [Added changes to how proc-macros are expanded in `macro_rules!` that should help to preserve more span information.][73084] These changes may cause compiliation errors if your macro was unhygenic or didn't correctly handle `Delimiter::None`. - [Moved support for the CloudABI target to tier 3.][75568] - [`linux-gnu` targets now require minimum kernel 2.6.32 and glibc 2.11.][74163] Internal Only -------- - [Improved default settings for bootstrapping in `x.py`.][73964] You can read details about this change in the ["Changes to `x.py` defaults"](https://blog.rust-lang.org/inside-rust/2020/08/30/changes-to-x-py-defaults.html) post on the Inside Rust blog. - [Added the `rustc-docs` component.][75560] This allows you to install and read the documentation for the compiler internal APIs. (Currently only available for `x86_64-unknown-linux-gnu`.) [1.47.0-cfg]: https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard [76980]: rust-lang/rust#76980 [75048]: rust-lang/rust#75048 [74163]: rust-lang/rust#74163 [71237]: rust-lang/rust#71237 [74869]: rust-lang/rust#74869 [73858]: rust-lang/rust#73858 [75716]: rust-lang/rust#75716 [75908]: rust-lang/rust#75908 [75516]: rust-lang/rust#75516 [75560]: rust-lang/rust#75560 [75568]: rust-lang/rust#75568 [75366]: rust-lang/rust#75366 [75204]: rust-lang/rust#75204 [74650]: rust-lang/rust#74650 [74419]: rust-lang/rust#74419 [73964]: rust-lang/rust#73964 [74021]: rust-lang/rust#74021 [74060]: rust-lang/rust#74060 [73893]: rust-lang/rust#73893 [73526]: rust-lang/rust#73526 [73583]: rust-lang/rust#73583 [73084]: rust-lang/rust#73084 [73197]: rust-lang/rust#73197 [72488]: rust-lang/rust#72488 [cargo/8456]: rust-lang/cargo#8456 [cargo/8478]: rust-lang/cargo#8478 [cargo/8485]: rust-lang/cargo#8485 [cargo/8500]: rust-lang/cargo#8500 [cargo/8571]: rust-lang/cargo#8571 [`Ident::new_raw`]: https://doc.rust-lang.org/nightly/proc_macro/struct.Ident.html#method.new_raw [`Range::is_empty`]: https://doc.rust-lang.org/nightly/std/ops/struct.Range.html#method.is_empty [`RangeInclusive::is_empty`]: https://doc.rust-lang.org/nightly/std/ops/struct.RangeInclusive.html#method.is_empty [`Result::as_deref_mut`]: https://doc.rust-lang.org/nightly/std/result/enum.Result.html#method.as_deref_mut [`Result::as_deref`]: https://doc.rust-lang.org/nightly/std/result/enum.Result.html#method.as_deref [`TypeId::of`]: https://doc.rust-lang.org/nightly/std/any/struct.TypeId.html#method.of [`Vec::leak`]: https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.leak [`f32::TAU`]: https://doc.rust-lang.org/nightly/std/f32/consts/constant.TAU.html [`f64::TAU`]: https://doc.rust-lang.org/nightly/std/f64/consts/constant.TAU.html [`pointer::offset_from`]: https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from
Couldn't find an issue about it.
Range
and friends probably can implementDefault
ifIdx: Default
. For example, the following would be possible:Maybe there are some concerns about safety or misunderstandings?