Skip to content

Commit 4ce85a9

Browse files
committed
Add test cases for implicit and dependant methods
Rejects all dependant methods used in structural type. They are pretty broken currently. Should be fixable
1 parent a22cd91 commit 4ce85a9

File tree

4 files changed

+113
-28
lines changed

4 files changed

+113
-28
lines changed

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
737737
case _ => This(ctx.owner.enclosingClass.asClass)
738738
}
739739

740-
/** Is this an application of a selection of a member of a structural type
740+
/** Is this a (potentially applied) selection of a member of a structural type
741741
* that is not a member of an underlying class or trait?
742742
*/
743743
def isStructuralTermSelectOrApply(tree: Tree)(implicit ctx: Context): Boolean = {

compiler/src/dotty/tools/dotc/typer/Dynamic.scala

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,20 @@ trait Dynamic { self: Typer with Applications =>
162162
structuralCall(nme.selectDynamic, Nil).asInstance(tpe)
163163

164164
case tpe: MethodType =>
165-
if (tpe.isParamDependent)
165+
def isDependentMethod(tpe: Type): Boolean = tpe match {
166+
case tpe: MethodType =>
167+
tpe.isParamDependent ||
168+
tpe.isResultDependent ||
169+
isDependentMethod(tpe.resultType)
170+
case _ =>
171+
false
172+
}
173+
174+
if (isDependentMethod(tpe))
166175
fail(name, i"has a method type with inter-parameter dependencies")
167176
else {
168177
val ctags = tpe.paramInfoss.flatten.map(pt =>
169-
implicitArgTree(defn.ClassTagType.appliedTo(pt :: Nil), fun.pos.endPos))
178+
implicitArgTree(defn.ClassTagType.appliedTo(pt.widenDealias :: Nil), fun.pos.endPos))
170179
structuralCall(nme.applyDynamic, ctags).asInstance(tpe.finalResultType)
171180
}
172181

tests/neg/structural.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,20 @@ object Test3 {
2020

2121
type G = { def foo(x: Int, y: Int): Unit }
2222
def j(x: G) = x.foo(???) // error: missing argument
23+
24+
class H { type S = String; type I }
25+
class I extends H { type I = Int }
26+
type Dep = {
27+
def fun1(x: H, y: x.S): Int
28+
def fun2(x: H, y: x.I): Int
29+
def fun3(y: H): y.S
30+
def fun4(y: H): y.I
31+
}
32+
def k(x: Dep) = {
33+
val y = new I
34+
x.fun1(y, "Hello")
35+
x.fun2(y, 1) // error
36+
x.fun3(y)
37+
x.fun4(y) // error
38+
}
2339
}

tests/run/structural.scala

Lines changed: 85 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,106 @@
11
import scala.reflect.Selectable.reflectiveSelectable
22

33
object Test {
4+
class C { type S = String; type I }
5+
class D extends C { type I = Int }
6+
47
type Foo = {
5-
def foo(x: Int)(y: Int): Int
6-
def bar(x: Int): Int => Int
7-
def bat(a1: Int, a2: Int, a3: Int)
8-
(a4: Int, a5: Int, a6: Int)
9-
(a7: Int, a8: Int, a9: Int): Int
10-
def baz(x: Int): Int
8+
def sel0: Int
9+
def sel1: Int => Int
10+
def fun0(x: Int): Int
11+
12+
def fun1(x: Int)(y: Int): Int
13+
def fun2(x: Int): Int => Int
14+
def fun3(a1: Int, a2: Int, a3: Int)
15+
(a4: Int, a5: Int, a6: Int)
16+
(a7: Int, a8: Int, a9: Int): Int
17+
18+
def fun4(implicit x: Int): Int
19+
def fun5(x: Int)(implicit y: Int): Int
20+
21+
def fun6(x: C, y: x.S): Int
22+
def fun7(x: C, y: x.I): Int
23+
def fun8(y: C): y.S
24+
def fun9(y: C): y.I
1125
}
1226

1327
class FooI {
14-
def foo(x: Int)(y: Int): Int = x + y
15-
def bar(x: Int): Int => Int = y => x * y
16-
def bat(a1: Int, a2: Int, a3: Int)
17-
(a4: Int, a5: Int, a6: Int)
18-
(a7: Int, a8: Int, a9: Int): Int = -1
19-
def baz(x: Int): Int = x
28+
def sel0: Int = 1
29+
def sel1: Int => Int = x => x
30+
def fun0(x: Int): Int = x
31+
32+
def fun1(x: Int)(y: Int): Int = x + y
33+
def fun2(x: Int): Int => Int = y => x * y
34+
def fun3(a1: Int, a2: Int, a3: Int)
35+
(a4: Int, a5: Int, a6: Int)
36+
(a7: Int, a8: Int, a9: Int): Int = -1
37+
38+
def fun4(implicit x: Int): Int = x
39+
def fun5(x: Int)(implicit y: Int): Int = x + y
40+
41+
def fun6(x: C, y: x.S): Int = 1
42+
def fun7(x: C, y: x.I): Int = 2
43+
def fun8(y: C): y.S = "Hello"
44+
def fun9(y: C): y.I = 1.asInstanceOf[y.I]
45+
}
46+
47+
def basic(x: Foo): Unit ={
48+
assert(x.sel0 == 1)
49+
assert(x.sel1(2) == 2)
50+
assert(x.fun0(3) == 3)
51+
52+
val f = x.sel1
53+
assert(f(3) == 3)
54+
}
55+
56+
def currying(x: Foo): Unit = {
57+
assert(x.fun1(1)(2) == 3)
58+
assert(x.fun2(1)(2) == 2)
59+
assert(x.fun3(1, 2, 3)(4, 5, 6)(7, 8, 9) == -1)
2060
}
2161

22-
def test(x: Foo): Unit = {
23-
assert(x.foo(1)(2) == 3)
24-
assert(x.bar(1)(2) == 2)
25-
assert(x.bat(1, 2, 3)(4, 5, 6)(7, 8, 9) == -1)
62+
def etaExpansion(x: Foo): Unit = {
63+
val f0 = x.fun0(_)
64+
assert(f0(2) == 2)
2665

27-
val f1 = x.foo(1)(_)
28-
assert(f1(2) == 3)
66+
val f1 = x.fun0 _
67+
assert(f1(2) == 2)
2968

30-
val f2 = x.foo(1) _
69+
val f2 = x.fun1(1)(_)
3170
assert(f2(2) == 3)
3271

33-
val f3 = x.foo(1)
72+
val f3 = x.fun1(1) _
3473
assert(f3(2) == 3)
3574

36-
val f4 = x.baz
37-
assert(f4(1) == 1)
75+
val f4 = x.fun1(1)
76+
assert(f4(2) == 3)
77+
}
78+
79+
def implicits(x: Foo) = {
80+
implicit val y = 2
81+
assert(x.fun4 == 2)
82+
assert(x.fun5(1) == 3)
83+
}
84+
85+
// Limited support for dependant methods
86+
def dependant(x: Foo) = {
87+
val y = new D
88+
89+
assert(x.fun6(y, "Hello") == 1)
90+
// assert(x.fun7(y, 1) == 2) // error: No ClassTag available for x.I
91+
92+
val s = x.fun8(y)
93+
assert((s: String) == "Hello")
3894

39-
val f5 = x.baz _
40-
assert(f5(2) == 2)
95+
// val i = x.fun9(y) // error: rejected (blows up in pickler if not rejected)
96+
// assert((i: String) == "Hello") // error: Type mismatch: found: y.S(i); required: String
4197
}
4298

4399
def main(args: Array[String]): Unit = {
44-
test(new FooI)
100+
basic(new FooI)
101+
currying(new FooI)
102+
etaExpansion(new FooI)
103+
implicits(new FooI)
104+
dependant(new FooI)
45105
}
46106
}

0 commit comments

Comments
 (0)