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