@@ -986,22 +986,36 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
986
986
record(" typedSelect" )
987
987
988
988
def typeSelectOnTerm (using Context ): Tree =
989
- val qual = typedExpr(tree.qualifier, shallowSelectionProto(tree.name, pt, this , tree.nameSpan))
990
989
if ctx.isJava then
991
- javaSelection(qual)
990
+ def tryQual (qual : untpd.Tree )(using Context ): Tree =
991
+ javaSelection(typedExpr(qual, shallowSelectionProto(tree.name, pt, this , tree.nameSpan)))
992
+ // permitted selection depends on Java context (type or expression).
993
+ // we don't propagate (as a mode) whether a.b.m is a type name; OK since we only see type contexts.
994
+ // to allow correct selections, approximate by fallback for x.y: take x as class or (rooted) package.
995
+ def tryQualFallback (qual : untpd.Ident , name : Name )(using Context ): Tree =
996
+ val qualTpe =
997
+ val maybeClass = findRef(name, WildcardType , EmptyFlags , EmptyFlags , qual.srcPos)
998
+ if maybeClass.exists then maybeClass
999
+ else
1000
+ val maybePackage = defn.RootPackage .info.member(name)
1001
+ if maybePackage.exists then maybePackage.info
1002
+ else NoType
1003
+ if qualTpe.exists then
1004
+ javaSelection(assignType(cpy.Ident (qual)(name), qualTpe))
1005
+ else
1006
+ errorTree(tree, em " no class or package to resolve ` $name` " ) // just fail fallback
1007
+ tree.qualifier match
1008
+ case qual @ Ident (name) => tryAlternatively(tryQual(qual))(tryQualFallback(qual, name))
1009
+ case qual => tryQual(qual)
992
1010
else
1011
+ val qual = typedExpr(tree.qualifier, shallowSelectionProto(tree.name, pt, this , tree.nameSpan))
993
1012
typedSelectWithAdapt(tree, pt, qual).withSpan(tree.span).computeNullable()
994
1013
995
1014
def javaSelection (qual : Tree )(using Context ) =
996
1015
qual match
997
1016
case id @ Ident (name) if id.symbol.is(Package ) && ! id.symbol.owner.isRoot =>
998
- def nextPackage (last : Symbol )(using Context ): Type =
999
- val startAt = ctx.outersIterator.dropWhile(_.owner != last.owner).drop(1 ).next()
1000
- val next = findRef(name, WildcardType , required = Package , EmptyFlags , qual.srcPos)(using startAt)
1001
- if next.exists && ! next.typeSymbol.owner.isRoot then nextPackage(next.typeSymbol)
1002
- else next
1003
- val next = nextPackage(id.symbol)
1004
- val qual1 = if next.exists then assignType(cpy.Ident (id)(tree.name), next) else qual
1017
+ val rooted = defn.RootPackage .info.member(name).info
1018
+ val qual1 = if rooted.exists then assignType(cpy.Ident (id)(name), rooted) else qual
1005
1019
assignType(cpy.Select (tree)(qual1, tree.name), qual1)
1006
1020
case _ =>
1007
1021
val tree1 = assignType(cpy.Select (tree)(qual, tree.name), qual)
@@ -1027,17 +1041,14 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
1027
1041
errorTree(tree, em " cannot convert to type selection " ) // will never be printed due to fallback
1028
1042
}
1029
1043
1030
- def selectWithFallback (fallBack : Context ?=> Tree ) =
1031
- tryAlternatively(typeSelectOnTerm)(fallBack)
1032
-
1033
1044
if (tree.qualifier.isType) {
1034
1045
val qual1 = typedType(tree.qualifier, shallowSelectionProto(tree.name, pt, this , tree.nameSpan))
1035
1046
assignType(cpy.Select (tree)(qual1, tree.name), qual1)
1036
1047
}
1037
1048
else if (ctx.isJava && tree.name.isTypeName)
1038
- // SI- 3120 Java uses the same syntax, A.B, to express selection from the
1039
- // value A and from the type A. We have to try both.
1040
- selectWithFallback( tryJavaSelectOnType) // !!! possibly exponential bcs of qualifier retyping
1049
+ // scala/bug# 3120 Java uses the same syntax, A.B, to express selection from the
1050
+ // value A and from the type A. We have to try both. (possibly exponential bc of qualifier retyping)
1051
+ tryAlternatively(typeSelectOnTerm)( tryJavaSelectOnType)
1041
1052
else
1042
1053
typeSelectOnTerm
1043
1054
}
0 commit comments