rust/src/test/mir-opt
bors 3a2190a9cd Auto merge of #53438 - matthewjasper:permissive-match-access, r=pnkfelix
[NLL] Be more permissive when checking access due to Match

Partially addresses #53114. notably, we should now have parity with AST borrowck. Matching on uninitialized values is still forbidden.

* ~~Give fake borrows for match their own `BorrowKind`~~
* ~~Allow borrows with this kind to happen on values that are already mutably borrowed.~~
* ~~Track borrows with this type even behind shared reference dereferences and consider all accesses to be deep when checking for conflicts with this borrow type. See [src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.rs](cb5c989598 (diff-a2126cd3263a1f5342e2ecd5e699fbc6)) for an example soundness issue this fixes (a case of #27282 that wasn't handled correctly).~~
* Create a new `BorrowKind`: `Shallow` (name can be bike-shed)
* `Shallow` borrows differ from shared borrows in that
  * When we check for access we treat them as a `Shallow(Some(_))` read
  * When we check for conflicts with them, if the borrow place is a strict prefix of the access place then we don't consider that a conflict.
    * For example, a `Shallow` borrow of `x` does not conflict with any access or borrow of `x.0` or `*x`
* Remove the current fake borrow in matches.
* When building matches, we take a `Shallow` borrow of any `Place` that we switch on or bind in a match, and any prefix of those places. (There are some optimizations where we do fewer borrows, but this shouldn't change semantics)
  * `match x { &Some(1) => (),  _ => (), }` would `Shallow` borrow `x`, `*x` and `(*x as Some).0` (the `*x` borrow is unnecessary, but I'm not sure how easy it would be to remove.)
* Replace the fake discriminant read with a `ReadForMatch`.
* Change ReadForMatch to only check for initializedness (to prevent `let x: !; match x {}`), but not conflicting borrows. It is still considered a use for liveness and `unsafe` checking.
* Give special cased error messages for this kind of borrow.

Table from the above issue after this PR

| Thing | AST | MIR | Want | Example |
| --- | --- | --- | --- |---|
| `let _ = <unsafe-field>` | 💚  | 💚  |  |  [playground](https://play.rust-lang.org/?gist=bb7843e42fa5318c1043d04bd72abfe4&version=nightly&mode=debug&edition=2015) |
| `match <unsafe_field> { _ => () }` |   |  |  | [playground](https://play.rust-lang.org/?gist=3e3af05fbf1fae28fab2aaf9412fb2ea&version=nightly&mode=debug&edition=2015) |
| `let _ = <moved>` | 💚  | 💚 | 💚 | [playground](https://play.rust-lang.org/?gist=91a6efde8288558e584aaeee0a50558b&version=nightly&mode=debug&edition=2015) |
| `match <moved> { _ => () }` |  |   | 💚 | [playground](https://play.rust-lang.org/?gist=804f8185040b2fe131f2c4a64b3048ca&version=nightly&mode=debug&edition=2015) |
| `let _ = <borrowed>` | 💚  | 💚 | 💚 | [playground](https://play.rust-lang.org/?gist=0e487c2893b89cb772ec2f2b7c5da876&version=nightly&mode=debug&edition=2015) |
| `match <borrowed> { _ => () }` | 💚  | 💚 | 💚 | [playground](https://play.rust-lang.org/?gist=0e487c2893b89cb772ec2f2b7c5da876&version=nightly&mode=debug&edition=2015) |

r? @nikomatsakis
2018-09-25 01:04:12 +00:00
..
nll Update mir-opt test suite 2018-09-18 14:36:37 +02:00
basic_assignment.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
box_expr.rs Update mir opt tests 2018-09-24 23:33:13 +01:00
combine_array_len.rs
copy_propagation_arg.rs
copy_propagation.rs
deaggregator_test_enum_2.rs
deaggregator_test_enum.rs
deaggregator_test_multiple.rs
deaggregator_test.rs
end_region_1.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
end_region_2.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
end_region_3.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
end_region_4.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
end_region_5.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
end_region_6.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
end_region_7.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
end_region_8.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
end_region_9.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
end_region_cyclic.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
end_region_destruction_extents_1.rs Skip a shared borrow of a immutable local variables 2018-09-06 21:46:52 +01:00
inline-any-operand.rs Add test to check if inlining works for any operand 2018-09-23 16:15:46 -05:00
inline-closure-borrows-arg.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
inline-closure.rs
issue-38669.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
issue-41110.rs
issue-41697.rs
issue-41888.rs
issue-43457.rs
issue-49232.rs Update mir opt tests 2018-09-24 23:33:13 +01:00
loop_test.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
lower_128bit_debug_test.rs Restrict most uses of const_fn to min_const_fn 2018-08-31 08:40:00 +02:00
lower_128bit_test.rs Restrict most uses of const_fn to min_const_fn 2018-08-31 08:40:00 +02:00
match_false_edges.rs Update mir opt tests 2018-09-24 23:33:13 +01:00
packed-struct-drop-aligned.rs
README.md
remove_fake_borrows.rs Add a MIR transform to remove fake reads 2018-09-24 23:33:13 +01:00
return_an_array.rs
simplify_if.rs
storage_live_dead_in_statics.rs Skip a shared borrow of a immutable local variables 2018-09-06 21:46:52 +01:00
storage_ranges.rs Update mir-opt test suite 2018-09-18 14:36:37 +02:00
uniform_array_move_out.rs
validate_1.rs Update mir opt tests 2018-09-24 23:33:13 +01:00
validate_2.rs Update mir opt tests 2018-09-24 23:33:13 +01:00
validate_3.rs Update mir opt tests 2018-09-24 23:33:13 +01:00
validate_4.rs
validate_5.rs

This folder contains tests for MIR optimizations.

The test format is:

(arbitrary rust code)
// END RUST SOURCE
// START $file_name_of_some_mir_dump_0
//  $expected_line_0
// (lines or elision)
// $expected_line_N
// END $file_name_of_some_mir_dump_0
// (lines or elision)
// START $file_name_of_some_mir_dump_N
//  $expected_line_0
// (lines or elision)
// $expected_line_N
// END $file_name_of_some_mir_dump_N

All the test information is in comments so the test is runnable.

For each $file_name, compiletest expects [$expected_line_0, ..., $expected_line_N] to appear in the dumped MIR in order. Currently it allows other non-matched lines before and after, but not between $expected_lines, should you want to skip lines, you must include an elision comment, of the form (as a regex) //\s*...\s*. The lines will be skipped lazily, that is, if there are two identical lines in the output that match the line after the elision comment, the first one will be matched.

Examples:

The following blocks will not match the one after it.

bb0: {
    StorageLive(_1);
    _1 = const true;
    StorageDead(_1);
}
bb0: {
    StorageLive(_1);
    _1 = const true;
    goto -> bb1
}
bb1: {
    StorageDead(_1);
    return;
}

But this will match the one above,

bb0: {
    StorageLive(_1);
    _1 = const true;
    ...
    StorageDead(_1);
    ...
}

Lines match ignoring whitespace, and the prefix "//" is removed.

It also currently strips trailing comments -- partly because the full file path in "scope comments" is unpredictable and partly because tidy complains about the lines being too long.

compiletest handles dumping the MIR before and after every pass for you. The test writer only has to specify the file names of the dumped files (not the full path to the file) and what lines to expect. There is an option to rustc that tells it to dump the mir into some directly (rather then always dumping to the current directory).