@@ -686,72 +686,96 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
686686 val tree = cpy.Select (tree0)(qual, selName)
687687 val superAccess = qual.isInstanceOf [Super ]
688688 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.
739711 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 ) =
743751 val tree2 = cpy.Select (tree0)(untpd.TypedSplice (qual), selName)
744752 if pt.isInstanceOf [FunOrPolyProto ] || pt == AssignProto then
745753 assignType(tree2, TryDynamicCallType )
746754 else
747755 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())
755779 end typedSelectWithAdapt
756780
757781 def typedSelect (tree : untpd.Select , pt : Type )(using Context ): Tree = {
0 commit comments