Skip to content

Commit 48dcb89

Browse files
committed
Fixes to positions
- harden addChild to also work if existing children don't have positions (this can happen if they came from other compilation units) - tweak position of Deriver, so that it always points to the deriving class template.
1 parent af94114 commit 48dcb89

File tree

5 files changed

+25
-13
lines changed

5 files changed

+25
-13
lines changed

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

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,13 @@ object desugar {
2222
/** If a Select node carries this attachment, suppress the check
2323
* that its type refers to an acessible symbol.
2424
*/
25-
val SuppressAccessCheck = new Property.Key[Unit]
25+
val SuppressAccessCheck: Property.Key[Unit] = new Property.Key
26+
27+
/** An attachment for companion modules of classes that have a `derives` clause.
28+
* The position value indicates the start position of the template of the
29+
* deriving class.
30+
*/
31+
val DerivingCompanion: Property.Key[Position] = new Property.Key
2632

2733
/** Info of a variable in a pattern: The named tree and its type */
2834
private type VarInfo = (NameTree, Tree)
@@ -545,12 +551,17 @@ object desugar {
545551

546552
// The thicket which is the desugared version of the companion object
547553
// synthetic object C extends parentTpt derives class-derived { defs }
548-
def companionDefs(parentTpt: Tree, defs: List[Tree]) =
549-
moduleDef(
554+
def companionDefs(parentTpt: Tree, defs: List[Tree]) = {
555+
val mdefs = moduleDef(
550556
ModuleDef(
551557
className.toTermName, Template(emptyConstructor, parentTpt :: Nil, companionDerived, EmptyValDef, defs))
552558
.withMods(companionMods | Synthetic))
553-
.withPos(cdef.pos).toList
559+
.withPos(cdef.pos).toList
560+
if (companionDerived.nonEmpty)
561+
for (modClsDef @ TypeDef(_, _) <- mdefs)
562+
modClsDef.putAttachment(DerivingCompanion, impl.pos.startPos)
563+
mdefs
564+
}
554565

555566
val companionMembers = defaultGetters ::: eqInstances ::: enumCases
556567

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,6 @@ class Namer { typer: Typer =>
196196
val TypedAhead: Property.Key[tpd.Tree] = new Property.Key
197197
val ExpandedTree: Property.Key[untpd.Tree] = new Property.Key
198198
val SymOfTree: Property.Key[Symbol] = new Property.Key
199-
val DerivingCompanion: Property.Key[Unit] = new Property.Key
200199
val Deriver: Property.Key[typer.Deriver] = new Property.Key
201200

202201
/** A partial map from unexpanded member and pattern defs and to their expansions.
@@ -508,7 +507,7 @@ class Namer { typer: Typer =>
508507
val childStart = child.pos.start
509508
def insertInto(annots: List[Annotation]): List[Annotation] =
510509
annots.find(_.symbol == defn.ChildAnnot) match {
511-
case Some(Annotation.Child(other)) if childStart <= other.pos.start =>
510+
case Some(Annotation.Child(other)) if other.pos.exists && childStart <= other.pos.start =>
512511
if (child == other)
513512
annots // can happen if a class has several inaccessible children
514513
else {
@@ -574,7 +573,7 @@ class Namer { typer: Typer =>
574573
if (fromTempl.derived.nonEmpty) {
575574
if (modTempl.derived.nonEmpty)
576575
ctx.error(em"a class and its companion cannot both have `derives' clauses", mdef.pos)
577-
res.putAttachment(DerivingCompanion, ())
576+
res.putAttachment(desugar.DerivingCompanion, fromTempl.pos.startPos)
578577
}
579578
res
580579
}
@@ -1012,11 +1011,11 @@ class Namer { typer: Typer =>
10121011
typr.println(i"completing $denot, parents = $parents%, %, parentTypes = $parentTypes%, %")
10131012

10141013
if (impl.derived.nonEmpty) {
1015-
val derivingClass =
1016-
if (original.removeAttachment(DerivingCompanion).isDefined ||
1017-
original.mods.is(Synthetic)) cls.companionClass.asClass
1018-
else cls
1019-
val deriver = new Deriver(derivingClass, impl.pos.startPos)(localCtx)
1014+
val (derivingClass, derivePos) = original.removeAttachment(desugar.DerivingCompanion) match {
1015+
case Some(pos) => (cls.companionClass.asClass, pos)
1016+
case None => (cls, impl.pos.startPos)
1017+
}
1018+
val deriver = new Deriver(derivingClass, derivePos)(localCtx)
10201019
deriver.enterDerived(impl.derived)
10211020
original.putAttachment(Deriver, deriver)
10221021
}

compiler/test/dotc/run-from-tasty.blacklist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ typeclass-derivation1.scala
1010
typeclass-derivation2.scala
1111
typeclass-derivation2a.scala
1212
typeclass-derivation3.scala
13+
derive-generic.scala
1314
deriving-interesting-prefixes.scala
1415

compiler/test/dotc/run-test-pickling.blacklist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ typeclass-derivation1.scala
1818
typeclass-derivation2.scala
1919
typeclass-derivation2a.scala
2020
typeclass-derivation3.scala
21+
derive-generic.scala
2122
deriving-interesting-prefixes.scala

tests/neg/deriving.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import reflect.Generic
22

3-
sealed trait A derives Generic // error: cannot take shape, it has anonymous or inaccessible subclasses
3+
sealed trait A derives Generic // error: cannot take shape, it has anonymous or inaccessible subclasses
44

55
object A {
66
def f() = {

0 commit comments

Comments
 (0)