Skip to content

Commit aa832f8

Browse files
committed
Add existing tests and a new one inspired by recent issue
1 parent 10e182b commit aa832f8

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

tests/neg/appliedTerm.scala

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
object SimpleEqs {
2+
val x = 1
3+
val y: {x} = x
4+
implicitly[{x + 1} =:= {y}] // error
5+
implicitly[{x + 1} =:= {y + 2}] // error
6+
implicitly[{x + 1} =:= {1 + y}] // error: TypeComparer doesn't know about commutativity
7+
8+
val b = true
9+
implicitly[{b} =:= {b}]
10+
implicitly[{!b} =:= {!b}]
11+
implicitly[{!b} =:= {b}] // error
12+
}
13+
14+
15+
object Stability {
16+
def f1(x: Int): Int = x
17+
def f2(x: Int): {x} = x
18+
19+
val x = 1
20+
implicitly[{f1(x)} =:= {x}] // error: f1 is not considered stable // error: f1's result type is not precise enough
21+
implicitly[{f1(x)} =:= {f1(x)}] // error: f1 is not considered stable // error: f1 is not considered stable
22+
implicitly[{f2(x)} =:= {x}]
23+
implicitly[{f2(x)} =:= {f2(x)}]
24+
implicitly[{f1(x)} =:= {f2(x)}] // error: f1 is not considered stable // error: f1's result type is not precise enough
25+
}

tests/pos/appliedTerm.scala

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
object SimpleEqs {
2+
val x = 1
3+
val y: {x} = x
4+
5+
type YPlusOne = {y + 1}
6+
7+
implicitly[{x + 1} =:= {y + 1}]
8+
implicitly[{x + 1} =:= YPlusOne]
9+
}
10+
11+
12+
object AvoidLocalRefs {
13+
type Id[T] = T
14+
15+
val x = 1
16+
def y = { val a: {x} = x; val t: Id[{a + 1}] = a + 1; t }
17+
def z: {x + 1} = { val a: {x} = x; val t: Id[{a + 1}] = a + 1; t }
18+
19+
val _ = { val a = 0; a + 1 }
20+
val _ = { val a = 0; 1 + a }
21+
}
22+
23+
24+
object Bounds {
25+
@annotation.implicitNotFound(msg = "Cannot prove that ${B} holds.")
26+
sealed abstract class P[B <: Boolean](val b: B)
27+
private[this] val prop_singleton = new P[true](true) {}
28+
object P {
29+
def assume(b: Boolean): P[b.type] = prop_singleton.asInstanceOf[P[b.type]]
30+
}
31+
32+
def if_(cond: Boolean): (P[cond.type] ?=> Unit) => Unit =
33+
thn => if (cond) thn(using P.assume(cond))
34+
35+
36+
// Bounds-checked
37+
38+
def index(k: Int)(implicit ev: P[{k >= 0}]): Int = k
39+
40+
def run(i: Int) =
41+
if_(i >= 0) {
42+
index(i)
43+
}
44+
45+
46+
// Boxed value with a predicate
47+
48+
class PredBox[T, B <: Boolean](val v: T)(val p: P[B])
49+
object PredBox {
50+
def apply[T, B <: Boolean](v: T)(implicit ev: P[B]) = new PredBox[T, B](v)(ev)
51+
}
52+
53+
def run2(i: Int) =
54+
if_(i != 0) {
55+
PredBox[Int, {i != 0}](i)
56+
}
57+
}
58+
59+
60+
object ArithmeticIdentities {
61+
type SInt = Int & Singleton
62+
63+
class DecomposeHelper[V <: SInt](val v: V) {
64+
import DecomposeHelper._
65+
def asSumOf[X <: SInt, Y <: SInt](x: X, y: Y)(implicit ev: {v} =:= {x + y}): SumOf[{x}, {y}] = SumOf(x, y)(ev(v))
66+
}
67+
68+
object DecomposeHelper {
69+
/* Axioms */
70+
sealed trait Decomposition[V <: SInt]
71+
case class SumOf[X <: SInt, Y <: SInt](x: X, y: Y)(val v: {x + y}) extends Decomposition[{v}] {
72+
def commuted: SumOf[Y, X] = SumOf(y, x)(v.asInstanceOf[{y + x}])
73+
}
74+
}
75+
76+
implicit def toDecomposeHelper[V <: Int](v: V): DecomposeHelper[v.type] = new DecomposeHelper(v)
77+
78+
79+
// Let's "show" that x + 1 == 1 + x
80+
81+
val x = 123
82+
(x + 1).asSumOf(x, 1).v: {x + 1}
83+
(x + 1).asSumOf(x, 1).commuted.v: {1 + x}
84+
}
85+
86+
87+
object Matrices {
88+
type SInt = Int & Singleton
89+
90+
case class Matrix[M <: SInt, N <: SInt](m: M, n: N) {
91+
val size: {m * n} = m * n
92+
}
93+
94+
val a: 123 = 123
95+
val b: Int = ???
96+
val mat = Matrix(a, b)
97+
val _ = mat.m: 123
98+
val _ = mat.n: b.type
99+
val _ = mat.size: {123 * b}
100+
}

0 commit comments

Comments
 (0)