Skip to content
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

Let annotations on parameters see preceding type parameters #12980

Merged
merged 3 commits into from
Jun 30, 2021
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
19 changes: 15 additions & 4 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ class Namer { typer: Typer =>
case original: DefDef =>
val typer1 = ctx.typer.newLikeThis
nestedTyper(sym) = typer1
typer1.defDefSig(original, sym)(using localContext(sym).setTyper(typer1))
typer1.defDefSig(original, sym, this)(using localContext(sym).setTyper(typer1))
case imp: Import =>
try
val expr1 = typedImportQualifier(imp, typedAheadExpr(_, _)(using ctx.withOwner(sym)))
Expand Down Expand Up @@ -733,6 +733,15 @@ class Namer { typer: Typer =>
completer.complete(denot)
}

private var completedTypeParamSyms: List[TypeSymbol] = null

def setCompletedTypeParams(tparams: List[TypeSymbol]) =
completedTypeParamSyms = tparams

override def completerTypeParams(sym: Symbol)(using Context): List[TypeSymbol] =
if completedTypeParamSyms != null then completedTypeParamSyms
else Nil

protected def addAnnotations(sym: Symbol): Unit = original match {
case original: untpd.MemberDef =>
lazy val annotCtx = annotContext(original, sym)
Expand Down Expand Up @@ -1639,7 +1648,7 @@ class Namer { typer: Typer =>
}

/** The type signature of a DefDef with given symbol */
def defDefSig(ddef: DefDef, sym: Symbol)(using Context): Type = {
def defDefSig(ddef: DefDef, sym: Symbol, completer: Namer#Completer)(using Context): Type = {
// Beware: ddef.name need not match sym.name if sym was freshened!
val isConstructor = sym.name == nme.CONSTRUCTOR

Expand Down Expand Up @@ -1668,8 +1677,10 @@ class Namer { typer: Typer =>
// 5. Info of CP is copied to DP and DP is completed.
index(ddef.leadingTypeParams)
if (isConstructor) sym.owner.typeParams.foreach(_.ensureCompleted())
for (tparam <- ddef.leadingTypeParams) typedAheadExpr(tparam)

val completedTypeParams =
for tparam <- ddef.leadingTypeParams yield typedAheadExpr(tparam).symbol
if completedTypeParams.forall(_.isType) then
completer.setCompletedTypeParams(completedTypeParams.asInstanceOf[List[TypeSymbol]])
ddef.trailingParamss.foreach(completeParams)
val paramSymss = normalizeIfConstructor(ddef.paramss.nestedMap(symbolOfTree), isConstructor)
sym.setParamss(paramSymss)
Expand Down
13 changes: 12 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2081,10 +2081,21 @@ class Typer extends Namer
def annotContext(mdef: untpd.Tree, sym: Symbol)(using Context): Context = {
def isInner(owner: Symbol) = owner == sym || sym.is(Param) && owner == sym.owner
val outer = ctx.outersIterator.dropWhile(c => isInner(c.owner)).next()
outer.property(ExprOwner) match {
var adjusted = outer.property(ExprOwner) match {
case Some(exprOwner) if outer.owner.isClass => outer.exprContext(mdef, exprOwner)
case _ => outer
}
sym.owner.infoOrCompleter match
case completer: Namer#Completer if sym.is(Param) =>
val tparams = completer.completerTypeParams(sym)
if tparams.nonEmpty then
// Create a new local context with a dummy owner and a scope containing the
// type parameters of the enclosing method or class. Thus annotations can see
// these type parameters. See i12953.scala for a test case.
val dummyOwner = newLocalDummy(sym.owner)
adjusted = adjusted.fresh.setOwner(dummyOwner).setScope(newScopeWith(tparams*))
case _ =>
adjusted
}

def completeAnnotations(mdef: untpd.MemberDef, sym: Symbol)(using Context): Unit = {
Expand Down
7 changes: 7 additions & 0 deletions tests/pos/i12953.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Schema(impl: Class[_]) extends scala.annotation.StaticAnnotation

class Ann[A] extends scala.annotation.StaticAnnotation

case class Foo[A](@Schema(classOf[List[A]]) foo: String)
case class Bar[A](@Ann[A] foo: String)
def baz[A](@Ann[A] foo: String) = ()