Skip to content

Commit 1613ee1

Browse files
committed
Reject recursive dynamicSelect corner case
1 parent 92d22c9 commit 1613ee1

File tree

3 files changed

+15
-2
lines changed

3 files changed

+15
-2
lines changed

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -822,14 +822,20 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
822822
// and the selector is neither applied nor assigned to,
823823
// expand to a typed dynamic dispatch using selectDynamic wrapped in a cast
824824
if qual.tpe.derivesFrom(defn.SelectableClass) && !isDynamicExpansion(tree)
825-
&& !pt.isInstanceOf[FunOrPolyProto] && pt != LhsProto
825+
&& !pt.isInstanceOf[FunOrPolyProto] && pt != LhsProto
826826
then
827827
val fieldsType = qual.tpe.select(tpnme.Fields).dealias.simplified
828828
val fields = fieldsType.namedTupleElementTypes
829829
typr.println(i"try dyn select $qual, $selName, $fields")
830830
fields.find(_._1 == selName) match
831831
case Some((_, fieldType)) =>
832-
return dynamicSelect(fieldType).ensureConforms(fieldType)
832+
val dynSelected = dynamicSelect(fieldType)
833+
dynSelected match
834+
case Apply(sel: Select, _) if !sel.denot.symbol.exists =>
835+
// Reject corner case where selectDynamic needs annother selectDynamic to be called. E.g. as in neg/unselectable-fields.scala.
836+
report.error(i"Cannot use selectDynamic here since it it needs another selectDynamic to be invoked", tree.srcPos)
837+
case _ =>
838+
return dynSelected.ensureConforms(fieldType)
833839
case _ =>
834840

835841
// Otherwise, report an error

tests/neg/unselectable-fields.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- Error: tests/neg/unselectable-fields.scala:4:13 ---------------------------------------------------------------------
2+
4 |val _ = foo1.xyz // error
3+
| ^^^^^^^^
4+
| Cannot use selectDynamic here since it it needs another selectDynamic to be invoked
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
val foo1 = new Selectable:
22
type Fields = (xyz: Int)
33
def selectDynamic(name: String): Any = 23
4+
val _ = foo1.xyz // error
5+
6+

0 commit comments

Comments
 (0)