|
3 | 3 |
|
4 | 4 | // * The MLscript subtyping system is currently ill-formed in some corner cases.
|
5 | 5 | // * Notably, it considers functions and classes to intersect to nothing
|
6 |
| -// * and also considers positive negated function/record types equivalent to nothing. |
| 6 | +// * and also used to considers positive negated function/record types equivalent to nothing. |
7 | 7 |
|
8 | 8 | // * (This isn't the case in MLstruct, which has a sound subtyping lattice.)
|
9 | 9 |
|
10 | 10 |
|
11 |
| -// * Example 1 |
| 11 | + |
| 12 | +// * Example 1 – now fixed |
| 13 | + |
12 | 14 | oops = 42 : ~(int -> int)
|
13 |
| -not oops |
14 |
| -//│ oops: nothing |
| 15 | +//│ oops: ~(int -> int) |
15 | 16 | //│ = 42
|
16 |
| -//│ res: bool |
| 17 | + |
| 18 | +:e |
| 19 | +not oops |
| 20 | +//│ ╔══[ERROR] Type mismatch in application: |
| 21 | +//│ ║ l.19: not oops |
| 22 | +//│ ║ ^^^^^^^^ |
| 23 | +//│ ╟── type `~(int -> int)` is not an instance of type `bool` |
| 24 | +//│ ║ l.14: oops = 42 : ~(int -> int) |
| 25 | +//│ ║ ^^^^^^^^^^^^^ |
| 26 | +//│ ╟── but it flows into reference with expected type `bool` |
| 27 | +//│ ║ l.19: not oops |
| 28 | +//│ ╙── ^^^^ |
| 29 | +//│ res: bool | error |
17 | 30 | //│ = false
|
18 | 31 |
|
19 | 32 |
|
20 |
| -// * OTOH, this doesn't lead to immediate unsoundness: |
| 33 | +// * This was accepted but didn't immediately lead to immediate unsoundness: |
21 | 34 | def f: (~{x: int}) -> 'a
|
22 |
| -f = id |
23 |
| -//│ f: in nothing -> nothing out ~{x: int} -> nothing |
| 35 | +//│ f: ~{x: int} -> nothing |
24 | 36 | //│ = <missing implementation>
|
| 37 | + |
| 38 | +:e |
| 39 | +f = id |
25 | 40 | //│ 'a -> 'a
|
26 | 41 | //│ <: f:
|
27 |
| -//│ nothing -> nothing |
| 42 | +//│ ~{x: int} -> nothing |
| 43 | +//│ ╔══[ERROR] Type mismatch in def definition: |
| 44 | +//│ ║ l.39: f = id |
| 45 | +//│ ║ ^^^^^^ |
| 46 | +//│ ╟── type `~{x: int}` does not match type `'a` |
| 47 | +//│ ║ l.34: def f: (~{x: int}) -> 'a |
| 48 | +//│ ║ ^^^^^^^^^^^ |
| 49 | +//│ ╟── Note: constraint arises from type variable: |
| 50 | +//│ ║ l.34: def f: (~{x: int}) -> 'a |
| 51 | +//│ ╙── ^^ |
28 | 52 | //│ = [Function: id]
|
29 | 53 |
|
30 | 54 | :e
|
|
33 | 57 | f {}
|
34 | 58 | f (forall 'a. fun (x: 'a) -> x)
|
35 | 59 | //│ ╔══[ERROR] Type mismatch in application:
|
36 |
| -//│ ║ l.31: f 0 |
| 60 | +//│ ║ l.55: f 0 |
37 | 61 | //│ ║ ^^^
|
38 | 62 | //│ ╟── integer literal of type `0` does not match type `~{x: int}`
|
39 |
| -//│ ║ l.31: f 0 |
| 63 | +//│ ║ l.55: f 0 |
40 | 64 | //│ ║ ^
|
41 | 65 | //│ ╟── Note: constraint arises from type negation:
|
42 |
| -//│ ║ l.21: def f: (~{x: int}) -> 'a |
| 66 | +//│ ║ l.34: def f: (~{x: int}) -> 'a |
43 | 67 | //│ ╙── ^^^^^^^^^^^
|
44 | 68 | //│ res: error
|
45 | 69 | //│ = 0
|
46 | 70 | //│ ╔══[ERROR] Type mismatch in application:
|
47 |
| -//│ ║ l.32: f id |
| 71 | +//│ ║ l.56: f id |
48 | 72 | //│ ║ ^^^^
|
49 | 73 | //│ ╟── reference of type `?a -> ?a` does not match type `~{x: int}`
|
50 |
| -//│ ║ l.32: f id |
| 74 | +//│ ║ l.56: f id |
51 | 75 | //│ ║ ^^
|
52 | 76 | //│ ╟── Note: constraint arises from type negation:
|
53 |
| -//│ ║ l.21: def f: (~{x: int}) -> 'a |
| 77 | +//│ ║ l.34: def f: (~{x: int}) -> 'a |
54 | 78 | //│ ╙── ^^^^^^^^^^^
|
55 | 79 | //│ res: error
|
56 | 80 | //│ = [Function: id]
|
57 | 81 | //│ ╔══[ERROR] Type mismatch in application:
|
58 |
| -//│ ║ l.33: f {} |
| 82 | +//│ ║ l.57: f {} |
59 | 83 | //│ ║ ^^^^
|
60 | 84 | //│ ╟── record literal of type `anything` does not match type `~{x: int}`
|
61 |
| -//│ ║ l.33: f {} |
| 85 | +//│ ║ l.57: f {} |
62 | 86 | //│ ║ ^^
|
63 | 87 | //│ ╟── Note: constraint arises from type negation:
|
64 |
| -//│ ║ l.21: def f: (~{x: int}) -> 'a |
| 88 | +//│ ║ l.34: def f: (~{x: int}) -> 'a |
65 | 89 | //│ ╙── ^^^^^^^^^^^
|
66 | 90 | //│ res: error
|
67 | 91 | //│ = {}
|
68 | 92 | //│ ╔══[ERROR] Type mismatch in application:
|
69 |
| -//│ ║ l.34: f (forall 'a. fun (x: 'a) -> x) |
| 93 | +//│ ║ l.58: f (forall 'a. fun (x: 'a) -> x) |
70 | 94 | //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
71 | 95 | //│ ╟── function of type `'a -> 'a` does not match type `~{x: int}`
|
72 |
| -//│ ║ l.34: f (forall 'a. fun (x: 'a) -> x) |
| 96 | +//│ ║ l.58: f (forall 'a. fun (x: 'a) -> x) |
73 | 97 | //│ ║ ^^^^^^^^^^^^^^^^
|
74 | 98 | //│ ╟── Note: constraint arises from type negation:
|
75 |
| -//│ ║ l.21: def f: (~{x: int}) -> 'a |
| 99 | +//│ ║ l.34: def f: (~{x: int}) -> 'a |
76 | 100 | //│ ╙── ^^^^^^^^^^^
|
77 | 101 | //│ res: error
|
78 | 102 | //│ = [Function (anonymous)]
|
79 | 103 |
|
80 | 104 |
|
81 |
| -// * Example 2 |
| 105 | +// * Example 2 – now fixed |
82 | 106 |
|
83 | 107 | def g(x: 'a | {f: nothing}) = x.f(0)
|
84 | 108 | //│ g: {f: 0 -> 'a} -> 'a
|
85 | 109 | //│ = [Function: g]
|
86 | 110 |
|
| 111 | +:e |
87 | 112 | foo = forall 'x. fun (x: 'x) -> g(x)
|
88 |
| -//│ foo: anything -> nothing |
| 113 | +//│ ╔══[ERROR] Type mismatch in application: |
| 114 | +//│ ║ l.112: foo = forall 'x. fun (x: 'x) -> g(x) |
| 115 | +//│ ║ ^^^^ |
| 116 | +//│ ╟── expression of type `'x & ~{f: nothing}` does not have field 'f' |
| 117 | +//│ ╟── Note: constraint arises from field selection: |
| 118 | +//│ ║ l.107: def g(x: 'a | {f: nothing}) = x.f(0) |
| 119 | +//│ ║ ^^^ |
| 120 | +//│ ╟── from type variable: |
| 121 | +//│ ║ l.107: def g(x: 'a | {f: nothing}) = x.f(0) |
| 122 | +//│ ╙── ^^ |
| 123 | +//│ foo: anything -> error |
89 | 124 | //│ = [Function: foo]
|
90 | 125 |
|
91 | 126 | :re
|
92 | 127 | foo 0
|
93 |
| -//│ res: nothing |
| 128 | +//│ res: error |
94 | 129 | //│ Runtime error:
|
95 | 130 | //│ TypeError: x.f is not a function
|
96 | 131 |
|
@@ -135,11 +170,11 @@ b = a
|
135 | 170 | //│ <: b:
|
136 | 171 | //│ Foo & {x: int}
|
137 | 172 | //│ ╔══[ERROR] Type mismatch in def definition:
|
138 |
| -//│ ║ l.133: b = a |
| 173 | +//│ ║ l.168: b = a |
139 | 174 | //│ ║ ^^^^^
|
140 | 175 | //│ ╟── expression of type `anything` is not an instance of type `int`
|
141 | 176 | //│ ╟── Note: constraint arises from type reference:
|
142 |
| -//│ ║ l.109: def b: int -> int & Foo | {x: int} & Foo |
| 177 | +//│ ║ l.144: def b: int -> int & Foo | {x: int} & Foo |
143 | 178 | //│ ╙── ^^^
|
144 | 179 |
|
145 | 180 |
|
|
0 commit comments