Skip to content

Commit 7ec1ca3

Browse files
committed
support float patterns
1 parent d8ea4b1 commit 7ec1ca3

File tree

6 files changed

+73
-9
lines changed

6 files changed

+73
-9
lines changed

compiler/rustc_mir_build/messages.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ mir_build_loop_match_missing_assignment =
239239
240240
mir_build_loop_match_unsupported_type =
241241
this `#[loop_match]` state value has type `{$ty}`, which is not supported
242-
.note = only integers and enums without fields are supported
242+
.note = only integers, floats, bool, char, and enums without fields are supported
243243
244244
mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper =
245245
lower range bound must be less than or equal to upper

compiler/rustc_mir_build/src/builder/expr/into.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
255255

256256
fn is_supported_loop_match_type(ty: Ty<'_>) -> bool {
257257
match ty.kind() {
258-
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => true,
258+
ty::Uint(_) | ty::Int(_) | ty::Float(_) | ty::Bool | ty::Char => true,
259259
ty::Adt(adt_def, _) => match adt_def.adt_kind() {
260260
ty::AdtKind::Struct | ty::AdtKind::Union => false,
261261
ty::AdtKind::Enum => {

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

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc_middle::ty::{
2121
self, CanonicalUserTypeAnnotation, Ty, TypeVisitableExt, ValTree, ValTreeKind,
2222
};
2323
use rustc_middle::{bug, span_bug};
24+
use rustc_pattern_analysis::constructor::RangeEnd;
2425
use rustc_pattern_analysis::rustc::{DeconstructedPat, RustcPatCtxt};
2526
use rustc_span::{BytePos, Pos, Span, Symbol, sym};
2627
use tracing::{debug, instrument};
@@ -1893,7 +1894,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
18931894
debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats);
18941895
candidate.or_span = Some(match_pair.pattern_span);
18951896
candidate.subcandidates = pats
1896-
.into_vec()
18971897
.into_iter()
18981898
.map(|flat_pat| Candidate::from_flat_pat(flat_pat, candidate.has_guard))
18991899
.collect();
@@ -2977,6 +2977,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
29772977
Ok(actual_value) => *pattern_value == actual_value,
29782978
Err(()) => bug!("bool value with invalid bits"),
29792979
},
2980+
Constructor::F16Range(l, h, end) => {
2981+
let actual = valtree.unwrap_leaf().to_f16();
2982+
match end {
2983+
RangeEnd::Included => (*l..=*h).contains(&actual),
2984+
RangeEnd::Excluded => (*l..*h).contains(&actual),
2985+
}
2986+
}
2987+
Constructor::F32Range(l, h, end) => {
2988+
let actual = valtree.unwrap_leaf().to_f32();
2989+
match end {
2990+
RangeEnd::Included => (*l..=*h).contains(&actual),
2991+
RangeEnd::Excluded => (*l..*h).contains(&actual),
2992+
}
2993+
}
2994+
Constructor::F64Range(l, h, end) => {
2995+
let actual = valtree.unwrap_leaf().to_f64();
2996+
match end {
2997+
RangeEnd::Included => (*l..=*h).contains(&actual),
2998+
RangeEnd::Excluded => (*l..*h).contains(&actual),
2999+
}
3000+
}
3001+
Constructor::F128Range(l, h, end) => {
3002+
let actual = valtree.unwrap_leaf().to_f128();
3003+
match end {
3004+
RangeEnd::Included => (*l..=*h).contains(&actual),
3005+
RangeEnd::Excluded => (*l..*h).contains(&actual),
3006+
}
3007+
}
29803008
Constructor::Wildcard => true,
29813009

29823010
// These we may eventually support:
@@ -2985,10 +3013,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
29853013
| Constructor::Slice(_)
29863014
| Constructor::UnionField
29873015
| Constructor::Or
2988-
| Constructor::F16Range(..)
2989-
| Constructor::F32Range(..)
2990-
| Constructor::F64Range(..)
2991-
| Constructor::F128Range(..)
29923016
| Constructor::Str(_) => bug!("unsupported pattern constructor {:?}", pat.ctor()),
29933017

29943018
// These should never occur here:

compiler/rustc_mir_build/src/builder/scope.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
868868
ty::Adt(adt_def, _) if adt_def.is_enum() => {
869869
(state_ty.discriminant_ty(self.tcx), Rvalue::Discriminant(scope.state_place))
870870
}
871-
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
871+
ty::Uint(_) | ty::Int(_) | ty::Float(_) | ty::Bool | ty::Char => {
872872
(state_ty, Rvalue::Use(Operand::Copy(scope.state_place)))
873873
}
874874
_ => span_bug!(state_decl.source_info.span, "unsupported #[loop_match] state"),

tests/ui/loop-match/unsupported-type.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: this `#[loop_match]` state value has type `Option<bool>`, which is not su
44
LL | state = 'blk: {
55
| ^^^^^
66
|
7-
= note: only integers and enums without fields are supported
7+
= note: only integers, floats, bool, char, and enums without fields are supported
88

99
error: aborting due to 1 previous error
1010

tests/ui/loop-match/integer-patterns.rs renamed to tests/ui/loop-match/valid-patterns.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ fn main() {
1717
assert_eq!(character('b'), 'b');
1818
assert_eq!(character('c'), 'd');
1919
assert_eq!(character('d'), 'd');
20+
21+
assert_eq!(test_f32(1.0), core::f32::consts::PI);
22+
assert_eq!(test_f32(2.5), core::f32::consts::PI);
23+
assert_eq!(test_f32(4.0), 4.0);
24+
25+
assert_eq!(test_f64(1.0), core::f64::consts::PI);
26+
assert_eq!(test_f64(2.5), core::f64::consts::PI);
27+
assert_eq!(test_f64(4.0), 4.0);
2028
}
2129

2230
fn integer(mut state: i32) -> i32 {
@@ -75,3 +83,35 @@ fn character(mut state: char) -> char {
7583
}
7684
}
7785
}
86+
87+
fn test_f32(mut state: f32) -> f32 {
88+
#[loop_match]
89+
loop {
90+
state = 'blk: {
91+
match state {
92+
1.0 => {
93+
#[const_continue]
94+
break 'blk 2.5;
95+
}
96+
2.0..3.0 => return core::f32::consts::PI,
97+
_ => return state,
98+
}
99+
}
100+
}
101+
}
102+
103+
fn test_f64(mut state: f64) -> f64 {
104+
#[loop_match]
105+
loop {
106+
state = 'blk: {
107+
match state {
108+
1.0 => {
109+
#[const_continue]
110+
break 'blk 2.5;
111+
}
112+
2.0..3.0 => return core::f64::consts::PI,
113+
_ => return state,
114+
}
115+
}
116+
}
117+
}

0 commit comments

Comments
 (0)