@@ -1001,22 +1001,35 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
10011001 record(" typedSelect" )
10021002
10031003 def typeSelectOnTerm (using Context ): Tree =
1004- val qual = typedExpr(tree.qualifier, shallowSelectionProto(tree.name, pt, this , tree.nameSpan))
10051004 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)
10071024 else
1025+ val qual = typedExpr(tree.qualifier, shallowSelectionProto(tree.name, pt, this , tree.nameSpan))
10081026 typedSelectWithAdapt(tree, pt, qual).withSpan(tree.span).computeNullable()
10091027
10101028 def javaSelection (qual : Tree )(using Context ) =
10111029 qual match
10121030 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
10201033 assignType(cpy.Select (tree)(qual1, tree.name), qual1)
10211034 case _ =>
10221035 val tree1 = assignType(cpy.Select (tree)(qual, tree.name), qual)
@@ -1042,17 +1055,14 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
10421055 errorTree(tree, em " cannot convert to type selection " ) // will never be printed due to fallback
10431056 }
10441057
1045- def selectWithFallback (fallBack : Context ?=> Tree ) =
1046- tryAlternatively(typeSelectOnTerm)(fallBack)
1047-
10481058 if (tree.qualifier.isType) {
10491059 val qual1 = typedType(tree.qualifier, shallowSelectionProto(tree.name, pt, this , tree.nameSpan))
10501060 assignType(cpy.Select (tree)(qual1, tree.name), qual1)
10511061 }
10521062 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)
10561066 else
10571067 typeSelectOnTerm
10581068 }
0 commit comments