diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 27c39a79cf14..583613169e48 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -21,6 +21,7 @@ import typer.{NoChecking, LiftErased} import typer.Inliner import typer.ProtoTypes._ import typer.ErrorReporting.errorTree +import typer.Checking.checkValue import core.TypeErasure._ import core.Decorators._ import dotty.tools.dotc.ast.{tpd, untpd} @@ -569,18 +570,6 @@ object Erasure { /** Check that Java statics and packages can only be used in selections. */ - private def checkValue(tree: Tree, proto: Type)(using Context): tree.type = - if (!proto.isInstanceOf[SelectionProto] && !proto.isInstanceOf[ApplyingProto]) then - checkValue(tree) - tree - - private def checkValue(tree: Tree)(using Context): Unit = - val sym = tree.tpe.termSymbol - if (sym is Flags.Package) - || (sym.isAllOf(Flags.JavaModule) && !ctx.isJava) - then - report.error(JavaSymbolIsNotAValue(sym), tree.srcPos) - private def checkNotErased(tree: Tree)(using Context): tree.type = { if (!ctx.mode.is(Mode.Type)) { if (isErased(tree)) @@ -644,7 +633,7 @@ object Erasure { super.typedLiteral(tree) override def typedIdent(tree: untpd.Ident, pt: Type)(using Context): Tree = - checkValue(checkNotErased(super.typedIdent(tree, pt)), pt) + checkNotErased(super.typedIdent(tree, pt)) /** Type check select nodes, applying the following rewritings exhaustively * on selections `e.m`, where `OT` is the type of the owner of `m` and `ET` @@ -772,7 +761,7 @@ object Erasure { } } - checkValue(checkNotErased(recur(qual1)), pt) + checkNotErased(recur(qual1)) } override def typedThis(tree: untpd.This)(using Context): Tree = diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index bce4f6cbb242..adb4dd41162b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -653,6 +653,21 @@ object Checking { || to.isRef(defn.ObjectClass, skipRefined = false) then report.error(em"the result of an implicit conversion must be more specific than $to", pos) + + def checkValue(tree: Tree)(using Context): Unit = + val sym = tree.tpe.termSymbol + if sym.is(Flags.Package) || sym.isAllOf(Flags.JavaModule) && !ctx.isJava then + report.error(JavaSymbolIsNotAValue(sym), tree.srcPos) + + def checkValue(tree: Tree, proto: Type)(using Context): tree.type = + tree match + case tree: RefTree + if tree.name.isTermName + && !proto.isInstanceOf[SelectionProto] + && !proto.isInstanceOf[FunOrPolyProto] => + checkValue(tree) + case _ => + tree } trait Checking { diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index cff9407e9328..c36e3fd0ef2e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -499,7 +499,7 @@ class Typer extends Namer case _ => tree.withType(ownType) val tree2 = toNotNullTermRef(tree1, pt) - checkStableIdentPattern(tree2, pt) + checkLegalValue(tree2, pt) tree2 def isLocalExtensionMethodRef: Boolean = rawType match @@ -537,9 +537,12 @@ class Typer extends Namer errorTree(tree, MissingIdent(tree, kind, name)) end typedIdent - /** Check that a stable identifier pattern is indeed stable (SLS 8.1.5) + /** (1) If this reference is neither applied nor selected, check that it does + * not refer to a package or Java companion object. + * (2) Check that a stable identifier pattern is indeed stable (SLS 8.1.5) */ - private def checkStableIdentPattern(tree: Tree, pt: Type)(using Context): Unit = + private def checkLegalValue(tree: Tree, pt: Type)(using Context): Unit = + checkValue(tree, pt) if ctx.mode.is(Mode.Pattern) && !tree.isType && !pt.isInstanceOf[ApplyingProto] @@ -557,7 +560,7 @@ class Typer extends Namer if checkedType.exists then val select = toNotNullTermRef(assignType(tree, checkedType), pt) if selName.isTypeName then checkStable(qual.tpe, qual.srcPos, "type prefix") - checkStableIdentPattern(select, pt) + checkLegalValue(select, pt) ConstFold(select) else if couldInstantiateTypeVar(qual.tpe.widen) then // try again with more defined qualifier type @@ -2343,7 +2346,7 @@ class Typer extends Namer assert(imp.selectors.length == 1, imp) val from = imp.selectors.head.imported val sel = tryAlternatively - (typedIdent(from, WildcardType)) + (typedIdent(from, AnySelectionProto)) (typedIdent(cpy.Ident(from)(from.name.toTypeName), WildcardType)) sel.tpe match diff --git a/tests/neg/i11430.scala b/tests/neg/i11430.scala new file mode 100644 index 000000000000..c98bcd551f5c --- /dev/null +++ b/tests/neg/i11430.scala @@ -0,0 +1,4 @@ +def a(o: String) = Seq(o, org) // error: package org is not a value +def a2(o: String) = Seq[String](o, org) // error: package org is not a value +def a3(o: String): Seq[String] = Seq(o, org) // error: package org is not a value +def a4(o: String): Seq[String] = Seq(o, org) // error: package org is not a value