Skip to content

Disallow package names as types #14888

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import printing.Printer
import printing.Texts.Text
import util.{Stats, Attachment, Property, SourceFile, NoSource, SrcPos, SourcePosition}
import config.Config
import config.Printers.overload
import annotation.internal.sharable
import annotation.unchecked.uncheckedVariance
import annotation.constructorOnly
Expand Down Expand Up @@ -1729,7 +1730,9 @@ object Trees {
val typer = ctx.typer
val proto = FunProto(args, expectedType)
val denot = receiver.tpe.member(method)
assert(denot.exists, i"no member $receiver . $method, members = ${receiver.tpe.decls}")
if !denot.exists then
overload.println(i"members = ${receiver.tpe.decls}")
report.error(i"no member $receiver . $method", receiver.srcPos)
val selected =
if (denot.isOverloaded) {
def typeParamCount(tp: Type) = tp.widen match {
Expand Down
29 changes: 18 additions & 11 deletions compiler/src/dotty/tools/dotc/transform/PostTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import core._
import dotty.tools.dotc.typer.Checking
import dotty.tools.dotc.typer.Inliner
import dotty.tools.dotc.typer.VarianceChecker
import typer.ErrorReporting.errorTree
import Types._, Contexts._, Names._, Flags._, DenotTransformers._, Phases._
import SymDenotations._, StdNames._, Annotations._, Trees._, Scopes._
import Decorators._
Expand Down Expand Up @@ -263,6 +264,10 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
case Select(qual, _) => check(qual) // simple select _n
case Apply(TypeApply(Select(qual, _), _), _) => check(qual) // generic select .apply[T](n)

def checkNotPackage(tree: Tree)(using Context): Tree =
if !tree.symbol.is(Package) then tree
else errorTree(tree, i"${tree.symbol} cannot be used as a type")

override def transform(tree: Tree)(using Context): Tree =
try tree match {
// TODO move CaseDef case lower: keep most probable trees first for performance
Expand All @@ -273,21 +278,23 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
case None =>
ctx
super.transform(tree)(using gadtCtx)
case tree: Ident if !tree.isType =>
if tree.symbol.is(Inline) && !Inliner.inInlineMethod then
ctx.compilationUnit.needsInlining = true
checkNoConstructorProxy(tree)
tree.tpe match {
case tpe: ThisType => This(tpe.cls).withSpan(tree.span)
case _ => tree
}
case tree: Ident =>
if tree.isType then
checkNotPackage(tree)
else
if tree.symbol.is(Inline) && !Inliner.inInlineMethod then
ctx.compilationUnit.needsInlining = true
checkNoConstructorProxy(tree)
tree.tpe match {
case tpe: ThisType => This(tpe.cls).withSpan(tree.span)
case _ => tree
}
case tree @ Select(qual, name) =>
if tree.symbol.is(Inline) then
ctx.compilationUnit.needsInlining = true
if (name.isTypeName) {
if name.isTypeName then
Checking.checkRealizable(qual.tpe, qual.srcPos)
withMode(Mode.Type)(super.transform(tree))
}
withMode(Mode.Type)(super.transform(checkNotPackage(tree)))
else
checkNoConstructorProxy(tree)
transformSelect(tree, Nil)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
// compare primitive fields first, slow equality checks of non-primitive fields can be skipped when primitives differ
val sortedAccessors = accessors.sortBy(accessor => if (accessor.info.typeSymbol.isPrimitiveValueClass) 0 else 1)
val comparisons = sortedAccessors.map { accessor =>
This(clazz).select(accessor).equal(ref(thatAsClazz).select(accessor)) }
This(clazz).withSpan(ctx.owner.span.focus).select(accessor).equal(ref(thatAsClazz).select(accessor)) }
var rhs = // this.x == this$0.x && this.y == x$0.y && that.canEqual(this)
if comparisons.isEmpty then Literal(Constant(true)) else comparisons.reduceLeft(_ and _)
val canEqualMeth = existingDef(defn.Product_canEqual, clazz)
Expand Down
4 changes: 4 additions & 0 deletions tests/neg/i12432.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

case class i1 ( i1 : annotation ) // error // error
class i2 ( a : scala.annotation ) // error