@@ -697,12 +697,16 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
697
697
ConstFold (select)
698
698
else EmptyTree
699
699
700
+ // Otherwise, simplify `m.apply(...)` to `m(...)`
700
701
def trySimplifyApply () =
701
702
if selName == nme.apply && qual.tpe.widen.isInstanceOf [MethodType ] then
702
- // Simplify `m.apply(...)` to `m(...)`
703
703
qual
704
704
else EmptyTree
705
705
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.
706
710
def tryInstantiateTypeVar () =
707
711
if couldInstantiateTypeVar(qual.tpe.widen) then
708
712
// 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
711
715
typedSelectWithAdapt(tree, pt, qual)
712
716
else EmptyTree
713
717
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
714
732
def trySmallGenericTuple (qual : Tree , withCast : Boolean ) =
715
733
if qual.tpe.isSmallGenericTuple then
716
734
if withCast then
@@ -720,14 +738,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
720
738
typedSelectWithAdapt(tree, pt, qual)
721
739
else EmptyTree
722
740
741
+ // Otherwise try an extension or conversion
723
742
def tryExt (tree : untpd.Select , qual : Tree ) =
724
743
tryExtensionOrConversion(
725
744
tree, pt, IgnoredProto (pt), qual, ctx.typerState.ownedVars, this , inSelect = true
726
745
)
727
746
747
+ // Otherwise, try a GADT approximation if we're trying to select a member
728
748
def tryGadt () =
729
749
if ctx.gadt.isNarrowing then
730
- // try GADT approximation if we're trying to select a member
731
750
// Member lookup cannot take GADTs into account b/c of cache, so we
732
751
// approximate types based on GADT constraints instead. For an example,
733
752
// see MemberHealing in gadt-approximation-interaction.scala.
@@ -742,6 +761,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
742
761
.orElse(tryExt(tree1, qual1))
743
762
else EmptyTree
744
763
764
+ // Otherwise, if there are uninstantiated type variables in the qualifier type,
765
+ // instantiate them and try again
745
766
def tryDefineFurther () =
746
767
if canDefineFurther(qual.tpe.widen) then
747
768
typedSelectWithAdapt(tree, pt, qual)
@@ -754,6 +775,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
754
775
else
755
776
typedDynamicSelect(tree2, Nil , pt)
756
777
778
+ // Otherwise, if the qualifier derives from class Dynamic, expand to a
779
+ // dynamic dispatch using selectDynamic or applyDynamic
757
780
def tryDynamic () =
758
781
if qual.tpe.derivesFrom(defn.DynamicClass ) && selName.isTermName && ! isDynamicExpansion(tree) then
759
782
dynamicSelect(pt)
@@ -770,6 +793,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
770
793
tryType(tree, qual, rawType)
771
794
.orElse(trySimplifyApply())
772
795
.orElse(tryInstantiateTypeVar())
796
+ .orElse(tryLiftToThis())
773
797
.orElse(trySmallGenericTuple(qual, withCast = true ))
774
798
.orElse(tryExt(tree, qual))
775
799
.orElse(tryGadt())
0 commit comments