@@ -688,72 +688,92 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
688
688
val tree = cpy.Select (tree0)(qual, selName)
689
689
val superAccess = qual.isInstanceOf [Super ]
690
690
val rawType = selectionType(tree, qual)
691
- val checkedType = accessibleType(rawType, superAccess)
692
-
693
- def finish (tree : untpd.Select , qual : Tree , checkedType : Type ): Tree =
694
- val select = toNotNullTermRef(assignType(tree, checkedType), pt)
695
- if selName.isTypeName then checkStable(qual.tpe, qual.srcPos, " type prefix" )
696
- checkLegalValue(select, pt)
697
- ConstFold (select)
698
-
699
- if checkedType.exists then
700
- finish(tree, qual, checkedType)
701
- else if selName == nme.apply && qual.tpe.widen.isInstanceOf [MethodType ] then
702
- // Simplify `m.apply(...)` to `m(...)`
703
- qual
704
- else if couldInstantiateTypeVar(qual.tpe.widen) then
705
- // there's a simply visible type variable in the result; try again with a more defined qualifier type
706
- // There's a second trial where we try to instantiate all type variables in `qual.tpe.widen`,
707
- // but that is done only after we search for extension methods or conversions.
708
- typedSelect(tree, pt, qual)
709
- else if qual.tpe.isSmallGenericTuple then
710
- val elems = qual.tpe.widenTermRefExpr.tupleElementTypes.getOrElse(Nil )
711
- typedSelect(tree, pt, qual.cast(defn.tupleType(elems)))
712
- else
713
- val tree1 = tryExtensionOrConversion(
714
- tree, pt, IgnoredProto (pt), qual, ctx.typerState.ownedVars, this , inSelect = true )
715
- .orElse {
716
- if ctx.gadt.isNarrowing then
717
- // try GADT approximation if we're trying to select a member
718
- // Member lookup cannot take GADTs into account b/c of cache, so we
719
- // approximate types based on GADT constraints instead. For an example,
720
- // see MemberHealing in gadt-approximation-interaction.scala.
721
- val wtp = qual.tpe.widen
722
- gadts.println(i " Trying to heal member selection by GADT-approximating $wtp" )
723
- val gadtApprox = Inferencing .approximateGADT(wtp)
724
- gadts.println(i " GADT-approximated $wtp ~~ $gadtApprox" )
725
- val qual1 = qual.cast(gadtApprox)
726
- val tree1 = cpy.Select (tree0)(qual1, selName)
727
- val checkedType1 = accessibleType(selectionType(tree1, qual1), superAccess = false )
728
- if checkedType1.exists then
729
- gadts.println(i " Member selection healed by GADT approximation " )
730
- finish(tree1, qual1, checkedType1)
731
- else if qual1.tpe.isSmallGenericTuple then
732
- gadts.println(i " Tuple member selection healed by GADT approximation " )
733
- typedSelect(tree, pt, qual1)
734
- else
735
- tryExtensionOrConversion(tree1, pt, IgnoredProto (pt), qual1, ctx.typerState.ownedVars, this , inSelect = true )
736
- else EmptyTree
737
- }
738
- if ! tree1.isEmpty then
739
- tree1
740
- else if canDefineFurther(qual.tpe.widen) then
741
- typedSelect(tree, pt, qual)
742
- else if qual.tpe.derivesFrom(defn.DynamicClass )
743
- && selName.isTermName && ! isDynamicExpansion(tree)
744
- then
745
- val tree2 = cpy.Select (tree0)(untpd.TypedSplice (qual), selName)
746
- if pt.isInstanceOf [FunOrPolyProto ] || pt == LhsProto then
747
- assignType(tree2, TryDynamicCallType )
691
+
692
+ def tryType (tree : untpd.Select , qual : Tree , rawType : Type ) =
693
+ val checkedType = accessibleType(rawType, superAccess)
694
+ if checkedType.exists then
695
+ val select = toNotNullTermRef(assignType(tree, checkedType), pt)
696
+ if selName.isTypeName then checkStable(qual.tpe, qual.srcPos, " type prefix" )
697
+ checkLegalValue(select, pt)
698
+ ConstFold (select)
699
+ else EmptyTree
700
+
701
+ def trySmallGenericTuple (tree : untpd.Select , qual : Tree , withCast : Boolean ) =
702
+ if qual.tpe.isSmallGenericTuple then
703
+ if withCast then
704
+ val elems = qual.tpe.widenTermRefExpr.tupleElementTypes.getOrElse(Nil )
705
+ typedSelect(tree, pt, qual.cast(defn.tupleType(elems)))
748
706
else
749
- typedDynamicSelect(tree2, Nil , pt)
750
- else
751
- assignType(tree,
752
- rawType match
753
- case rawType : NamedType =>
754
- inaccessibleErrorType(rawType, superAccess, tree.srcPos)
755
- case _ =>
756
- notAMemberErrorType(tree, qual, pt))
707
+ typedSelect(tree, pt, qual)
708
+ else EmptyTree
709
+
710
+ def tryExt (tree : untpd.Select , qual : Tree ) =
711
+ tryExtensionOrConversion(
712
+ tree, pt, IgnoredProto (pt), qual, ctx.typerState.ownedVars, this , inSelect = true )
713
+
714
+ def tryGadt (tree : untpd.Select ) =
715
+ if ctx.gadt.isNarrowing then
716
+ // try GADT approximation if we're trying to select a member
717
+ // Member lookup cannot take GADTs into account b/c of cache, so we
718
+ // approximate types based on GADT constraints instead. For an example,
719
+ // see MemberHealing in gadt-approximation-interaction.scala.
720
+ val wtp = qual.tpe.widen
721
+ gadts.println(i " Trying to heal member selection by GADT-approximating $wtp" )
722
+ val gadtApprox = Inferencing .approximateGADT(wtp)
723
+ gadts.println(i " GADT-approximated $wtp ~~ $gadtApprox" )
724
+ val qual1 = qual.cast(gadtApprox)
725
+ val tree1 = cpy.Select (tree0)(qual1, selName)
726
+ tryType(tree1, qual1, selectionType(tree1, qual1))
727
+ .orElse(trySmallGenericTuple(tree, qual1, withCast = false ))
728
+ .orElse(tryExt(tree1, qual1))
729
+ else EmptyTree
730
+
731
+ tryType(tree, qual, rawType)
732
+ .orElse {
733
+ if selName == nme.apply && qual.tpe.widen.isInstanceOf [MethodType ] then
734
+ // Simplify `m.apply(...)` to `m(...)`
735
+ qual
736
+ else EmptyTree
737
+ }
738
+ .orElse {
739
+ if couldInstantiateTypeVar(qual.tpe.widen) then
740
+ // there's a simply visible type variable in the result; try again with a more defined qualifier type
741
+ // There's a second trial where we try to instantiate all type variables in `qual.tpe.widen`,
742
+ // but that is done only after we search for extension methods or conversions.
743
+ typedSelect(tree, pt, qual)
744
+ else EmptyTree
745
+ }
746
+ .orElse {
747
+ val wtp = qual.tpe.widen
748
+ val liftedTp = comparing(_.liftToThis(wtp))
749
+ if liftedTp ne wtp then
750
+ val qual1 = qual.cast(liftedTp)
751
+ val tree1 = cpy.Select (tree0)(qual1, selName)
752
+ val rawType1 = selectionType(tree1, qual1)
753
+ tryType(tree1, qual1, rawType1)
754
+ else EmptyTree
755
+ }
756
+ .orElse(trySmallGenericTuple(tree, qual, withCast = true ))
757
+ .orElse(tryExt(tree, qual))
758
+ .orElse(tryGadt(tree))
759
+ .orElse:
760
+ if canDefineFurther(qual.tpe.widen) then
761
+ typedSelect(tree, pt, qual)
762
+ else if qual.tpe.derivesFrom(defn.DynamicClass )
763
+ && selName.isTermName && ! isDynamicExpansion(tree)
764
+ then
765
+ val tree2 = cpy.Select (tree0)(untpd.TypedSplice (qual), selName)
766
+ if pt.isInstanceOf [FunOrPolyProto ] || pt == LhsProto then
767
+ assignType(tree2, TryDynamicCallType )
768
+ else
769
+ typedDynamicSelect(tree2, Nil , pt)
770
+ else
771
+ assignType(tree,
772
+ rawType match
773
+ case rawType : NamedType =>
774
+ inaccessibleErrorType(rawType, superAccess, tree.srcPos)
775
+ case _ =>
776
+ notAMemberErrorType(tree, qual, pt))
757
777
end typedSelect
758
778
759
779
def typedSelect (tree : untpd.Select , pt : Type )(using Context ): Tree = {
0 commit comments