Rollup merge of #151207 - always-discriminate-prelim, r=Zalathar

Preliminary match/capture test cleanup for PR 150681

Review for rust-lang/rust#150681 requested that this cleanup gets extracted to a separate PR.

r? @Zalathar
This commit is contained in:
Stuart Cook 2026-01-17 11:47:19 +11:00 committed by GitHub
commit bd909dd5c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 108 additions and 117 deletions

View file

@ -47,10 +47,11 @@ fn as_match() {
// CHECK: bb1: {
// CHECK: [[eq:_.*]] = Ne({{.*}}, const 1_isize);
// CHECK-NEXT: assume(move [[eq]]);
// CHECK-NEXT: goto -> bb2;
// CHECK: bb2: {
// CHECK-NEXT: goto -> [[return:bb.*]];
// CHECK: [[return]]: {
// CHECK-NOT: {{bb.*}}: {
// CHECK: return;
// CHECK: bb3: {
// CHECK: {{bb.*}}: {
// CHECK-NEXT: unreachable;
match empty() {
Some(_x) => match _x {},

View file

@ -49,7 +49,7 @@ struct Plop {
fn simple() {
// CHECK-LABEL: fn simple(
// CHECK: [[discr:_.*]] = discriminant(
// CHECK: switchInt(move [[discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: bb1, otherwise: [[unreachable]]];
// CHECK: switchInt(move [[discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: {{bb.*}}, otherwise: [[unreachable]]];
// CHECK: [[unreachable]]: {
// CHECK-NEXT: unreachable;
match Test1::C {
@ -63,7 +63,7 @@ fn simple() {
fn custom_discriminant() {
// CHECK-LABEL: fn custom_discriminant(
// CHECK: [[discr:_.*]] = discriminant(
// CHECK: switchInt(move [[discr]]) -> [4: bb3, 5: bb2, otherwise: [[unreachable:bb.*]]];
// CHECK: switchInt(move [[discr]]) -> [4: {{bb.*}}, 5: {{bb.*}}, otherwise: [[unreachable:bb.*]]];
// CHECK: [[unreachable]]: {
// CHECK-NEXT: unreachable;
match Test2::D {
@ -76,7 +76,7 @@ fn custom_discriminant() {
fn otherwise_t1() {
// CHECK-LABEL: fn otherwise_t1(
// CHECK: [[discr:_.*]] = discriminant(
// CHECK: switchInt(move [[discr]]) -> [0: bb5, 1: bb5, 2: bb1, otherwise: [[unreachable:bb.*]]];
// CHECK: switchInt(move [[discr]]) -> [0: {{bb.*}}, 1: {{bb.*}}, 2: {{bb.*}}, otherwise: [[unreachable:bb.*]]];
// CHECK: [[unreachable]]: {
// CHECK-NEXT: unreachable;
match Test1::C {
@ -90,7 +90,7 @@ fn otherwise_t1() {
fn otherwise_t2() {
// CHECK-LABEL: fn otherwise_t2(
// CHECK: [[discr:_.*]] = discriminant(
// CHECK: switchInt(move [[discr]]) -> [4: bb2, 5: bb1, otherwise: [[unreachable:bb.*]]];
// CHECK: switchInt(move [[discr]]) -> [4: {{bb.*}}, 5: {{bb.*}}, otherwise: [[unreachable:bb.*]]];
// CHECK: [[unreachable]]: {
// CHECK-NEXT: unreachable;
match Test2::D {

View file

@ -1,6 +1,7 @@
//@ edition:2021
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
enum Info {
Point(i32, i32, String),
@ -14,9 +15,6 @@ fn multi_variant_enum() {
let meta = Info::Meta("meta".into(), vec);
let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
//~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|| {
//~^ ERROR First Pass analysis includes:
//~| ERROR Min Capture analysis includes:
@ -48,9 +46,6 @@ fn single_variant_enum() {
let point = SingleVariant::Point(10, -10, "1".into());
let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
//~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|| {
//~^ ERROR First Pass analysis includes:
//~| ERROR Min Capture analysis includes:

View file

@ -1,25 +1,5 @@
error[E0658]: attributes on expressions are experimental
--> $DIR/capture-enums.rs:16:13
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: attributes on expressions are experimental
--> $DIR/capture-enums.rs:50:13
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: First Pass analysis includes:
--> $DIR/capture-enums.rs:20:5
--> $DIR/capture-enums.rs:18:5
|
LL | / || {
LL | |
@ -30,38 +10,38 @@ LL | | };
| |_____^
|
note: Capturing point[] -> Immutable
--> $DIR/capture-enums.rs:23:41
--> $DIR/capture-enums.rs:21:41
|
LL | if let Info::Point(_, _, str) = point {
| ^^^^^
note: Capturing point[] -> Immutable
--> $DIR/capture-enums.rs:23:41
--> $DIR/capture-enums.rs:21:41
|
LL | if let Info::Point(_, _, str) = point {
| ^^^^^
note: Capturing point[(2, 0)] -> ByValue
--> $DIR/capture-enums.rs:23:41
--> $DIR/capture-enums.rs:21:41
|
LL | if let Info::Point(_, _, str) = point {
| ^^^^^
note: Capturing meta[] -> Immutable
--> $DIR/capture-enums.rs:31:35
--> $DIR/capture-enums.rs:29:35
|
LL | if let Info::Meta(_, v) = meta {
| ^^^^
note: Capturing meta[] -> Immutable
--> $DIR/capture-enums.rs:31:35
--> $DIR/capture-enums.rs:29:35
|
LL | if let Info::Meta(_, v) = meta {
| ^^^^
note: Capturing meta[(1, 1)] -> ByValue
--> $DIR/capture-enums.rs:31:35
--> $DIR/capture-enums.rs:29:35
|
LL | if let Info::Meta(_, v) = meta {
| ^^^^
error: Min Capture analysis includes:
--> $DIR/capture-enums.rs:20:5
--> $DIR/capture-enums.rs:18:5
|
LL | / || {
LL | |
@ -72,18 +52,18 @@ LL | | };
| |_____^
|
note: Min Capture point[] -> ByValue
--> $DIR/capture-enums.rs:23:41
--> $DIR/capture-enums.rs:21:41
|
LL | if let Info::Point(_, _, str) = point {
| ^^^^^
note: Min Capture meta[] -> ByValue
--> $DIR/capture-enums.rs:31:35
--> $DIR/capture-enums.rs:29:35
|
LL | if let Info::Meta(_, v) = meta {
| ^^^^
error: First Pass analysis includes:
--> $DIR/capture-enums.rs:54:5
--> $DIR/capture-enums.rs:49:5
|
LL | / || {
LL | |
@ -95,13 +75,13 @@ LL | | };
| |_____^
|
note: Capturing point[(2, 0)] -> ByValue
--> $DIR/capture-enums.rs:57:47
--> $DIR/capture-enums.rs:52:47
|
LL | let SingleVariant::Point(_, _, str) = point;
| ^^^^^
error: Min Capture analysis includes:
--> $DIR/capture-enums.rs:54:5
--> $DIR/capture-enums.rs:49:5
|
LL | / || {
LL | |
@ -113,11 +93,10 @@ LL | | };
| |_____^
|
note: Min Capture point[(2, 0)] -> ByValue
--> $DIR/capture-enums.rs:57:47
--> $DIR/capture-enums.rs:52:47
|
LL | let SingleVariant::Point(_, _, str) = point;
| ^^^^^
error: aborting due to 6 previous errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -34,4 +34,82 @@ fn edge_case_if() {
_b();
}
struct Unit;
enum TSingle {
A(u32, u32),
}
enum SSingle {
A { a: u32, b: u32 },
}
struct TStruct(u32, u32);
struct SStruct { a: u32, b: u32 }
// Destructuring a unit struct should not capture it
fn match_unit_struct(mut x: (Unit, u32)) {
let r = &mut x.0;
let _ = || {
let (Unit, a) = x;
a
};
let _ = *r;
}
// The same is true for an equivalent enum
fn match_unit_enum(mut x: (SingleVariant, u32)) {
let r = &mut x.0;
let _ = || {
let (SingleVariant::A, a) = x;
a
};
let _ = *r;
}
// More generally, destructuring a struct should only capture the fields being touched
fn match_struct(mut x: SStruct) {
let r = &mut x.a;
let _ = || {
let SStruct { b, .. } = x;
b
};
let _ = *r;
}
fn match_tuple_struct(mut x: TStruct) {
let r = &mut x.0;
let _ = || {
let TStruct(_, a) = x;
a
};
let _ = *r;
}
// The same is true for an equivalent enum as well
fn match_singleton(mut x: SSingle) {
let SSingle::A { a: ref mut r, .. } = x;
let _ = || {
let SSingle::A { b, .. } = x;
b
};
let _ = *r;
}
fn match_tuple_singleton(mut x: TSingle) {
let TSingle::A(ref mut r, _) = x;
let _ = || {
let TSingle::A(_, a) = x;
a
};
let _ = *r;
}
fn main() {}

View file

@ -10,6 +10,8 @@
// Ignore non_exhaustive in the same crate
#[non_exhaustive]
enum L1 { A, B }
#[non_exhaustive]
enum L2 { C }
extern crate match_non_exhaustive_lib;

View file

@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: `L1::B` not covered
--> $DIR/non-exhaustive-match.rs:26:25
--> $DIR/non-exhaustive-match.rs:28:25
|
LL | let _b = || { match l1 { L1::A => () } };
| ^^ pattern `L1::B` not covered
@ -16,7 +16,7 @@ LL | let _b = || { match l1 { L1::A => (), L1::B => todo!() } };
| ++++++++++++++++++
error[E0004]: non-exhaustive patterns: type `E1` is non-empty
--> $DIR/non-exhaustive-match.rs:37:25
--> $DIR/non-exhaustive-match.rs:39:25
|
LL | let _d = || { match e1 {} };
| ^^
@ -35,7 +35,7 @@ LL ~ } };
|
error[E0004]: non-exhaustive patterns: `_` not covered
--> $DIR/non-exhaustive-match.rs:39:25
--> $DIR/non-exhaustive-match.rs:41:25
|
LL | let _e = || { match e2 { E2::A => (), E2::B => () } };
| ^^ pattern `_` not covered
@ -53,7 +53,7 @@ LL | let _e = || { match e2 { E2::A => (), E2::B => (), _ => todo!() } };
| ++++++++++++++
error[E0505]: cannot move out of `e3` because it is borrowed
--> $DIR/non-exhaustive-match.rs:46:22
--> $DIR/non-exhaustive-match.rs:48:22
|
LL | let _g = || { match e3 { E3::C => (), _ => () } };
| -- -- borrow occurs due to use in closure

View file

@ -40,30 +40,6 @@ fn match_unit_variant(x: (Choice, u32, u32)) {
};
}
struct Unit;
fn match_unit_struct(mut x: (Unit, u32)) {
let r = &mut x.0;
let _ = || {
let (Unit, a) = x;
a
};
let _ = *r;
}
enum Also { Unit }
fn match_unit_enum(mut x: (Also, u32)) {
let r = &mut x.0;
let _ = || {
let (Also::Unit, a) = x;
a
};
let _ = *r;
}
enum TEnum {
A(u32),
B(u32),
@ -99,46 +75,6 @@ enum SSingle {
struct TStruct(u32, u32);
struct SStruct { a: u32, b: u32 }
fn match_struct(mut x: SStruct) {
let r = &mut x.a;
let _ = || {
let SStruct { b, .. } = x;
b
};
let _ = *r;
}
fn match_tuple_struct(mut x: TStruct) {
let r = &mut x.0;
let _ = || {
let TStruct(_, a) = x;
a
};
let _ = *r;
}
fn match_singleton(mut x: SSingle) {
let SSingle::A { a: ref mut r, .. } = x;
let _ = || {
let SSingle::A { b, .. } = x;
b
};
let _ = *r;
}
fn match_tuple_singleton(mut x: TSingle) {
let TSingle::A(ref mut r, _) = x;
let _ = || {
let TSingle::A(_, a) = x;
a
};
let _ = *r;
}
fn match_slice(x: (&[u32], u32, u32)) {
let _ = || {
let (([], a, _) | ([_, ..], _, a)) = x;