Skip to content

Commit 7a4d4de

Browse files
committed
add tests for array/slice const patterns
1 parent 3779c6b commit 7a4d4de

File tree

2 files changed

+137
-0
lines changed

2 files changed

+137
-0
lines changed
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//! Tests that arrays and slices in constants aren't interchangeable when used as patterns.
2+
3+
#[derive(PartialEq, Eq)]
4+
struct SomeStruct<T: ?Sized>(T);
5+
6+
const BSTR_SIZED: &'static [u8; 3] = b"012";
7+
const BSTR_UNSIZED: &'static [u8] = BSTR_SIZED;
8+
const STRUCT_SIZED: &'static SomeStruct<[u8; 3]> = &SomeStruct(*BSTR_SIZED);
9+
const STRUCT_UNSIZED: &'static SomeStruct<[u8]> = STRUCT_SIZED;
10+
11+
fn type_mismatches() {
12+
// Test that array consts can't be used where a slice pattern is expected. This helps ensure
13+
// that `const_to_pat` won't produce irrefutable `thir::PatKind::Array` patterns when matching
14+
// on slices, which would result in missing length checks.
15+
// See also `tests/ui/match/pattern-deref-miscompile.rs`, which tests that byte string literal
16+
// patterns check slices' length appropriately when matching on slices.
17+
match BSTR_UNSIZED {
18+
BSTR_SIZED => {}
19+
//~^ ERROR: mismatched types
20+
_ => {}
21+
}
22+
match STRUCT_UNSIZED {
23+
STRUCT_SIZED => {}
24+
//~^ ERROR: mismatched types
25+
_ => {}
26+
}
27+
28+
// Test that slice consts can't be used where an array pattern is expected.
29+
match BSTR_UNSIZED {
30+
BSTR_SIZED => {}
31+
//~^ ERROR: mismatched types
32+
_ => {}
33+
}
34+
// If the types matched here, this would still error, since unsized structs aren't permitted in
35+
// constant patterns. See the `invalid_patterns` test below.
36+
match STRUCT_UNSIZED {
37+
STRUCT_SIZED => {}
38+
//~^ ERROR: mismatched types
39+
_ => {}
40+
}
41+
}
42+
43+
fn invalid_patterns() {
44+
// Test that unsized structs containing slices can't be used as patterns.
45+
// See `tests/ui/consts/issue-87046.rs` for an example with `str`.
46+
match STRUCT_UNSIZED {
47+
STRUCT_UNSIZED => {}
48+
//~^ ERROR: cannot use unsized non-slice type `SomeStruct<[u8]>` in constant patterns
49+
_ => {}
50+
}
51+
}
52+
53+
fn main() {}
+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/arrays-and-slices.rs:18:9
3+
|
4+
LL | const BSTR_SIZED: &'static [u8; 3] = b"012";
5+
| ---------------------------------- constant defined here
6+
...
7+
LL | match BSTR_UNSIZED {
8+
| ------------ this expression has type `&[u8]`
9+
LL | BSTR_SIZED => {}
10+
| ^^^^^^^^^^
11+
| |
12+
| expected `&[u8]`, found `&[u8; 3]`
13+
| `BSTR_SIZED` is interpreted as a constant, not a new binding
14+
| help: introduce a new binding instead: `other_bstr_sized`
15+
|
16+
= note: expected reference `&[u8]`
17+
found reference `&'static [u8; 3]`
18+
19+
error[E0308]: mismatched types
20+
--> $DIR/arrays-and-slices.rs:23:9
21+
|
22+
LL | const STRUCT_SIZED: &'static SomeStruct<[u8; 3]> = &SomeStruct(*BSTR_SIZED);
23+
| ------------------------------------------------ constant defined here
24+
...
25+
LL | match STRUCT_UNSIZED {
26+
| -------------- this expression has type `&SomeStruct<[u8]>`
27+
LL | STRUCT_SIZED => {}
28+
| ^^^^^^^^^^^^
29+
| |
30+
| expected `&SomeStruct<[u8]>`, found `&SomeStruct<[u8; 3]>`
31+
| `STRUCT_SIZED` is interpreted as a constant, not a new binding
32+
| help: introduce a new binding instead: `other_struct_sized`
33+
|
34+
= note: expected reference `&SomeStruct<[u8]>`
35+
found reference `&'static SomeStruct<[u8; 3]>`
36+
37+
error[E0308]: mismatched types
38+
--> $DIR/arrays-and-slices.rs:30:9
39+
|
40+
LL | const BSTR_SIZED: &'static [u8; 3] = b"012";
41+
| ---------------------------------- constant defined here
42+
...
43+
LL | match BSTR_UNSIZED {
44+
| ------------ this expression has type `&[u8]`
45+
LL | BSTR_SIZED => {}
46+
| ^^^^^^^^^^
47+
| |
48+
| expected `&[u8]`, found `&[u8; 3]`
49+
| `BSTR_SIZED` is interpreted as a constant, not a new binding
50+
| help: introduce a new binding instead: `other_bstr_sized`
51+
|
52+
= note: expected reference `&[u8]`
53+
found reference `&'static [u8; 3]`
54+
55+
error[E0308]: mismatched types
56+
--> $DIR/arrays-and-slices.rs:37:9
57+
|
58+
LL | const STRUCT_SIZED: &'static SomeStruct<[u8; 3]> = &SomeStruct(*BSTR_SIZED);
59+
| ------------------------------------------------ constant defined here
60+
...
61+
LL | match STRUCT_UNSIZED {
62+
| -------------- this expression has type `&SomeStruct<[u8]>`
63+
LL | STRUCT_SIZED => {}
64+
| ^^^^^^^^^^^^
65+
| |
66+
| expected `&SomeStruct<[u8]>`, found `&SomeStruct<[u8; 3]>`
67+
| `STRUCT_SIZED` is interpreted as a constant, not a new binding
68+
| help: introduce a new binding instead: `other_struct_sized`
69+
|
70+
= note: expected reference `&SomeStruct<[u8]>`
71+
found reference `&'static SomeStruct<[u8; 3]>`
72+
73+
error: cannot use unsized non-slice type `SomeStruct<[u8]>` in constant patterns
74+
--> $DIR/arrays-and-slices.rs:47:9
75+
|
76+
LL | const STRUCT_UNSIZED: &'static SomeStruct<[u8]> = STRUCT_SIZED;
77+
| ----------------------------------------------- constant defined here
78+
...
79+
LL | STRUCT_UNSIZED => {}
80+
| ^^^^^^^^^^^^^^
81+
82+
error: aborting due to 5 previous errors
83+
84+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)