fix expected type

Rust's u128 and Roc's U128 have different alignment. They can not be used interchangebly, that leads to segmentation faults. See also https://roc.zulipchat.com/#narrow/stream/395097-compiler-development/topic/str_to_u128.20segfault/near/434410692
This commit is contained in:
Anton-4 2024-04-20 19:57:47 +02:00
parent 99ca3f545f
commit c1d0c24194
No known key found for this signature in database
GPG Key ID: 0971D718C0A9B937
6 changed files with 181 additions and 99 deletions

View File

@ -1056,7 +1056,7 @@ mod decode_immediate {
use indoc::indoc; use indoc::indoc;
#[cfg(all(test, feature = "gen-llvm"))] #[cfg(all(test, feature = "gen-llvm"))]
use roc_std::RocStr; use roc_std::{RocStr, I128, U128};
#[test] #[test]
#[cfg(feature = "gen-llvm")] #[cfg(feature = "gen-llvm")]
@ -1121,7 +1121,7 @@ mod decode_immediate {
} }
macro_rules! num_immediate { macro_rules! num_immediate {
($($num:expr, $typ:ident)*) => {$( ($($num:expr, $typ:ident, $expected_type:ident)*) => {$(
#[test] #[test]
#[cfg(feature = "gen-llvm")] #[cfg(feature = "gen-llvm")]
fn $typ() { fn $typ() {
@ -1137,25 +1137,25 @@ mod decode_immediate {
"# "#
), $num, stringify!($typ), stringify!($typ)), ), $num, stringify!($typ), stringify!($typ)),
$num, $num,
$typ $expected_type
) )
} }
)*} )*}
} }
num_immediate! { num_immediate! {
17, i8 17, i8, i8
17, i16 17, i16, i16
17, i32 17, i32, i32
17, i64 17, i64, i64
17, i128 I128::from(17), i128, I128
17, u8 17, u8, u8
17, u16 17, u16, u16
17, u32 17, u32, u32
17, u64 17, u64, u64
17, u128 U128::from(17), u128, U128
17.23, f32 17.23, f32, f32
17.23, f64 17.23, f64, f64
} }
#[test] #[test]

View File

@ -11,7 +11,7 @@ use crate::helpers::wasm::assert_evals_to;
#[allow(unused_imports)] #[allow(unused_imports)]
use indoc::indoc; use indoc::indoc;
#[allow(unused_imports)] #[allow(unused_imports)]
use roc_std::{RocDec, RocOrder, RocResult}; use roc_std::{RocDec, RocOrder, RocResult, I128, U128};
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
@ -42,8 +42,8 @@ fn i128_signed_int_alias() {
i i
" "
), ),
128, I128::from(128),
i128 I128
); );
} }
#[test] #[test]
@ -126,8 +126,8 @@ fn i128_hex_int_alias() {
f f
" "
), ),
0x123, I128::from(0x123),
i128 I128
); );
} }
#[test] #[test]
@ -207,8 +207,8 @@ fn u128_signed_int_alias() {
i i
" "
), ),
128, U128::from(128),
u128 U128
); );
} }
#[test] #[test]
@ -288,8 +288,8 @@ fn u128_hex_int_alias() {
f f
" "
), ),
0x123, I128::from(0x123),
i128 I128
); );
} }
#[test] #[test]
@ -429,8 +429,8 @@ fn dec_float_alias() {
x x
" "
), ),
RocDec::from_str_to_i128_unsafe("2.1"), RocDec::from_str("2.1").unwrap(),
i128 RocDec
); );
} }
@ -568,14 +568,14 @@ fn various_sized_abs() {
assert_evals_to!("Num.abs -6i32", 6, i32); assert_evals_to!("Num.abs -6i32", 6, i32);
assert_evals_to!("Num.abs -6i64", 6, i64); assert_evals_to!("Num.abs -6i64", 6, i64);
if !cfg!(feature = "gen-wasm") { if !cfg!(feature = "gen-wasm") {
assert_evals_to!("Num.abs -6i128", 6, i128); assert_evals_to!("Num.abs -6i128", I128::from(6), I128);
} }
assert_evals_to!("Num.abs 6u8", 6, u8); assert_evals_to!("Num.abs 6u8", 6, u8);
assert_evals_to!("Num.abs 6u16", 6, u16); assert_evals_to!("Num.abs 6u16", 6, u16);
assert_evals_to!("Num.abs 6u32", 6, u32); assert_evals_to!("Num.abs 6u32", 6, u32);
assert_evals_to!("Num.abs 6u64", 6, u64); assert_evals_to!("Num.abs 6u64", 6, u64);
if !cfg!(feature = "gen-wasm") { if !cfg!(feature = "gen-wasm") {
assert_evals_to!("Num.abs 6u128", 6, u128); assert_evals_to!("Num.abs 6u128", U128::from(6), U128);
} }
} }
@ -652,8 +652,8 @@ fn gen_add_dec() {
z z
" "
), ),
RocDec::from_str_to_i128_unsafe("5.2"), RocDec::from_str("5.2").unwrap(),
i128 RocDec
); );
} }
#[test] #[test]
@ -742,8 +742,8 @@ fn gen_div_dec() {
x / y x / y
" "
), ),
RocDec::from_str_to_i128_unsafe("3.333333333333333333"), RocDec::from_str("3.333333333333333333").unwrap(),
i128 RocDec
); );
} }
@ -764,8 +764,8 @@ fn gen_div_checked_dec() {
Err _ -> -1 Err _ -> -1
" "
), ),
RocDec::from_str_to_i128_unsafe("3.333333333333333333"), RocDec::from_str("3.333333333333333333").unwrap(),
i128 RocDec
); );
} }
#[test] #[test]
@ -785,8 +785,8 @@ fn gen_div_checked_by_zero_dec() {
Err _ -> -1 Err _ -> -1
" "
), ),
RocDec::from_str_to_i128_unsafe("-1"), RocDec::from_str("-1").unwrap(),
i128 RocDec
); );
} }
@ -794,7 +794,7 @@ fn gen_div_checked_by_zero_dec() {
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
#[should_panic(expected = r#"Roc failed with message: "Decimal division by 0!"#)] #[should_panic(expected = r#"Roc failed with message: "Decimal division by 0!"#)]
fn gen_div_dec_by_zero() { fn gen_div_dec_by_zero() {
assert_evals_to!("1dec / 0", RocDec::from_str_to_i128_unsafe("-1"), i128); assert_evals_to!("1dec / 0", RocDec::from_str("-1").unwrap(), RocDec);
} }
#[test] #[test]
@ -1030,8 +1030,8 @@ fn gen_sub_dec() {
(x - y) - z (x - y) - z
" "
), ),
RocDec::from_str_to_i128_unsafe("-3.9"), RocDec::from_str("-3.9").unwrap(),
i128 RocDec
); );
} }
@ -1053,8 +1053,8 @@ fn gen_mul_dec() {
x * y * z x * y * z
" "
), ),
RocDec::from_str_to_i128_unsafe("48.0"), RocDec::from_str("48.0").unwrap(),
i128 RocDec
); );
} }
@ -2064,7 +2064,7 @@ fn int_mul_wrap_i64() {
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn int_mul_wrap_i128() { fn int_mul_wrap_i128() {
assert_evals_to!("Num.mulWrap Num.maxI128 2", -2, i128); assert_evals_to!("Num.mulWrap Num.maxI128 2", I128::from(-2), I128);
} }
#[test] #[test]
@ -2195,13 +2195,13 @@ fn shift_right_cast_i8() {
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn min_i128() { fn min_i128() {
assert_evals_to!("Num.minI128", i128::MIN, i128); assert_evals_to!("Num.minI128", I128::from(i128::MIN), I128);
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn max_i128() { fn max_i128() {
assert_evals_to!("Num.maxI128", i128::MAX, i128); assert_evals_to!("Num.maxI128", I128::from(i128::MAX), I128);
} }
#[test] #[test]
@ -2498,13 +2498,6 @@ to_int_checked_tests! {
to_i64_checked_larger_width_unsigned_fits_pos, "15u128", 15 to_i64_checked_larger_width_unsigned_fits_pos, "15u128", 15
to_i64_checked_larger_width_unsigned_oob_pos, "9223372036854775808u128", None to_i64_checked_larger_width_unsigned_oob_pos, "9223372036854775808u128", None
) )
"Num.toI128Checked", i128, (
to_i128_checked_smaller_width_pos, "15i8", 15
to_i128_checked_smaller_width_neg, "-15i8", -15
to_i128_checked_same, "15i128", 15
to_i128_checked_same_width_unsigned_fits, "15u128", 15
to_i128_checked_same_width_unsigned_oob, "170141183460469231731687303715884105728u128", None
)
"Num.toU8Checked", u8, ( "Num.toU8Checked", u8, (
to_u8_checked_same, "15u8", 15 to_u8_checked_same, "15u8", 15
to_u8_checked_same_width_signed_fits, "15i8", 15 to_u8_checked_same_width_signed_fits, "15i8", 15
@ -2551,13 +2544,81 @@ to_int_checked_tests! {
to_u64_checked_larger_width_unsigned_fits_pos, "15u128", 15 to_u64_checked_larger_width_unsigned_fits_pos, "15u128", 15
to_u64_checked_larger_width_unsigned_oob_pos, "18446744073709551616u128", None to_u64_checked_larger_width_unsigned_oob_pos, "18446744073709551616u128", None
) )
"Num.toU128Checked", u128, ( }
to_u128_checked_smaller_width_pos, "15i8", 15
to_u128_checked_smaller_width_neg_oob, "-15i8", None fn wrap_with_default(test_roc_code: &str) -> String {
to_u128_checked_same, "15u128", 15 format!("Result.withDefault ({}) 123454321", test_roc_code)
to_u128_checked_same_width_signed_fits, "15i128", 15 }
to_u128_checked_same_width_signed_oob, "-1i128", None
) #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn to_i128_checked_smaller_width_pos() {
let test_roc_code = wrap_with_default("Num.toI128Checked 15i8");
assert_evals_to!(&test_roc_code, I128::from(15), I128)
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn to_i128_checked_smaller_width_neg() {
let test_roc_code = wrap_with_default("Num.toI128Checked -15i8");
assert_evals_to!(&test_roc_code, I128::from(-15), I128)
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn to_i128_checked_same() {
let test_roc_code = wrap_with_default("Num.toI128Checked 15i128");
assert_evals_to!(&test_roc_code, I128::from(15), I128)
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn to_i128_checked_same_width_unsigned_fits() {
let test_roc_code = wrap_with_default("Num.toI128Checked 15u128");
assert_evals_to!(&test_roc_code, I128::from(15), I128)
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn to_i128_checked_same_width_unsigned_oob() {
let test_roc_code =
"Result.isErr (Num.toI128Checked 170141183460469231731687303715884105728u128)";
assert_evals_to!(&test_roc_code, true, bool)
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn to_u128_checked_smaller_width_pos() {
let test_roc_code = wrap_with_default("Num.toU128Checked 15i8");
assert_evals_to!(&test_roc_code, U128::from(15), U128)
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn to_u128_checked_smaller_width_neg_oob() {
let test_roc_code = "Result.isErr (Num.toU128Checked -15i8)";
assert_evals_to!(&test_roc_code, true, bool)
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn to_u128_checked_same() {
let test_roc_code = wrap_with_default("Num.toU128Checked 15u128");
assert_evals_to!(&test_roc_code, U128::from(15), U128)
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn to_u128_checked_same_width_signed_fits() {
let test_roc_code = wrap_with_default("Num.toU128Checked 15i128");
assert_evals_to!(&test_roc_code, U128::from(15), U128)
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn to_u128_checked_same_width_signed_oob() {
let test_roc_code = "Result.isErr (Num.toU128Checked -1i128)";
assert_evals_to!(&test_roc_code, true, bool)
} }
#[test] #[test]
@ -3263,8 +3324,8 @@ fn dec_float_suffix() {
123.0dec 123.0dec
" "
), ),
RocDec::from_str_to_i128_unsafe("123.0"), RocDec::from_str("123.0").unwrap(),
i128 RocDec
); );
} }
@ -3277,8 +3338,8 @@ fn dec_no_decimal() {
3dec 3dec
" "
), ),
RocDec::from_str_to_i128_unsafe("3.0"), RocDec::from_str("3.0").unwrap(),
i128 RocDec
); );
} }
@ -3356,8 +3417,11 @@ fn promote_i128_number_layout() {
} }
" "
), ),
(18446744073709551617, -9223372036854775808), (
(i128, i128) I128::from(18446744073709551617),
I128::from(-9223372036854775808)
),
(I128, I128)
); );
} }
@ -3370,8 +3434,8 @@ fn promote_u128_number_layout() {
170141183460469231731687303715884105728 + 1 170141183460469231731687303715884105728 + 1
" "
), ),
170141183460469231731687303715884105729, U128::from(170141183460469231731687303715884105729),
u128 U128
); );
} }
@ -3498,10 +3562,14 @@ fn num_abs_diff_int() {
#[test] #[test]
#[cfg(feature = "gen-llvm")] #[cfg(feature = "gen-llvm")]
fn num_abs_diff_large_bits() { fn num_abs_diff_large_bits() {
assert_evals_to!(r"Num.absDiff 0u128 0u128", 0, u128); assert_evals_to!(r"Num.absDiff 0u128 0u128", U128::from(0), U128);
assert_evals_to!(r"Num.absDiff 1u128 2u128", 1, u128); assert_evals_to!(r"Num.absDiff 1u128 2u128", U128::from(1), U128);
assert_evals_to!(r"Num.absDiff -1i128 1i128", 2, i128); assert_evals_to!(r"Num.absDiff -1i128 1i128", I128::from(2), I128);
assert_evals_to!(r"Num.absDiff Num.minI128 -1i128", i128::MAX, i128); assert_evals_to!(
r"Num.absDiff Num.minI128 -1i128",
I128::from(i128::MAX),
I128
);
} }
#[test] #[test]
@ -3532,7 +3600,7 @@ fn num_abs_int_min_overflow() {
#[cfg(feature = "gen-llvm")] #[cfg(feature = "gen-llvm")]
#[should_panic(expected = r#"Roc failed with message: "Integer subtraction overflowed!"#)] #[should_panic(expected = r#"Roc failed with message: "Integer subtraction overflowed!"#)]
fn num_abs_large_bits_min_overflow() { fn num_abs_large_bits_min_overflow() {
assert_evals_to!(r"Num.absDiff Num.minI128 0", 0, i128); assert_evals_to!(r"Num.absDiff Num.minI128 0", I128::from(0), I128);
} }
#[test] #[test]
@ -3619,8 +3687,8 @@ fn mul_checked_u128() {
x x
" "
), ),
RocResult::ok(5u128 * 2u128), RocResult::ok(U128::from(5u128 * 2u128)),
RocResult<u128, ()> RocResult<U128, ()>
); );
} }
@ -3636,8 +3704,8 @@ fn sub_checked_u128() {
x x
" "
), ),
RocResult::ok(5u128 - 2u128), RocResult::ok(U128::from(5u128 - 2u128)),
RocResult<u128, ()> RocResult<U128, ()>
); );
} }
@ -3653,8 +3721,8 @@ fn add_checked_u128() {
x x
" "
), ),
RocResult::ok(5u128 + 2u128), RocResult::ok(U128::from(5u128 + 2u128)),
RocResult<u128, ()> RocResult<U128, ()>
); );
} }
@ -3717,18 +3785,18 @@ fn without_decimal_point() {
); );
assert_evals_to!( assert_evals_to!(
r"Num.withoutDecimalPoint 123.000000000000000000", r"Num.withoutDecimalPoint 123.000000000000000000",
123000000000000000000, I128::from(123000000000000000000),
i128 I128
); );
assert_evals_to!( assert_evals_to!(
r"Num.withoutDecimalPoint 170141183460469231731.687303715884105727", r"Num.withoutDecimalPoint 170141183460469231731.687303715884105727",
i128::MAX, I128::from(i128::MAX),
i128 I128
); );
assert_evals_to!( assert_evals_to!(
r"Num.withoutDecimalPoint -170141183460469231731.687303715884105728", r"Num.withoutDecimalPoint -170141183460469231731.687303715884105728",
i128::MIN, I128::from(i128::MIN),
i128 I128
); );
} }

View File

@ -13,7 +13,7 @@ use crate::helpers::dev::assert_evals_to as assert_llvm_evals_to;
#[allow(unused_imports)] #[allow(unused_imports)]
use indoc::indoc; use indoc::indoc;
#[allow(unused_imports)] #[allow(unused_imports)]
use roc_std::{RocList, RocResult, RocStr}; use roc_std::{RocList, RocResult, RocStr, I128, U128};
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
@ -1345,8 +1345,8 @@ fn str_to_i128() {
Str.toI128 "1" Str.toI128 "1"
"# "#
), ),
RocResult::ok(1), RocResult::ok(I128::from(1)),
RocResult<i128, ()> RocResult<I128, ()>
); );
} }
@ -1359,11 +1359,12 @@ fn str_to_u128() {
Str.toU128 "1" Str.toU128 "1"
"# "#
), ),
RocResult::ok(1), RocResult::ok(U128::from(1)),
RocResult<u128, ()> RocResult<U128, ()>
); );
} }
// TODO add alignment check between i64 and I64 somewhere
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))] #[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
fn str_to_i64() { fn str_to_i64() {

View File

@ -15,7 +15,7 @@ use indoc::indoc;
use roc_mono::layout::{LayoutRepr, STLayoutInterner}; use roc_mono::layout::{LayoutRepr, STLayoutInterner};
#[cfg(test)] #[cfg(test)]
use roc_std::{RocList, RocStr, U128}; use roc_std::{RocList, RocStr, I128, U128};
#[test] #[test]
fn width_and_alignment_u8_u8() { fn width_and_alignment_u8_u8() {
@ -1779,7 +1779,24 @@ fn alignment_i128() {
x x
#" #"
), ),
// NOTE: roc_std::U128 is always aligned to 16, unlike rust's u128 // NOTE: roc_std::I128 is always aligned to 16, unlike rust's i128
((I128::from(42), true), 1),
((I128, bool), u8)
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn alignment_u128() {
assert_evals_to!(
indoc!(
r"#
x : [One U128 Bool, Empty]
x = One 42 (1 == 1)
x
#"
),
// NOTE: roc_std::U128 is always aligned to 16, unlike rust's i128
((U128::from(42), true), 1), ((U128::from(42), true), 1),
((U128, bool), u8) ((U128, bool), u8)
); );

View File

@ -12,7 +12,7 @@ use crate::helpers::wasm::assert_evals_to;
#[allow(unused_imports)] #[allow(unused_imports)]
use indoc::indoc; use indoc::indoc;
use roc_std::{RocList, RocStr}; use roc_std::{RocList, RocStr, I128, U128};
#[test] #[test]
fn str_split_empty_delimiter() { fn str_split_empty_delimiter() {
@ -998,8 +998,8 @@ fn str_to_i128() {
Err _ -> 0 Err _ -> 0
"# "#
), ),
1, I128::from(1),
i128 I128
); );
} }
@ -1013,8 +1013,8 @@ fn str_to_u128() {
Err _ -> 0 Err _ -> 0
"# "#
), ),
1, U128::from(1),
u128 U128
); );
} }

View File

@ -377,10 +377,6 @@ impl RocDec {
} }
} }
pub fn from_str_to_i128_unsafe(val: &str) -> i128 {
Self::from_str(val).unwrap().as_i128()
}
/// This is private because RocDec being an i128 is an implementation detail /// This is private because RocDec being an i128 is an implementation detail
#[inline(always)] #[inline(always)]
fn as_i128(&self) -> i128 { fn as_i128(&self) -> i128 {