Skip to content

Set Span for top level annotations generated in PostTyper #16378

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
Dec 22, 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
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ object desugar {
case Into(tpt1) =>
mods1 = vdef.mods.withAddedAnnotation(
TypedSplice(
Annotation(defn.AllowConversionsAnnot).tree.withSpan(tpt.span.startPos)))
Annotation(defn.AllowConversionsAnnot, tpt.span.startPos).tree))
tpt1
case ByNameTypeTree(tpt1) =>
cpy.ByNameTypeTree(tpt)(dropInto(tpt1))
Expand Down
36 changes: 15 additions & 21 deletions compiler/src/dotty/tools/dotc/core/Annotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -194,27 +194,21 @@ object Annotations {
object Annotation {

def apply(tree: Tree): ConcreteAnnotation = ConcreteAnnotation(tree)

def apply(cls: ClassSymbol, span: Span)(using Context): Annotation =
apply(cls, Nil, span)

def apply(cls: ClassSymbol)(using Context): Annotation =
apply(cls, Nil)
def apply(cls: ClassSymbol, arg: Tree, span: Span)(using Context): Annotation =
apply(cls, arg :: Nil, span)

def apply(cls: ClassSymbol, arg: Tree)(using Context): Annotation =
apply(cls, arg :: Nil)
def apply(cls: ClassSymbol, args: List[Tree], span: Span)(using Context): Annotation =
apply(cls.typeRef, args, span)

def apply(cls: ClassSymbol, arg1: Tree, arg2: Tree)(using Context): Annotation =
apply(cls, arg1 :: arg2 :: Nil)

def apply(cls: ClassSymbol, args: List[Tree])(using Context): Annotation =
apply(cls.typeRef, args)

def apply(atp: Type, arg: Tree)(using Context): Annotation =
apply(atp, arg :: Nil)

def apply(atp: Type, arg1: Tree, arg2: Tree)(using Context): Annotation =
apply(atp, arg1 :: arg2 :: Nil)

def apply(atp: Type, args: List[Tree])(using Context): Annotation =
apply(New(atp, args))
def apply(atp: Type, arg: Tree, span: Span)(using Context): Annotation =
apply(atp, arg :: Nil, span)

def apply(atp: Type, args: List[Tree], span: Span)(using Context): Annotation =
apply(New(atp, args).withSpan(span))

/** Create an annotation where the tree is computed lazily. */
def deferred(sym: Symbol)(treeFn: Context ?=> Tree): Annotation =
Expand Down Expand Up @@ -251,15 +245,15 @@ object Annotations {
else None
}

def makeSourceFile(path: String)(using Context): Annotation =
apply(defn.SourceFileAnnot, Literal(Constant(path)))
def makeSourceFile(path: String, span: Span)(using Context): Annotation =
apply(defn.SourceFileAnnot, Literal(Constant(path)), span)
}

@sharable val EmptyAnnotation = Annotation(EmptyTree)

def ThrowsAnnotation(cls: ClassSymbol)(using Context): Annotation = {
val tref = cls.typeRef
Annotation(defn.ThrowsAnnot.typeRef.appliedTo(tref), Ident(tref))
Annotation(defn.ThrowsAnnot.typeRef.appliedTo(tref), Ident(tref), cls.span)
}

/** Extracts the type of the thrown exception from an annotation.
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ object SymDenotations {

/** Add the given annotation without parameters to the annotations of this denotation */
final def addAnnotation(cls: ClassSymbol)(using Context): Unit =
addAnnotation(Annotation(cls))
addAnnotation(Annotation(cls, symbol.span))

/** Remove annotation with given class from this denotation */
final def removeAnnotation(cls: Symbol)(using Context): Unit =
Expand Down
10 changes: 5 additions & 5 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3965,9 +3965,9 @@ object Types {
* - wrap types of parameters that have an @allowConversions annotation with Into[_]
*/
def fromSymbols(params: List[Symbol], resultType: Type)(using Context): MethodType =
def addAnnotation(tp: Type, cls: ClassSymbol): Type = tp match
case ExprType(resType) => ExprType(addAnnotation(resType, cls))
case _ => AnnotatedType(tp, Annotation(cls))
def addAnnotation(tp: Type, cls: ClassSymbol, param: Symbol): Type = tp match
case ExprType(resType) => ExprType(addAnnotation(resType, cls, param))
case _ => AnnotatedType(tp, Annotation(cls, param.span))

def wrapConvertible(tp: Type) =
AppliedType(defn.IntoType.typeRef, tp :: Nil)
Expand All @@ -3992,9 +3992,9 @@ object Types {
def paramInfo(param: Symbol) =
var paramType = param.info.annotatedToRepeated
if param.is(Inline) then
paramType = addAnnotation(paramType, defn.InlineParamAnnot)
paramType = addAnnotation(paramType, defn.InlineParamAnnot, param)
if param.is(Erased) then
paramType = addAnnotation(paramType, defn.ErasedParamAnnot)
paramType = addAnnotation(paramType, defn.ErasedParamAnnot, param)
if param.hasAnnotation(defn.AllowConversionsAnnot) then
paramType = addInto(paramType)
paramType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ class ClassfileParser(
res.namedParams += (i -> name.name)

case tpnme.AnnotationDefaultATTR =>
sym.addAnnotation(Annotation(defn.AnnotationDefaultAnnot, Nil))
sym.addAnnotation(Annotation(defn.AnnotationDefaultAnnot, Nil, sym.span))

// Java annotations on classes / methods / fields with RetentionPolicy.RUNTIME
case tpnme.RuntimeVisibleAnnotationATTR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
yield {
def forwarderSym(flags: FlagSet, info: Type): Symbol { type ThisName = TermName } =
val sym = newSymbol(clazz, enumValue.name.asTermName, flags, info)
sym.addAnnotation(Annotations.Annotation(defn.ScalaStaticAnnot))
sym.addAnnotation(Annotations.Annotation(defn.ScalaStaticAnnot, sym.span))
sym
val body = moduleRef.select(enumValue)
if ctx.settings.scalajs.value then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ object ContextFunctionResults:
val count = contextResultCount(mdef.rhs, mdef.tpt.tpe)

if Config.flattenContextFunctionResults && count != 0 && !disabled then
val countAnnot = Annotation(defn.ContextResultCountAnnot, Literal(Constant(count)))
val countAnnot = Annotation(defn.ContextResultCountAnnot, Literal(Constant(count)), mdef.symbol.span)
mdef.symbol.addAnnotation(countAnnot)
end annotateContextResults

Expand Down
10 changes: 5 additions & 5 deletions compiler/src/dotty/tools/dotc/transform/LazyVals.scala
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
appendOffsetDefs.get(cls) match {
case None => template
case Some(data) =>
data.defs.foreach(_.symbol.addAnnotation(Annotation(defn.ScalaStaticAnnot)))
data.defs.foreach(defin => defin.symbol.addAnnotation(Annotation(defn.ScalaStaticAnnot, defin.symbol.span)))
cpy.Template(template)(body = addInFront(data.defs, template.body))
}
}
Expand Down Expand Up @@ -464,7 +464,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
def offsetName(id: Int) = s"${StdNames.nme.LAZY_FIELD_OFFSET}${if (x.symbol.owner.is(Module)) "_m_" else ""}$id".toTermName
val containerName = LazyLocalName.fresh(x.name.asTermName)
val containerSymbol = newSymbol(claz, containerName, x.symbol.flags &~ containerFlagsMask | containerFlags | Private, defn.ObjectType, coord = x.symbol.coord).enteredAfter(this)
containerSymbol.addAnnotation(Annotation(defn.VolatileAnnot)) // private @volatile var _x: AnyRef
containerSymbol.addAnnotation(Annotation(defn.VolatileAnnot, containerSymbol.span)) // private @volatile var _x: AnyRef
containerSymbol.addAnnotations(x.symbol.annotations) // pass annotations from original definition
val stat = x.symbol.isStatic
if stat then
Expand All @@ -482,7 +482,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
newSymbol(claz, offsetName(info.defs.size), Synthetic, defn.LongType).enteredAfter(this)
case None =>
newSymbol(claz, offsetName(0), Synthetic, defn.LongType).enteredAfter(this)
offsetSymbol.nn.addAnnotation(Annotation(defn.ScalaStaticAnnot))
offsetSymbol.nn.addAnnotation(Annotation(defn.ScalaStaticAnnot, offsetSymbol.nn.span))
val fieldTree = thizClass.select(lazyNme.RLazyVals.getDeclaredField).appliedTo(Literal(Constant(containerName.mangledString)))
val offsetTree = ValDef(offsetSymbol.nn, getOffset.appliedTo(fieldTree))
val offsetInfo = appendOffsetDefs.getOrElseUpdate(claz, new OffsetInfo(Nil))
Expand Down Expand Up @@ -625,7 +625,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
.symbol.asTerm
else { // need to create a new flag
offsetSymbol = newSymbol(claz, offsetById, Synthetic, defn.LongType).enteredAfter(this)
offsetSymbol.nn.addAnnotation(Annotation(defn.ScalaStaticAnnot))
offsetSymbol.nn.addAnnotation(Annotation(defn.ScalaStaticAnnot, offsetSymbol.nn.span))
val flagName = LazyBitMapName.fresh(id.toString.toTermName)
val flagSymbol = newSymbol(claz, flagName, containerFlags, defn.LongType).enteredAfter(this)
flag = ValDef(flagSymbol, Literal(Constant(0L)))
Expand All @@ -636,7 +636,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {

case None =>
offsetSymbol = newSymbol(claz, offsetName(0), Synthetic, defn.LongType).enteredAfter(this)
offsetSymbol.nn.addAnnotation(Annotation(defn.ScalaStaticAnnot))
offsetSymbol.nn.addAnnotation(Annotation(defn.ScalaStaticAnnot, offsetSymbol.nn.span))
val flagName = LazyBitMapName.fresh("0".toTermName)
val flagSymbol = newSymbol(claz, flagName, containerFlags, defn.LongType).enteredAfter(this)
flag = ValDef(flagSymbol, Literal(Constant(0L)))
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/MoveStatics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class MoveStatics extends MiniPhase with SymTransformer {
if (staticFields.nonEmpty) {
/* do NOT put Flags.JavaStatic here. It breaks .enclosingClass */
val staticCostructor = newSymbol(orig.symbol, nme.STATIC_CONSTRUCTOR, Flags.Synthetic | Flags.Method | Flags.Private, MethodType(Nil, defn.UnitType))
staticCostructor.addAnnotation(Annotation(defn.ScalaStaticAnnot))
staticCostructor.addAnnotation(Annotation(defn.ScalaStaticAnnot, staticCostructor.span))
staticCostructor.entered

val staticAssigns = staticFields.map(x => Assign(ref(x.symbol), x.rhs.changeOwner(x.symbol, staticCostructor)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ object PCPCheckAndHeal {
flags = Synthetic,
info = TypeAlias(splicedTree.tpe.select(tpnme.Underlying)),
coord = span).asType
local.addAnnotation(Annotation(defn.QuotedRuntime_SplicedTypeAnnot))
local.addAnnotation(Annotation(defn.QuotedRuntime_SplicedTypeAnnot, span))
ctx.typeAssigner.assignType(untpd.TypeDef(local.name, alias), local)
}

Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/transform/PostTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -395,9 +395,9 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
if ctx.compilationUnit.source.exists && sym != defn.SourceFileAnnot then
val reference = ctx.settings.sourceroot.value
val relativePath = util.SourceFile.relativePath(ctx.compilationUnit.source, reference)
sym.addAnnotation(Annotation.makeSourceFile(relativePath))
sym.addAnnotation(Annotation.makeSourceFile(relativePath, tree.span))
if Feature.pureFunsEnabled && sym != defn.WithPureFunsAnnot then
sym.addAnnotation(Annotation(defn.WithPureFunsAnnot))
sym.addAnnotation(Annotation(defn.WithPureFunsAnnot, tree.span))
else
if !sym.is(Param) && !sym.owner.isOneOf(AbstractOrTrait) then
Checking.checkGoodBounds(tree.symbol)
Expand Down Expand Up @@ -499,8 +499,8 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase

private def annotateExperimental(sym: Symbol)(using Context): Unit =
if sym.is(Module) && sym.companionClass.hasAnnotation(defn.ExperimentalAnnot) then
sym.addAnnotation(defn.ExperimentalAnnot)
sym.companionModule.addAnnotation(defn.ExperimentalAnnot)
sym.addAnnotation(Annotation(defn.ExperimentalAnnot, sym.span))
sym.companionModule.addAnnotation(Annotation(defn.ExperimentalAnnot, sym.span))

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class RepeatableAnnotations extends MiniPhase:
Nil
else
val aggregated = JavaSeqLiteral(anns.map(_.tree).toList, TypeTree(sym.typeRef))
Annotation(containerTpe, NamedArg("value".toTermName, aggregated)) :: Nil
Annotation(containerTpe, NamedArg("value".toTermName, aggregated), sym.span) :: Nil
case _ =>
val pos = anns.head.tree.srcPos
report.error("Not repeatable annotation repeated", pos)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/SymUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ object SymUtils:
if original.hasAnnotation(defn.TargetNameAnnot) then
self.addAnnotation(
Annotation(defn.TargetNameAnnot,
Literal(Constant(nameFn(original.targetName).toString)).withSpan(original.span)))
Literal(Constant(nameFn(original.targetName).toString)).withSpan(original.span), original.span))

/** The return type as seen from the body of this definition. It is
* computed from the symbol's type by replacing param refs by param symbols.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import ast.untpd
import ValueClasses.isDerivedValueClass
import SymUtils._
import util.Property
import util.Spans.Span
import config.Printers.derive
import NullOpsDecorator._

Expand Down Expand Up @@ -155,7 +156,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
case nme.hashCode_ => chooseHashcode
case nme.toString_ => toStringBody(vrefss)
case nme.equals_ => equalsBody(vrefss.head.head)
case nme.canEqual_ => canEqualBody(vrefss.head.head)
case nme.canEqual_ => canEqualBody(vrefss.head.head, synthetic.span)
case nme.ordinal => ordinalRef
case nme.productArity => Literal(Constant(accessors.length))
case nme.productPrefix if isEnumValue => nameRef
Expand Down Expand Up @@ -260,7 +261,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
def equalsBody(that: Tree)(using Context): Tree = {
val thatAsClazz = newSymbol(ctx.owner, nme.x_0, SyntheticCase, clazzType, coord = ctx.owner.span) // x$0
def wildcardAscription(tp: Type) = Typed(Underscore(tp), TypeTree(tp))
val pattern = Bind(thatAsClazz, wildcardAscription(AnnotatedType(clazzType, Annotation(defn.UncheckedAnnot)))) // x$0 @ (_: C @unchecked)
val pattern = Bind(thatAsClazz, wildcardAscription(AnnotatedType(clazzType, Annotation(defn.UncheckedAnnot, thatAsClazz.span)))) // x$0 @ (_: C @unchecked)
// 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 =>
Expand Down Expand Up @@ -390,7 +391,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
*
* `@unchecked` is needed for parametric case classes.
*/
def canEqualBody(that: Tree): Tree = that.isInstance(AnnotatedType(clazzType, Annotation(defn.UncheckedAnnot)))
def canEqualBody(that: Tree, span: Span): Tree = that.isInstance(AnnotatedType(clazzType, Annotation(defn.UncheckedAnnot, span)))

symbolsToSynthesize.flatMap(syntheticDefIfMissing)
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ class Namer { typer: Typer =>
val isProvisional = parents.exists(!_.baseType(defn.AnyClass).exists)
if isProvisional then
typr.println(i"provisional superclass $first for $cls")
first = AnnotatedType(first, Annotation(defn.ProvisionalSuperClassAnnot))
first = AnnotatedType(first, Annotation(defn.ProvisionalSuperClassAnnot, cls.span))
checkFeasibleParent(first, cls.srcPos, i" in inferred superclass $first") :: parents
end ensureFirstIsClass

Expand Down Expand Up @@ -1883,7 +1883,7 @@ class Namer { typer: Typer =>
// larger choice of overrides (see `default-getter.scala`).
// For justification on the use of `@uncheckedVariance`, see
// `default-getter-variance.scala`.
AnnotatedType(defaultTp, Annotation(defn.UncheckedVarianceAnnot))
AnnotatedType(defaultTp, Annotation(defn.UncheckedVarianceAnnot, sym.span))
else
// don't strip @uncheckedVariance annot for default getters
TypeOps.simplify(tp.widenTermRefExpr,
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1663,7 +1663,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer

// skip exhaustivity check in later phase
// TODO: move the check above to patternMatcher phase
val uncheckedTpe = AnnotatedType(sel.tpe.widen, Annotation(defn.UncheckedAnnot))
val uncheckedTpe = AnnotatedType(sel.tpe.widen, Annotation(defn.UncheckedAnnot, tree.selector.span))
tpd.cpy.Match(result)(
selector = tpd.Typed(sel, tpd.TypeTree(uncheckedTpe)),
cases = result.cases
Expand Down Expand Up @@ -1898,7 +1898,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
Typed(res,
TypeTree(
AnnotatedType(res.tpe,
Annotation(defn.RequiresCapabilityAnnot, cap))))
Annotation(defn.RequiresCapabilityAnnot, cap, tree.span))))
else res

def typedSeqLiteral(tree: untpd.SeqLiteral, pt: Type)(using Context): SeqLiteral = {
Expand Down Expand Up @@ -4297,7 +4297,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
// this is needed for -Ycheck. Without the annotation Ycheck will
// skolemize the result type which will lead to different types before
// and after checking. See i11955.scala.
AnnotatedType(conj, Annotation(defn.UncheckedStableAnnot))
AnnotatedType(conj, Annotation(defn.UncheckedStableAnnot, tree.symbol.span))
else conj
else pt
gadts.println(i"insert GADT cast from $tree to $target")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import core.*
import Contexts.*, Decorators.*, Denotations.*, SymDenotations.*, Symbols.*, Types.*
import Annotations.*

import dotty.tools.dotc.util.Spans.Span

import org.junit.Test
import org.junit.Assert.*

Expand All @@ -15,7 +17,7 @@ class TypeTestsCastsTest extends DottyTest:
@Test def orL = checkFound(List(StringType, LongType), OrType(LongType, StringType, false))
@Test def orR = checkFound(List(LongType, StringType), OrType(StringType, LongType, false))

@Test def annot = checkFound(List(StringType, LongType), AnnotatedType(OrType(LongType, StringType, false), Annotation(defn.UncheckedAnnot)))
@Test def annot = checkFound(List(StringType, LongType), AnnotatedType(OrType(LongType, StringType, false), Annotation(defn.UncheckedAnnot, Span(0))))

@Test def andL = checkFound(List(StringType), AndType(StringType, AnyType))
@Test def andR = checkFound(List(StringType), AndType(AnyType, StringType))
Expand Down
11 changes: 11 additions & 0 deletions tests/pos-macros/i16318/Macro_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import scala.quoted.*

final case class Record(a: String, b: Int)

transparent inline def ann[T]: List[Any] = ${ annsImpl[T] }

def annsImpl[T: Type](using Quotes): Expr[List[Any]] = {
import quotes.reflect.*
val annExpr = TypeRepr.of[T].typeSymbol.annotations.head.asExpr
'{ List($annExpr) }
}
2 changes: 2 additions & 0 deletions tests/pos-macros/i16318/Test_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def Test =
val a = ann[Record]