@@ -616,11 +616,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
616616 val superAccess = qual.isInstanceOf [Super ]
617617 val rawType = selectionType(tree, qual)
618618 val checkedType = accessibleType(rawType, superAccess)
619- if checkedType.exists then
619+
620+ def finish (tree : untpd.Select , qual : Tree , checkedType : Type ): Tree =
620621 val select = toNotNullTermRef(assignType(tree, checkedType), pt)
621622 if selName.isTypeName then checkStable(qual.tpe, qual.srcPos, " type prefix" )
622623 checkLegalValue(select, pt)
623624 ConstFold (select)
625+
626+ if checkedType.exists then
627+ finish(tree, qual, checkedType)
624628 else if selName == nme.apply && qual.tpe.widen.isInstanceOf [MethodType ] then
625629 // Simplify `m.apply(...)` to `m(...)`
626630 qual
@@ -632,6 +636,26 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
632636 else
633637 val tree1 = tryExtensionOrConversion(
634638 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+ }
635659 if ! tree1.isEmpty then
636660 tree1
637661 else if canDefineFurther(qual.tpe.widen) then
@@ -3969,19 +3993,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
39693993
39703994 pt match
39713995 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
39853997 // If this is a generic tuple we need to cast it to make the TupleN/ members accessible.
39863998 // This works only for generic tuples of known size up to 22.
39873999 defn.tupleTypes(tree.tpe.widenTermRefExpr) match
0 commit comments