Skip to content

Commit e6bb414

Browse files
Merge pull request #9300 from dotty-staging/fix-#9295
Fix #9295: Avoid recursive Dynamics conversion
2 parents 480f95f + a00788d commit e6bb414

File tree

9 files changed

+106
-1
lines changed

9 files changed

+106
-1
lines changed

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

+11-1
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,19 @@ trait TypeAssigner {
140140
val name = tree.name
141141
val pre = maybeSkolemizePrefix(qualType, name)
142142
val mbr = qualType.findMember(name, pre)
143+
def isDynamicExpansion(tree: untpd.RefTree): Boolean = {
144+
Dynamic.isDynamicMethod(name) || (
145+
tree match
146+
case Select(Apply(fun: untpd.RefTree, _), nme.apply) if defn.isContextFunctionClass(fun.symbol.owner) =>
147+
isDynamicExpansion(fun)
148+
case Select(qual, nme.apply) =>
149+
Dynamic.isDynamicMethod(qual.symbol.name) && tree.span.isSynthetic
150+
case _ => false
151+
)
152+
}
143153
if (reallyExists(mbr))
144154
qualType.select(name, mbr)
145-
else if (qualType.derivesFrom(defn.DynamicClass) && name.isTermName && !Dynamic.isDynamicMethod(name))
155+
else if (qualType.derivesFrom(defn.DynamicClass) && name.isTermName && !isDynamicExpansion(tree))
146156
TryDynamicCallType
147157
else if (qualType.isErroneous || name.toTermName == nme.ERROR)
148158
UnspecifiedErrorType

tests/neg/i9295a.scala

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import scala.language.dynamics
2+
3+
class Foo extends Dynamic {
4+
def applyDynamic(arg: Any): Foo = ???
5+
}
6+
object F {
7+
val foo = new Foo
8+
def baz = foo.blah(43) // error: method applyDynamic in class Foo does not take more parameters
9+
}

tests/neg/i9295b.scala

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import scala.language.dynamics
2+
3+
class Foo extends Dynamic {
4+
def applyDynamic(arg: Any): Bar = ???
5+
}
6+
class Bar extends Dynamic {
7+
def applyDynamic(arg: Any)(x: Int): Int = ???
8+
}
9+
object F {
10+
val foo = new Foo
11+
def baz = foo.blah(43) // error: method applyDynamic in class Foo does not take more parameters
12+
def qux = foo.blah.blah(43) // error: value selectDynamic is not a member of Foo
13+
def quxx = foo.blah().blah(43) // error: method applyDynamic in class Foo does not take more parameters
14+
}

tests/neg/i9295c.scala

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import scala.language.dynamics
2+
3+
class Foo extends Dynamic {
4+
def selectDynamic(name: String)(using DummyImplicit): Bar = ???
5+
}
6+
7+
class Bar extends Dynamic {
8+
def applyDynamic(name: String)(x: Int) = ???
9+
}
10+
11+
val foo = new Foo
12+
def baz = foo.blah(42) // error

tests/neg/i9295d.scala

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import scala.language.dynamics
2+
3+
class Foo extends Dynamic {
4+
def applyDynamic(name: String)(): DummyImplicit ?=> Bar = ???
5+
}
6+
7+
class Bar extends Dynamic {
8+
def applyDynamic(name: String)(x: Int) = ???
9+
}
10+
11+
val foo = new Foo
12+
def baz = foo.blah()(42) // error

tests/pos/i9295.scala

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import scala.language.dynamics
2+
3+
class Foo extends Dynamic {
4+
def applyDynamic(name: String)(): Bar = ???
5+
}
6+
7+
class Bar extends Dynamic {
8+
def applyDynamic(name: String)(x: Int) = ???
9+
}
10+
11+
val foo = new Foo
12+
def baz = foo.blah().apply(42)

tests/pos/i9295b.scala

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import scala.language.dynamics
2+
3+
class Foo extends Dynamic {
4+
def applyDynamic(name: String)()(using DummyImplicit): Bar = ???
5+
}
6+
7+
class Bar extends Dynamic {
8+
def applyDynamic(name: String)(x: Int) = ???
9+
}
10+
11+
val foo = new Foo
12+
def baz = foo.blah().apply(42)

tests/pos/i9295c.scala

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import scala.language.dynamics
2+
3+
class Foo extends Dynamic {
4+
def selectDynamic(name: String)(using DummyImplicit): Bar = ???
5+
}
6+
7+
class Bar extends Dynamic {
8+
def applyDynamic(name: String)(x: Int) = ???
9+
}
10+
11+
val foo = new Foo
12+
def baz = foo.blah.apply(42)

tests/pos/i9295d.scala

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import scala.language.dynamics
2+
3+
class Foo extends Dynamic {
4+
def applyDynamic(name: String)(): DummyImplicit ?=> DummyImplicit ?=> Bar = ???
5+
}
6+
7+
class Bar extends Dynamic {
8+
def applyDynamic(name: String)(x: Int) = ???
9+
}
10+
11+
val foo = new Foo
12+
def baz = foo.blah().apply(42)

0 commit comments

Comments
 (0)