Skip to content

Commit ab96412

Browse files
committed
Allow matching on consts of pattern types
1 parent d62f885 commit ab96412

File tree

4 files changed

+62
-9
lines changed

4 files changed

+62
-9
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2153,11 +2153,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21532153
}
21542154
}
21552155
CastKind::Transmute => {
2156-
span_mirbug!(
2157-
self,
2158-
rvalue,
2159-
"Unexpected CastKind::Transmute, which is not permitted in Analysis MIR",
2160-
);
2156+
let ty_from = op.ty(body, tcx);
2157+
match ty_from.kind() {
2158+
ty::Pat(base, _) if base == ty => {}
2159+
_ => span_mirbug!(
2160+
self,
2161+
rvalue,
2162+
"Unexpected CastKind::Transmute {ty_from:?} -> {ty:?}, which is not permitted in Analysis MIR",
2163+
),
2164+
}
21612165
}
21622166
}
21632167
}

compiler/rustc_mir_build/src/builder/matches/test.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
146146
let success_block = target_block(TestBranch::Success);
147147
let fail_block = target_block(TestBranch::Failure);
148148

149-
let expect_ty = value.ty();
150-
let expect = self.literal_operand(test.span, value);
149+
let mut expect_ty = value.ty();
150+
let mut expect = self.literal_operand(test.span, value);
151151

152152
let mut place = place;
153153
let mut block = block;
@@ -180,6 +180,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
180180
place = ref_str;
181181
ty = ref_str_ty;
182182
}
183+
&ty::Pat(base, _) => {
184+
assert_eq!(ty, value.ty());
185+
186+
let transmuted_place = self.temp(base, test.span);
187+
self.cfg.push_assign(
188+
block,
189+
self.source_info(scrutinee_span),
190+
transmuted_place,
191+
Rvalue::Cast(CastKind::Transmute, Operand::Copy(place), base),
192+
);
193+
194+
let transmuted_expect = self.temp(base, test.span);
195+
self.cfg.push_assign(
196+
block,
197+
self.source_info(test.span),
198+
transmuted_expect,
199+
Rvalue::Cast(CastKind::Transmute, expect, base),
200+
);
201+
202+
place = transmuted_place;
203+
expect = Operand::Copy(transmuted_expect);
204+
ty = base;
205+
expect_ty = base;
206+
}
183207
_ => {}
184208
}
185209

tests/ui/lint/invalid_value.stderr

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,6 @@ LL | let _val: (NonZero<u32>, i32) = mem::uninitialized();
333333
|
334334
= note: `std::num::NonZero<u32>` must be non-null
335335
= note: because `core::num::niche_types::NonZeroU32Inner` must be non-null
336-
= note: integers must be initialized
337336

338337
error: the type `*const dyn Send` does not permit zero-initialization
339338
--> $DIR/invalid_value.rs:97:37
@@ -430,7 +429,6 @@ note: because `std::num::NonZero<u32>` must be non-null (in this field of the on
430429
LL | Banana(NonZero<u32>),
431430
| ^^^^^^^^^^^^
432431
= note: because `core::num::niche_types::NonZeroU32Inner` must be non-null
433-
= note: integers must be initialized
434432

435433
error: the type `bool` does not permit being left uninitialized
436434
--> $DIR/invalid_value.rs:111:26
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#![feature(pattern_types, pattern_type_macro, structural_match)]
2+
3+
//@ check-pass
4+
5+
use std::marker::StructuralPartialEq;
6+
use std::pat::pattern_type;
7+
8+
struct Thing(pattern_type!(u32 is 1..));
9+
10+
impl StructuralPartialEq for Thing {}
11+
impl Eq for Thing {}
12+
impl PartialEq for Thing {
13+
fn eq(&self, other: &Thing) -> bool {
14+
// Never called, pattern matching of struct-eq types
15+
// destructures the type and equates its fields.
16+
todo!()
17+
}
18+
}
19+
20+
const TWO: Thing = Thing(unsafe { std::mem::transmute(2_u32) });
21+
22+
const _: () = match TWO {
23+
TWO => {}
24+
_ => unreachable!(),
25+
};
26+
27+
fn main() {}

0 commit comments

Comments
 (0)