Merge pull request #4885 from roc-lang/weakening-4

Weakening 4
This commit is contained in:
Folkert de Vries 2023-01-14 17:23:40 +01:00 committed by GitHub
commit 43a8d1e610
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 164 additions and 207 deletions

View file

@ -47,7 +47,7 @@ interface Dict
## its population as the associated value.
##
## populationByCity =
## Dict.empty
## Dict.empty {}
## |> Dict.insert "London" 8_961_989
## |> Dict.insert "Philadelphia" 1_603_797
## |> Dict.insert "Shanghai" 24_870_895
@ -100,8 +100,8 @@ Dict k v := {
} | k has Hash & Eq
## Return an empty dictionary.
empty : Dict k v | k has Hash & Eq
empty =
empty : {} -> Dict k v | k has Hash & Eq
empty = \{} ->
@Dict {
metadata: List.repeat emptySlot 8,
dataIndices: List.repeat 0 8,
@ -122,16 +122,16 @@ capacity = \@Dict { dataIndices } ->
withCapacity : Nat -> Dict k v | k has Hash & Eq
withCapacity = \_ ->
# TODO: power of 2 * 8 and actual implementation
empty
empty {}
## Returns a dictionary containing the key and value provided as input.
##
## expect
## Dict.single "A" "B"
## |> Bool.isEq (Dict.insert Dict.empty "A" "B")
## |> Bool.isEq (Dict.insert (Dict.empty {}) "A" "B")
single : k, v -> Dict k v | k has Hash & Eq
single = \k, v ->
insert empty k v
insert (empty {}) k v
## Returns dictionary with the keys and values specified by the input [List].
##
@ -144,12 +144,12 @@ single = \k, v ->
fromList : List (T k v) -> Dict k v | k has Hash & Eq
fromList = \data ->
# TODO: make this efficient. Should just set data and then set all indicies in the hashmap.
List.walk data empty (\dict, T k v -> insert dict k v)
List.walk data (empty {}) (\dict, T k v -> insert dict k v)
## Returns the number of values in the dictionary.
##
## expect
## Dict.empty
## Dict.empty {}
## |> Dict.insert "One" "A Song"
## |> Dict.insert "Two" "Candy Canes"
## |> Dict.insert "Three" "Boughs of Holly"
@ -166,7 +166,7 @@ clear = \@Dict { metadata, dataIndices, data } ->
# Only clear large allocations.
if cap > 128 * 8 then
empty
empty {}
else
@Dict {
metadata: List.map metadata (\_ -> emptySlot),
@ -182,7 +182,7 @@ clear = \@Dict { metadata, dataIndices, data } ->
## initial `state` value provided for the first call.
##
## expect
## Dict.empty
## Dict.empty {}
## |> Dict.insert "Apples" 12
## |> Dict.insert "Orange" 24
## |> Dict.walk 0 (\count, _, qty -> count + qty)
@ -210,7 +210,7 @@ walkUntil = \@Dict { data }, initialState, transform ->
## will return [Ok value], otherwise return [Err KeyNotFound].
##
## dictionary =
## Dict.empty
## Dict.empty {}
## |> Dict.insert 1 "Apple"
## |> Dict.insert 2 "Orange"
##
@ -239,7 +239,7 @@ get = \@Dict { metadata, dataIndices, data }, key ->
## Check if the dictionary has a value for a specified key.
##
## expect
## Dict.empty
## Dict.empty {}
## |> Dict.insert 1234 "5678"
## |> Dict.contains 1234
## |> Bool.isEq Bool.true
@ -263,7 +263,7 @@ contains = \@Dict { metadata, dataIndices, data }, key ->
## Insert a value into the dictionary at a specified key.
##
## expect
## Dict.empty
## Dict.empty {}
## |> Dict.insert "Apples" 12
## |> Dict.get "Apples"
## |> Bool.isEq (Ok 12)
@ -307,7 +307,7 @@ insert = \@Dict { metadata, dataIndices, data, size }, key, value ->
## Remove a value from the dictionary for a specified key.
##
## expect
## Dict.empty
## Dict.empty {}
## |> Dict.insert "Some" "Value"
## |> Dict.remove "Some"
## |> Dict.len
@ -352,9 +352,9 @@ remove = \@Dict { metadata, dataIndices, data, size }, key ->
## Missing -> Present Bool.false
## Present value -> if value then Missing else Present Bool.true
##
## expect Dict.update Dict.empty "a" alterValue == Dict.single "a" Bool.false
## expect Dict.update (Dict.empty {}) "a" alterValue == Dict.single "a" Bool.false
## expect Dict.update (Dict.single "a" Bool.false) "a" alterValue == Dict.single "a" Bool.true
## expect Dict.update (Dict.single "a" Bool.true) "a" alterValue == Dict.empty
## expect Dict.update (Dict.single "a" Bool.true) "a" alterValue == Dict.empty {}
update : Dict k v, k, ([Present v, Missing] -> [Present v, Missing]) -> Dict k v | k has Hash & Eq
update = \dict, key, alter ->
# TODO: look into optimizing by merging substeps and reducing lookups.
@ -457,7 +457,7 @@ keepShared : Dict k v, Dict k v -> Dict k v | k has Hash & Eq
keepShared = \xs, ys ->
walk
xs
empty
(empty {})
(\state, k, v ->
if contains ys k then
insert state k v
@ -688,7 +688,7 @@ h2 = \hashKey ->
expect
val =
empty
empty {}
|> insert "foo" "bar"
|> get "foo"
@ -696,7 +696,7 @@ expect
expect
val =
empty
empty {}
|> insert "foo" "bar"
|> insert "foo" "baz"
|> get "foo"
@ -705,20 +705,20 @@ expect
expect
val =
empty
empty {}
|> insert "foo" "bar"
|> get "bar"
val == Err KeyNotFound
expect
empty
empty {}
|> insert "foo" {}
|> contains "foo"
expect
dict =
empty
empty {}
|> insert "foo" {}
|> insert "bar" {}
|> insert "baz" {}
@ -746,7 +746,7 @@ expect
# Reach capacity, no rehash.
expect
val =
empty
empty {}
|> insert "a" 0
|> insert "b" 1
|> insert "c" 2
@ -760,7 +760,7 @@ expect
expect
dict =
empty
empty {}
|> insert "a" 0
|> insert "b" 1
|> insert "c" 2
@ -780,7 +780,7 @@ expect
# Force rehash.
expect
val =
empty
empty {}
|> insert "a" 0
|> insert "b" 1
|> insert "c" 2
@ -795,7 +795,7 @@ expect
expect
dict =
empty
empty {}
|> insert "a" 0
|> insert "b" 1
|> insert "c" 2
@ -815,7 +815,7 @@ expect
&& (get dict "h" == Ok 7)
expect
empty
empty {}
|> insert "Some" "Value"
|> remove "Some"
|> len
@ -823,7 +823,7 @@ expect
# Makes sure a Dict with Nat keys works
expect
empty
empty {}
|> insert 7nat "Testing"
|> get 7
|> Bool.isEq (Ok "Testing")

View file

@ -43,9 +43,9 @@ isEq = \xs, ys ->
else
Break Bool.false
## An empty set.
empty : Set k | k has Hash & Eq
empty = @Set Dict.empty
## Creates a new empty set.
empty : {} -> Set k | k has Hash & Eq
empty = \{} -> @Set (Dict.empty {})
single : k -> Set k | k has Hash & Eq
single = \key ->
@ -58,14 +58,14 @@ insert = \@Set dict, key ->
# Inserting a duplicate key has no effect.
expect
actual =
empty
empty {}
|> insert "foo"
|> insert "bar"
|> insert "foo"
|> insert "baz"
expected =
empty
empty {}
|> insert "foo"
|> insert "bar"
|> insert "baz"
@ -79,7 +79,7 @@ len = \@Set dict ->
# Inserting a duplicate key has no effect on length.
expect
actual =
empty
empty {}
|> insert "foo"
|> insert "bar"
|> insert "foo"

View file

@ -969,7 +969,7 @@ mod test_can {
fn dict() {
let src = indoc!(
r#"
x = Dict.empty
x = Dict.empty {}
Dict.len x
"#

View file

@ -12,6 +12,7 @@ roc_error_macros = { path = "../../error_macros" }
roc_region = { path = "../region" }
roc_module = { path = "../module" }
roc_parse = { path = "../parse" }
roc_problem = { path = "../problem" }
roc_types = { path = "../types" }
roc_can = { path = "../can" }
arrayvec = "0.7.2"

View file

@ -3825,32 +3825,44 @@ fn is_generalizable_expr(mut expr: &Expr) -> bool {
match expr {
Num(..) | Int(..) | Float(..) => return true,
Closure(_) => return true,
OpaqueRef { argument, .. } => expr = &argument.1.value,
Str(_) | List { .. } | SingleQuote(_, _, _, _) | When { .. } | If { .. } => {
return false
Accessor(_) => {
// Accessor functions `.field` are equivalent to closures `\r -> r.field`, no need to weaken them.
return true;
}
// TODO(weakening)
Var(_, _)
| AbilityMember(_, _, _)
OpaqueWrapFunction(_) => {
// Opaque wrapper functions `@Q` are equivalent to closures `\x -> @Q x`, no need to weaken them.
return true;
}
RuntimeError(roc_problem::can::RuntimeError::NoImplementation)
| RuntimeError(roc_problem::can::RuntimeError::NoImplementationNamed { .. }) => {
// Allow generalization of signatures with no implementation
return true;
}
OpaqueRef { argument, .. } => expr = &argument.1.value,
Str(_)
| List { .. }
| SingleQuote(_, _, _, _)
| When { .. }
| If { .. }
| LetRec(_, _, _)
| LetNonRec(_, _)
| Call(_, _, _)
| RunLowLevel { .. }
| ForeignCall { .. }
| Expr::Record { .. }
| EmptyRecord
| Expr::Record { .. }
| Crash { .. }
| Access { .. }
| Accessor(_)
| Update { .. }
| Tag { .. }
| ZeroArgumentTag { .. }
| OpaqueWrapFunction(_)
| Expect { .. }
| ExpectFx { .. }
| Dbg { .. }
| TypedHole(_)
| RuntimeError(_) => return true,
| RuntimeError(..) => return false,
// TODO(weakening)
Var(_, _) | AbilityMember(_, _, _) | Tag { .. } | ZeroArgumentTag { .. } => {
return true
}
}
}
}

View file

@ -15,7 +15,7 @@ Model position :
initialModel : position -> Model position
initialModel = \start ->
{ evaluated : Set.empty
{ evaluated : Set.empty {}
, openSet : Set.single start
, costs : Dict.single start 0.0
, cameFrom : Map.empty

View file

@ -15,10 +15,10 @@ Model position :
initialModel : position -> Model position | position has Hash & Eq
initialModel = \start ->
{ evaluated : Set.empty
{ evaluated : Set.empty {}
, openSet : Set.single start
, costs : Dict.single start 0.0
, cameFrom : Dict.empty
, cameFrom : Dict.empty {}
}

View file

@ -7140,7 +7140,7 @@ mod solve_expr {
#^^^{-1}
"#
),
@r#"fun : {} -[[thunk(5) [A Str]*, thunk(5) { a : Str }]]-> Str"#
@r#"fun : {} -[[thunk(5) [A Str]w_a, thunk(5) { a : Str }]]-> Str"#
);
}
@ -7264,7 +7264,7 @@ mod solve_expr {
}
#[test]
fn polymorphic_lambda_set_specialization_with_let_generalization() {
fn polymorphic_lambda_set_specialization_with_let_weakened() {
infer_queries!(
indoc!(
r#"
@ -7282,6 +7282,7 @@ mod solve_expr {
#^{-1}
main =
# h should get weakened
h = f (@Fo {})
# ^ ^
h (@Go {})
@ -7291,15 +7292,15 @@ mod solve_expr {
@r###"
Fo#f(7) : Fo -[[f(7)]]-> (b -[[] + b:g(4):1]-> {}) | b has G
Go#g(8) : Go -[[g(8)]]-> {}
h : b -[[] + b:g(4):1]-> {} | b has G
Fo#f(7) : Fo -[[f(7)]]-> (b -[[] + b:g(4):1]-> {}) | b has G
h : Go -[[g(8)]]-> {}
Fo#f(7) : Fo -[[f(7)]]-> (Go -[[g(8)]]-> {})
h : Go -[[g(8)]]-> {}
"###
);
}
#[test]
fn polymorphic_lambda_set_specialization_with_let_generalization_unapplied() {
fn polymorphic_lambda_set_specialization_with_let_weakened_unapplied() {
infer_queries!(
indoc!(
r#"
@ -7461,9 +7462,9 @@ mod solve_expr {
main =
#^^^^{-1}
it =
it = \x ->
# ^^
(f A (@C {}) (@D {}))
(f A (@C {}) (@D {})) x
# ^
if Bool.true
then it (@E {})
@ -7484,10 +7485,10 @@ mod solve_expr {
J#j(2) : j -[[] + j:j(2):1]-> (k -[[] + j1:j(2):2 + j:j(2):2]-> {}) | j has J, j1 has J, k has K
it : k -[[] + j:j(2):2 + j1:j(2):2]-> {} | j has J, j1 has J, k has K
main : {}
it : k -[[] + k:k(4):1]-> {} | k has K
it : k -[[it(21)]]-> {} | k has K
f : [A, B], C, D -[[f(13)]]-> (k -[[] + k:k(4):1]-> {}) | k has K
it : E -[[kE(11)]]-> {}
it : F -[[kF(12)]]-> {}
it : E -[[it(21)]]-> {}
it : F -[[it(21)]]-> {}
"###
);
}
@ -8475,10 +8476,10 @@ mod solve_expr {
main =
s1 : Set U8
s1 = Set.empty
s1 = Set.empty {}
s2 : Set Str
s2 = Set.empty
s2 = Set.empty {}
Bool.isEq s1 s1 && Bool.isEq s2 s2
# ^^^^^^^^^ ^^^^^^^^^

View file

@ -21,7 +21,7 @@ fn dict_empty_len() {
assert_evals_to!(
indoc!(
r#"
Dict.len Dict.empty
Dict.len (Dict.empty {})
"#
),
0,
@ -35,7 +35,7 @@ fn dict_insert_empty() {
assert_evals_to!(
indoc!(
r#"
Dict.empty
Dict.empty {}
|> Dict.insert 42 32
|> Dict.len
"#
@ -52,7 +52,7 @@ fn dict_empty_contains() {
indoc!(
r#"
empty : Dict.Dict I64 F64
empty = Dict.empty
empty = Dict.empty {}
Dict.contains empty 42
"#
@ -69,7 +69,7 @@ fn dict_nonempty_contains() {
indoc!(
r#"
empty : Dict.Dict I64 F64
empty = Dict.insert Dict.empty 42 1.23
empty = Dict.insert (Dict.empty {}) 42 1.23
Dict.contains empty 42
"#
@ -87,7 +87,7 @@ fn dict_empty_remove() {
indoc!(
r#"
empty : Dict.Dict I64 F64
empty = Dict.empty
empty = Dict.empty {}
empty
|> Dict.remove 42
@ -106,7 +106,7 @@ fn dict_nonempty_remove() {
indoc!(
r#"
empty : Dict.Dict I64 F64
empty = Dict.insert Dict.empty 42 1.23
empty = Dict.insert (Dict.empty {}) 42 1.23
empty
|> Dict.remove 42
@ -126,7 +126,7 @@ fn dict_nonempty_get() {
indoc!(
r#"
empty : Dict.Dict I64 F64
empty = Dict.insert Dict.empty 42 1.23
empty = Dict.insert (Dict.empty {}) 42 1.23
withDefault = \x, def ->
when x is
@ -151,7 +151,7 @@ fn dict_nonempty_get() {
Ok v -> v
Err _ -> def
Dict.empty
Dict.empty {}
|> Dict.insert 42 1.23
|> Dict.get 43
|> withDefault 0
@ -170,7 +170,7 @@ fn keys() {
r#"
myDict : Dict.Dict I64 I64
myDict =
Dict.empty
Dict.empty {}
|> Dict.insert 0 100
|> Dict.insert 1 100
|> Dict.insert 2 100
@ -192,7 +192,7 @@ fn values() {
r#"
myDict : Dict.Dict I64 I64
myDict =
Dict.empty
Dict.empty {}
|> Dict.insert 0 100
|> Dict.insert 1 200
|> Dict.insert 2 300
@ -215,7 +215,7 @@ fn from_list_with_fold_simple() {
myDict : Dict.Dict I64 I64
myDict =
[1,2,3]
|> List.walk Dict.empty (\accum, value -> Dict.insert accum value value)
|> List.walk (Dict.empty {}) (\accum, value -> Dict.insert accum value value)
Dict.values myDict
"#
@ -242,7 +242,7 @@ fn from_list_with_fold_reallocates() {
myDict =
# 25 elements (8 + 16 + 1) is guaranteed to overflow/reallocate at least twice
range 0 25 []
|> List.walk Dict.empty (\accum, value -> Dict.insert accum value value)
|> List.walk (Dict.empty {}) (\accum, value -> Dict.insert accum value value)
Dict.values myDict
"#
@ -267,7 +267,7 @@ fn small_str_keys() {
r#"
myDict : Dict.Dict Str I64
myDict =
Dict.empty
Dict.empty {}
|> Dict.insert "a" 100
|> Dict.insert "b" 100
|> Dict.insert "c" 100
@ -289,7 +289,7 @@ fn big_str_keys() {
r#"
myDict : Dict.Dict Str I64
myDict =
Dict.empty
Dict.empty {}
|> Dict.insert "Leverage agile frameworks to provide a robust" 100
|> Dict.insert "synopsis for high level overviews. Iterative approaches" 200
|> Dict.insert "to corporate strategy foster collaborative thinking to" 300
@ -314,7 +314,7 @@ fn big_str_values() {
r#"
myDict : Dict.Dict I64 Str
myDict =
Dict.empty
Dict.empty {}
|> Dict.insert 100 "Leverage agile frameworks to provide a robust"
|> Dict.insert 200 "synopsis for high level overviews. Iterative approaches"
|> Dict.insert 300 "to corporate strategy foster collaborative thinking to"
@ -339,7 +339,7 @@ fn unit_values() {
r#"
myDict : Dict.Dict I64 {}
myDict =
Dict.empty
Dict.empty {}
|> Dict.insert 0 {}
|> Dict.insert 1 {}
|> Dict.insert 2 {}
@ -417,7 +417,7 @@ fn keep_shared() {
r#"
dict1 : Dict.Dict I64 {}
dict1 =
Dict.empty
Dict.empty {}
|> Dict.insert 1 {}
|> Dict.insert 2 {}
|> Dict.insert 3 {}
@ -426,7 +426,7 @@ fn keep_shared() {
dict2 : Dict.Dict I64 {}
dict2 =
Dict.empty
Dict.empty {}
|> Dict.insert 0 {}
|> Dict.insert 2 {}
|> Dict.insert 4 {}
@ -449,7 +449,7 @@ fn keep_shared_prefer_first() {
r#"
dict1 : Dict.Dict I64 I64
dict1 =
Dict.empty
Dict.empty {}
|> Dict.insert 1 1
|> Dict.insert 2 2
|> Dict.insert 3 3
@ -458,7 +458,7 @@ fn keep_shared_prefer_first() {
dict2 : Dict.Dict I64 I64
dict2 =
Dict.empty
Dict.empty {}
|> Dict.insert 0 100
|> Dict.insert 2 200
|> Dict.insert 4 300
@ -480,7 +480,7 @@ fn remove_all() {
r#"
dict1 : Dict.Dict I64 {}
dict1 =
Dict.empty
Dict.empty {}
|> Dict.insert 1 {}
|> Dict.insert 2 {}
|> Dict.insert 3 {}
@ -489,7 +489,7 @@ fn remove_all() {
dict2 : Dict.Dict I64 {}
dict2 =
Dict.empty
Dict.empty {}
|> Dict.insert 0 {}
|> Dict.insert 2 {}
|> Dict.insert 4 {}
@ -512,7 +512,7 @@ fn remove_all_prefer_first() {
r#"
dict1 : Dict.Dict I64 I64
dict1 =
Dict.empty
Dict.empty {}
|> Dict.insert 1 1
|> Dict.insert 2 2
|> Dict.insert 3 3
@ -521,7 +521,7 @@ fn remove_all_prefer_first() {
dict2 : Dict.Dict I64 I64
dict2 =
Dict.empty
Dict.empty {}
|> Dict.insert 0 100
|> Dict.insert 2 200
|> Dict.insert 4 300
@ -543,7 +543,7 @@ fn walk_sum_keys() {
r#"
dict1 : Dict.Dict I64 I64
dict1 =
Dict.empty
Dict.empty {}
|> Dict.insert 1 1
|> Dict.insert 2 2
|> Dict.insert 3 3

View file

@ -21,7 +21,7 @@ fn empty_len() {
assert_evals_to!(
indoc!(
r#"
Set.len Set.empty
Set.len (Set.empty {})
"#
),
0,
@ -73,7 +73,7 @@ fn insert() {
assert_evals_to!(
indoc!(
r#"
Set.empty
Set.empty {}
|> Set.insert 0
|> Set.insert 1
|> Set.insert 2
@ -91,7 +91,7 @@ fn remove() {
assert_evals_to!(
indoc!(
r#"
Set.empty
Set.empty {}
|> Set.insert 0
|> Set.insert 1
|> Set.remove 1
@ -259,7 +259,7 @@ fn to_list_empty() {
assert_evals_to!(
indoc!(
r#"
Set.toList Set.empty
Set.toList (Set.empty {})
"#
),
RocList::<std::convert::Infallible>::default(),

View file

@ -1,7 +1,3 @@
procedure Bool.11 (#Attr.2, #Attr.3):
let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.23;
procedure Bool.11 (#Attr.2, #Attr.3):
let Bool.24 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.24;
@ -18,18 +14,6 @@ procedure List.26 (List.152, List.153, List.154):
let List.156 : U64 = UnionAtIndex (Id 0) (Index 0) List.493;
ret List.156;
procedure List.26 (List.152, List.153, List.154):
let List.515 : [C I64, C I64] = CallByName List.90 List.152 List.153 List.154;
let List.518 : U8 = 1i64;
let List.519 : U8 = GetTagId List.515;
let List.520 : Int1 = lowlevel Eq List.518 List.519;
if List.520 then
let List.155 : I64 = UnionAtIndex (Id 1) (Index 0) List.515;
ret List.155;
else
let List.156 : I64 = UnionAtIndex (Id 0) (Index 0) List.515;
ret List.156;
procedure List.29 (List.294, List.295):
let List.492 : U64 = CallByName List.6 List.294;
let List.296 : U64 = CallByName Num.77 List.492 List.295;
@ -75,13 +59,7 @@ procedure List.90 (List.426, List.427, List.428):
let List.499 : [C U64, C U64] = CallByName List.91 List.426 List.427 List.428 List.500 List.501;
ret List.499;
procedure List.90 (List.426, List.427, List.428):
let List.522 : U64 = 0i64;
let List.523 : U64 = CallByName List.6 List.426;
let List.521 : [C I64, C I64] = CallByName List.91 List.426 List.427 List.428 List.522 List.523;
ret List.521;
procedure List.91 (List.549, List.550, List.551, List.552, List.553):
procedure List.91 (List.528, List.529, List.530, List.531, List.532):
joinpoint List.502 List.429 List.430 List.431 List.432 List.433:
let List.504 : Int1 = CallByName Num.22 List.432 List.433;
if List.504 then
@ -103,66 +81,35 @@ procedure List.91 (List.549, List.550, List.551, List.552, List.553):
let List.503 : [C U64, C U64] = TagId(1) List.430;
ret List.503;
in
jump List.502 List.549 List.550 List.551 List.552 List.553;
procedure List.91 (List.562, List.563, List.564, List.565, List.566):
joinpoint List.524 List.429 List.430 List.431 List.432 List.433:
let List.526 : Int1 = CallByName Num.22 List.432 List.433;
if List.526 then
let List.535 : U8 = CallByName List.66 List.429 List.432;
let List.527 : [C I64, C I64] = CallByName Test.4 List.430 List.535;
let List.532 : U8 = 1i64;
let List.533 : U8 = GetTagId List.527;
let List.534 : Int1 = lowlevel Eq List.532 List.533;
if List.534 then
let List.434 : I64 = UnionAtIndex (Id 1) (Index 0) List.527;
let List.530 : U64 = 1i64;
let List.529 : U64 = CallByName Num.19 List.432 List.530;
jump List.524 List.429 List.434 List.431 List.529 List.433;
else
let List.435 : I64 = UnionAtIndex (Id 0) (Index 0) List.527;
let List.531 : [C I64, C I64] = TagId(0) List.435;
ret List.531;
else
let List.525 : [C I64, C I64] = TagId(1) List.430;
ret List.525;
in
jump List.524 List.562 List.563 List.564 List.565 List.566;
jump List.502 List.528 List.529 List.530 List.531 List.532;
procedure Num.19 (#Attr.2, #Attr.3):
let Num.259 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
ret Num.259;
let Num.258 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
ret Num.258;
procedure Num.22 (#Attr.2, #Attr.3):
let Num.261 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
ret Num.261;
let Num.259 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
ret Num.259;
procedure Num.77 (#Attr.2, #Attr.3):
let Num.257 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3;
ret Num.257;
procedure Test.1 (Test.2):
let Test.18 : I64 = 0i64;
let Test.19 : {} = Struct {};
let Test.12 : I64 = CallByName List.26 Test.2 Test.18 Test.19;
let Test.14 : U64 = 0i64;
let Test.15 : {} = Struct {};
let Test.3 : U64 = CallByName List.26 Test.2 Test.14 Test.15;
let Test.13 : I64 = 0i64;
let Test.10 : Int1 = CallByName Bool.11 Test.12 Test.13;
let Test.13 : U64 = 0i64;
let Test.14 : {} = Struct {};
let Test.3 : U64 = CallByName List.26 Test.2 Test.13 Test.14;
let Test.12 : U64 = 0i64;
let Test.10 : Int1 = CallByName Bool.11 Test.3 Test.12;
if Test.10 then
ret Test.2;
else
let Test.9 : List U8 = CallByName List.29 Test.2 Test.3;
ret Test.9;
procedure Test.4 (Test.5, Test.16):
let Test.17 : [C U64, C U64] = TagId(0) Test.5;
ret Test.17;
procedure Test.4 (Test.5, Test.16):
let Test.21 : [C U64, C U64] = TagId(0) Test.5;
ret Test.21;
procedure Test.4 (Test.5, Test.15):
let Test.16 : [C U64, C U64] = TagId(0) Test.5;
ret Test.16;
procedure Test.0 ():
let Test.8 : List U8 = Array [1i64, 2i64, 3i64];

View file

@ -1,18 +1,18 @@
procedure Dict.1 ():
let Dict.520 : List {[], []} = Array [];
let Dict.527 : U64 = 0i64;
let Dict.528 : U64 = 8i64;
let Dict.521 : List U64 = CallByName List.11 Dict.527 Dict.528;
let Dict.524 : I8 = CallByName Dict.34;
let Dict.525 : U64 = 8i64;
let Dict.522 : List I8 = CallByName List.11 Dict.524 Dict.525;
let Dict.523 : U64 = 0i64;
let Dict.519 : {List {[], []}, List U64, List I8, U64} = Struct {Dict.520, Dict.521, Dict.522, Dict.523};
ret Dict.519;
procedure Dict.1 (Dict.518):
let Dict.521 : List {[], []} = Array [];
let Dict.528 : U64 = 0i64;
let Dict.529 : U64 = 8i64;
let Dict.522 : List U64 = CallByName List.11 Dict.528 Dict.529;
let Dict.525 : I8 = CallByName Dict.34;
let Dict.526 : U64 = 8i64;
let Dict.523 : List I8 = CallByName List.11 Dict.525 Dict.526;
let Dict.524 : U64 = 0i64;
let Dict.520 : {List {[], []}, List U64, List I8, U64} = Struct {Dict.521, Dict.522, Dict.523, Dict.524};
ret Dict.520;
procedure Dict.34 ():
let Dict.526 : I8 = -128i64;
ret Dict.526;
let Dict.527 : I8 = -128i64;
ret Dict.527;
procedure Dict.4 (Dict.507):
let Dict.85 : U64 = StructAtIndex 3 Dict.507;
@ -82,6 +82,7 @@ procedure Num.24 (#Attr.2, #Attr.3):
ret Num.259;
procedure Test.0 ():
let Test.2 : {List {[], []}, List U64, List I8, U64} = CallByName Dict.1;
let Test.3 : {} = Struct {};
let Test.2 : {List {[], []}, List U64, List I8, U64} = CallByName Dict.1 Test.3;
let Test.1 : U64 = CallByName Dict.4 Test.2;
ret Test.1;

View file

@ -0,0 +1,13 @@
procedure Test.1 ():
let Test.7 : U8 = 1i64;
let Test.8 : U8 = 2i64;
let Test.6 : {U8, U8} = Struct {Test.7, Test.8};
ret Test.6;
procedure Test.0 ():
let Test.9 : {U8, U8} = CallByName Test.1;
let Test.3 : U8 = StructAtIndex 0 Test.9;
let Test.5 : {U8, U8} = CallByName Test.1;
let Test.4 : U8 = StructAtIndex 1 Test.5;
let Test.2 : List U8 = Array [Test.3, Test.4];
ret Test.2;

View file

@ -1,19 +0,0 @@
procedure Test.1 ():
let Test.11 : I64 = 2i64;
let Test.12 : U8 = 1i64;
let Test.10 : {I64, U8} = Struct {Test.11, Test.12};
ret Test.10;
procedure Test.1 ():
let Test.7 : I64 = 1i64;
let Test.8 : U8 = 2i64;
let Test.6 : {I64, U8} = Struct {Test.7, Test.8};
ret Test.6;
procedure Test.0 ():
let Test.9 : {I64, U8} = CallByName Test.1;
let Test.3 : U8 = StructAtIndex 1 Test.9;
let Test.5 : {I64, U8} = CallByName Test.1;
let Test.4 : U8 = StructAtIndex 1 Test.5;
let Test.2 : List U8 = Array [Test.3, Test.4];
ret Test.2;

View file

@ -385,7 +385,7 @@ fn when_on_two_values() {
#[mono_test]
fn dict() {
r#"
Dict.len Dict.empty
Dict.len (Dict.empty {})
"#
}
@ -1273,7 +1273,7 @@ fn aliased_polymorphic_closure() {
}
#[mono_test]
fn issue_2535_polymorphic_fields_referenced_in_list() {
fn issue_2535_let_weakened_fields_referenced_in_list() {
indoc!(
r#"
app "test" provides [nums] to "./platform"

View file

@ -4049,11 +4049,11 @@ fn flat_type_to_err_type(
ErrorType::RecursiveTagUnion(rec_error_type, sub_tags.union(err_tags), sub_ext, pol)
}
ErrorType::FlexVar(var) => {
ErrorType::FlexVar(var) | ErrorType::FlexAbleVar(var, _) => {
ErrorType::RecursiveTagUnion(rec_error_type, err_tags, TypeExt::FlexOpen(var), pol)
}
ErrorType::RigidVar(var) => {
ErrorType::RigidVar(var) | ErrorType::RigidAbleVar(var, _) => {
ErrorType::RecursiveTagUnion(rec_error_type, err_tags, TypeExt::RigidOpen(var), pol)
}