-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Stabilize let
bindings and destructuring in constants and const fn
#57175
Conversation
This comment has been minimized.
This comment has been minimized.
yes, we're preventing both |
I see, e.g. this test here. |
Assigning over to: @cramertj I will write up a stabilization report in a bit either as a separate issue or in this PR and I'll fcp merge that one. |
This comment has been minimized.
This comment has been minimized.
Stabilization proposalI propose that we stabilize @rfcbot merge Tracking issue: #48821 What is stabilizedIn the following places:
We stabilize:
What is not stabilized
Divergences from RFC
TestsThe tests can be primarily seen in the PR itself. Here are some of them:
MotivationFrom the RFC:
As for motivations to do this now despite the lack of stable control flow,
History
|
Team member @Centril 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. |
This comment has been minimized.
This comment has been minimized.
Since we already had ugly let statements by just making another function, I'm glad to see real ones. |
Two clarifications here:
|
@oli-obk knows better than me, but the gist of it is that we haven't implemented #![feature(const_fn)]
const fn foo() {
match 0 { // error[E0019]: constant function contains unimplemented expression type
1 => {}
_ => {}
};
} And we can think of match lhs { false => false, true => rhs } Meanwhile, match lhs { false => rhs, true => true } I think the main hurdle is just doing the work, which we eventually will, but it will take its time.
Yep, and sadly we already support a buggy, non-short-circuiting, version of |
This is correct. It requires control-flow support, which does not exist whatsoever yet. I'm hoping @oli-obk can pick up where eddyb left off with this. I can help perhaps. |
This comment has been minimized.
This comment has been minimized.
@bors r=nikomatsakis p=1 |
📌 Commit 6c62322 has been approved by |
…nikomatsakis Stabilize `let` bindings and destructuring in constants and const fn r? @Centril This PR stabilizes the following features in constants and `const` functions: * irrefutable destructuring patterns (e.g. `const fn foo((x, y): (u8, u8)) { ... }`) * `let` bindings (e.g. `let x = 1;`) * mutable `let` bindings (e.g. `let mut x = 1;`) * assignment (e.g. `x = y`) and assignment operator (e.g. `x += y`) expressions, even where the assignment target is a projection (e.g. a struct field or index operation like `x[3] = 42`) * expression statements (e.g. `3;`) This PR does explicitly *not* stabilize: * mutable references (i.e. `&mut T`) * dereferencing mutable references * refutable patterns (e.g. `Some(x)`) * operations on `UnsafeCell` types (as that would need raw pointers and mutable references and such, not because it is explicitly forbidden. We can't explicitly forbid it as such values are OK as long as they aren't mutated.) * We are not stabilizing `let` bindings in constants that use `&&` and `||` short circuiting operations. These are treated as `&` and `|` inside `const` and `static` items right now. If we stopped treating them as `&` and `|` after stabilizing `let` bindings, we'd break code like `let mut x = false; false && { x = true; false };`. So to use `let` bindings in constants you need to change `&&` and `||` to `&` and `|` respectively.
Rollup of 26 pull requests Successful merges: - #56425 (Redo the docs for Vec::set_len) - #56906 (Issue #56905) - #57042 (Don't call `FieldPlacement::count` when count is too large) - #57175 (Stabilize `let` bindings and destructuring in constants and const fn) - #57192 (Change std::error::Error trait documentation to talk about `source` instead of `cause`) - #57296 (Fixed the link to the ? operator) - #57368 (Use CMAKE_{C,CXX}_COMPILER_LAUNCHER for ccache) - #57400 (Rustdoc: update Source Serif Pro and replace Heuristica italic) - #57417 (rustdoc: use text-based doctest parsing if a macro is wrapping main) - #57433 (Add link destination for `read-ownership`) - #57434 (Remove `CrateNum::Invalid`.) - #57441 (Supporting backtrace for x86_64-fortanix-unknown-sgx.) - #57450 (actually take a slice in this example) - #57459 (Reference tracking issue for inherent associated types in diagnostic) - #57463 (docs: Fix some 'second-edition' links) - #57466 (Remove outdated comment) - #57493 (use structured suggestion when casting a reference) - #57498 (make note of one more normalization that Paths do) - #57499 (note that FromStr does not work for borrowed types) - #57505 (Remove submodule step from README) - #57510 (Add a profiles section to the manifest) - #57511 (Fix undefined behavior) - #57519 (Correct RELEASES.md for 1.32.0) - #57522 (don't unwrap unexpected tokens in `format!`) - #57530 (Fixing a typographical error.) - #57535 (Stabilise irrefutable if-let and while-let patterns) Failed merges: r? @ghost
Pkgsrc changes: * Bump required rust version to build to 1.32.0. * Adapt patches to changed file locations. * Since we now patch some more vendor/ modules, doctor the corresponding .cargo-checksum.json files accordingly Upstream changes: Version 1.33.0 (2019-02-28) ========================== Language -------- - [You can now use the `cfg(target_vendor)` attribute.][57465] E.g. `#[cfg(target_vendor="apple")] fn main() { println!("Hello Apple!"); }` - [Integer patterns such as in a match expression can now be exhaustive.][56362] E.g. You can have match statement on a `u8` that covers `0..=255` and you would no longer be required to have a `_ => unreachable!()` case. - [You can now have multiple patterns in `if let` and `while let` expressions.][57532] You can do this with the same syntax as a `match` expression. E.g. ```rust enum Creature { Crab(String), Lobster(String), Person(String), } fn main() { let state = Creature::Crab("Ferris"); if let Creature::Crab(name) | Creature::Person(name) = state { println!("This creature's name is: {}", name); } } ``` - [You can now have irrefutable `if let` and `while let` patterns.][57535] Using this feature will by default produce a warning as this behaviour can be unintuitive. E.g. `if let _ = 5 {}` - [You can now use `let` bindings, assignments, expression statements, and irrefutable pattern destructuring in const functions.][57175] - [You can now call unsafe const functions.][57067] E.g. ```rust const unsafe fn foo() -> i32 { 5 } const fn bar() -> i32 { unsafe { foo() } } ``` - [You can now specify multiple attributes in a `cfg_attr` attribute.][57332] E.g. `#[cfg_attr(all(), must_use, optimize)]` - [You can now specify a specific alignment with the `#[repr(packed)]` attribute.][57049] E.g. `#[repr(packed(2))] struct Foo(i16, i32);` is a struct with an alignment of 2 bytes and a size of 6 bytes. - [You can now import an item from a module as an `_`.][56303] This allows you to import a trait's impls, and not have the name in the namespace. E.g. ```rust use std::io::Read as _; // Allowed as there is only one `Read` in the module. pub trait Read {} ``` - [You may now use `Rc`, `Arc`, and `Pin` as method receivers][56805]. Compiler -------- - [You can now set a linker flavor for `rustc` with the `-Clinker-flavor` command line argument.][56351] - [The mininum required LLVM version has been bumped to 6.0.][56642] - [Added support for the PowerPC64 architecture on FreeBSD.][57615] - [The `x86_64-fortanix-unknown-sgx` target support has been upgraded to tier 2 support.][57130] Visit the [platform support][platform-support] page for information on Rust's platform support. - [Added support for the `thumbv7neon-linux-androideabi` and `thumbv7neon-unknown-linux-gnueabihf` targets.][56947] - [Added support for the `x86_64-unknown-uefi` target.][56769] Libraries --------- - [The methods `overflowing_{add, sub, mul, shl, shr}` are now `const` functions for all numeric types.][57566] - [The methods `rotate_left`, `rotate_right`, and `wrapping_{add, sub, mul, shl, shr}` are now `const` functions for all numeric types.][57105] - [The methods `is_positive` and `is_negative` are now `const` functions for all signed numeric types.][57105] - [The `get` method for all `NonZero` types is now `const`.][57167] - [The methods `count_ones`, `count_zeros`, `leading_zeros`, `trailing_zeros`, `swap_bytes`, `from_be`, `from_le`, `to_be`, `to_le` are now `const` for all numeric types.][57234] - [`Ipv4Addr::new` is now a `const` function][57234] Stabilized APIs --------------- - [`unix::FileExt::read_exact_at`] - [`unix::FileExt::write_all_at`] - [`Option::transpose`] - [`Result::transpose`] - [`convert::identity`] - [`pin::Pin`] - [`marker::Unpin`] - [`marker::PhantomPinned`] - [`Vec::resize_with`] - [`VecDeque::resize_with`] - [`Duration::as_millis`] - [`Duration::as_micros`] - [`Duration::as_nanos`] Cargo ----- - [Cargo should now rebuild a crate if a file was modified during the initial build.][cargo/6484] Compatibility Notes ------------------- - The methods `str::{trim_left, trim_right, trim_left_matches, trim_right_matches}` are now deprecated in the standard library, and their usage will now produce a warning. Please use the `str::{trim_start, trim_end, trim_start_matches, trim_end_matches}` methods instead. - The `Error::cause` method has been deprecated in favor of `Error::source` which supports downcasting. [55982]: rust-lang/rust#55982 [56303]: rust-lang/rust#56303 [56351]: rust-lang/rust#56351 [56362]: rust-lang/rust#56362 [56642]: rust-lang/rust#56642 [56769]: rust-lang/rust#56769 [56805]: rust-lang/rust#56805 [56947]: rust-lang/rust#56947 [57049]: rust-lang/rust#57049 [57067]: rust-lang/rust#57067 [57105]: rust-lang/rust#57105 [57130]: rust-lang/rust#57130 [57167]: rust-lang/rust#57167 [57175]: rust-lang/rust#57175 [57234]: rust-lang/rust#57234 [57332]: rust-lang/rust#57332 [57465]: rust-lang/rust#57465 [57532]: rust-lang/rust#57532 [57535]: rust-lang/rust#57535 [57566]: rust-lang/rust#57566 [57615]: rust-lang/rust#57615 [cargo/6484]: rust-lang/cargo#6484 [`unix::FileExt::read_exact_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.read_exact_at [`unix::FileExt::write_all_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.write_all_at [`Option::transpose`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.transpose [`Result::transpose`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.transpose [`convert::identity`]: https://doc.rust-lang.org/std/convert/fn.identity.html [`pin::Pin`]: https://doc.rust-lang.org/std/pin/struct.Pin.html [`marker::Unpin`]: https://doc.rust-lang.org/stable/std/marker/trait.Unpin.html [`marker::PhantomPinned`]: https://doc.rust-lang.org/nightly/std/marker/struct.PhantomPinned.html [`Vec::resize_with`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.resize_with [`VecDeque::resize_with`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.resize_with [`Duration::as_millis`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_millis [`Duration::as_micros`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_micros [`Duration::as_nanos`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_nanos [platform-support]: https://forge.rust-lang.org/platform-support.html
Pkgsrc changes: * Bump required rust version to build to 1.32.0. * Adapt patches to changed file locations. * Since we now patch some more vendor/ modules, doctor the corresponding .cargo-checksum.json files accordingly Upstream changes: Version 1.33.0 (2019-02-28) ========================== Language -------- - [You can now use the `cfg(target_vendor)` attribute.][57465] E.g. `#[cfg(target_vendor="apple")] fn main() { println!("Hello Apple!"); }` - [Integer patterns such as in a match expression can now be exhaustive.][56362] E.g. You can have match statement on a `u8` that covers `0..=255` and you would no longer be required to have a `_ => unreachable!()` case. - [You can now have multiple patterns in `if let` and `while let` expressions.][57532] You can do this with the same syntax as a `match` expression. E.g. ```rust enum Creature { Crab(String), Lobster(String), Person(String), } fn main() { let state = Creature::Crab("Ferris"); if let Creature::Crab(name) | Creature::Person(name) = state { println!("This creature's name is: {}", name); } } ``` - [You can now have irrefutable `if let` and `while let` patterns.][57535] Using this feature will by default produce a warning as this behaviour can be unintuitive. E.g. `if let _ = 5 {}` - [You can now use `let` bindings, assignments, expression statements, and irrefutable pattern destructuring in const functions.][57175] - [You can now call unsafe const functions.][57067] E.g. ```rust const unsafe fn foo() -> i32 { 5 } const fn bar() -> i32 { unsafe { foo() } } ``` - [You can now specify multiple attributes in a `cfg_attr` attribute.][57332] E.g. `#[cfg_attr(all(), must_use, optimize)]` - [You can now specify a specific alignment with the `#[repr(packed)]` attribute.][57049] E.g. `#[repr(packed(2))] struct Foo(i16, i32);` is a struct with an alignment of 2 bytes and a size of 6 bytes. - [You can now import an item from a module as an `_`.][56303] This allows you to import a trait's impls, and not have the name in the namespace. E.g. ```rust use std::io::Read as _; // Allowed as there is only one `Read` in the module. pub trait Read {} ``` - [You may now use `Rc`, `Arc`, and `Pin` as method receivers][56805]. Compiler -------- - [You can now set a linker flavor for `rustc` with the `-Clinker-flavor` command line argument.][56351] - [The mininum required LLVM version has been bumped to 6.0.][56642] - [Added support for the PowerPC64 architecture on FreeBSD.][57615] - [The `x86_64-fortanix-unknown-sgx` target support has been upgraded to tier 2 support.][57130] Visit the [platform support][platform-support] page for information on Rust's platform support. - [Added support for the `thumbv7neon-linux-androideabi` and `thumbv7neon-unknown-linux-gnueabihf` targets.][56947] - [Added support for the `x86_64-unknown-uefi` target.][56769] Libraries --------- - [The methods `overflowing_{add, sub, mul, shl, shr}` are now `const` functions for all numeric types.][57566] - [The methods `rotate_left`, `rotate_right`, and `wrapping_{add, sub, mul, shl, shr}` are now `const` functions for all numeric types.][57105] - [The methods `is_positive` and `is_negative` are now `const` functions for all signed numeric types.][57105] - [The `get` method for all `NonZero` types is now `const`.][57167] - [The methods `count_ones`, `count_zeros`, `leading_zeros`, `trailing_zeros`, `swap_bytes`, `from_be`, `from_le`, `to_be`, `to_le` are now `const` for all numeric types.][57234] - [`Ipv4Addr::new` is now a `const` function][57234] Stabilized APIs --------------- - [`unix::FileExt::read_exact_at`] - [`unix::FileExt::write_all_at`] - [`Option::transpose`] - [`Result::transpose`] - [`convert::identity`] - [`pin::Pin`] - [`marker::Unpin`] - [`marker::PhantomPinned`] - [`Vec::resize_with`] - [`VecDeque::resize_with`] - [`Duration::as_millis`] - [`Duration::as_micros`] - [`Duration::as_nanos`] Cargo ----- - [Cargo should now rebuild a crate if a file was modified during the initial build.][cargo/6484] Compatibility Notes ------------------- - The methods `str::{trim_left, trim_right, trim_left_matches, trim_right_matches}` are now deprecated in the standard library, and their usage will now produce a warning. Please use the `str::{trim_start, trim_end, trim_start_matches, trim_end_matches}` methods instead. - The `Error::cause` method has been deprecated in favor of `Error::source` which supports downcasting. [55982]: rust-lang/rust#55982 [56303]: rust-lang/rust#56303 [56351]: rust-lang/rust#56351 [56362]: rust-lang/rust#56362 [56642]: rust-lang/rust#56642 [56769]: rust-lang/rust#56769 [56805]: rust-lang/rust#56805 [56947]: rust-lang/rust#56947 [57049]: rust-lang/rust#57049 [57067]: rust-lang/rust#57067 [57105]: rust-lang/rust#57105 [57130]: rust-lang/rust#57130 [57167]: rust-lang/rust#57167 [57175]: rust-lang/rust#57175 [57234]: rust-lang/rust#57234 [57332]: rust-lang/rust#57332 [57465]: rust-lang/rust#57465 [57532]: rust-lang/rust#57532 [57535]: rust-lang/rust#57535 [57566]: rust-lang/rust#57566 [57615]: rust-lang/rust#57615 [cargo/6484]: rust-lang/cargo#6484 [`unix::FileExt::read_exact_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.read_exact_at [`unix::FileExt::write_all_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.write_all_at [`Option::transpose`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.transpose [`Result::transpose`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.transpose [`convert::identity`]: https://doc.rust-lang.org/std/convert/fn.identity.html [`pin::Pin`]: https://doc.rust-lang.org/std/pin/struct.Pin.html [`marker::Unpin`]: https://doc.rust-lang.org/stable/std/marker/trait.Unpin.html [`marker::PhantomPinned`]: https://doc.rust-lang.org/nightly/std/marker/struct.PhantomPinned.html [`Vec::resize_with`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.resize_with [`VecDeque::resize_with`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.resize_with [`Duration::as_millis`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_millis [`Duration::as_micros`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_micros [`Duration::as_nanos`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_nanos [platform-support]: https://forge.rust-lang.org/platform-support.html
…atch, r=oli-obk Stabilize `#![feature(const_if_match)]` Quoting from the [stabilization report](rust-lang#49146 (comment)): > `if` and `match` expressions as well as the short-circuiting logic operators `&&` and `||` will become legal in all [const contexts](https://doc.rust-lang.org/reference/const_eval.html#const-context). A const context is any of the following: > > - The initializer of a `const`, `static`, `static mut` or enum discriminant. > - The body of a `const fn`. > - The value of a const generic (nightly only). > - The length of an array type (`[u8; 3]`) or an array repeat expression (`[0u8; 3]`). > > Furthermore, the short-circuiting logic operators will no longer be lowered to their bitwise equivalents (`&` and `|` respectively) in `const` and `static` initializers (see rust-lang#57175). As a result, `let` bindings can be used alongside short-circuiting logic in those initializers. Resolves rust-lang#49146. Ideally, we would resolve 🐳 rust-lang#66753 before this lands on stable, so it might be worth pushing this back a release. Also, this means we should get the process started for rust-lang#52000, otherwise people will have no recourse except recursion for iterative `const fn`. r? @oli-obk
…atch, r=oli-obk Stabilize `#![feature(const_if_match)]` Quoting from the [stabilization report](rust-lang#49146 (comment)): > `if` and `match` expressions as well as the short-circuiting logic operators `&&` and `||` will become legal in all [const contexts](https://doc.rust-lang.org/reference/const_eval.html#const-context). A const context is any of the following: > > - The initializer of a `const`, `static`, `static mut` or enum discriminant. > - The body of a `const fn`. > - The value of a const generic (nightly only). > - The length of an array type (`[u8; 3]`) or an array repeat expression (`[0u8; 3]`). > > Furthermore, the short-circuiting logic operators will no longer be lowered to their bitwise equivalents (`&` and `|` respectively) in `const` and `static` initializers (see rust-lang#57175). As a result, `let` bindings can be used alongside short-circuiting logic in those initializers. Resolves rust-lang#49146. Ideally, we would resolve 🐳 rust-lang#66753 before this lands on stable, so it might be worth pushing this back a release. Also, this means we should get the process started for rust-lang#52000, otherwise people will have no recourse except recursion for iterative `const fn`. r? @oli-obk
…ch, r=oli-obk Stabilize `#![feature(const_if_match)]` Quoting from the [stabilization report](rust-lang#49146 (comment)): > `if` and `match` expressions as well as the short-circuiting logic operators `&&` and `||` will become legal in all [const contexts](https://doc.rust-lang.org/reference/const_eval.html#const-context). A const context is any of the following: > > - The initializer of a `const`, `static`, `static mut` or enum discriminant. > - The body of a `const fn`. > - The value of a const generic (nightly only). > - The length of an array type (`[u8; 3]`) or an array repeat expression (`[0u8; 3]`). > > Furthermore, the short-circuiting logic operators will no longer be lowered to their bitwise equivalents (`&` and `|` respectively) in `const` and `static` initializers (see rust-lang#57175). As a result, `let` bindings can be used alongside short-circuiting logic in those initializers. Resolves rust-lang#49146. Ideally, we would resolve 🐳 rust-lang#66753 before this lands on stable, so it might be worth pushing this back a release. Also, this means we should get the process started for rust-lang#52000, otherwise people will have no recourse except recursion for iterative `const fn`. r? @oli-obk
r? @Centril
This PR stabilizes the following features in constants and
const
functions:const fn foo((x, y): (u8, u8)) { ... }
)let
bindings (e.g.let x = 1;
)let
bindings (e.g.let mut x = 1;
)x = y
) and assignment operator (e.g.x += y
) expressions, even where the assignment target is a projection (e.g. a struct field or index operation likex[3] = 42
)3;
)This PR does explicitly not stabilize:
&mut T
)Some(x)
)UnsafeCell
types (as that would need raw pointers and mutable references and such, not because it is explicitly forbidden. We can't explicitly forbid it as such values are OK as long as they aren't mutated.)let
bindings in constants that use&&
and||
short circuiting operations. These are treated as&
and|
insideconst
andstatic
items right now. If we stopped treating them as&
and|
after stabilizinglet
bindings, we'd break code likelet mut x = false; false && { x = true; false };
. So to uselet
bindings in constants you need to change&&
and||
to&
and|
respectively.