Skip to content

Commit ce3e3d4

Browse files
committed
Enable matching on pattern types via constants
1 parent 832c927 commit ce3e3d4

File tree

8 files changed

+70
-6
lines changed

8 files changed

+70
-6
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -742,9 +742,17 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
742742
ProjectionElem::OpaqueCast(ty) => {
743743
let ty = self.sanitize_type(place, ty);
744744
let ty = self.cx.normalize(ty, location);
745+
let compare_ty = match *base.ty.kind() {
746+
ty::Alias(ty::Opaque, _) => base.ty,
747+
ty::Pat(inner, _) => inner,
748+
_ => {
749+
span_mirbug!(self, place, "tried to cast {} to {ty}", base.ty);
750+
base.ty
751+
}
752+
};
745753
self.cx
746754
.eq_types(
747-
base.ty,
755+
compare_ty,
748756
ty,
749757
location.to_locations(),
750758
ConstraintCategory::TypeAnnotation,

compiler/rustc_middle/src/mir/syntax.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -959,8 +959,10 @@ pub enum ProjectionElem<V, T> {
959959
/// The included Symbol is the name of the variant, used for printing MIR.
960960
Downcast(Option<Symbol>, VariantIdx),
961961

962-
/// Like an explicit cast from an opaque type to a concrete type, but without
963-
/// requiring an intermediate variable.
962+
/// Like an explicit cast, but without requiring an intermediate variable.
963+
/// Can cast the following things:
964+
/// * from an opaque type to a concrete type
965+
/// * from a pattern type to its inner type
964966
OpaqueCast(T),
965967
}
966968

compiler/rustc_mir_build/src/build/matches/simplify.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::build::expr::as_place::PlaceBuilder;
1616
use crate::build::matches::{Ascription, Binding, Candidate, MatchPair};
1717
use crate::build::Builder;
1818
use rustc_hir::RangeEnd;
19+
use rustc_middle::mir::ProjectionElem;
1920
use rustc_middle::thir::{self, *};
2021
use rustc_middle::ty;
2122
use rustc_middle::ty::layout::IntegerExt;
@@ -174,7 +175,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
174175
}
175176

176177
PatKind::PatTy { ref value } => {
177-
candidate.match_pairs.push(MatchPair::new(match_pair.place, value, self));
178+
let place = match_pair.place.project(ProjectionElem::OpaqueCast(value.ty));
179+
candidate.match_pairs.push(MatchPair::new(place, value, self));
178180
Ok(())
179181
}
180182

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
158158
) {
159159
let place = place_builder.to_place(self);
160160
let place_ty = place.ty(&self.local_decls, self.tcx);
161-
debug!(?place, ?place_ty,);
161+
debug!(?place, ?place_ty);
162162

163163
let source_info = self.source_info(test.span);
164164
match test.kind {

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ impl<'tcx> ConstToPat<'tcx> {
229229
}
230230

231231
// Recursive helper for `to_pat`; invoke that (instead of calling this directly).
232-
#[instrument(skip(self), level = "debug")]
232+
#[instrument(skip(self), level = "debug", ret)]
233233
fn recur(
234234
&self,
235235
cv: mir::ConstantKind<'tcx>,

library/core/src/time.rs

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ const MICROS_PER_SEC: u64 = 1_000_000;
3535
#[rustc_layout_scalar_valid_range_end(999_999_999)]
3636
struct Nanoseconds(u32);
3737

38+
impl crate::marker::StructuralPartialEq for Nanoseconds {}
39+
3840
impl PartialEq for Nanoseconds {
3941
fn eq(&self, other: &Self) -> bool {
4042
self.0 as u32 == other.0 as u32

tests/mir-opt/match_pattern_type.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use std::time::Duration;
2+
3+
// EMIT_MIR match_pattern_type.system_time_math.built.after.mir
4+
fn system_time_math() {
5+
match Duration::ZERO {
6+
Duration::ZERO => {}
7+
_ => {}
8+
}
9+
}
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// MIR for `system_time_math` after built
2+
3+
fn system_time_math() -> () {
4+
let mut _0: (); // return place in scope 0 at $DIR/match_pattern_type.rs:+0:23: +0:23
5+
let mut _1: std::time::Duration; // in scope 0 at $DIR/match_pattern_type.rs:+1:11: +1:25
6+
7+
bb0: {
8+
StorageLive(_1); // scope 0 at $DIR/match_pattern_type.rs:+1:11: +1:25
9+
_1 = const _; // scope 0 at $DIR/match_pattern_type.rs:+1:11: +1:25
10+
// mir::Constant
11+
// + span: $DIR/match_pattern_type.rs:5:11: 5:25
12+
// + literal: Const { ty: Duration, val: Unevaluated(Duration::ZERO, [], None) }
13+
FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/match_pattern_type.rs:+1:11: +1:25
14+
switchInt((_1.0: u64)) -> [0: bb1, otherwise: bb3]; // scope 0 at $DIR/match_pattern_type.rs:+1:5: +1:25
15+
}
16+
17+
bb1: {
18+
switchInt((((_1.1: core::time::Nanoseconds).0: u32 is 0..=999999999) as u32)) -> [0: bb2, otherwise: bb3]; // scope 0 at $DIR/match_pattern_type.rs:+1:5: +1:25
19+
}
20+
21+
bb2: {
22+
falseEdge -> [real: bb4, imaginary: bb3]; // scope 0 at $DIR/match_pattern_type.rs:+2:9: +2:23
23+
}
24+
25+
bb3: {
26+
_0 = const (); // scope 0 at $DIR/match_pattern_type.rs:+3:14: +3:16
27+
goto -> bb5; // scope 0 at $DIR/match_pattern_type.rs:+3:14: +3:16
28+
}
29+
30+
bb4: {
31+
_0 = const (); // scope 0 at $DIR/match_pattern_type.rs:+2:27: +2:29
32+
goto -> bb5; // scope 0 at $DIR/match_pattern_type.rs:+2:27: +2:29
33+
}
34+
35+
bb5: {
36+
StorageDead(_1); // scope 0 at $DIR/match_pattern_type.rs:+5:1: +5:2
37+
return; // scope 0 at $DIR/match_pattern_type.rs:+5:2: +5:2
38+
}
39+
}

0 commit comments

Comments
 (0)