Skip to content

Commit 5e752c3

Browse files
committed
Drop annotations from constructor parameters
Scala 2 preserves annotations both on the param accessors and on compiler-generated methods such as copy, so we should do the same. But there doesn't seem to be much point in preserving them on the type parameters of the constructors. Removing them avoids a cyclic reference error involving `@specialized` which happened in the past and resurfaced with the completions-related changes in this PR.
1 parent c5ba1e9 commit 5e752c3

File tree

2 files changed

+43
-20
lines changed

2 files changed

+43
-20
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,8 @@ object desugar {
267267
def defaultGetter: DefDef =
268268
DefDef(
269269
name = DefaultGetterName(methName, n),
270-
tparams = meth.tparams.map(tparam => dropContextBounds(toDefParam(tparam))),
271-
vparamss = takeUpTo(normalizedVparamss.nestedMap(toDefParam), n),
270+
tparams = meth.tparams.map(tparam => dropContextBounds(toDefParam(tparam, keepAnnotations = true))),
271+
vparamss = takeUpTo(normalizedVparamss.nestedMap(toDefParam(_, keepAnnotations = true)), n),
272272
tpt = TypeTree(),
273273
rhs = vparam.rhs
274274
)
@@ -372,10 +372,16 @@ object desugar {
372372

373373
@sharable private val synthetic = Modifiers(Synthetic)
374374

375-
private def toDefParam(tparam: TypeDef): TypeDef =
376-
tparam.withMods(tparam.rawMods & EmptyFlags | Param)
377-
private def toDefParam(vparam: ValDef): ValDef =
378-
vparam.withMods(vparam.rawMods & (GivenOrImplicit | Erased) | Param)
375+
private def toDefParam(tparam: TypeDef, keepAnnotations: Boolean): TypeDef = {
376+
var mods = tparam.rawMods
377+
if (!keepAnnotations) mods = mods.withAnnotations(Nil)
378+
tparam.withMods(mods & EmptyFlags | Param)
379+
}
380+
private def toDefParam(vparam: ValDef, keepAnnotations: Boolean): ValDef = {
381+
var mods = vparam.rawMods
382+
if (!keepAnnotations) mods = mods.withAnnotations(Nil)
383+
vparam.withMods(mods & (GivenOrImplicit | Erased) | Param)
384+
}
379385

380386
/** The expansion of a class definition. See inline comments for what is involved */
381387
def classDef(cdef: TypeDef)(implicit ctx: Context): Tree = {
@@ -437,7 +443,7 @@ object desugar {
437443
else originalTparams
438444
}
439445
else originalTparams
440-
val constrTparams = impliedTparams.map(toDefParam)
446+
val constrTparams = impliedTparams.map(toDefParam(_, keepAnnotations = false))
441447
val constrVparamss =
442448
if (originalVparamss.isEmpty) { // ensure parameter list is non-empty
443449
if (isCaseClass && originalTparams.isEmpty)
@@ -447,7 +453,7 @@ object desugar {
447453
ctx.error("Case classes should have a non-implicit parameter list", namePos)
448454
ListOfNil
449455
}
450-
else originalVparamss.nestedMap(toDefParam)
456+
else originalVparamss.nestedMap(toDefParam(_, keepAnnotations = false))
451457
val constr = cpy.DefDef(constr1)(tparams = constrTparams, vparamss = constrVparamss)
452458

453459
val (normalizedBody, enumCases, enumCompanionRef) = {
@@ -459,7 +465,7 @@ object desugar {
459465
defDef(
460466
addEvidenceParams(
461467
cpy.DefDef(ddef)(tparams = constrTparams),
462-
evidenceParams(constr1).map(toDefParam))))
468+
evidenceParams(constr1).map(toDefParam(_, keepAnnotations = false)))))
463469
case stat =>
464470
stat
465471
}
@@ -482,8 +488,19 @@ object desugar {
482488

483489
def anyRef = ref(defn.AnyRefAlias.typeRef)
484490

485-
val derivedTparams = constrTparams.map(derivedTypeParam(_))
486-
val derivedVparamss = constrVparamss.nestedMap(derivedTermParam(_))
491+
// Annotations are dropped from the constructor parameters but should be
492+
// preserved in all derived parameters.
493+
val derivedTparams = {
494+
val impliedTparamsIt = impliedTparams.toIterator
495+
constrTparams.map(tparam => derivedTypeParam(tparam)
496+
.withAnnotations(impliedTparamsIt.next().mods.annotations))
497+
}
498+
val derivedVparamss = {
499+
val constrVparamsIt = constrVparamss.toIterator.flatten
500+
constrVparamss.nestedMap(vparam => derivedTermParam(vparam)
501+
.withAnnotations(constrVparamsIt.next().mods.annotations))
502+
}
503+
487504
val arity = constrVparamss.head.length
488505

489506
val classTycon: Tree = TypeRefTree() // watching is set at end of method
@@ -772,16 +789,20 @@ object desugar {
772789
}
773790

774791
val cdef1 = addEnumFlags {
775-
val originalTparamsIt = impliedTparams.toIterator
776-
val originalVparamsIt = originalVparamss.toIterator.flatten
777-
val tparamAccessors = derivedTparams.map(_.withMods(originalTparamsIt.next().mods))
792+
val tparamAccessors = {
793+
val impliedTparamsIt = impliedTparams.toIterator
794+
derivedTparams.map(_.withMods(impliedTparamsIt.next().mods))
795+
}
778796
val caseAccessor = if (isCaseClass) CaseAccessor else EmptyFlags
779-
val vparamAccessors = derivedVparamss match {
780-
case first :: rest =>
781-
first.map(_.withMods(originalVparamsIt.next().mods | caseAccessor)) ++
782-
rest.flatten.map(_.withMods(originalVparamsIt.next().mods))
783-
case _ =>
784-
Nil
797+
val vparamAccessors = {
798+
val originalVparamsIt = originalVparamss.toIterator.flatten
799+
derivedVparamss match {
800+
case first :: rest =>
801+
first.map(_.withMods(originalVparamsIt.next().mods | caseAccessor)) ++
802+
rest.flatten.map(_.withMods(originalVparamsIt.next().mods))
803+
case _ =>
804+
Nil
805+
}
785806
}
786807
cpy.TypeDef(cdef: TypeDef)(
787808
name = className,

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,8 @@ object Trees {
327327

328328
def rawComment: Option[Comment] = getAttachment(DocComment)
329329

330+
def withAnnotations(annots: List[untpd.Tree]): ThisTree[Untyped] = withMods(rawMods.withAnnotations(annots))
331+
330332
def withMods(mods: untpd.Modifiers): ThisTree[Untyped] = {
331333
val tree = if (myMods == null || (myMods == mods)) this else cloneIn(source)
332334
tree.setMods(mods)

0 commit comments

Comments
 (0)