Skip to content

Commit 0ebaccd

Browse files
GearsDatapackslpil
authored andcommitted
Fix size checks for assignment patterns
1 parent 94b5585 commit 0ebaccd

File tree

2 files changed

+25
-22
lines changed

2 files changed

+25
-22
lines changed

compiler-core/src/exhaustiveness.rs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,7 @@ mod missing_patterns;
8585
pub mod printer;
8686

8787
use crate::{
88-
ast::{
89-
self, AssignName, BitArrayOption, Endianness, TypedClause, TypedPattern,
90-
TypedPatternBitArraySegment,
91-
},
88+
ast::{self, AssignName, Endianness, TypedClause, TypedPattern, TypedPatternBitArraySegment},
9289
strings::{convert_string_escape_chars, length_utf16, length_utf32},
9390
type_::{
9491
Environment, Type, TypeValueConstructor, TypeValueConstructorField, TypeVar,
@@ -2789,7 +2786,7 @@ impl CaseToCompile {
27892786

27902787
let segments_count = segments.len();
27912788
for (i, segment) in segments.iter().enumerate() {
2792-
let segment_size = segment_size(segment, &pattern_variables);
2789+
let segment_size = segment_size(segment, &pattern_variables, None);
27932790

27942791
// If we're reading a variable number of bits we need to make sure
27952792
// that that variable is positive!
@@ -2831,7 +2828,7 @@ impl CaseToCompile {
28312828

28322829
// Each segment is also turned into a match test, checking the
28332830
// selected bits match with the pattern's value.
2834-
let value = segment_matched_value(&segment.value, &segment.options);
2831+
let value = segment_matched_value(segment, None);
28352832

28362833
let type_ = match &segment.type_ {
28372834
type_ if type_.is_int() => ReadType::Int,
@@ -2873,27 +2870,22 @@ impl CaseToCompile {
28732870
}
28742871

28752872
fn segment_matched_value(
2876-
pattern: &TypedPattern,
2877-
options: &[BitArrayOption<TypedPattern>],
2873+
segment: &TypedPatternBitArraySegment,
2874+
// Override for the segment pattern, if we need to determine the value of
2875+
// an assignment segment.
2876+
pattern: Option<&TypedPattern>,
28782877
) -> BitArrayMatchedValue {
2878+
let pattern = pattern.unwrap_or(&segment.value);
28792879
match pattern {
28802880
ast::Pattern::Int { int_value, .. } => BitArrayMatchedValue::LiteralInt(int_value.clone()),
28812881
ast::Pattern::Float { value, .. } => BitArrayMatchedValue::LiteralFloat(value.clone()),
2882-
ast::Pattern::String { value, .. }
2883-
if options
2884-
.iter()
2885-
.any(|x| matches!(x, BitArrayOption::Utf16 { .. })) =>
2886-
{
2882+
ast::Pattern::String { value, .. } if segment.has_utf16_option() => {
28872883
BitArrayMatchedValue::LiteralString {
28882884
value: value.clone(),
28892885
encoding: StringEncoding::Utf16,
28902886
}
28912887
}
2892-
ast::Pattern::String { value, .. }
2893-
if options
2894-
.iter()
2895-
.any(|x| matches!(x, BitArrayOption::Utf32 { .. })) =>
2896-
{
2888+
ast::Pattern::String { value, .. } if segment.has_utf32_option() => {
28972889
BitArrayMatchedValue::LiteralString {
28982890
value: value.clone(),
28992891
encoding: StringEncoding::Utf32,
@@ -2907,7 +2899,7 @@ fn segment_matched_value(
29072899
ast::Pattern::Discard { name, .. } => BitArrayMatchedValue::Discard(name.clone()),
29082900
ast::Pattern::Assign { name, pattern, .. } => BitArrayMatchedValue::Assign {
29092901
name: name.clone(),
2910-
value: Box::new(segment_matched_value(pattern, options)),
2902+
value: Box::new(segment_matched_value(segment, Some(pattern))),
29112903
},
29122904
x => panic!("unexpected segment value pattern {:?}", x),
29132905
}
@@ -2916,7 +2908,12 @@ fn segment_matched_value(
29162908
fn segment_size(
29172909
segment: &TypedPatternBitArraySegment,
29182910
pattern_variables: &HashMap<EcoString, ReadAction>,
2911+
// Override for the segment pattern, if we need to determine the size of an
2912+
// assignment segment.
2913+
pattern: Option<&TypedPattern>,
29192914
) -> ReadSize {
2915+
let pattern = pattern.unwrap_or(&segment.value);
2916+
29202917
match segment.size() {
29212918
// Size could either be a constant or a variable usage. In either case
29222919
// we need to take the segment's unit into account!
@@ -2946,7 +2943,11 @@ fn segment_size(
29462943
// If there's no size option we go for a default: 8 bits for int
29472944
// segments, and 64 for anything else.
29482945
None if segment.type_.is_int() => ReadSize::ConstantBits(8.into()),
2949-
None => match segment.value.as_ref() {
2946+
None => match pattern {
2947+
ast::Pattern::Assign { pattern, .. } => {
2948+
segment_size(segment, pattern_variables, Some(pattern))
2949+
}
2950+
29502951
ast::Pattern::String { value, .. } if segment.has_utf16_option() => {
29512952
ReadSize::ConstantBits(
29522953
// Each utf16 code unit is 16 bits

compiler-core/src/javascript/decision.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ use crate::{
1616
maybe_escape_property,
1717
},
1818
pretty::{Document, Documentable, break_, join, line, nil},
19-
strings::{convert_string_escape_chars, string_to_utf16_bytes, string_to_utf32_bytes},
19+
strings::{
20+
convert_string_escape_chars, length_utf16, string_to_utf16_bytes, string_to_utf32_bytes,
21+
},
2022
};
2123
use ecow::{EcoString, eco_format};
2224
use itertools::Itertools;
@@ -1634,5 +1636,5 @@ fn let_doc(variable_name: EcoString, value: Document<'_>) -> Document<'_> {
16341636
/// Calculates the length of str as utf16 without escape characters.
16351637
///
16361638
fn utf16_no_escape_len(str: &EcoString) -> usize {
1637-
convert_string_escape_chars(str).encode_utf16().count()
1639+
length_utf16(&convert_string_escape_chars(str))
16381640
}

0 commit comments

Comments
 (0)