Skip to content

Commit

Permalink
fix #10122: check parent types of references and types of parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
bishabosha committed Oct 30, 2020
1 parent 9ec34f8 commit 572a824
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 12 deletions.
50 changes: 38 additions & 12 deletions compiler/src/dotty/tools/dotc/transform/Erasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -550,15 +550,41 @@ object Erasure {
if (!ctx.mode.is(Mode.Type)) {
if (isErased(tree))
report.error(em"${tree.symbol} is declared as erased, but is in fact used", tree.srcPos)
tree.symbol.getAnnotation(defn.CompileTimeOnlyAnnot) match {
case Some(annot) =>
def defaultMsg =
i"""Reference to ${tree.symbol.showLocated} should not have survived,
|it should have been processed and eliminated during expansion of an enclosing macro or term erasure."""
val message = annot.argumentConstant(0).fold(defaultMsg)(_.stringValue)
report.error(message, tree.srcPos)
case _ => // OK
}

def parentSyms(tpe: Type): LazyList[Symbol] =
val ref = tpe.widen.finalResultType
ref.classSymbol #:: ref.parents.to(LazyList).flatMap(parentSyms)

def checkTree(tree: Tree, pos: util.SrcPos, toCheck: LazyList[Symbol]): Boolean =
toCheck.exists { sym =>
sym.getAnnotation(defn.CompileTimeOnlyAnnot) match {
case Some(annot) =>
def defaultMsg =
i"""Reference to ${tree.symbol.showLocated} should not have survived,
|it should have been processed and eliminated during expansion of an enclosing macro or term erasure."""
val message = annot.argumentConstant(0).fold(defaultMsg)(_.stringValue)
report.error(message, pos)
true
case _ => // OK
false
}
}

tree match
case ddef: DefDef =>
for
vparams <- ddef.vparamss
vparam <- vparams
do
checkTree(vparam, vparam.tpt.srcPos, parentSyms(vparam.tpt.tpe))
checkTree(ddef, ddef.tpt.srcPos, parentSyms(ddef.tpt.tpe))

case vdef: ValDef => checkTree(vdef, vdef.tpt.srcPos, parentSyms(vdef.tpt.tpe))

case tree =>
// in the other branches we avoid checking the symbol itself
// in-case it is annotated for downstream members
checkTree(tree, tree.srcPos, tree.symbol #:: parentSyms(tree.tpe))
}
tree
}
Expand Down Expand Up @@ -844,8 +870,8 @@ object Erasure {
override def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree =
if (sym.isEffectivelyErased) erasedDef(sym)
else
super.typedValDef(untpd.cpy.ValDef(vdef)(
tpt = untpd.TypedSplice(TypeTree(sym.info).withSpan(vdef.tpt.span))), sym)
checkNotErased(super.typedValDef(untpd.cpy.ValDef(vdef)(
tpt = untpd.TypedSplice(TypeTree(sym.info).withSpan(vdef.tpt.span))), sym))

/** Besides normal typing, this function also compacts anonymous functions
* with more than `MaxImplementedFunctionArity` parameters to use a single
Expand Down Expand Up @@ -889,7 +915,7 @@ object Erasure {
vparamss = vparams :: Nil,
tpt = untpd.TypedSplice(TypeTree(restpe).withSpan(ddef.tpt.span)),
rhs = rhs1)
super.typedDefDef(ddef1, sym)
checkNotErased(super.typedDefDef(ddef1, sym))
end typedDefDef

/** The outer parameter definition of a constructor if it needs one */
Expand Down
17 changes: 17 additions & 0 deletions tests/neg/i10122.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import scala.annotation.compileTimeOnly

@compileTimeOnly("FooBar can not be used as an expression") trait FooBar

object foo extends FooBar // error

val fooAnon = new FooBar {} // error // error
val fooRef1: FooBar = ??? // error
def fooRef2: FooBar = ??? // error
def useFoo(foo: FooBar): foo.type = foo // error // error // error
val bar = fooRef2 // error

@compileTimeOnly("baz can not be used as an expression") val baz = 23
val qux = baz // error

@compileTimeOnly("quux can not be used as an expression") def quux = 47
val quxx = quux // error
8 changes: 8 additions & 0 deletions tests/neg/i9825.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
object Module {
@deprecated("Module.Foo is deprecated")
type Foo[+A] = scala.List[A]
}

object Test {
val m: Module.Foo[String] = List("wow")
}

0 comments on commit 572a824

Please sign in to comment.