@@ -688,72 +688,92 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
688688 val tree = cpy.Select (tree0)(qual, selName)
689689 val superAccess = qual.isInstanceOf [Super ]
690690 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)))
748706 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))
757777 end typedSelect
758778
759779 def typedSelect (tree : untpd.Select , pt : Type )(using Context ): Tree = {
0 commit comments