Skip to content

Commit

Permalink
Always add spans to compiler generated anonotations
Browse files Browse the repository at this point in the history
Achieved by removing the apply methods without a span argument,
which would generate Annotation trees with empty spans. One can still
put NoSpan as the span argument, so this will not make much of a
difference, but will hopefully provide an additional incentive to always
add one.
  • Loading branch information
jchyb committed Dec 21, 2022
1 parent ed2799a commit dfad52b
Show file tree
Hide file tree
Showing 16 changed files with 34 additions and 49 deletions.
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
24 changes: 3 additions & 21 deletions compiler/src/dotty/tools/dotc/core/Annotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -194,36 +194,18 @@ object Annotations {
object Annotation {

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

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

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

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

def apply(cls: ClassSymbol, arg: Tree, span: Span)(using Context): Annotation =
apply(cls, arg :: Nil, 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(cls: ClassSymbol, args: List[Tree], span: Span)(using Context): Annotation =
apply(cls.typeRef, args, span)

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))
Expand Down Expand Up @@ -271,7 +253,7 @@ object Annotations {

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
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

0 comments on commit dfad52b

Please sign in to comment.