Skip to content

Commit

Permalink
Allow apply adaptation on Selectable with Fields (#20489)
Browse files Browse the repository at this point in the history
Just like when using a regular Selectable with refinements, this change
allows:

    fromFlds.xs(0)

to be expanded to:

    fromFlds.xs.apply(0)
  • Loading branch information
odersky authored May 30, 2024
2 parents 110600b + 2c4889e commit 3c9d985
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 2 deletions.
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -821,10 +821,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer

// Otherwise, if the qualifier derives from class Selectable,
// and the selector name matches one of the element of the `Fields` type member,
// and the selector is neither applied nor assigned to,
// and the selector is not assigned to,
// expand to a typed dynamic dispatch using selectDynamic wrapped in a cast
if qual.tpe.derivesFrom(defn.SelectableClass) && !isDynamicExpansion(tree)
&& !pt.isInstanceOf[FunOrPolyProto] && pt != LhsProto
&& pt != LhsProto
then
val pre = if !TypeOps.isLegalPrefix(qual.tpe) then SkolemType(qual.tpe) else qual.tpe
val fieldsType = pre.select(tpnme.Fields).dealias.simplified
Expand Down
29 changes: 29 additions & 0 deletions tests/neg/named-tuple-selectable.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import scala.language.experimental.namedTuples

class FromFields extends Selectable:
type Fields = (i: Int)
def selectDynamic(key: String) =
List(1, 2, 3)

trait FromRefs extends Selectable:
def selectDynamic(key: String) =
List(1, 2, 3)

def test(
fromFlds: FromFields,
fromRefs: FromRefs { val i: Int }
): Unit =
fromFlds.i(0) // error
fromRefs.i(0) // error

fromFlds.i.apply(0) // error
fromRefs.i.apply(0) // error

fromFlds.i[Int](List(1)) // error
fromRefs.i[Int](List(1)) // error

fromFlds.i(List(1)) // error
fromRefs.i(List(1)) // error

fromFlds.i.apply(List(1)) // error
fromRefs.i.apply(List(1)) // error
29 changes: 29 additions & 0 deletions tests/pos/named-tuple-selectable.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import scala.language.experimental.namedTuples

class FromFields extends Selectable:
type Fields = (xs: List[Int], poly: [T] => (x: List[T]) => Option[T])
def selectDynamic(key: String) =
List(1, 2, 3)

trait FromRefs extends Selectable:
def selectDynamic(key: String) =
List(1, 2, 3)

def test(
fromFlds: FromFields,
fromRefs: FromRefs { val xs: List[Int]; val poly: [T] => (x: List[T]) => Option[T] }
): Unit =
fromFlds.xs(0)
fromRefs.xs(0)

fromFlds.xs.apply(0)
fromRefs.xs.apply(0)

fromFlds.poly[Int](List(1)): Option[Int]
fromRefs.poly[Int](List(1)): Option[Int]

fromFlds.poly(List(1))
fromRefs.poly(List(1))

fromFlds.poly.apply(List(1))
fromRefs.poly.apply(List(1))

0 comments on commit 3c9d985

Please sign in to comment.