Rollup merge of #76119 - Amjad50:stabilizing-move_ref_pattern, r=nikomatsakis
Stabilize move_ref_pattern # Implementation - Initially the rule was added in the run-up to 1.0. The AST-based borrow checker was having difficulty correctly enforcing match expressions that combined ref and move bindings, and so it was decided to simplify forbid the combination out right. - The move to MIR-based borrow checking made it possible to enforce the rules in a finer-grained level, but we kept the rule in place in an effort to be conservative in our changes. - In #68376, @Centril lifted the restriction but required a feature-gate. - This PR removes the feature-gate. Tracking issue: #68354. # Description This PR is to stabilize the feature `move_ref_pattern`, which allows patterns containing both `by-ref` and `by-move` bindings at the same time. For example: `Foo(ref x, y)`, where `x` is `by-ref`, and `y` is `by-move`. The rules of moving a variable also apply here when moving *part* of a variable, such as it can't be referenced or moved before. If this pattern is used, it would result in *partial move*, which means that part of the variable is moved. The variable that was partially moved from cannot be used as a whole in this case, only the parts that are still not moved can be used. ## Documentation - The reference (rust-lang/reference#881) - Rust by example (rust-lang/rust-by-example#1377) ## Tests There are many tests, but I think one of the comperhensive ones: - [borrowck-move-ref-pattern-pass.rs](85fbf49ce0/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs
) - [borrowck-move-ref-pattern.rs](85fbf49ce0/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs
) # Examples ```rust #[derive(PartialEq, Eq)] struct Finished {} #[derive(PartialEq, Eq)] struct Processing { status: ProcessStatus, } #[derive(PartialEq, Eq)] enum ProcessStatus { One, Two, Three, } #[derive(PartialEq, Eq)] enum Status { Finished(Finished), Processing(Processing), } fn check_result(_url: &str) -> Status { // fetch status from some server Status::Processing(Processing { status: ProcessStatus::One, }) } fn wait_for_result(url: &str) -> Finished { let mut previous_status = None; loop { match check_result(url) { Status::Finished(f) => return f, Status::Processing(p) => { match (&mut previous_status, p.status) { (None, status) => previous_status = Some(status), // first status (Some(previous), status) if *previous == status => {} // no change, ignore (Some(previous), status) => { // Now it can be used // new status *previous = status; } } } } } } ``` Before, we would have used: ```rust match (&previous_status, p.status) { (Some(previous), status) if *previous == status => {} // no change, ignore (_, status) => { // new status previous_status = Some(status); } } ``` Demonstrating *partial move* ```rust fn main() { #[derive(Debug)] struct Person { name: String, age: u8, } let person = Person { name: String::from("Alice"), age: 20, }; // `name` is moved out of person, but `age` is referenced let Person { name, ref age } = person; println!("The person's age is {}", age); println!("The person's name is {}", name); // Error! borrow of partially moved value: `person` partial move occurs //println!("The person struct is {:?}", person); // `person` cannot be used but `person.age` can be used as it is not moved println!("The person's age from person struct is {}", person.age); } ```
This commit is contained in:
commit
85dbb03490
50 changed files with 277 additions and 494 deletions
|
@ -270,6 +270,9 @@ declare_features! (
|
|||
(accepted, track_caller, "1.46.0", Some(47809), None),
|
||||
/// Allows `#[doc(alias = "...")]`.
|
||||
(accepted, doc_alias, "1.48.0", Some(50146), None),
|
||||
/// Allows patterns with concurrent by-move and by-ref bindings.
|
||||
/// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
|
||||
(accepted, move_ref_pattern, "1.48.0", Some(68354), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: accepted features
|
||||
|
|
|
@ -526,10 +526,6 @@ declare_features! (
|
|||
/// For example, you can write `x @ Some(y)`.
|
||||
(active, bindings_after_at, "1.41.0", Some(65490), None),
|
||||
|
||||
/// Allows patterns with concurrent by-move and by-ref bindings.
|
||||
/// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
|
||||
(active, move_ref_pattern, "1.42.0", Some(68354), None),
|
||||
|
||||
/// Allows `impl const Trait for T` syntax.
|
||||
(active, const_trait_impl, "1.42.0", Some(67792), None),
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue