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