Skip to content

Commit 2e56dc4

Browse files
committed
Reject recursive dynamicSelect corner case
1 parent 164005a commit 2e56dc4

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
@@ -818,14 +818,20 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
818818
// and the selector is neither applied nor assigned to,
819819
// expand to a typed dynamic dispatch using selectDynamic wrapped in a cast
820820
if qual.tpe.derivesFrom(defn.SelectableClass) && !isDynamicExpansion(tree)
821-
&& !pt.isInstanceOf[FunOrPolyProto] && pt != LhsProto
821+
&& !pt.isInstanceOf[FunOrPolyProto] && pt != LhsProto
822822
then
823823
val fieldsType = qual.tpe.select(tpnme.Fields).dealias.simplified
824824
val fields = fieldsType.namedTupleElementTypes
825825
typr.println(i"try dyn select $qual, $selName, $fields")
826826
fields.find(_._1 == selName) match
827827
case Some((_, fieldType)) =>
828-
return dynamicSelect(fieldType).ensureConforms(fieldType)
828+
val dynSelected = dynamicSelect(fieldType)
829+
dynSelected match
830+
case Apply(sel: Select, _) if !sel.denot.symbol.exists =>
831+
// Reject corner case where selectDynamic needs annother selectDynamic to be called. E.g. as in neg/unselectable-fields.scala.
832+
report.error(i"Cannot use selectDynamic here since it it needs another selectDynamic to be invoked", tree.srcPos)
833+
case _ =>
834+
return dynSelected.ensureConforms(fieldType)
829835
case _ =>
830836

831837
// 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)