From 41ff7c286525855e345fc0641481a7cd9ec2ccee Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 26 Sep 2016 08:44:39 +0200 Subject: [PATCH 1/4] Drop tpd.modsDeco Prefer to access directly via symbol. --- .../backend/jvm/DottyBackendInterface.scala | 6 ++--- src/dotty/tools/dotc/ast/TreeInfo.scala | 27 ++++++++++--------- src/dotty/tools/dotc/ast/Trees.scala | 7 +---- src/dotty/tools/dotc/ast/tpd.scala | 4 --- src/dotty/tools/dotc/ast/untpd.scala | 17 +++--------- .../tools/dotc/printing/RefinedPrinter.scala | 6 +++-- src/dotty/tools/dotc/transform/LazyVals.scala | 6 ++--- .../tools/dotc/transform/TreeChecker.scala | 1 - 8 files changed, 28 insertions(+), 46 deletions(-) diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 34bcd0757cef..c70cb4be2188 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -944,7 +944,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma } object ValDef extends ValDefDeconstructor { - def _1: Modifiers = field.mods + def _1: Modifiers = tpd.Modifiers(field.symbol) def _2: Name = field.name def _3: Tree = field.tpt def _4: Tree = field.rhs @@ -1055,7 +1055,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma } object DefDef extends DefDefDeconstructor { - def _1: Modifiers = field.mods + def _1: Modifiers = tpd.Modifiers(field.symbol) def _2: Name = field.name def _3: List[TypeDef] = field.tparams def _4: List[List[ValDef]] = field.vparamss @@ -1081,7 +1081,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma } object ClassDef extends ClassDefDeconstructor { - def _1: Modifiers = field.mods + def _1: Modifiers = tpd.Modifiers(field.symbol) def _2: Name = field.name def _4: Template = field.rhs.asInstanceOf[Template] def _3: List[TypeDef] = Nil diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala index d6df204c1631..725838ef6d2d 100644 --- a/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -249,17 +249,6 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] => /** Is this case guarded? */ def isGuardedCase(cdef: CaseDef) = cdef.guard ne EmptyTree - /** True iff definition is a val or def with no right-hand-side, or it - * is an abstract typoe declaration - */ - def lacksDefinition(mdef: MemberDef)(implicit ctx: Context) = mdef match { - case mdef: ValOrDefDef => - mdef.unforcedRhs == EmptyTree && !mdef.name.isConstructorName && !mdef.mods.is(ParamAccessor) - case mdef: TypeDef => - mdef.rhs.isEmpty || mdef.rhs.isInstanceOf[TypeBoundsTree] - case _ => false - } - /** The underlying pattern ignoring any bindings */ def unbind(x: Tree): Tree = unsplice(x) match { case Bind(_, y) => unbind(y) @@ -279,9 +268,21 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] => trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped] => import TreeInfo._ + import untpd._ + + /** True iff definition is a val or def with no right-hand-side, or it + * is an abstract typoe declaration + */ + def lacksDefinition(mdef: MemberDef)(implicit ctx: Context) = mdef match { + case mdef: ValOrDefDef => + mdef.unforcedRhs == EmptyTree && !mdef.name.isConstructorName && !mdef.mods.is(ParamAccessor) + case mdef: TypeDef => + mdef.rhs.isEmpty || mdef.rhs.isInstanceOf[TypeBoundsTree] + case _ => false + } def isFunctionWithUnknownParamType(tree: Tree) = tree match { - case untpd.Function(args, _) => + case Function(args, _) => args.exists { case ValDef(_, tpt, _) => tpt.isEmpty case _ => false @@ -307,7 +308,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => | DefDef(_, _, _, _, _) => Pure case vdef @ ValDef(_, _, _) => - if (vdef.mods is Mutable) Impure else exprPurity(vdef.rhs) + if (vdef.symbol.flags is Mutable) Impure else exprPurity(vdef.rhs) case _ => Impure } diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index 528e3c589bb1..061a0c019d54 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -322,7 +322,7 @@ object Trees { private[this] var myMods: Modifiers[T] = null - private[ast] def rawMods: Modifiers[T] = + private[dotc] def rawMods: Modifiers[T] = if (myMods == null) genericEmptyModifiers else myMods def rawComment: Option[Comment] = getAttachment(DocComment) @@ -870,11 +870,6 @@ object Trees { case ys => Thicket(ys) } - // ----- Accessing modifiers ---------------------------------------------------- - - abstract class ModsDeco { def mods: Modifiers } - implicit def modsDeco(mdef: MemberDef)(implicit ctx: Context): ModsDeco - // ----- Helper classes for copying, transforming, accumulating ----------------- val cpy: TreeCopier diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala index 31a9c6975ea8..355843cad31a 100644 --- a/src/dotty/tools/dotc/ast/tpd.scala +++ b/src/dotty/tools/dotc/ast/tpd.scala @@ -446,10 +446,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } else foldOver(sym, tree) } - implicit class modsDeco(mdef: MemberDef)(implicit ctx: Context) extends ModsDeco { - def mods = if (mdef.hasType) Modifiers(mdef.symbol) else mdef.rawMods - } - override val cpy = new TypedTreeCopier class TypedTreeCopier extends TreeCopier { diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala index d6af6ecd016c..102ee2e4eb26 100644 --- a/src/dotty/tools/dotc/ast/untpd.scala +++ b/src/dotty/tools/dotc/ast/untpd.scala @@ -264,22 +264,11 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { /** A repeated argument such as `arg: _*` */ def repeated(arg: Tree)(implicit ctx: Context) = Typed(arg, Ident(tpnme.WILDCARD_STAR)) -// ------- Decorators ------------------------------------------------- +// ----- Accessing modifiers ---------------------------------------------------- - implicit class UntypedTreeDecorator(val self: Tree) extends AnyVal { - def locateEnclosing(base: List[Tree], pos: Position): List[Tree] = { - def encloses(elem: Any) = elem match { - case t: Tree => t.pos contains pos - case _ => false - } - base.productIterator find encloses match { - case Some(tree: Tree) => locateEnclosing(tree :: base, pos) - case none => base - } - } - } + abstract class ModsDecorator { def mods: Modifiers } - implicit class modsDeco(val mdef: MemberDef)(implicit ctx: Context) extends ModsDeco { + implicit class modsDeco(val mdef: MemberDef)(implicit ctx: Context) { def mods = mdef.rawMods } diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 1125f5f01f0a..8b91d1a7aad2 100644 --- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -161,8 +161,10 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { import untpd.{modsDeco => _, _} /** Print modifiers from symbols if tree has type, overriding the untpd behavior. */ - implicit def modsDeco(mdef: untpd.MemberDef)(implicit ctx: Context): untpd.ModsDeco = - tpd.modsDeco(mdef.asInstanceOf[tpd.MemberDef]).asInstanceOf[untpd.ModsDeco] + implicit def modsDeco(mdef: untpd.MemberDef)(implicit ctx: Context): untpd.ModsDecorator = + new untpd.ModsDecorator { + def mods = if (mdef.hasType) tpd.Modifiers(mdef.symbol) else mdef.rawMods + } def isLocalThis(tree: Tree) = tree.typeOpt match { case tp: ThisType => tp.cls == ctx.owner.enclosingClass diff --git a/src/dotty/tools/dotc/transform/LazyVals.scala b/src/dotty/tools/dotc/transform/LazyVals.scala index 424bc4f8eb68..e63a7c3a7575 100644 --- a/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/src/dotty/tools/dotc/transform/LazyVals.scala @@ -210,7 +210,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { def transformMemberDefNonVolatile(x: ValOrDefDef)(implicit ctx: Context) = { val claz = x.symbol.owner.asClass val tpe = x.tpe.widen.resultType.widen - assert(!(x.mods is Flags.Mutable)) + assert(!(x.symbol is Flags.Mutable)) val containerName = ctx.freshName(x.name.asTermName.lazyLocalName).toTermName val containerSymbol = ctx.newSymbol(claz, containerName, x.symbol.flags &~ containerFlagsMask | containerFlags | Flags.Private, @@ -331,7 +331,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { } def transformMemberDefVolatile(x: ValOrDefDef)(implicit ctx: Context) = { - assert(!(x.mods is Flags.Mutable)) + assert(!(x.symbol is Flags.Mutable)) val tpe = x.tpe.widen.resultType.widen val claz = x.symbol.owner.asClass @@ -377,7 +377,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { } val containerName = ctx.freshName(x.name.asTermName.lazyLocalName).toTermName - val containerSymbol = ctx.newSymbol(claz, containerName, (x.mods &~ containerFlagsMask | containerFlags).flags, tpe, coord = x.symbol.coord).enteredAfter(this) + val containerSymbol = ctx.newSymbol(claz, containerName, x.symbol.flags &~ containerFlagsMask | containerFlags, tpe, coord = x.symbol.coord).enteredAfter(this) val containerTree = ValDef(containerSymbol, defaultValue(tpe)) diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala index 7cd1267b81b7..e7342aec9c02 100644 --- a/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -164,7 +164,6 @@ class TreeChecker extends Phase with SymTransformer { tree match { case t: MemberDef => if (t.name ne sym.name) ctx.warning(s"symbol ${sym.fullName} name doesn't correspond to AST: ${t}") - if (sym.flags != t.mods.flags) ctx.warning(s"symbol ${sym.fullName} flags ${sym.flags} doesn't match AST definition flags ${t.mods.flags}") // todo: compare trees inside annotations case _ => } From 517aafc8e42f7204debdd2d9bff30c9fb90fab98 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 26 Sep 2016 13:46:26 +0200 Subject: [PATCH 2/4] Eliminate tpd.Modifiers. Backend does not need them after all, can just use nulls there. So the functionality is only used for printing, and it makes sense to move everything there. --- src/dotty/tools/backend/jvm/DottyBackendInterface.scala | 8 ++++---- src/dotty/tools/dotc/ast/tpd.scala | 5 ----- src/dotty/tools/dotc/printing/RefinedPrinter.scala | 7 ++++++- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index c70cb4be2188..2d60d851cf96 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -70,7 +70,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma type Bind = tpd.Bind type New = tpd.New type Super = tpd.Super - type Modifiers = tpd.Modifiers + type Modifiers = Null type Annotation = Annotations.Annotation type ArrayValue = tpd.JavaSeqLiteral type ApplyDynamic = Null @@ -944,7 +944,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma } object ValDef extends ValDefDeconstructor { - def _1: Modifiers = tpd.Modifiers(field.symbol) + def _1: Modifiers = null def _2: Name = field.name def _3: Tree = field.tpt def _4: Tree = field.rhs @@ -1055,7 +1055,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma } object DefDef extends DefDefDeconstructor { - def _1: Modifiers = tpd.Modifiers(field.symbol) + def _1: Modifiers = null def _2: Name = field.name def _3: List[TypeDef] = field.tparams def _4: List[List[ValDef]] = field.vparamss @@ -1081,7 +1081,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma } object ClassDef extends ClassDefDeconstructor { - def _1: Modifiers = tpd.Modifiers(field.symbol) + def _1: Modifiers = null def _2: Name = field.name def _4: Template = field.rhs.asInstanceOf[Template] def _3: List[TypeDef] = Nil diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala index 355843cad31a..f59bb7a476e2 100644 --- a/src/dotty/tools/dotc/ast/tpd.scala +++ b/src/dotty/tools/dotc/ast/tpd.scala @@ -19,11 +19,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { private def ta(implicit ctx: Context) = ctx.typeAssigner - def Modifiers(sym: Symbol)(implicit ctx: Context): Modifiers = Modifiers( - sym.flags & (if (sym.isType) ModifierFlags | VarianceFlags else ModifierFlags), - if (sym.privateWithin.exists) sym.privateWithin.asType.name else tpnme.EMPTY, - sym.annotations map (_.tree)) - def Ident(tp: NamedType)(implicit ctx: Context): Ident = ta.assignType(untpd.Ident(tp.name), tp) diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 8b91d1a7aad2..205d2b6b93bf 100644 --- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -163,9 +163,14 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { /** Print modifiers from symbols if tree has type, overriding the untpd behavior. */ implicit def modsDeco(mdef: untpd.MemberDef)(implicit ctx: Context): untpd.ModsDecorator = new untpd.ModsDecorator { - def mods = if (mdef.hasType) tpd.Modifiers(mdef.symbol) else mdef.rawMods + def mods = if (mdef.hasType) Modifiers(mdef.symbol) else mdef.rawMods } + def Modifiers(sym: Symbol)(implicit ctx: Context): Modifiers = untpd.Modifiers( + sym.flags & (if (sym.isType) ModifierFlags | VarianceFlags else ModifierFlags), + if (sym.privateWithin.exists) sym.privateWithin.asType.name else tpnme.EMPTY, + sym.annotations map (_.tree)) + def isLocalThis(tree: Tree) = tree.typeOpt match { case tp: ThisType => tp.cls == ctx.owner.enclosingClass case _ => false From 992c72ee5f2f105d587de20efd3858824fc7e7c8 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 28 Sep 2016 09:33:32 +0200 Subject: [PATCH 3/4] Make Modifiers untyped only. The typed variant is no longer needed. This means modifiers can safely be ignored in typed trees if we so choose. --- src/dotty/tools/dotc/ast/Trees.scala | 68 +++---------------- src/dotty/tools/dotc/ast/untpd.scala | 46 +++++++++++++ .../tools/dotc/core/tasty/TreeUnpickler.scala | 4 +- .../core/unpickleScala2/Scala2Unpickler.scala | 3 +- 4 files changed, 58 insertions(+), 63 deletions(-) diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index 061a0c019d54..619ac36e500b 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -33,51 +33,7 @@ object Trees { /** Attachment key for trees with documentation strings attached */ val DocComment = new Attachment.Key[Comment] - /** Modifiers and annotations for definitions - * @param flags The set flags - * @param privateWithin If a private or protected has is followed by a - * qualifier [q], the name q, "" as a typename otherwise. - * @param annotations The annotations preceding the modifiers - */ - case class Modifiers[-T >: Untyped] ( - flags: FlagSet = EmptyFlags, - privateWithin: TypeName = tpnme.EMPTY, - annotations: List[Tree[T]] = Nil) extends Positioned with Cloneable { - - def is(fs: FlagSet): Boolean = flags is fs - def is(fc: FlagConjunction): Boolean = flags is fc - - def | (fs: FlagSet): Modifiers[T] = withFlags(flags | fs) - def & (fs: FlagSet): Modifiers[T] = withFlags(flags & fs) - def &~(fs: FlagSet): Modifiers[T] = withFlags(flags &~ fs) - - def toTypeFlags: Modifiers[T] = withFlags(flags.toTypeFlags) - def toTermFlags: Modifiers[T] = withFlags(flags.toTermFlags) - - def withFlags(flags: FlagSet) = - if (this.flags == flags) this - else copy(flags = flags) - - def withAddedAnnotation[U >: Untyped <: T](annot: Tree[U]): Modifiers[U] = - if (annotations.exists(_ eq annot)) this - else withAnnotations(annotations :+ annot) - - def withAnnotations[U >: Untyped <: T](annots: List[Tree[U]]): Modifiers[U] = - if (annots eq annotations) this - else copy(annotations = annots) - - def withPrivateWithin(pw: TypeName) = - if (pw.isEmpty) this - else copy(privateWithin = pw) - - def hasFlags = flags != EmptyFlags - def hasAnnotations = annotations.nonEmpty - def hasPrivateWithin = privateWithin != tpnme.EMPTY - - def tokenPos: Seq[(Token, Position)] = ??? - } - - @sharable private var nextId = 0 // for debugging + @sharable private var nextId = 0 // for debugging type LazyTree = AnyRef /* really: Tree | Lazy[Tree] */ type LazyTreeList = AnyRef /* really: List[Tree] | Lazy[List[Tree]] */ @@ -320,27 +276,27 @@ object Trees { abstract class MemberDef[-T >: Untyped] extends NameTree[T] with DefTree[T] { type ThisTree[-T >: Untyped] <: MemberDef[T] - private[this] var myMods: Modifiers[T] = null + private[this] var myMods: untpd.Modifiers = null - private[dotc] def rawMods: Modifiers[T] = - if (myMods == null) genericEmptyModifiers else myMods + private[dotc] def rawMods: untpd.Modifiers = + if (myMods == null) untpd.EmptyModifiers else myMods def rawComment: Option[Comment] = getAttachment(DocComment) - def withMods(mods: Modifiers[Untyped]): ThisTree[Untyped] = { + def withMods(mods: untpd.Modifiers): ThisTree[Untyped] = { val tree = if (myMods == null || (myMods == mods)) this else clone.asInstanceOf[MemberDef[Untyped]] tree.setMods(mods) tree.asInstanceOf[ThisTree[Untyped]] } - def withFlags(flags: FlagSet): ThisTree[Untyped] = withMods(Modifiers(flags)) + def withFlags(flags: FlagSet): ThisTree[Untyped] = withMods(untpd.Modifiers(flags)) def setComment(comment: Option[Comment]): ThisTree[Untyped] = { comment.map(putAttachment(DocComment, _)) asInstanceOf[ThisTree[Untyped]] } - protected def setMods(mods: Modifiers[T @uncheckedVariance]) = myMods = mods + protected def setMods(mods: untpd.Modifiers) = myMods = mods } /** A ValDef or DefDef tree */ @@ -727,16 +683,14 @@ object Trees { class EmptyValDef[T >: Untyped] extends ValDef[T]( nme.WILDCARD, genericEmptyTree[T], genericEmptyTree[T]) with WithoutTypeOrPos[T] { override def isEmpty: Boolean = true - setMods(Modifiers[T](PrivateLocal)) + setMods(untpd.Modifiers(PrivateLocal)) } @sharable val theEmptyTree: Thicket[Type] = Thicket(Nil) @sharable val theEmptyValDef = new EmptyValDef[Type] - @sharable val theEmptyModifiers = new Modifiers() def genericEmptyValDef[T >: Untyped]: ValDef[T] = theEmptyValDef.asInstanceOf[ValDef[T]] def genericEmptyTree[T >: Untyped]: Thicket[T] = theEmptyTree.asInstanceOf[Thicket[T]] - def genericEmptyModifiers[T >: Untyped]: Modifiers[T] = theEmptyModifiers.asInstanceOf[Modifiers[T]] def flatten[T >: Untyped](trees: List[Tree[T]]): List[Tree[T]] = { var buf: ListBuffer[Tree[T]] = null @@ -795,7 +749,6 @@ object Trees { abstract class Instance[T >: Untyped <: Type] extends DotClass { inst => - type Modifiers = Trees.Modifiers[T] type Tree = Trees.Tree[T] type TypTree = Trees.TypTree[T] type TermTree = Trees.TermTree[T] @@ -853,14 +806,9 @@ object Trees { @sharable val EmptyTree: Thicket = genericEmptyTree @sharable val EmptyValDef: ValDef = genericEmptyValDef - @sharable val EmptyModifiers: Modifiers = genericEmptyModifiers // ----- Auxiliary creation methods ------------------ - def Modifiers(flags: FlagSet = EmptyFlags, - privateWithin: TypeName = tpnme.EMPTY, - annotations: List[Tree] = Nil) = new Modifiers(flags, privateWithin, annotations) - def Thicket(trees: List[Tree]): Thicket = new Thicket(trees) def Thicket(): Thicket = EmptyTree def Thicket(x1: Tree, x2: Tree): Thicket = Thicket(x1 :: x2 :: Nil) diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala index 102ee2e4eb26..61c3a79a4a16 100644 --- a/src/dotty/tools/dotc/ast/untpd.scala +++ b/src/dotty/tools/dotc/ast/untpd.scala @@ -86,6 +86,52 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { */ class InfixOpBlock(leftOperand: Tree, rightOp: Tree) extends Block(leftOperand :: Nil, rightOp) + // ----- Modifiers ----------------------------------------------------- + + /** Modifiers and annotations for definitions + * @param flags The set flags + * @param privateWithin If a private or protected has is followed by a + * qualifier [q], the name q, "" as a typename otherwise. + * @param annotations The annotations preceding the modifiers + */ + case class Modifiers ( + flags: FlagSet = EmptyFlags, + privateWithin: TypeName = tpnme.EMPTY, + annotations: List[Tree] = Nil) extends Positioned with Cloneable { + + def is(fs: FlagSet): Boolean = flags is fs + def is(fc: FlagConjunction): Boolean = flags is fc + + def | (fs: FlagSet): Modifiers = withFlags(flags | fs) + def & (fs: FlagSet): Modifiers = withFlags(flags & fs) + def &~(fs: FlagSet): Modifiers = withFlags(flags &~ fs) + + def toTypeFlags: Modifiers = withFlags(flags.toTypeFlags) + def toTermFlags: Modifiers = withFlags(flags.toTermFlags) + + def withFlags(flags: FlagSet) = + if (this.flags == flags) this + else copy(flags = flags) + + def withAddedAnnotation(annot: Tree): Modifiers = + if (annotations.exists(_ eq annot)) this + else withAnnotations(annotations :+ annot) + + def withAnnotations(annots: List[Tree]): Modifiers = + if (annots eq annotations) this + else copy(annotations = annots) + + def withPrivateWithin(pw: TypeName) = + if (pw.isEmpty) this + else copy(privateWithin = pw) + + def hasFlags = flags != EmptyFlags + def hasAnnotations = annotations.nonEmpty + def hasPrivateWithin = privateWithin != tpnme.EMPTY + } + + @sharable val EmptyModifiers: Modifiers = new Modifiers() + // ----- TypeTrees that refer to other tree's symbols ------------------- /** A type tree that gets its type from some other tree's symbol. Enters the diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index f7363e72bba7..9d070e7771d7 100644 --- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -729,8 +729,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { } } val mods = - if (sym.annotations.isEmpty) EmptyModifiers - else Modifiers(annotations = sym.annotations.map(_.tree)) + if (sym.annotations.isEmpty) untpd.EmptyModifiers + else untpd.Modifiers(annotations = sym.annotations.map(_.tree)) tree.withMods(mods) // record annotations in tree so that tree positions can be filled in. goto(end) setPos(start, tree) diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index d278fdef1fff..70148b3e2a61 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -12,6 +12,7 @@ import StdNames._, Denotations._, NameOps._, Flags._, Constants._, Annotations._ import dotty.tools.dotc.typer.ProtoTypes.{FunProtoTyped, FunProto} import util.Positions._ import dotty.tools.dotc.ast.{tpd, Trees, untpd}, ast.tpd._ +import ast.untpd.Modifiers import printing.Texts._ import printing.Printer import io.AbstractFile @@ -1236,7 +1237,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas val pflags = (pflagsHi.toLong << 32) + pflagsLo val flags = unpickleScalaFlags(pflags, isType) val privateWithin = readNameRef().asTypeName - Trees.Modifiers[Type](flags, privateWithin, Nil) + Modifiers(flags, privateWithin, Nil) } protected def readTemplateRef()(implicit ctx: Context): Template = From 887a63a3dac0dcbaa7fc07ebb6ccac0dbe515427 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 29 Sep 2016 14:00:29 +0200 Subject: [PATCH 4/4] Make namePos a member of memberDef That way it can be accessed by other parts which deal with error messages. --- src/dotty/tools/dotc/ast/Trees.scala | 14 ++++++++++++++ .../tools/dotc/core/tasty/TreeUnpickler.scala | 5 ++++- src/dotty/tools/dotc/typer/Namer.scala | 15 ++------------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index 619ac36e500b..bb6fbd5baa38 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -297,6 +297,20 @@ object Trees { } protected def setMods(mods: untpd.Modifiers) = myMods = mods + + /** The position of the name defined by this definition. + * This is a point position if the definition is synthetic, or a range position + * if the definition comes from source. + * It might also be that the definition does not have a position (for instance when synthesized by + * a calling chain from `viewExists`), in that case the return position is NoPosition. + */ + def namePos = + if (pos.exists) + if (rawMods.is(Synthetic)) Position(pos.point, pos.point) + else Position(pos.point, pos.point + name.length, pos.point) + else pos + + } /** A ValDef or DefDef tree */ diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 9d070e7771d7..56bb8498aa5b 100644 --- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -731,7 +731,10 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { val mods = if (sym.annotations.isEmpty) untpd.EmptyModifiers else untpd.Modifiers(annotations = sym.annotations.map(_.tree)) - tree.withMods(mods) // record annotations in tree so that tree positions can be filled in. + tree.withMods(mods) + // record annotations in tree so that tree positions can be filled in. + // Note: Once the inline PR with its changes to positions is in, this should be + // no longer necessary. goto(end) setPos(start, tree) } diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index a0862ee38b54..cfd49fd8704d 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -274,17 +274,6 @@ class Namer { typer: Typer => val inSuperCall = if (ctx.mode is Mode.InSuperCall) InSuperCall else EmptyFlags - /** The position of the name defined by `tree` - * This is a point position if tree is synthetic, a range position if it comes from source. - * It might also be that tree does not have a position (for instance when synthesized by - * a calling chain from `viewExists`), in that case the return position is NoPosition. - */ - def namePos(tree: MemberDef) = - if (tree.pos.exists) - if (tree.mods.is(Synthetic)) Position(tree.pos.point, tree.pos.point) - else Position(tree.pos.point, tree.pos.point + tree.name.length, tree.pos.point) - else tree.pos - tree match { case tree: TypeDef if tree.isClassDef => val name = checkNoConflict(tree.name.encode).asTypeName @@ -292,7 +281,7 @@ class Namer { typer: Typer => val cls = recordSym(ctx.newClassSymbol( ctx.owner, name, flags | inSuperCall, cls => adjustIfModule(new ClassCompleter(cls, tree)(ctx), tree), - privateWithinClass(tree.mods), namePos(tree), ctx.source.file), tree) + privateWithinClass(tree.mods), tree.namePos, ctx.source.file), tree) cls.completer.asInstanceOf[ClassCompleter].init() cls case tree: MemberDef => @@ -327,7 +316,7 @@ class Namer { typer: Typer => recordSym(ctx.newSymbol( ctx.owner, name, flags | deferred | method | higherKinded | inSuperCall1, adjustIfModule(completer, tree), - privateWithinClass(tree.mods), namePos(tree)), tree) + privateWithinClass(tree.mods), tree.namePos), tree) case tree: Import => recordSym(ctx.newSymbol( ctx.owner, nme.IMPORT, Synthetic, new Completer(tree), NoSymbol, tree.pos), tree)