rust/compiler
Dylan DPC 85dbb03490
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);
}
```
2020-10-16 02:10:07 +02:00
..
rustc just max_level_info 2020-09-11 09:37:51 -07:00
rustc_apfloat Backport another LLVM commit to rustc_apfloat 2020-10-04 02:02:25 +02:00
rustc_arena Remove unused #[allow(...)] statements from compiler/ 2020-09-26 01:25:55 +02:00
rustc_ast Rollup merge of #77739 - est31:remove_unused_code, r=petrochenkov,varkor 2020-10-15 07:32:29 +09:00
rustc_ast_lowering Replace target.target with target and target.ptr_width with target.pointer_width 2020-10-15 12:02:24 +02:00
rustc_ast_passes Replace target.target with target and target.ptr_width with target.pointer_width 2020-10-15 12:02:24 +02:00
rustc_ast_pretty Auto merge of #77135 - Aaron1011:pretty-ignore-paren, r=petrochenkov 2020-10-14 00:26:50 +00:00
rustc_attr Move PartialOrd impl out of rustc 2020-10-11 11:11:33 -04:00
rustc_builtin_macros Replace target.target with target and target.ptr_width with target.pointer_width 2020-10-15 12:02:24 +02:00
rustc_codegen_llvm Remove rustc_session::config::Config 2020-10-15 12:02:24 +02:00
rustc_codegen_ssa Remove rustc_session::config::Config 2020-10-15 12:02:24 +02:00
rustc_data_structures Remove unused code from remaining compiler crates 2020-10-14 04:14:32 +02:00
rustc_driver Replace target.target with target and target.ptr_width with target.pointer_width 2020-10-15 12:02:24 +02:00
rustc_error_codes Rollup merge of #76119 - Amjad50:stabilizing-move_ref_pattern, r=nikomatsakis 2020-10-16 02:10:07 +02:00
rustc_errors Remove unused code from remaining compiler crates 2020-10-14 04:14:32 +02:00
rustc_expand Remove unused code from remaining compiler crates 2020-10-14 04:14:32 +02:00
rustc_feature Rollup merge of #76119 - Amjad50:stabilizing-move_ref_pattern, r=nikomatsakis 2020-10-16 02:10:07 +02:00
rustc_fs_util Remove unused code from remaining compiler crates 2020-10-14 04:14:32 +02:00
rustc_graphviz /nightly/nightly-rustc 2020-09-23 21:51:56 +02:00
rustc_hir ensure arguments are included in count mismatch span 2020-10-15 10:22:39 -04:00
rustc_hir_pretty Rollup merge of #77739 - est31:remove_unused_code, r=petrochenkov,varkor 2020-10-15 07:32:29 +09:00
rustc_incremental /nightly/nightly-rustc 2020-09-23 21:51:56 +02:00
rustc_index cache types during normalization 2020-09-19 17:27:13 +02:00
rustc_infer Remove unused code from rustc_infer 2020-10-14 04:14:32 +02:00
rustc_interface Rollup merge of #77795 - bjorn3:codegen_backend_interface_refactor, r=oli-obk 2020-10-14 02:30:38 +02:00
rustc_lexer Noticed a potential bug in eat_while(): it doesn't account for number of UTF8 bytes. 2020-10-09 11:12:54 +02:00
rustc_lint Replace target.target with target and target.ptr_width with target.pointer_width 2020-10-15 12:02:24 +02:00
rustc_llvm Auto merge of #76859 - Aaron1011:fix/llvm-cgu-reuse, r=davidtwco,nikic 2020-10-11 20:50:02 +00:00
rustc_macros Remove unused #[allow(...)] statements from compiler/ 2020-09-26 01:25:55 +02:00
rustc_metadata Replace target.target with target and target.ptr_width with target.pointer_width 2020-10-15 12:02:24 +02:00
rustc_middle Rollup merge of #75675 - davidtwco:symbol-mangling-impl-params, r=eddyb 2020-10-16 02:10:02 +02:00
rustc_mir Replace target.target with target and target.ptr_width with target.pointer_width 2020-10-15 12:02:24 +02:00
rustc_mir_build Rollup merge of #76119 - Amjad50:stabilizing-move_ref_pattern, r=nikomatsakis 2020-10-16 02:10:07 +02:00
rustc_parse fix off-by-one in parameter spans 2020-10-15 09:49:36 -04:00
rustc_parse_format /nightly/nightly-rustc 2020-09-23 21:51:56 +02:00
rustc_passes Replace target.target with target and target.ptr_width with target.pointer_width 2020-10-15 12:02:24 +02:00
rustc_plugin_impl /nightly/nightly-rustc 2020-09-23 21:51:56 +02:00
rustc_privacy Separate bounds and predicates for associated/opaque types 2020-10-06 11:19:29 +01:00
rustc_query_system Remove unused code from rustc_query_system 2020-10-14 04:14:32 +02:00
rustc_resolve Rollup merge of #77825 - ethanboxx:min_const_generics_diagnostic, r=lcnr 2020-10-14 06:02:29 +09:00
rustc_save_analysis /nightly/nightly-rustc 2020-09-23 21:51:56 +02:00
rustc_serialize Replace absolute paths with relative ones 2020-10-13 14:16:45 +02:00
rustc_session Remove rustc_session::config::Config 2020-10-15 12:02:24 +02:00
rustc_span Rollup merge of #77739 - est31:remove_unused_code, r=petrochenkov,varkor 2020-10-15 07:32:29 +09:00
rustc_symbol_mangling Rollup merge of #75675 - davidtwco:symbol-mangling-impl-params, r=eddyb 2020-10-16 02:10:02 +02:00
rustc_target Replace target.target with target and target.ptr_width with target.pointer_width 2020-10-15 12:02:24 +02:00
rustc_trait_selection Auto merge of #77873 - sexxi-goose:use_tuple_inference_for_closures, r=nikomatsakis 2020-10-15 04:17:10 +00:00
rustc_traits Address comments 2020-10-14 00:17:42 -04:00
rustc_ty Move item_bounds to typeck::collect 2020-10-06 11:18:45 +01:00
rustc_typeck Rollup merge of #75023 - euclio:argument-span, r=estebank 2020-10-16 02:09:58 +02:00