@@ -616,11 +616,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
616
616
val superAccess = qual.isInstanceOf [Super ]
617
617
val rawType = selectionType(tree, qual)
618
618
val checkedType = accessibleType(rawType, superAccess)
619
- if checkedType.exists then
619
+
620
+ def finish (tree : untpd.Select , qual : Tree , checkedType : Type ): Tree =
620
621
val select = toNotNullTermRef(assignType(tree, checkedType), pt)
621
622
if selName.isTypeName then checkStable(qual.tpe, qual.srcPos, " type prefix" )
622
623
checkLegalValue(select, pt)
623
624
ConstFold (select)
625
+
626
+ if checkedType.exists then
627
+ finish(tree, qual, checkedType)
624
628
else if selName == nme.apply && qual.tpe.widen.isInstanceOf [MethodType ] then
625
629
// Simplify `m.apply(...)` to `m(...)`
626
630
qual
@@ -632,6 +636,26 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
632
636
else
633
637
val tree1 = tryExtensionOrConversion(
634
638
tree, pt, IgnoredProto (pt), qual, ctx.typerState.ownedVars, this , inSelect = true )
639
+ .orElse {
640
+ if ctx.gadt.isNarrowing then
641
+ // try GADT approximation if we're trying to select a member
642
+ // Member lookup cannot take GADTs into account b/c of cache, so we
643
+ // approximate types based on GADT constraints instead. For an example,
644
+ // see MemberHealing in gadt-approximation-interaction.scala.
645
+ val wtp = qual.tpe.widen
646
+ gadts.println(i " Trying to heal member selection by GADT-approximating $wtp" )
647
+ val gadtApprox = Inferencing .approximateGADT(wtp)
648
+ gadts.println(i " GADT-approximated $wtp ~~ $gadtApprox" )
649
+ val qual1 = qual.cast(gadtApprox)
650
+ val tree1 = cpy.Select (tree0)(qual1, selName)
651
+ val checkedType1 = accessibleType(selectionType(tree1, qual1), superAccess = false )
652
+ if checkedType1.exists then
653
+ gadts.println(i " Member selection healed by GADT approximation " )
654
+ finish(tree1, qual1, checkedType1)
655
+ else
656
+ tryExtensionOrConversion(tree1, pt, IgnoredProto (pt), qual1, ctx.typerState.ownedVars, this , inSelect = true )
657
+ else EmptyTree
658
+ }
635
659
if ! tree1.isEmpty then
636
660
tree1
637
661
else if canDefineFurther(qual.tpe.widen) then
@@ -3969,19 +3993,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
3969
3993
3970
3994
pt match
3971
3995
case pt : SelectionProto =>
3972
- if ctx.gadt.isNarrowing then
3973
- // try GADT approximation if we're trying to select a member
3974
- // Member lookup cannot take GADTs into account b/c of cache, so we
3975
- // approximate types based on GADT constraints instead. For an example,
3976
- // see MemberHealing in gadt-approximation-interaction.scala.
3977
- gadts.println(i " Trying to heal member selection by GADT-approximating $wtp" )
3978
- val gadtApprox = Inferencing .approximateGADT(wtp)
3979
- gadts.println(i " GADT-approximated $wtp ~~ $gadtApprox" )
3980
- if pt.isMatchedBy(gadtApprox) then
3981
- gadts.println(i " Member selection healed by GADT approximation " )
3982
- tree.cast(gadtApprox)
3983
- else tree
3984
- else if tree.tpe.derivesFrom(defn.PairClass ) && ! defn.isTupleNType(tree.tpe.widenDealias) then
3996
+ if tree.tpe.derivesFrom(defn.PairClass ) && ! defn.isTupleNType(tree.tpe.widenDealias) then
3985
3997
// If this is a generic tuple we need to cast it to make the TupleN/ members accessible.
3986
3998
// This works only for generic tuples of known size up to 22.
3987
3999
defn.tupleTypes(tree.tpe.widenTermRefExpr) match
0 commit comments