@@ -697,12 +697,16 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
697697 ConstFold (select)
698698 else EmptyTree
699699
700+ // Otherwise, simplify `m.apply(...)` to `m(...)`
700701 def trySimplifyApply () =
701702 if selName == nme.apply && qual.tpe.widen.isInstanceOf [MethodType ] then
702- // Simplify `m.apply(...)` to `m(...)`
703703 qual
704704 else EmptyTree
705705
706+ // Otherwise, if there's a simply visible type variable in the result, try again
707+ // with a more defined qualifier type. There's a second trial where we try to instantiate
708+ // all type variables in `qual.tpe.widen`, but that is done only after we search for
709+ // extension methods or conversions.
706710 def tryInstantiateTypeVar () =
707711 if couldInstantiateTypeVar(qual.tpe.widen) then
708712 // there's a simply visible type variable in the result; try again with a more defined qualifier type
@@ -711,6 +715,20 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
711715 typedSelectWithAdapt(tree, pt, qual)
712716 else EmptyTree
713717
718+ // Otherwise, heal member selection on an opaque reference,
719+ // reusing the logic in TypeComparer.
720+ def tryLiftToThis () =
721+ val wtp = qual.tpe.widen
722+ val liftedTp = comparing(_.liftToThis(wtp))
723+ if liftedTp ne wtp then
724+ val qual1 = qual.cast(liftedTp)
725+ val tree1 = cpy.Select (tree0)(qual1, selName)
726+ val rawType1 = selectionType(tree1, qual1)
727+ tryType(tree1, qual1, rawType1)
728+ else EmptyTree
729+
730+ // Otherwise, map combinations of A *: B *: .... EmptyTuple with nesting levels <= 22
731+ // to the Tuple class of the right arity and select from that one
714732 def trySmallGenericTuple (qual : Tree , withCast : Boolean ) =
715733 if qual.tpe.isSmallGenericTuple then
716734 if withCast then
@@ -720,14 +738,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
720738 typedSelectWithAdapt(tree, pt, qual)
721739 else EmptyTree
722740
741+ // Otherwise try an extension or conversion
723742 def tryExt (tree : untpd.Select , qual : Tree ) =
724743 tryExtensionOrConversion(
725744 tree, pt, IgnoredProto (pt), qual, ctx.typerState.ownedVars, this , inSelect = true
726745 )
727746
747+ // Otherwise, try a GADT approximation if we're trying to select a member
728748 def tryGadt () =
729749 if ctx.gadt.isNarrowing then
730- // try GADT approximation if we're trying to select a member
731750 // Member lookup cannot take GADTs into account b/c of cache, so we
732751 // approximate types based on GADT constraints instead. For an example,
733752 // see MemberHealing in gadt-approximation-interaction.scala.
@@ -742,6 +761,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
742761 .orElse(tryExt(tree1, qual1))
743762 else EmptyTree
744763
764+ // Otherwise, if there are uninstantiated type variables in the qualifier type,
765+ // instantiate them and try again
745766 def tryDefineFurther () =
746767 if canDefineFurther(qual.tpe.widen) then
747768 typedSelectWithAdapt(tree, pt, qual)
@@ -754,6 +775,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
754775 else
755776 typedDynamicSelect(tree2, Nil , pt)
756777
778+ // Otherwise, if the qualifier derives from class Dynamic, expand to a
779+ // dynamic dispatch using selectDynamic or applyDynamic
757780 def tryDynamic () =
758781 if qual.tpe.derivesFrom(defn.DynamicClass ) && selName.isTermName && ! isDynamicExpansion(tree) then
759782 dynamicSelect(pt)
@@ -770,6 +793,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
770793 tryType(tree, qual, rawType)
771794 .orElse(trySimplifyApply())
772795 .orElse(tryInstantiateTypeVar())
796+ .orElse(tryLiftToThis())
773797 .orElse(trySmallGenericTuple(qual, withCast = true ))
774798 .orElse(tryExt(tree, qual))
775799 .orElse(tryGadt())
0 commit comments