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