diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bdb535f0a4..52b83a507e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,6 @@ on: [pull_request] name: CI -variables: - RUSTC_WRAPPER: "./ci/sccache" - jobs: test: name: fmt, clippy, test, test --release @@ -31,6 +28,24 @@ jobs: - run: rustup component add rustfmt + - name: Cache cargo registry + uses: actions/cache@v1 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo index + uses: actions/cache@v1 + with: + path: ~/.cargo/git + key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache compiled valgrind + uses: actions/cache@v1 + with: + path: ~/valgrind-3.6.1/ + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + - uses: actions-rs/cargo@v1 name: rustfmt version with: @@ -69,5 +84,3 @@ jobs: with: command: test args: --release - - - run: ./ci/sccache --show-stats diff --git a/ci/sccache b/ci/sccache deleted file mode 100755 index 57ecbea0db..0000000000 Binary files a/ci/sccache and /dev/null differ diff --git a/compiler/builtins/src/unique.rs b/compiler/builtins/src/unique.rs index 1b1f9c7510..ce7a5e75c8 100644 --- a/compiler/builtins/src/unique.rs +++ b/compiler/builtins/src/unique.rs @@ -1242,36 +1242,34 @@ fn lift(u: VarId, a: SolvedType) -> SolvedType { #[inline(always)] fn float_type(u: VarId) -> SolvedType { + let b_64 = builtin_aliases::binary64_type(); + let attr_b_64 = lift(u, b_64); + let fp = builtin_aliases::floatingpoint_type(attr_b_64); + let attr_fb = lift(u, fp); + let num = builtin_aliases::num_type(attr_fb); + SolvedType::Apply( Symbol::ATTR_ATTR, vec![ flex(u), - SolvedType::Alias( - Symbol::NUM_F64, - Vec::new(), - Box::new(builtin_aliases::num_type(SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![flex(u), builtin_aliases::floatingpoint_type()], - ))), - ), + SolvedType::Alias(Symbol::NUM_F64, Vec::new(), Box::new(num)), ], ) } #[inline(always)] fn int_type(u: VarId) -> SolvedType { + let signed_64 = builtin_aliases::signed64_type(); + let attr_signed_64 = lift(u, signed_64); + let integer = builtin_aliases::integer_type(attr_signed_64); + let attr_fb = lift(u, integer); + let num = builtin_aliases::num_type(attr_fb); + SolvedType::Apply( Symbol::ATTR_ATTR, vec![ flex(u), - SolvedType::Alias( - Symbol::NUM_I64, - Vec::new(), - Box::new(builtin_aliases::num_type(SolvedType::Apply( - Symbol::ATTR_ATTR, - vec![flex(u), builtin_aliases::integer_type()], - ))), - ), + SolvedType::Alias(Symbol::NUM_I64, Vec::new(), Box::new(num)), ], ) } diff --git a/compiler/constrain/src/builtins.rs b/compiler/constrain/src/builtins.rs index 9b57b9934a..1df15d5aef 100644 --- a/compiler/constrain/src/builtins.rs +++ b/compiler/constrain/src/builtins.rs @@ -76,33 +76,71 @@ pub fn num_float() -> Type { Type::Alias( Symbol::NUM_F64, vec![], - Box::new(num_num(num_floatingpoint())), + Box::new(num_num(num_floatingpoint(num_binary64()))), ) } #[inline(always)] -pub fn num_floatingpoint() -> Type { +pub fn num_floatingpoint(range: Type) -> Type { let alias_content = Type::TagUnion( - vec![(TagName::Private(Symbol::NUM_AT_FLOATINGPOINT), vec![])], + vec![( + TagName::Private(Symbol::NUM_AT_FLOATINGPOINT), + vec![range.clone()], + )], Box::new(Type::EmptyTagUnion), ); - Type::Alias(Symbol::NUM_FLOATINGPOINT, vec![], Box::new(alias_content)) + Type::Alias( + Symbol::NUM_FLOATINGPOINT, + vec![("range".into(), range)], + Box::new(alias_content), + ) +} + +#[inline(always)] +pub fn num_binary64() -> Type { + let alias_content = Type::TagUnion( + vec![(TagName::Private(Symbol::NUM_AT_BINARY64), vec![])], + Box::new(Type::EmptyTagUnion), + ); + + Type::Alias(Symbol::NUM_BINARY64, vec![], Box::new(alias_content)) } #[inline(always)] pub fn num_int() -> Type { - Type::Alias(Symbol::NUM_I64, vec![], Box::new(num_num(num_integer()))) + Type::Alias( + Symbol::NUM_I64, + vec![], + Box::new(num_num(num_integer(num_signed64()))), + ) } #[inline(always)] -pub fn num_integer() -> Type { +pub fn num_signed64() -> Type { let alias_content = Type::TagUnion( - vec![(TagName::Private(Symbol::NUM_AT_INTEGER), vec![])], + vec![(TagName::Private(Symbol::NUM_AT_SIGNED64), vec![])], Box::new(Type::EmptyTagUnion), ); - Type::Alias(Symbol::NUM_INTEGER, vec![], Box::new(alias_content)) + Type::Alias(Symbol::NUM_SIGNED64, vec![], Box::new(alias_content)) +} + +#[inline(always)] +pub fn num_integer(range: Type) -> Type { + let alias_content = Type::TagUnion( + vec![( + TagName::Private(Symbol::NUM_AT_INTEGER), + vec![range.clone()], + )], + Box::new(Type::EmptyTagUnion), + ); + + Type::Alias( + Symbol::NUM_INTEGER, + vec![("range".into(), range)], + Box::new(alias_content), + ) } #[inline(always)] diff --git a/compiler/constrain/src/pattern.rs b/compiler/constrain/src/pattern.rs index 7258dfe6ad..164df10b34 100644 --- a/compiler/constrain/src/pattern.rs +++ b/compiler/constrain/src/pattern.rs @@ -157,7 +157,7 @@ pub fn constrain_pattern( IntLiteral(_) => { state.constraints.push(Constraint::Pattern( region, - PatternCategory::Float, + PatternCategory::Int, builtins::num_int(), expected, )); diff --git a/compiler/constrain/src/uniq.rs b/compiler/constrain/src/uniq.rs index 25352f73e0..c3ce919dd3 100644 --- a/compiler/constrain/src/uniq.rs +++ b/compiler/constrain/src/uniq.rs @@ -1,4 +1,4 @@ -use crate::builtins::{num_floatingpoint, num_integer, num_num}; +use crate::builtins::{num_binary64, num_floatingpoint, num_integer, num_num, num_signed64}; use crate::expr::{exists, Info}; use roc_can::annotation::IntroducedVariables; use roc_can::constraint::Constraint::{self, *}; @@ -166,24 +166,25 @@ fn constrain_pattern( } NumLiteral(inner_var, _) => { - let (num_uvar, val_uvar, num_type, num_var) = unique_unbound_num(*inner_var, var_store); + let (inner_uvar, num_var, num_type) = unique_unbound_num(*inner_var, var_store); state.constraints.push(exists( - vec![val_uvar, num_uvar, num_var, *inner_var], + vec![num_var, inner_uvar, *inner_var], Constraint::Pattern(pattern.region, PatternCategory::Num, num_type, expected), )); } IntLiteral(_) => { - let (num_uvar, int_uvar, num_type) = unique_int(var_store); + let (a, b, c, num_type) = unique_int(var_store); state.constraints.push(exists( - vec![num_uvar, int_uvar], + vec![a, b, c], Constraint::Pattern(pattern.region, PatternCategory::Int, num_type, expected), )); } FloatLiteral(_) => { - let (num_uvar, float_uvar, num_type) = unique_float(var_store); + let (a, b, c, num_type) = unique_float(var_store); + state.constraints.push(exists( - vec![num_uvar, float_uvar], + vec![a, b, c], Constraint::Pattern(pattern.region, PatternCategory::Float, num_type, expected), )); } @@ -405,41 +406,47 @@ fn constrain_pattern( } } -fn unique_unbound_num( - inner_var: Variable, - var_store: &mut VarStore, -) -> (Variable, Variable, Type, Variable) { - let num_var = var_store.fresh(); +fn unique_unbound_num(inner_var: Variable, var_store: &mut VarStore) -> (Variable, Variable, Type) { let num_uvar = var_store.fresh(); - let val_uvar = var_store.fresh(); + let inner_uvar = var_store.fresh(); let val_type = Type::Variable(inner_var); - let val_utype = attr_type(Bool::variable(val_uvar), val_type); + let val_utype = attr_type(Bool::variable(inner_uvar), val_type); let num_utype = num_num(val_utype); let num_type = attr_type(Bool::variable(num_uvar), num_utype); - (num_uvar, val_uvar, num_type, num_var) + (inner_uvar, num_uvar, num_type) } -fn unique_num(var_store: &mut VarStore, val_type: Type) -> (Variable, Variable, Type) { - let num_uvar = var_store.fresh(); - let val_uvar = var_store.fresh(); +fn unique_int(var_store: &mut VarStore) -> (Variable, Variable, Variable, Type) { + let num_uvar1 = var_store.fresh(); + let num_uvar2 = var_store.fresh(); + let num_uvar3 = var_store.fresh(); - let val_utype = attr_type(Bool::variable(val_uvar), val_type); + let signed_64 = num_signed64(); + let attr_signed_64 = attr_type(Bool::variable(num_uvar1), signed_64); + let integer = num_integer(attr_signed_64); + let attr_int = attr_type(Bool::variable(num_uvar2), integer); + let num = num_num(attr_int); + let attr_num = attr_type(Bool::variable(num_uvar3), num); - let num_utype = num_num(val_utype); - let num_type = attr_type(Bool::variable(num_uvar), num_utype); - - (num_uvar, val_uvar, num_type) + (num_uvar1, num_uvar2, num_uvar3, attr_num) } -fn unique_int(var_store: &mut VarStore) -> (Variable, Variable, Type) { - unique_num(var_store, num_integer()) -} +fn unique_float(var_store: &mut VarStore) -> (Variable, Variable, Variable, Type) { + let num_uvar1 = var_store.fresh(); + let num_uvar2 = var_store.fresh(); + let num_uvar3 = var_store.fresh(); -fn unique_float(var_store: &mut VarStore) -> (Variable, Variable, Type) { - unique_num(var_store, num_floatingpoint()) + let binary_64 = num_binary64(); + let attr_binary_64 = attr_type(Bool::variable(num_uvar1), binary_64); + let fp = num_floatingpoint(attr_binary_64); + let attr_fp = attr_type(Bool::variable(num_uvar2), fp); + let num = num_num(attr_fp); + let attr_num = attr_type(Bool::variable(num_uvar3), num); + + (num_uvar1, num_uvar2, num_uvar3, attr_num) } pub fn constrain_expr( @@ -456,10 +463,10 @@ pub fn constrain_expr( match expr { Num(inner_var, _) => { let var = var_store.fresh(); - let (num_uvar, val_uvar, num_type, num_var) = unique_unbound_num(*inner_var, var_store); + let (inner_uvar, num_var, num_type) = unique_unbound_num(*inner_var, var_store); exists( - vec![var, *inner_var, val_uvar, num_uvar, num_var], + vec![var, *inner_var, inner_uvar, num_var], And(vec![ Eq( Type::Variable(var), @@ -472,10 +479,10 @@ pub fn constrain_expr( ) } Int(var, _) => { - let (num_uvar, int_uvar, num_type) = unique_int(var_store); + let (a, b, c, num_type) = unique_int(var_store); exists( - vec![*var, num_uvar, int_uvar], + vec![*var, a, b, c], And(vec![ Eq( Type::Variable(*var), @@ -488,10 +495,10 @@ pub fn constrain_expr( ) } Float(var, _) => { - let (num_uvar, float_uvar, num_type) = unique_float(var_store); + let (a, b, c, num_type) = unique_float(var_store); exists( - vec![*var, num_uvar, float_uvar], + vec![*var, a, b, c], And(vec![ Eq( Type::Variable(*var), diff --git a/compiler/gen/tests/gen_num.rs b/compiler/gen/tests/gen_num.rs index f3a5da674a..ba2117ff73 100644 --- a/compiler/gen/tests/gen_num.rs +++ b/compiler/gen/tests/gen_num.rs @@ -555,7 +555,7 @@ mod gen_num { assert_evals_to!( indoc!( r#" - always42 : Num.Num Num.Integer -> Num.Num Num.Integer + always42 : Num.Num (Num.Integer Num.Signed64) -> Num.Num (Num.Integer Num.Signed64) always42 = \_ -> 42 always42 5 diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index 951aaeb3e7..efa7f13cc1 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -797,11 +797,35 @@ define_builtins! { 54 NUM_ATAN: "atan" 55 NUM_ACOS: "acos" 56 NUM_ASIN: "asin" - 57 NUM_BITWISE_AND: "bitwiseAnd" - 58 NUM_SUB_WRAP: "subWrap" - 59 NUM_SUB_CHECKED: "subChecked" - 60 NUM_MUL_WRAP: "mulWrap" - 61 NUM_MUL_CHECKED: "mulChecked" + 57 NUM_AT_SIGNED128: "@Signed128" + 58 NUM_SIGNED128: "Signed128" imported + 59 NUM_AT_SIGNED64: "@Signed64" + 60 NUM_SIGNED64: "Signed64" imported + 61 NUM_AT_SIGNED32: "@Signed32" + 62 NUM_SIGNED32: "Signed32" imported + 63 NUM_AT_SIGNED16: "@Signed16" + 64 NUM_SIGNED16: "Signed16" imported + 65 NUM_AT_SIGNED8: "@Signed8" + 66 NUM_SIGNED8: "Signed8" imported + 67 NUM_AT_UNSIGNED128: "@Unsigned128" + 68 NUM_UNSIGNED128: "Unsigned128" imported + 69 NUM_AT_UNSIGNED64: "@Unsigned64" + 70 NUM_UNSIGNED64: "Unsigned64" imported + 71 NUM_AT_UNSIGNED32: "@Unsigned32" + 72 NUM_UNSIGNED32: "Unsigned32" imported + 73 NUM_AT_UNSIGNED16: "@Unsigned16" + 74 NUM_UNSIGNED16: "Unsigned16" imported + 75 NUM_AT_UNSIGNED8: "@Unsigned8" + 76 NUM_UNSIGNED8: "Unsigned8" imported + 77 NUM_AT_BINARY64: "@Binary64" + 78 NUM_BINARY64: "Binary64" imported + 79 NUM_AT_BINARY32: "@Binary32" + 80 NUM_BINARY32: "Binary32" imported + 81 NUM_BITWISE_AND: "bitwiseAnd" + 82 NUM_SUB_WRAP: "subWrap" + 83 NUM_SUB_CHECKED: "subChecked" + 84 NUM_MUL_WRAP: "mulWrap" + 85 NUM_MUL_CHECKED: "mulChecked" } 2 BOOL: "Bool" => { 0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 5ccfd4ee64..dc08c98176 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -5832,7 +5832,9 @@ pub enum IntOrFloat { pub fn num_argument_to_int_or_float(subs: &Subs, var: Variable) -> IntOrFloat { match subs.get_without_compacting(var).content { Content::Alias(Symbol::NUM_INTEGER, args, _) => { - debug_assert!(args.is_empty()); + debug_assert!(args.len() == 1); + + // TODO: we probably need to match on the type of the arg IntOrFloat::IntType } Content::FlexVar(_) => { @@ -5840,7 +5842,9 @@ pub fn num_argument_to_int_or_float(subs: &Subs, var: Variable) -> IntOrFloat { IntOrFloat::IntType } Content::Alias(Symbol::NUM_FLOATINGPOINT, args, _) => { - debug_assert!(args.is_empty()); + debug_assert!(args.len() == 1); + + // TODO: we probably need to match on the type of the arg IntOrFloat::FloatType } Content::Structure(FlatType::Apply(Symbol::ATTR_ATTR, attr_args)) => { @@ -5849,6 +5853,11 @@ pub fn num_argument_to_int_or_float(subs: &Subs, var: Variable) -> IntOrFloat { // Recurse on the second argument num_argument_to_int_or_float(subs, attr_args[1]) } + Content::Alias(Symbol::NUM_F64, args, _) | Content::Alias(Symbol::NUM_F32, args, _) => { + debug_assert!(args.is_empty()); + + IntOrFloat::FloatType + } other => { panic!( "Unrecognized Num type argument for var {:?} with Content: {:?}", diff --git a/compiler/mono/src/layout.rs b/compiler/mono/src/layout.rs index 4b74489946..aa9cb3be17 100644 --- a/compiler/mono/src/layout.rs +++ b/compiler/mono/src/layout.rs @@ -1296,11 +1296,17 @@ fn unwrap_num_tag<'a>(subs: &Subs, var: Variable) -> Result, LayoutPr } }, Content::Alias(Symbol::NUM_INTEGER, args, _) => { - debug_assert!(args.is_empty()); + debug_assert!(args.len() == 1); + + // TODO: we probably need to match on the type of the arg + // and return the correct builtin ex: Builtin::{Int32, Int16} Ok(Layout::Builtin(Builtin::Int64)) } Content::Alias(Symbol::NUM_FLOATINGPOINT, args, _) => { - debug_assert!(args.is_empty()); + debug_assert!(args.len() == 1); + + // TODO: we probably need to match on the type of the arg + // and return the correct builtin ex: Builtin::Float32 Ok(Layout::Builtin(Builtin::Float64)) } Content::FlexVar(_) | Content::RigidVar(_) => { diff --git a/compiler/reporting/src/error/type.rs b/compiler/reporting/src/error/type.rs index 1decdf059d..c5beb5dfc3 100644 --- a/compiler/reporting/src/error/type.rs +++ b/compiler/reporting/src/error/type.rs @@ -1643,6 +1643,17 @@ fn to_diff<'b>( ErrorType::Type(Symbol::NUM_F64, _) => true, ErrorType::Alias(Symbol::NUM_F64, _, _) => true, + ErrorType::Type(Symbol::NUM_NUM, args) => match &args.get(0) { + Some(ErrorType::Type(Symbol::NUM_FLOATINGPOINT, _)) => true, + Some(ErrorType::Alias(Symbol::NUM_FLOATINGPOINT, _, _)) => true, + _ => false, + }, + ErrorType::Alias(Symbol::NUM_NUM, args, _) => match &args.get(0) { + Some((_, ErrorType::Type(Symbol::NUM_FLOATINGPOINT, _))) => true, + Some((_, ErrorType::Alias(Symbol::NUM_FLOATINGPOINT, _, _))) => true, + _ => false, + }, + _ => false, }; diff --git a/compiler/reporting/tests/test_reporting.rs b/compiler/reporting/tests/test_reporting.rs index 0f3b3dfc56..8903fe25dc 100644 --- a/compiler/reporting/tests/test_reporting.rs +++ b/compiler/reporting/tests/test_reporting.rs @@ -448,8 +448,8 @@ mod test_reporting { baz Str - main U8 + F64 "# ), ) @@ -620,9 +620,9 @@ mod test_reporting { these names seem close though: + Result Num Set - Result U8 "# ), @@ -1374,7 +1374,7 @@ mod test_reporting { Bool U8 F64 - Num + Str "# ), ) @@ -2094,7 +2094,7 @@ mod test_reporting { But `add` needs the 2nd argument to be: - Num Integer + Num (Integer Signed64) "# ), ) @@ -2123,7 +2123,7 @@ mod test_reporting { But `add` needs the 2nd argument to be: - Num Integer + Num (Integer Signed64) Tip: You can convert between Int and Float using functions like `Num.toFloat` and `Num.round`. diff --git a/compiler/solve/tests/solve_expr.rs b/compiler/solve/tests/solve_expr.rs index 835473f518..c1fbb2dba9 100644 --- a/compiler/solve/tests/solve_expr.rs +++ b/compiler/solve/tests/solve_expr.rs @@ -1326,7 +1326,7 @@ mod solve_expr { infer_eq( indoc!( r#" - int : Num.Num Num.Integer + int : Num.Num (Num.Integer Num.Signed64) int "# @@ -1339,7 +1339,7 @@ mod solve_expr { infer_eq( indoc!( r#" - int : Num.Num Num.Integer + int : Num.Num (Num.Integer Num.Signed64) int = 5 int @@ -1353,7 +1353,7 @@ mod solve_expr { infer_eq( indoc!( r#" - int : Num Integer + int : Num (Integer Signed64) int "# @@ -1366,7 +1366,7 @@ mod solve_expr { infer_eq( indoc!( r#" - int : Num Integer + int : Num (Integer Signed64) int = 5 int @@ -1931,7 +1931,7 @@ mod solve_expr { infer_eq( indoc!( r#" - float : Num.Num Num.FloatingPoint + float : Num.Num (Num.FloatingPoint Num.Binary64) float "# @@ -1944,7 +1944,7 @@ mod solve_expr { infer_eq( indoc!( r#" - float : Num.Num Num.FloatingPoint + float : Num.Num (Num.FloatingPoint Num.Binary64) float = 5.5 float @@ -1958,7 +1958,7 @@ mod solve_expr { infer_eq( indoc!( r#" - float : Num FloatingPoint + float : Num (FloatingPoint Binary64) float "# @@ -1971,7 +1971,7 @@ mod solve_expr { infer_eq( indoc!( r#" - float : Num FloatingPoint + float : Num (FloatingPoint Binary64) float = 5.5 float @@ -2216,7 +2216,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - x : Num.Num Num.Integer + x : Num.Num (Num.Integer Num.Signed64) x = when 2 is 3 -> 4 @@ -2428,7 +2428,7 @@ mod solve_expr { r#" Foo a : { foo : a } - v : Foo (Num.Num Num.Integer) + v : Foo (Num.Num (Num.Integer Num.Signed64)) v = { foo: 42 } v @@ -2492,7 +2492,7 @@ mod solve_expr { r#" Peano : [ S Peano, Z ] - length : Peano -> Num.Num Num.Integer + length : Peano -> Num.Num (Num.Integer Num.Signed64) length = \peano -> when peano is Z -> 0 @@ -2592,10 +2592,10 @@ mod solve_expr { infer_eq( indoc!( r#" - r : { x : (Num.Num Num.Integer) } + r : { x : (Num.Num (Num.Integer Signed64)) } r = { x : 1 } - s : { left : { x : Num.Num Num.FloatingPoint } } + s : { left : { x : Num.Num (Num.FloatingPoint Num.Binary64) } } s = { left: { x : 3.14 } } when 0 is @@ -2757,7 +2757,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - { x, y } : { x : Str.Str, y : Num.Num Num.FloatingPoint } + { x, y } : { x : Str.Str, y : Num.Num (Num.FloatingPoint Num.Binary64) } { x, y } = { x : "foo", y : 3.14 } x @@ -2772,7 +2772,7 @@ mod solve_expr { infer_eq( indoc!( r#" - Foo : { x : Str.Str, y : Num.Num Num.FloatingPoint } + Foo : { x : Str.Str, y : Num.Num (Num.FloatingPoint Num.Binary64) } { x, y } : Foo { x, y } = { x : "foo", y : 3.14 } @@ -2830,7 +2830,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - Foo : { x : Str.Str, y : Num.Num Num.FloatingPoint } + Foo : { x : Str.Str, y : Num.Num (Num.FloatingPoint Num.Binary64) } { x, y } : Foo { x, y } = { x : "foo", y : 3.14 } diff --git a/compiler/solve/tests/solve_uniq_expr.rs b/compiler/solve/tests/solve_uniq_expr.rs index adf9f098bf..6f943c8bbe 100644 --- a/compiler/solve/tests/solve_uniq_expr.rs +++ b/compiler/solve/tests/solve_uniq_expr.rs @@ -1118,7 +1118,7 @@ mod solve_uniq_expr { infer_eq( indoc!( r#" - x : Num.Num Num.Integer + x : Num.Num (Num.Integer Num.Signed64) x = 4 x @@ -1368,7 +1368,7 @@ mod solve_uniq_expr { infer_eq( indoc!( r#" - x : Num.Num Num.Integer + x : I64 x = when 2 is 3 -> 4 @@ -1816,7 +1816,7 @@ mod solve_uniq_expr { infer_eq( indoc!( r#" - { x, y } : { x : Str.Str, y : Num.Num Num.FloatingPoint } + { x, y } : { x : Str.Str, y : F64 } { x, y } = { x : "foo", y : 3.14 } x @@ -2662,7 +2662,7 @@ mod solve_uniq_expr { f "# ), - "Attr * (Attr a I64, Attr b I64 -> Attr c I64)", + "Attr * (Attr b I64, Attr c I64 -> Attr d I64)", ); } @@ -3150,7 +3150,7 @@ mod solve_uniq_expr { indoc!( r#" empty : List I64 - empty = + empty = [] List.walkBackwards empty (\a, b -> a + b) 0 @@ -3159,4 +3159,55 @@ mod solve_uniq_expr { "Attr a I64", ); } + + #[test] + fn list_set_out_of_bounds_num() { + infer_eq( + indoc!( + r#" + List.set [2] 1337 0 + "# + ), + "Attr * (List (Attr * (Num (Attr * *))))", + ); + } + + #[test] + fn list_set_out_of_bounds_int() { + infer_eq( + indoc!( + r#" + List.set [0x2] 1337 0 + "# + ), + "Attr * (List (Attr * I64))", + ); + } + + #[test] + fn list_set_out_of_bounds_float() { + infer_eq( + indoc!( + r#" + List.set [0.2] 1337 0 + "# + ), + "Attr * (List (Attr * F64))", + ); + } + + #[test] + #[ignore] + fn list_set_out_of_bounds_int_int() { + // the unification of an integer list with a new integer element is a problem + // same for floats, but it's fine with the unspecified Num + infer_eq( + indoc!( + r#" + List.set [0x2] 1337 0x1 + "# + ), + "Attr * (List (Attr a I64))", + ); + } } diff --git a/compiler/types/src/builtin_aliases.rs b/compiler/types/src/builtin_aliases.rs index 885d9fa395..8e734fe99a 100644 --- a/compiler/types/src/builtin_aliases.rs +++ b/compiler/types/src/builtin_aliases.rs @@ -38,143 +38,213 @@ pub fn aliases() -> MutMap { }, ); - // Integer : [ @Integer ] + // Integer range : [ @Integer range ] add_alias( Symbol::NUM_INTEGER, BuiltinAlias { region: Region::zero(), - vars: Vec::new(), - typ: integer_alias_content(), + vars: vec![Located::at(Region::zero(), "range".into())], + typ: integer_alias_content(flex(TVAR1)), }, ); - // I128 Num Integer + // Signed128 : [ @Signed128 ] + add_alias( + Symbol::NUM_SIGNED128, + BuiltinAlias { + region: Region::zero(), + vars: vec![], + typ: signed128_alias_content(), + }, + ); + + // I128 : Num (Integer Signed128) add_alias( Symbol::NUM_I128, BuiltinAlias { region: Region::zero(), vars: Vec::new(), - typ: int_alias_content(), + typ: int_alias_content(signed128_type()), }, ); - // U128 : Num Integer + // U128 : Num (Integer Unsigned128) add_alias( Symbol::NUM_U128, BuiltinAlias { region: Region::zero(), vars: Vec::new(), - typ: int_alias_content(), + typ: int_alias_content(unsigned128_type()), }, ); - // I64 Num Integer + // Signed64 : [ @Signed64 ] + add_alias( + Symbol::NUM_SIGNED64, + BuiltinAlias { + region: Region::zero(), + vars: vec![], + typ: signed64_alias_content(), + }, + ); + + // I64 : Num (Integer Signed64) add_alias( Symbol::NUM_I64, BuiltinAlias { region: Region::zero(), vars: Vec::new(), - typ: int_alias_content(), + typ: int_alias_content(signed64_type()), }, ); - // U64 : Num Integer + // U64 : Num (Integer Unsigned64) add_alias( Symbol::NUM_U64, BuiltinAlias { region: Region::zero(), vars: Vec::new(), - typ: int_alias_content(), + typ: int_alias_content(unsigned64_type()), }, ); - // I32 Num Integer + // Signed32 : [ @Signed32 ] + add_alias( + Symbol::NUM_SIGNED32, + BuiltinAlias { + region: Region::zero(), + vars: vec![], + typ: signed32_alias_content(), + }, + ); + + // I32 : Num (Integer Signed32) add_alias( Symbol::NUM_I32, BuiltinAlias { region: Region::zero(), vars: Vec::new(), - typ: int_alias_content(), + typ: int_alias_content(signed32_type()), }, ); - // U32 : Num Integer + // U32 : Num (Integer Unsigned32) add_alias( Symbol::NUM_U32, BuiltinAlias { region: Region::zero(), vars: Vec::new(), - typ: int_alias_content(), + typ: int_alias_content(unsigned32_type()), }, ); - // I16 Num Integer + // Signed16 : [ @Signed16 ] + add_alias( + Symbol::NUM_SIGNED16, + BuiltinAlias { + region: Region::zero(), + vars: vec![], + typ: signed16_alias_content(), + }, + ); + + // I16 : Num (Integer Signed16) add_alias( Symbol::NUM_I16, BuiltinAlias { region: Region::zero(), vars: Vec::new(), - typ: int_alias_content(), + typ: int_alias_content(signed16_type()), }, ); - // U16 : Num Integer + // U16 : Num (Integer Unsigned16) add_alias( Symbol::NUM_U16, BuiltinAlias { region: Region::zero(), vars: Vec::new(), - typ: int_alias_content(), + typ: int_alias_content(unsigned16_type()), }, ); - // I8 Num Integer + // Signed8 : [ @Signed8 ] + add_alias( + Symbol::NUM_SIGNED8, + BuiltinAlias { + region: Region::zero(), + vars: vec![], + typ: signed8_alias_content(), + }, + ); + + // I8 : Num (Integer Signed8) add_alias( Symbol::NUM_I8, BuiltinAlias { region: Region::zero(), vars: Vec::new(), - typ: int_alias_content(), + typ: int_alias_content(signed8_type()), }, ); - // U8 : Num Integer + // U8 : Num (Integer Unsigned8) add_alias( Symbol::NUM_U8, BuiltinAlias { region: Region::zero(), vars: Vec::new(), - typ: int_alias_content(), + typ: int_alias_content(unsigned8_type()), }, ); - // FloatingPoint : [ @FloatingPoint ] + // Binary64 : [ @Binary64 ] + add_alias( + Symbol::NUM_BINARY64, + BuiltinAlias { + region: Region::zero(), + vars: vec![], + typ: binary64_alias_content(), + }, + ); + + // Binary32 : [ @Binary32 ] + add_alias( + Symbol::NUM_BINARY32, + BuiltinAlias { + region: Region::zero(), + vars: vec![], + typ: binary32_alias_content(), + }, + ); + + // FloatingPoint range : [ @FloatingPoint range ] add_alias( Symbol::NUM_FLOATINGPOINT, BuiltinAlias { region: Region::zero(), - vars: Vec::new(), - typ: floatingpoint_alias_content(), + vars: vec![Located::at(Region::zero(), "range".into())], + typ: floatingpoint_alias_content(flex(TVAR1)), }, ); - // F64 : Num FloatingPoint + // F64 : Num (FloatingPoint Binary64) add_alias( Symbol::NUM_F64, BuiltinAlias { region: Region::zero(), vars: Vec::new(), - typ: float_alias_content(), + typ: float_alias_content(binary64_type()), }, ); - // F32 : Num FloatingPoint + // F32 : Num (FloatingPoint Binary32) add_alias( Symbol::NUM_F32, BuiltinAlias { region: Region::zero(), vars: Vec::new(), - typ: float_alias_content(), + typ: float_alias_content(binary32_type()), }, ); @@ -226,57 +296,233 @@ fn num_alias_content(range: SolvedType) -> SolvedType { // FLOATING POINT #[inline(always)] -pub fn floatingpoint_type() -> SolvedType { +pub fn floatingpoint_type(range: SolvedType) -> SolvedType { SolvedType::Alias( Symbol::NUM_FLOATINGPOINT, - Vec::new(), - Box::new(floatingpoint_alias_content()), + vec![("range".into(), range.clone())], + Box::new(floatingpoint_alias_content(range)), ) } #[inline(always)] -fn floatingpoint_alias_content() -> SolvedType { - single_private_tag(Symbol::NUM_AT_FLOATINGPOINT, Vec::new()) +fn floatingpoint_alias_content(range: SolvedType) -> SolvedType { + single_private_tag(Symbol::NUM_AT_FLOATINGPOINT, vec![range]) } // FLOAT #[inline(always)] pub fn float_type() -> SolvedType { - SolvedType::Alias(Symbol::NUM_F64, Vec::new(), Box::new(float_alias_content())) + SolvedType::Alias( + Symbol::NUM_F64, + Vec::new(), + Box::new(float_alias_content(binary64_type())), + ) } #[inline(always)] -fn float_alias_content() -> SolvedType { - num_type(floatingpoint_type()) +fn float_alias_content(typ: SolvedType) -> SolvedType { + num_type(floatingpoint_type(typ)) } // INT #[inline(always)] pub fn int_type() -> SolvedType { - SolvedType::Alias(Symbol::NUM_I64, Vec::new(), Box::new(int_alias_content())) + SolvedType::Alias( + Symbol::NUM_I64, + Vec::new(), + Box::new(int_alias_content(signed64_type())), + ) } #[inline(always)] -fn int_alias_content() -> SolvedType { - num_type(integer_type()) +fn int_alias_content(range: SolvedType) -> SolvedType { + num_type(integer_type(range)) } // INTEGER #[inline(always)] -pub fn integer_type() -> SolvedType { +pub fn integer_type(range: SolvedType) -> SolvedType { SolvedType::Alias( Symbol::NUM_INTEGER, - Vec::new(), - Box::new(integer_alias_content()), + vec![("range".into(), range.clone())], + Box::new(integer_alias_content(range)), ) } #[inline(always)] -fn integer_alias_content() -> SolvedType { - single_private_tag(Symbol::NUM_AT_INTEGER, Vec::new()) +fn integer_alias_content(range: SolvedType) -> SolvedType { + single_private_tag(Symbol::NUM_AT_INTEGER, vec![range]) +} + +#[inline(always)] +pub fn binary64_type() -> SolvedType { + SolvedType::Alias( + Symbol::NUM_BINARY64, + vec![], + Box::new(binary64_alias_content()), + ) +} + +#[inline(always)] +pub fn binary64_alias_content() -> SolvedType { + single_private_tag(Symbol::NUM_AT_BINARY64, vec![]) +} + +#[inline(always)] +pub fn binary32_type() -> SolvedType { + SolvedType::Alias( + Symbol::NUM_BINARY32, + vec![], + Box::new(binary32_alias_content()), + ) +} + +#[inline(always)] +fn binary32_alias_content() -> SolvedType { + single_private_tag(Symbol::NUM_AT_BINARY32, vec![]) +} + +#[inline(always)] +pub fn signed128_type() -> SolvedType { + SolvedType::Alias( + Symbol::NUM_SIGNED128, + vec![], + Box::new(signed128_alias_content()), + ) +} + +#[inline(always)] +fn signed128_alias_content() -> SolvedType { + single_private_tag(Symbol::NUM_AT_SIGNED128, vec![]) +} + +#[inline(always)] +pub fn signed64_type() -> SolvedType { + SolvedType::Alias( + Symbol::NUM_SIGNED64, + vec![], + Box::new(signed64_alias_content()), + ) +} + +#[inline(always)] +fn signed64_alias_content() -> SolvedType { + single_private_tag(Symbol::NUM_AT_SIGNED64, vec![]) +} + +#[inline(always)] +pub fn signed32_type() -> SolvedType { + SolvedType::Alias( + Symbol::NUM_SIGNED32, + vec![], + Box::new(signed32_alias_content()), + ) +} + +#[inline(always)] +fn signed32_alias_content() -> SolvedType { + single_private_tag(Symbol::NUM_AT_SIGNED32, vec![]) +} + +#[inline(always)] +pub fn signed16_type() -> SolvedType { + SolvedType::Alias( + Symbol::NUM_SIGNED16, + vec![], + Box::new(signed16_alias_content()), + ) +} + +#[inline(always)] +fn signed16_alias_content() -> SolvedType { + single_private_tag(Symbol::NUM_AT_SIGNED16, vec![]) +} + +#[inline(always)] +pub fn signed8_type() -> SolvedType { + SolvedType::Alias( + Symbol::NUM_SIGNED8, + vec![], + Box::new(signed8_alias_content()), + ) +} + +#[inline(always)] +fn signed8_alias_content() -> SolvedType { + single_private_tag(Symbol::NUM_AT_SIGNED8, vec![]) +} + +#[inline(always)] +pub fn unsigned128_type() -> SolvedType { + SolvedType::Alias( + Symbol::NUM_UNSIGNED128, + vec![], + Box::new(unsigned128_alias_content()), + ) +} + +#[inline(always)] +fn unsigned128_alias_content() -> SolvedType { + single_private_tag(Symbol::NUM_AT_UNSIGNED128, vec![]) +} + +#[inline(always)] +pub fn unsigned64_type() -> SolvedType { + SolvedType::Alias( + Symbol::NUM_UNSIGNED64, + vec![], + Box::new(unsigned64_alias_content()), + ) +} + +#[inline(always)] +fn unsigned64_alias_content() -> SolvedType { + single_private_tag(Symbol::NUM_AT_UNSIGNED64, vec![]) +} + +#[inline(always)] +pub fn unsigned32_type() -> SolvedType { + SolvedType::Alias( + Symbol::NUM_UNSIGNED32, + vec![], + Box::new(unsigned32_alias_content()), + ) +} + +#[inline(always)] +fn unsigned32_alias_content() -> SolvedType { + single_private_tag(Symbol::NUM_AT_UNSIGNED32, vec![]) +} + +#[inline(always)] +pub fn unsigned16_type() -> SolvedType { + SolvedType::Alias( + Symbol::NUM_UNSIGNED16, + vec![], + Box::new(unsigned16_alias_content()), + ) +} + +#[inline(always)] +fn unsigned16_alias_content() -> SolvedType { + single_private_tag(Symbol::NUM_AT_UNSIGNED16, vec![]) +} + +#[inline(always)] +pub fn unsigned8_type() -> SolvedType { + SolvedType::Alias( + Symbol::NUM_UNSIGNED8, + vec![], + Box::new(unsigned8_alias_content()), + ) +} + +#[inline(always)] +fn unsigned8_alias_content() -> SolvedType { + single_private_tag(Symbol::NUM_AT_UNSIGNED8, vec![]) } #[inline(always)] @@ -351,7 +597,7 @@ pub fn dict_type(key: SolvedType, value: SolvedType) -> SolvedType { SolvedType::Apply(Symbol::DICT_DICT, vec![key, value]) } -fn single_private_tag(symbol: Symbol, type_arguments: Vec) -> SolvedType { +pub fn single_private_tag(symbol: Symbol, type_arguments: Vec) -> SolvedType { SolvedType::TagUnion( vec![(TagName::Private(symbol), type_arguments)], Box::new(SolvedType::EmptyTagUnion), diff --git a/compiler/types/src/pretty_print.rs b/compiler/types/src/pretty_print.rs index d2dd43db1c..b4891ce080 100644 --- a/compiler/types/src/pretty_print.rs +++ b/compiler/types/src/pretty_print.rs @@ -753,10 +753,10 @@ fn write_apply( match &arg_content { Content::Structure(FlatType::Apply(symbol, nested_args)) => match *symbol { - Symbol::NUM_INTEGER if nested_args.is_empty() => { + Symbol::NUM_INTEGER if nested_args.len() == 1 => { buf.push_str("I64"); } - Symbol::NUM_FLOATINGPOINT if nested_args.is_empty() => { + Symbol::NUM_FLOATINGPOINT if nested_args.len() == 1 => { buf.push_str("F64"); } Symbol::ATTR_ATTR => match nested_args @@ -767,10 +767,10 @@ fn write_apply( double_nested_symbol, double_nested_args, ))) => match double_nested_symbol { - Symbol::NUM_INTEGER if double_nested_args.is_empty() => { + Symbol::NUM_INTEGER if double_nested_args.len() == 1 => { buf.push_str("I64"); } - Symbol::NUM_FLOATINGPOINT if double_nested_args.is_empty() => { + Symbol::NUM_FLOATINGPOINT if double_nested_args.len() == 1 => { buf.push_str("F64"); } _ => default_case(subs, arg_content), diff --git a/compiler/unify/src/unify.rs b/compiler/unify/src/unify.rs index c3767540ad..96935b1e90 100644 --- a/compiler/unify/src/unify.rs +++ b/compiler/unify/src/unify.rs @@ -198,7 +198,7 @@ fn unify_alias( problems } else { - mismatch!() + mismatch!("{}", symbol) } } else { unify_pool(subs, pool, real_var, *other_real_var)