@@ -986,22 +986,36 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
986986 record(" typedSelect" )
987987
988988 def typeSelectOnTerm (using Context ): Tree =
989- val qual = typedExpr(tree.qualifier, shallowSelectionProto(tree.name, pt, this , tree.nameSpan))
990989 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)
9921010 else
1011+ val qual = typedExpr(tree.qualifier, shallowSelectionProto(tree.name, pt, this , tree.nameSpan))
9931012 typedSelectWithAdapt(tree, pt, qual).withSpan(tree.span).computeNullable()
9941013
9951014 def javaSelection (qual : Tree )(using Context ) =
9961015 qual match
9971016 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
10051019 assignType(cpy.Select (tree)(qual1, tree.name), qual1)
10061020 case _ =>
10071021 val tree1 = assignType(cpy.Select (tree)(qual, tree.name), qual)
@@ -1027,17 +1041,14 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
10271041 errorTree(tree, em " cannot convert to type selection " ) // will never be printed due to fallback
10281042 }
10291043
1030- def selectWithFallback (fallBack : Context ?=> Tree ) =
1031- tryAlternatively(typeSelectOnTerm)(fallBack)
1032-
10331044 if (tree.qualifier.isType) {
10341045 val qual1 = typedType(tree.qualifier, shallowSelectionProto(tree.name, pt, this , tree.nameSpan))
10351046 assignType(cpy.Select (tree)(qual1, tree.name), qual1)
10361047 }
10371048 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)
10411052 else
10421053 typeSelectOnTerm
10431054 }
0 commit comments