Skip to content

Commit 4923fb8

Browse files
committed
Add interesting extrusion test
1 parent f6be56b commit 4923fb8

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

shared/src/main/scala/mlscript/NuTypeDefs.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer =>
10731073
private lazy val isGeneralized: Bool = decl match {
10741074
case fd: NuFunDef =>
10751075
println(s"Type ${fd.nme.name} polymorphically? ${fd.isGeneralized} && (${ctx.lvl} === 0 || ${
1076-
fd.signature.nonEmpty} || ${fd.outer.exists(_.kind isnt Mxn)}")
1076+
fd.signature.nonEmpty} || ${fd.outer.exists(_.kind isnt Mxn)})")
10771077
// * We only type polymorphically:
10781078
// * definitions that can be generalized (ie `fun`s or function-valued `let`s and `val`s); and
10791079
fd.isGeneralized && (
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
:NewDefs
2+
3+
:DontDistributeForalls
4+
5+
6+
// * This test reproduces a situation where ?A <: ?B <: ?A and we extrude both ?A and ?B to a lower level.
7+
// * The goal was to check how the resulting approximants were related.
8+
// * It turns out that in the current implementation,
9+
// * since we (arbitrarily) only register upper bounds in this case (i.e., ?B ∈ UB(?A) and ?A ∈ UB(?B))
10+
// * then the lower approximants end up being subtypes of each other,
11+
// * which happens when they are extruded negatively and their corresponding bounds are copied,
12+
// * but the upper approximants remain unrelated.
13+
// * This is sound, but the extra lower approximants bounds are not necessary,
14+
// * and indeed the SuperF constraining specification will not add them.
15+
16+
17+
class Invar[X, Y] { fun x: X -> X = id; fun y: Y -> Y = id }
18+
//│ class Invar[X, Y] {
19+
//│ constructor()
20+
//│ fun x: X -> X
21+
//│ fun y: Y -> Y
22+
//│ }
23+
24+
fun bar[A, B]: () -> [A -> A, (B -> B) -> Invar[A, B]] = () => [id, _ => new Invar]
25+
//│ fun bar: forall 'A 'B. () -> ['A -> 'A, ('B -> 'B) -> Invar['A, 'B]]
26+
27+
// :d
28+
:ns
29+
fun foo(x) =
30+
let inner() =
31+
let tmp = bar()
32+
let r = tmp.1(tmp.0)
33+
x(r)
34+
r
35+
//│ fun foo: forall 'a 'b 'A 'B 'A0 'B0 'c. 'a -> ()
36+
//│ where
37+
//│ 'a <: 'b -> 'c
38+
//│ 'c <: ()
39+
//│ 'b :> Invar[in 'A out 'A0, in 'B out 'B0]
40+
//│ 'B0 :> 'B
41+
//│ 'A0 :> 'A
42+
//│ 'A <: 'B
43+
//│ 'B <: 'A
44+
45+
// * Above, 'A and 'B are the lower approximants and 'A0 and 'B0 are the upper approximants.
46+
47+

0 commit comments

Comments
 (0)