From 32277934add4edbf9771471f2edfba151b69baf3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 18 Dec 2018 21:44:03 +0100 Subject: [PATCH 01/75] Rename nextId -> nextSymId in Context ... preparing to add a nextTreeId as well. --- compiler/src/dotty/tools/dotc/ast/Positioned.scala | 12 +++++++----- compiler/src/dotty/tools/dotc/core/Contexts.scala | 6 +++--- compiler/src/dotty/tools/dotc/core/Symbols.scala | 4 ++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index 55144d460145..4daa2df3be35 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package ast import util.Positions._ -import core.Contexts.Context +import core.Contexts.{Context, TreeIds} import core.Decorators._ import core.Flags.{JavaDefined, Extension} import core.StdNames.nme @@ -27,24 +27,26 @@ abstract class Positioned extends Product { if (pos.exists) setChildPositions(pos.toSynthetic) } + def cloned(implicit ids: TreeIds): Positioned + /** A positioned item like this one with the position set to `pos`. * if the positioned item is source-derived, a clone is returned. * If the positioned item is synthetic, the position is updated * destructively and the item itself is returned. */ - def withPos(pos: Position): this.type = { - val newpd = (if (pos == curPos || curPos.isSynthetic) this else clone.asInstanceOf[Positioned]) + def withPos(pos: Position)(implicit ids: TreeIds): this.type = { + val newpd = if (pos == curPos || curPos.isSynthetic) this else cloned newpd.setPos(pos) newpd.asInstanceOf[this.type] } - def withPos(posd: Positioned): this.type = + def withPos(posd: Positioned)(implicit ids: TreeIds): this.type = if (posd == null) this else withPos(posd.pos) /** This item with a position that's the union of the given `pos` and the * current position. */ - def addPos(pos: Position): this.type = withPos(pos union this.pos) + def addPos(pos: Position)(implicit ids: TreeIds): this.type = withPos(pos union this.pos) /** Set position of this tree only, without performing * any checks of consistency with - or updates of - other positions. diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index b212e3cbfcfb..b66a67b3224b 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -455,7 +455,7 @@ object Contexts { def pendingUnderlying: mutable.HashSet[Type] = base.pendingUnderlying def uniqueNamedTypes: Uniques.NamedTypeUniques = base.uniqueNamedTypes def uniques: util.HashSet[Type] = base.uniques - def nextId: Int = base.nextId + def nextSymId: Int = base.nextSymId def initialize()(implicit ctx: Context): Unit = base.initialize()(ctx) } @@ -626,9 +626,9 @@ object Contexts { // Symbols state /** A counter for unique ids */ - private[core] var _nextId: Int = 0 + private[core] var _nextSymId: Int = 0 - def nextId: Int = { _nextId += 1; _nextId } + def nextSymId: Int = { _nextSymId += 1; _nextSymId } /** Sources that were loaded */ val sources: mutable.HashMap[AbstractFile, SourceFile] = new mutable.HashMap[AbstractFile, SourceFile] diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 616970c9d373..62f3c1e90ec3 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -43,11 +43,11 @@ trait Symbols { this: Context => * it's debug-friendlier not to create an anonymous class here. */ def newNakedSymbol[N <: Name](coord: Coord = NoCoord)(implicit ctx: Context): Symbol { type ThisName = N } = - new Symbol(coord, ctx.nextId).asInstanceOf[Symbol { type ThisName = N }] + new Symbol(coord, ctx.nextSymId).asInstanceOf[Symbol { type ThisName = N }] /** Create a class symbol without a denotation. */ def newNakedClassSymbol(coord: Coord = NoCoord, assocFile: AbstractFile = null)(implicit ctx: Context): ClassSymbol = - new ClassSymbol(coord, assocFile, ctx.nextId) + new ClassSymbol(coord, assocFile, ctx.nextSymId) // ---- Symbol creation methods ---------------------------------- From 2e3dab3a0f08efaa644cf8e4d16d4017252f9e03 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 19 Dec 2018 10:33:27 +0100 Subject: [PATCH 02/75] Make nextTreeId counter a context field This removes some technical debt: nextId was a global counter, so unreliable under parallelism. That was OK so far since it was only intended for debugging. But now we want to give more significance to tree ids, since they will be used to determine the source file of a tree. Hence, we need to put this aspect in order by making nextTreeId a context field. This entailed a lot of changes, so no wonder it was not done before. --- .../src/dotty/tools/dotc/ast/Desugar.scala | 24 +- .../dotty/tools/dotc/ast/DesugarEnums.scala | 3 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 223 +++++++++-------- compiler/src/dotty/tools/dotc/ast/untpd.scala | 229 +++++++++--------- .../src/dotty/tools/dotc/core/Contexts.scala | 18 +- .../tools/dotc/core/tasty/TreePickler.scala | 4 +- .../tools/dotc/core/tasty/TreeUnpickler.scala | 2 +- .../dotc/parsing/xml/MarkupParsers.scala | 3 +- .../tools/dotc/tastyreflect/package.scala | 4 +- .../dotty/tools/dotc/typer/Applications.scala | 1 - .../dotty/tools/dotc/typer/Implicits.scala | 11 +- .../dotty/tools/dotc/typer/ProtoTypes.scala | 4 +- 12 files changed, 271 insertions(+), 255 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index c6706e3e2368..d61d59e69693 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -42,15 +42,15 @@ object desugar { // ----- DerivedTypeTrees ----------------------------------- - class SetterParamTree extends DerivedTypeTree { + class SetterParamTree(implicit ids: TreeIds) extends DerivedTypeTree { def derivedTree(sym: Symbol)(implicit ctx: Context): tpd.TypeTree = tpd.TypeTree(sym.info.resultType) } - class TypeRefTree extends DerivedTypeTree { + class TypeRefTree(implicit ids: TreeIds) extends DerivedTypeTree { def derivedTree(sym: Symbol)(implicit ctx: Context): tpd.TypeTree = tpd.TypeTree(sym.typeRef) } - class TermRefTree extends DerivedTypeTree { + class TermRefTree(implicit ids: TreeIds) extends DerivedTypeTree { def derivedTree(sym: Symbol)(implicit ctx: Context): tpd.Tree = tpd.ref(sym) } @@ -58,7 +58,7 @@ object desugar { * @param suffix String difference between existing parameter (call it `P`) and parameter owning the * DerivedTypeTree (call it `O`). We have: `O.name == P.name + suffix`. */ - class DerivedFromParamTree(suffix: String) extends DerivedTypeTree { + class DerivedFromParamTree(suffix: String)(implicit ids: TreeIds) extends DerivedTypeTree { /** Make sure that for all enclosing module classes their companion classes * are completed. Reason: We need the constructor of such companion classes to @@ -109,7 +109,7 @@ object desugar { } /** A type definition copied from `tdef` with a rhs typetree derived from it */ - def derivedTypeParam(tdef: TypeDef, suffix: String = ""): TypeDef = + def derivedTypeParam(tdef: TypeDef, suffix: String = "")(implicit ctx: Context): TypeDef = cpy.TypeDef(tdef)( name = tdef.name ++ suffix, rhs = new DerivedFromParamTree(suffix).withPos(tdef.rhs.pos).watching(tdef) @@ -120,9 +120,9 @@ object desugar { TypeDef(sym.name, new DerivedFromParamTree("").watching(sym)).withFlags(TypeParam) /** A value definition copied from `vdef` with a tpt typetree derived from it */ - def derivedTermParam(vdef: ValDef): ValDef = + def derivedTermParam(vdef: ValDef)(implicit ctx: Context): ValDef = cpy.ValDef(vdef)( - tpt = new DerivedFromParamTree("") withPos vdef.tpt.pos watching vdef) + tpt = new DerivedFromParamTree("").withPos(vdef.tpt.pos).watching(vdef)) // ----- Desugar methods ------------------------------------------------- @@ -932,9 +932,10 @@ object desugar { * def $anonfun(params) = body * Closure($anonfun) */ - def makeClosure(params: List[ValDef], body: Tree, tpt: Tree = TypeTree(), isImplicit: Boolean)(implicit ctx: Context): Block = + def makeClosure(params: List[ValDef], body: Tree, tpt: Tree = null, isImplicit: Boolean)(implicit ctx: Context): Block = Block( - DefDef(nme.ANON_FUN, Nil, params :: Nil, tpt, body).withMods(synthetic | Artifact), + DefDef(nme.ANON_FUN, Nil, params :: Nil, if (tpt == null) TypeTree() else tpt, body) + .withMods(synthetic | Artifact), Closure(Nil, Ident(nme.ANON_FUN), if (isImplicit) ImplicitEmptyTree else EmptyTree)) /** If `nparams` == 1, expand partial function @@ -1024,7 +1025,7 @@ object desugar { mayNeedSetter } - private def derivedDefDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers) = + private def derivedDefDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit ids: TreeIds) = DefDef(named.name.asTermName, Nil, Nil, tpt, rhs) .withMods(mods) .withPos(original.pos.withPoint(named.pos.start)) @@ -1388,5 +1389,6 @@ object desugar { buf.toList } - private class IrrefutableGenFrom(pat: Tree, expr: Tree) extends GenFrom(pat, expr) + private class IrrefutableGenFrom(pat: Tree, expr: Tree)(implicit ids: TreeIds) + extends GenFrom(pat, expr) } diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index 69b0bf780b75..0e9a8b4368c9 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -73,7 +73,8 @@ object DesugarEnums { else if (isEnumCase(cdef)) cdef.withMods(cdef.mods.withFlags(cdef.mods.flags | Final)) else cdef - private def valuesDot(name: String) = Select(Ident(nme.DOLLAR_VALUES), name.toTermName) + private def valuesDot(name: String)(implicit ids: TreeIds) = + Select(Ident(nme.DOLLAR_VALUES), name.toTermName) private def registerCall(implicit ctx: Context): List[Tree] = if (enumClass.typeParams.nonEmpty) Nil else Apply(valuesDot("register"), This(EmptyTypeIdent) :: Nil) :: Nil diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 603e95af29ef..30b3e71f0eef 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -30,8 +30,6 @@ object Trees { /** Property key for trees with documentation strings attached */ val DocComment: Property.StickyKey[Comments.Comment] = new Property.StickyKey - @sharable private[this] var nextId = 0 // for debugging - type LazyTree = AnyRef /* really: Tree | Lazy[Tree] */ type LazyTreeList = AnyRef /* really: List[Tree] | Lazy[List[Tree]] */ @@ -51,24 +49,19 @@ object Trees { * - Type checking an untyped tree should remove all embedded `TypedSplice` * nodes. */ - abstract class Tree[-T >: Untyped] extends Positioned - with Product - with Attachment.Container - with printing.Showable - with Cloneable { + abstract class Tree[-T >: Untyped](implicit ids: TreeIds) + extends Positioned + with Product + with Attachment.Container + with printing.Showable + with Cloneable { if (Stats.enabled) ntrees += 1 - private def nxId = { - nextId += 1 - //assert(nextId != 199, this) - nextId - } - /** A unique identifier for this tree. Used for debugging, and potentially * tracking presentation compiler interactions. */ - @sharable private var myUniqueId: Int = nxId + @sharable private var myUniqueId: Int = ids.nextTreeId def uniqueId: Int = myUniqueId @@ -238,9 +231,9 @@ object Trees { override def hashCode(): Int = uniqueId // for debugging; was: System.identityHashCode(this) override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - override def clone: Tree[T] = { - val tree = super.clone.asInstanceOf[Tree[T]] - tree.myUniqueId = nxId + override def cloned(implicit ids: TreeIds): Tree[T] = { + val tree = clone.asInstanceOf[Tree[T]] + tree.myUniqueId = ids.nextTreeId tree } } @@ -276,7 +269,7 @@ object Trees { } /** Tree's denotation can be derived from its type */ - abstract class DenotingTree[-T >: Untyped] extends Tree[T] { + abstract class DenotingTree[-T >: Untyped](implicit ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] <: DenotingTree[T] override def denot(implicit ctx: Context): Denotation = typeOpt match { case tpe: NamedType => tpe.denot @@ -293,7 +286,7 @@ object Trees { /** Tree's denot/isType/isTerm properties come from a subtree * identified by `forwardTo`. */ - abstract class ProxyTree[-T >: Untyped] extends Tree[T] { + abstract class ProxyTree[-T >: Untyped](implicit ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] <: ProxyTree[T] def forwardTo: Tree[T] override def denot(implicit ctx: Context): Denotation = forwardTo.denot @@ -302,13 +295,13 @@ object Trees { } /** Tree has a name */ - abstract class NameTree[-T >: Untyped] extends DenotingTree[T] { + abstract class NameTree[-T >: Untyped](implicit ids: TreeIds) extends DenotingTree[T] { type ThisTree[-T >: Untyped] <: NameTree[T] def name: Name } /** Tree refers by name to a denotation */ - abstract class RefTree[-T >: Untyped] extends NameTree[T] { + abstract class RefTree[-T >: Untyped](implicit ids: TreeIds) extends NameTree[T] { type ThisTree[-T >: Untyped] <: RefTree[T] def qualifier: Tree[T] override def isType: Boolean = name.isTypeName @@ -327,7 +320,7 @@ object Trees { * The envelope of a MemberDef contains the whole definition and has its point * on the opening keyword (or the next token after that if keyword is missing). */ - abstract class MemberDef[-T >: Untyped] extends NameTree[T] with DefTree[T] { + abstract class MemberDef[-T >: Untyped](implicit ids: TreeIds) extends NameTree[T] with DefTree[T] { type ThisTree[-T >: Untyped] <: MemberDef[T] private[this] var myMods: untpd.Modifiers = null @@ -369,7 +362,7 @@ object Trees { } /** A ValDef or DefDef tree */ - trait ValOrDefDef[-T >: Untyped] extends MemberDef[T] with WithLazyField[Tree[T]] { + abstract class ValOrDefDef[-T >: Untyped](implicit ids: TreeIds) extends MemberDef[T] with WithLazyField[Tree[T]] { def name: TermName def tpt: Tree[T] def unforcedRhs: LazyTree = unforced @@ -379,7 +372,7 @@ object Trees { // ----------- Tree case classes ------------------------------------ /** name */ - case class Ident[-T >: Untyped] private[ast] (name: Name) + case class Ident[-T >: Untyped] private[ast] (name: Name)(implicit ids: TreeIds) extends RefTree[T] { type ThisTree[-T >: Untyped] = Ident[T] def qualifier: Tree[T] = genericEmptyTree @@ -388,31 +381,31 @@ object Trees { def isBackquoted: Boolean = false } - class BackquotedIdent[-T >: Untyped] private[ast] (name: Name) + class BackquotedIdent[-T >: Untyped]private[ast] (name: Name)(implicit ids: TreeIds) extends Ident[T](name) { override def isBackquoted: Boolean = true override def toString: String = s"BackquotedIdent($name)" } - class SearchFailureIdent[-T >: Untyped] private[ast] (name: Name) + class SearchFailureIdent[-T >: Untyped] private[ast] (name: Name)(implicit ids: TreeIds) extends Ident[T](name) { override def toString: String = s"SearchFailureIdent($name)" } /** qualifier.name, or qualifier#name, if qualifier is a type */ - case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name) + case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name)(implicit ids: TreeIds) extends RefTree[T] { type ThisTree[-T >: Untyped] = Select[T] } - class SelectWithSig[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name, val sig: Signature) + class SelectWithSig[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name, val sig: Signature)(implicit ids: TreeIds) extends Select[T](qualifier, name) { override def toString: String = s"SelectWithSig($qualifier, $name, $sig)" } /** qual.this */ - case class This[-T >: Untyped] private[ast] (qual: untpd.Ident) + case class This[-T >: Untyped] private[ast] (qual: untpd.Ident)(implicit ids: TreeIds) extends DenotingTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = This[T] // Denotation of a This tree is always the underlying class; needs correction for modules. @@ -427,13 +420,13 @@ object Trees { } /** C.super[mix], where qual = C.this */ - case class Super[-T >: Untyped] private[ast] (qual: Tree[T], mix: untpd.Ident) + case class Super[-T >: Untyped] private[ast] (qual: Tree[T], mix: untpd.Ident)(implicit ids: TreeIds) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Super[T] def forwardTo: Tree[T] = qual } - abstract class GenericApply[-T >: Untyped] extends ProxyTree[T] with TermTree[T] { + abstract class GenericApply[-T >: Untyped](implicit ids: TreeIds) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] <: GenericApply[T] val fun: Tree[T] val args: List[Tree[T]] @@ -441,50 +434,50 @@ object Trees { } /** fun(args) */ - case class Apply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]]) + case class Apply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit ids: TreeIds) extends GenericApply[T] { type ThisTree[-T >: Untyped] = Apply[T] } /** fun[args] */ - case class TypeApply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]]) + case class TypeApply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit ids: TreeIds) extends GenericApply[T] { type ThisTree[-T >: Untyped] = TypeApply[T] } /** const */ - case class Literal[-T >: Untyped] private[ast] (const: Constant) - extends TermTree[T] { + case class Literal[-T >: Untyped] private[ast] (const: Constant)(implicit ids: TreeIds) + extends Tree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Literal[T] } /** new tpt, but no constructor call */ - case class New[-T >: Untyped] private[ast] (tpt: Tree[T]) - extends TermTree[T] { + case class New[-T >: Untyped] private[ast] (tpt: Tree[T])(implicit ids: TreeIds) + extends Tree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = New[T] } /** expr : tpt */ - case class Typed[-T >: Untyped] private[ast] (expr: Tree[T], tpt: Tree[T]) + case class Typed[-T >: Untyped] private[ast] (expr: Tree[T], tpt: Tree[T])(implicit ids: TreeIds) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Typed[T] def forwardTo: Tree[T] = expr } /** name = arg, in a parameter list */ - case class NamedArg[-T >: Untyped] private[ast] (name: Name, arg: Tree[T]) + case class NamedArg[-T >: Untyped] private[ast] (name: Name, arg: Tree[T])(implicit ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] = NamedArg[T] } /** name = arg, outside a parameter list */ - case class Assign[-T >: Untyped] private[ast] (lhs: Tree[T], rhs: Tree[T]) + case class Assign[-T >: Untyped] private[ast] (lhs: Tree[T], rhs: Tree[T])(implicit ids: TreeIds) extends TermTree[T] { type ThisTree[-T >: Untyped] = Assign[T] } /** { stats; expr } */ - case class Block[-T >: Untyped] private[ast] (stats: List[Tree[T]], expr: Tree[T]) + case class Block[-T >: Untyped] private[ast] (stats: List[Tree[T]], expr: Tree[T])(implicit ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] = Block[T] override def isType: Boolean = expr.isType @@ -492,12 +485,12 @@ object Trees { } /** if cond then thenp else elsep */ - case class If[-T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T]) + case class If[-T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit ids: TreeIds) extends TermTree[T] { type ThisTree[-T >: Untyped] = If[T] def isInline = false } - class InlineIf[T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T]) + class InlineIf[T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit ids: TreeIds) extends If(cond, thenp, elsep) { override def isInline = true override def toString = s"InlineIf($cond, $thenp, $elsep)" @@ -512,32 +505,32 @@ object Trees { * of the closure is a function type, otherwise it is the type * given in `tpt`, which must be a SAM type. */ - case class Closure[-T >: Untyped] private[ast] (env: List[Tree[T]], meth: Tree[T], tpt: Tree[T]) + case class Closure[-T >: Untyped] private[ast] (env: List[Tree[T]], meth: Tree[T], tpt: Tree[T])(implicit ids: TreeIds) extends TermTree[T] { type ThisTree[-T >: Untyped] = Closure[T] } /** selector match { cases } */ - case class Match[-T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]]) + case class Match[-T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit ids: TreeIds) extends TermTree[T] { assert(cases.nonEmpty) type ThisTree[-T >: Untyped] = Match[T] def isInline = false } - class InlineMatch[T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]]) + class InlineMatch[T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit ids: TreeIds) extends Match(selector, cases) { override def isInline = true override def toString = s"InlineMatch($selector, $cases)" } /** case pat if guard => body; only appears as child of a Match */ - case class CaseDef[-T >: Untyped] private[ast] (pat: Tree[T], guard: Tree[T], body: Tree[T]) + case class CaseDef[-T >: Untyped] private[ast] (pat: Tree[T], guard: Tree[T], body: Tree[T])(implicit ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] = CaseDef[T] } /** label[tpt]: { expr } */ - case class Labeled[-T >: Untyped] private[ast] (bind: Bind[T], expr: Tree[T]) + case class Labeled[-T >: Untyped] private[ast] (bind: Bind[T], expr: Tree[T])(implicit ids: TreeIds) extends NameTree[T] { type ThisTree[-T >: Untyped] = Labeled[T] def name: Name = bind.name @@ -548,13 +541,13 @@ object Trees { * After program transformations this is not necessarily the enclosing method, because * closures can intervene. */ - case class Return[-T >: Untyped] private[ast] (expr: Tree[T], from: Tree[T] = genericEmptyTree) + case class Return[-T >: Untyped] private[ast] (expr: Tree[T], from: Tree[T] = genericEmptyTree)(implicit ids: TreeIds) extends TermTree[T] { type ThisTree[-T >: Untyped] = Return[T] } /** while (cond) { body } */ - case class WhileDo[-T >: Untyped] private[ast] (cond: Tree[T], body: Tree[T]) + case class WhileDo[-T >: Untyped] private[ast] (cond: Tree[T], body: Tree[T])(implicit ids: TreeIds) extends TermTree[T] { type ThisTree[-T >: Untyped] = WhileDo[T] } @@ -578,7 +571,7 @@ object Trees { * * Match(EmptyTree, $anonfun(x)>) */ - case class Try[-T >: Untyped] private[ast] (expr: Tree[T], cases: List[CaseDef[T]], finalizer: Tree[T]) + case class Try[-T >: Untyped] private[ast] (expr: Tree[T], cases: List[CaseDef[T]], finalizer: Tree[T])(implicit ids: TreeIds) extends TermTree[T] { type ThisTree[-T >: Untyped] = Try[T] } @@ -586,13 +579,13 @@ object Trees { /** Seq(elems) * @param tpt The element type of the sequence. */ - case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T]) + case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] = SeqLiteral[T] } /** Array(elems) */ - class JavaSeqLiteral[T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T]) + class JavaSeqLiteral[T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit ids: TreeIds) extends SeqLiteral(elems, elemtpt) { override def toString: String = s"JavaSeqLiteral($elems, $elemtpt)" } @@ -613,14 +606,14 @@ object Trees { * different context: `bindings` represent the arguments to the inlined * call, whereas `expansion` represents the body of the inlined function. */ - case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T]) + case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T])(implicit ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] = Inlined[T] override def initialPos: Position = call.pos } /** A type tree that represents an existing or inferred type */ - case class TypeTree[-T >: Untyped] () + case class TypeTree[-T >: Untyped]()(implicit ids: TreeIds) extends DenotingTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = TypeTree[T] override def isEmpty: Boolean = !hasType @@ -631,66 +624,66 @@ object Trees { /** A type tree that defines a new type variable. Its type is always a TypeVar. * Every TypeVar is created as the type of one TypeVarBinder. */ - class TypeVarBinder[-T >: Untyped] extends TypeTree[T] + class TypeVarBinder[-T >: Untyped](implicit ids: TreeIds) extends TypeTree[T] /** ref.type */ - case class SingletonTypeTree[-T >: Untyped] private[ast] (ref: Tree[T]) + case class SingletonTypeTree[-T >: Untyped] private[ast] (ref: Tree[T])(implicit ids: TreeIds) extends DenotingTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = SingletonTypeTree[T] } /** left & right */ - case class AndTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T]) + case class AndTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])(implicit ids: TreeIds) extends TypTree[T] { type ThisTree[-T >: Untyped] = AndTypeTree[T] } /** left | right */ - case class OrTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T]) + case class OrTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])(implicit ids: TreeIds) extends TypTree[T] { type ThisTree[-T >: Untyped] = OrTypeTree[T] } /** tpt { refinements } */ - case class RefinedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], refinements: List[Tree[T]]) + case class RefinedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], refinements: List[Tree[T]])(implicit ids: TreeIds) extends ProxyTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = RefinedTypeTree[T] def forwardTo: Tree[T] = tpt } /** tpt[args] */ - case class AppliedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], args: List[Tree[T]]) + case class AppliedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], args: List[Tree[T]])(implicit ids: TreeIds) extends ProxyTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = AppliedTypeTree[T] def forwardTo: Tree[T] = tpt } /** [typeparams] -> tpt */ - case class LambdaTypeTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T]) + case class LambdaTypeTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T])(implicit ids: TreeIds) extends TypTree[T] { type ThisTree[-T >: Untyped] = LambdaTypeTree[T] } /** [bound] selector match { cases } */ - case class MatchTypeTree[-T >: Untyped] private[ast] (bound: Tree[T], selector: Tree[T], cases: List[CaseDef[T]]) + case class MatchTypeTree[-T >: Untyped] private[ast] (bound: Tree[T], selector: Tree[T], cases: List[CaseDef[T]])(implicit ids: TreeIds) extends TypTree[T] { type ThisTree[-T >: Untyped] = MatchTypeTree[T] } /** => T */ - case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T]) + case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T])(implicit ids: TreeIds) extends TypTree[T] { type ThisTree[-T >: Untyped] = ByNameTypeTree[T] } /** >: lo <: hi */ - case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T]) + case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T])(implicit ids: TreeIds) extends TypTree[T] { type ThisTree[-T >: Untyped] = TypeBoundsTree[T] } /** name @ body */ - case class Bind[-T >: Untyped] private[ast] (name: Name, body: Tree[T]) + case class Bind[-T >: Untyped] private[ast] (name: Name, body: Tree[T])(implicit ids: TreeIds) extends NameTree[T] with DefTree[T] with PatternTree[T] { type ThisTree[-T >: Untyped] = Bind[T] override def isType: Boolean = name.isTypeName @@ -698,7 +691,7 @@ object Trees { } /** tree_1 | ... | tree_n */ - case class Alternative[-T >: Untyped] private[ast] (trees: List[Tree[T]]) + case class Alternative[-T >: Untyped] private[ast] (trees: List[Tree[T]])(implicit ids: TreeIds) extends PatternTree[T] { type ThisTree[-T >: Untyped] = Alternative[T] } @@ -717,13 +710,13 @@ object Trees { * val result = fun(sel)(implicits) * if (result.isDefined) "match patterns against result" */ - case class UnApply[-T >: Untyped] private[ast] (fun: Tree[T], implicits: List[Tree[T]], patterns: List[Tree[T]]) + case class UnApply[-T >: Untyped] private[ast] (fun: Tree[T], implicits: List[Tree[T]], patterns: List[Tree[T]])(implicit ids: TreeIds) extends PatternTree[T] { type ThisTree[-T >: Untyped] = UnApply[T] } /** mods val name: tpt = rhs */ - case class ValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], private var preRhs: LazyTree) + case class ValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], private var preRhs: LazyTree)(implicit ids: TreeIds) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = ValDef[T] assert(isEmpty || tpt != genericEmptyTree) @@ -733,7 +726,7 @@ object Trees { /** mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs */ case class DefDef[-T >: Untyped] private[ast] (name: TermName, tparams: List[TypeDef[T]], - vparamss: List[List[ValDef[T]]], tpt: Tree[T], private var preRhs: LazyTree) + vparamss: List[List[ValDef[T]]], tpt: Tree[T], private var preRhs: LazyTree)(implicit ids: TreeIds) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = DefDef[T] assert(tpt != genericEmptyTree) @@ -746,7 +739,7 @@ object Trees { * mods type name = rhs or * mods type name >: lo <: hi, if rhs = TypeBoundsTree(lo, hi) & (lo ne hi) */ - case class TypeDef[-T >: Untyped] private[ast] (name: TypeName, rhs: Tree[T]) + case class TypeDef[-T >: Untyped] private[ast] (name: TypeName, rhs: Tree[T])(implicit ids: TreeIds) extends MemberDef[T] { type ThisTree[-T >: Untyped] = TypeDef[T] @@ -755,7 +748,7 @@ object Trees { } /** extends parents { self => body } */ - case class Template[-T >: Untyped] private[ast] (constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], private var preBody: LazyTreeList) + case class Template[-T >: Untyped] private[ast] (constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], private var preBody: LazyTreeList)(implicit ids: TreeIds) extends DefTree[T] with WithLazyField[List[Tree[T]]] { type ThisTree[-T >: Untyped] = Template[T] def unforcedBody: LazyTreeList = unforced @@ -768,20 +761,20 @@ object Trees { * where a selector is either an untyped `Ident`, `name` or * an untyped thicket consisting of `name` and `rename`. */ - case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]]) + case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]])(implicit ids: TreeIds) extends DenotingTree[T] { type ThisTree[-T >: Untyped] = Import[T] } /** package pid { stats } */ - case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]]) + case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]])(implicit ids: TreeIds) extends ProxyTree[T] { type ThisTree[-T >: Untyped] = PackageDef[T] def forwardTo: RefTree[T] = pid } /** arg @annot */ - case class Annotated[-T >: Untyped] private[ast] (arg: Tree[T], annot: Tree[T]) + case class Annotated[-T >: Untyped] private[ast] (arg: Tree[T], annot: Tree[T])(implicit ids: TreeIds) extends ProxyTree[T] { type ThisTree[-T >: Untyped] = Annotated[T] def forwardTo: Tree[T] = arg @@ -798,7 +791,7 @@ object Trees { * The contained trees will be integrated when transformed with * a `transform(List[Tree])` call. */ - case class Thicket[-T >: Untyped](trees: List[Tree[T]]) + case class Thicket[-T >: Untyped](trees: List[Tree[T]])(implicit ids: TreeIds) extends Tree[T] with WithoutTypeOrPos[T] { myTpe = NoType.asInstanceOf[T] @@ -806,26 +799,28 @@ object Trees { override def isEmpty: Boolean = trees.isEmpty override def toList: List[Tree[T]] = flatten(trees) override def toString: String = if (isEmpty) "EmptyTree" else "Thicket(" + trees.mkString(", ") + ")" - override def withPos(pos: Position): this.type = { + override def withPos(pos: Position)(implicit ids: TreeIds): this.type = { val newTrees = trees.mapConserve(_.withPos(pos)) if (trees eq newTrees) this else - new Thicket[T](newTrees).asInstanceOf[this.type] + Thicket[T](newTrees).asInstanceOf[this.type] } override def pos: Position = (NoPosition /: trees) ((pos, t) => pos union t.pos) override def foreachInThicket(op: Tree[T] => Unit): Unit = trees foreach (_.foreachInThicket(op)) } + class EmptyTree[T >: Untyped] extends Thicket(Nil)(GlobalTreeIds) + class EmptyValDef[T >: Untyped] extends ValDef[T]( - nme.WILDCARD, genericEmptyTree[T], genericEmptyTree[T]) with WithoutTypeOrPos[T] { + nme.WILDCARD, genericEmptyTree[T], genericEmptyTree[T])(GlobalTreeIds) with WithoutTypeOrPos[T] { myTpe = NoType.asInstanceOf[T] override def isEmpty: Boolean = true setMods(untpd.Modifiers(PrivateLocal)) } - @sharable val theEmptyTree: Thicket[Type] = Thicket(Nil) + @sharable val theEmptyTree: EmptyTree[Type] = new EmptyTree[Type] @sharable val theEmptyValDef: EmptyValDef[Type] = new EmptyValDef[Type] def genericEmptyValDef[T >: Untyped]: ValDef[T] = theEmptyValDef.asInstanceOf[ValDef[T]] @@ -950,15 +945,15 @@ object Trees { @sharable val EmptyTree: Thicket = genericEmptyTree @sharable val EmptyValDef: ValDef = genericEmptyValDef - @sharable val ImplicitEmptyTree: Thicket = Thicket(Nil) // an empty tree marking an implicit closure + @sharable val ImplicitEmptyTree: Thicket = new EmptyTree // an empty tree marking an implicit closure // ----- Auxiliary creation methods ------------------ - def Thicket(trees: List[Tree]): Thicket = new Thicket(trees) + def Thicket(trees: List[Tree])(implicit ids:TreeIds): Thicket = new Thicket(trees) def Thicket(): Thicket = EmptyTree - def Thicket(x1: Tree, x2: Tree): Thicket = Thicket(x1 :: x2 :: Nil) - def Thicket(x1: Tree, x2: Tree, x3: Tree): Thicket = Thicket(x1 :: x2 :: x3 :: Nil) - def flatTree(xs: List[Tree]): Tree = flatten(xs) match { + def Thicket(x1: Tree, x2: Tree)(implicit ids:TreeIds): Thicket = Thicket(x1 :: x2 :: Nil) + def Thicket(x1: Tree, x2: Tree, x3: Tree)(implicit ids:TreeIds): Thicket = Thicket(x1 :: x2 :: x3 :: Nil) + def flatTree(xs: List[Tree])(implicit ids:TreeIds): Tree = flatten(xs) match { case x :: Nil => x case ys => Thicket(ys) } @@ -978,13 +973,13 @@ object Trees { protected def postProcess(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] protected def postProcess(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T] - protected def finalize(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] = + protected def finalize(tree: Tree, copied: untpd.Tree)(implicit ids:TreeIds): copied.ThisTree[T] = postProcess(tree, copied.withPos(tree.pos).withAttachmentsFrom(tree)) - protected def finalize(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T] = + protected def finalize(tree: Tree, copied: untpd.MemberDef)(implicit ids:TreeIds): copied.ThisTree[T] = postProcess(tree, copied.withPos(tree.pos).withAttachmentsFrom(tree)) - def Ident(tree: Tree)(name: Name): Ident = tree match { + def Ident(tree: Tree)(name: Name)(implicit ctx: Context): Ident = tree match { case tree: BackquotedIdent => if (name == tree.name) tree else finalize(tree, new BackquotedIdent(name)) @@ -1003,11 +998,11 @@ object Trees { case Ident(_) => Ident(tree)(name) case Select(qual, _) => Select(tree)(qual, name) } - def This(tree: Tree)(qual: untpd.Ident): This = tree match { + def This(tree: Tree)(qual: untpd.Ident)(implicit ctx: Context): This = tree match { case tree: This if qual eq tree.qual => tree case _ => finalize(tree, untpd.This(qual)) } - def Super(tree: Tree)(qual: Tree, mix: untpd.Ident): Super = tree match { + def Super(tree: Tree)(qual: Tree, mix: untpd.Ident)(implicit ctx: Context): Super = tree match { case tree: Super if (qual eq tree.qual) && (mix eq tree.mix) => tree case _ => finalize(tree, untpd.Super(qual, mix)) } @@ -1088,75 +1083,75 @@ object Trees { case tree: Inlined if (call eq tree.call) && (bindings eq tree.bindings) && (expansion eq tree.expansion) => tree case _ => finalize(tree, untpd.Inlined(call, bindings, expansion)) } - def SingletonTypeTree(tree: Tree)(ref: Tree): SingletonTypeTree = tree match { + def SingletonTypeTree(tree: Tree)(ref: Tree)(implicit ctx: Context): SingletonTypeTree = tree match { case tree: SingletonTypeTree if ref eq tree.ref => tree case _ => finalize(tree, untpd.SingletonTypeTree(ref)) } - def AndTypeTree(tree: Tree)(left: Tree, right: Tree): AndTypeTree = tree match { + def AndTypeTree(tree: Tree)(left: Tree, right: Tree)(implicit ctx: Context): AndTypeTree = tree match { case tree: AndTypeTree if (left eq tree.left) && (right eq tree.right) => tree case _ => finalize(tree, untpd.AndTypeTree(left, right)) } - def OrTypeTree(tree: Tree)(left: Tree, right: Tree): OrTypeTree = tree match { + def OrTypeTree(tree: Tree)(left: Tree, right: Tree)(implicit ctx: Context): OrTypeTree = tree match { case tree: OrTypeTree if (left eq tree.left) && (right eq tree.right) => tree case _ => finalize(tree, untpd.OrTypeTree(left, right)) } - def RefinedTypeTree(tree: Tree)(tpt: Tree, refinements: List[Tree]): RefinedTypeTree = tree match { + def RefinedTypeTree(tree: Tree)(tpt: Tree, refinements: List[Tree])(implicit ctx: Context): RefinedTypeTree = tree match { case tree: RefinedTypeTree if (tpt eq tree.tpt) && (refinements eq tree.refinements) => tree case _ => finalize(tree, untpd.RefinedTypeTree(tpt, refinements)) } - def AppliedTypeTree(tree: Tree)(tpt: Tree, args: List[Tree]): AppliedTypeTree = tree match { + def AppliedTypeTree(tree: Tree)(tpt: Tree, args: List[Tree])(implicit ctx: Context): AppliedTypeTree = tree match { case tree: AppliedTypeTree if (tpt eq tree.tpt) && (args eq tree.args) => tree case _ => finalize(tree, untpd.AppliedTypeTree(tpt, args)) } - def LambdaTypeTree(tree: Tree)(tparams: List[TypeDef], body: Tree): LambdaTypeTree = tree match { + def LambdaTypeTree(tree: Tree)(tparams: List[TypeDef], body: Tree)(implicit ctx: Context): LambdaTypeTree = tree match { case tree: LambdaTypeTree if (tparams eq tree.tparams) && (body eq tree.body) => tree case _ => finalize(tree, untpd.LambdaTypeTree(tparams, body)) } - def MatchTypeTree(tree: Tree)(bound: Tree, selector: Tree, cases: List[CaseDef]): MatchTypeTree = tree match { + def MatchTypeTree(tree: Tree)(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit ctx: Context): MatchTypeTree = tree match { case tree: MatchTypeTree if (bound eq tree.bound) && (selector eq tree.selector) && (cases eq tree.cases) => tree case _ => finalize(tree, untpd.MatchTypeTree(bound, selector, cases)) } - def ByNameTypeTree(tree: Tree)(result: Tree): ByNameTypeTree = tree match { + def ByNameTypeTree(tree: Tree)(result: Tree)(implicit ctx: Context): ByNameTypeTree = tree match { case tree: ByNameTypeTree if result eq tree.result => tree case _ => finalize(tree, untpd.ByNameTypeTree(result)) } - def TypeBoundsTree(tree: Tree)(lo: Tree, hi: Tree): TypeBoundsTree = tree match { + def TypeBoundsTree(tree: Tree)(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree = tree match { case tree: TypeBoundsTree if (lo eq tree.lo) && (hi eq tree.hi) => tree case _ => finalize(tree, untpd.TypeBoundsTree(lo, hi)) } - def Bind(tree: Tree)(name: Name, body: Tree): Bind = tree match { + def Bind(tree: Tree)(name: Name, body: Tree)(implicit ctx: Context): Bind = tree match { case tree: Bind if (name eq tree.name) && (body eq tree.body) => tree case _ => finalize(tree, untpd.Bind(name, body)) } - def Alternative(tree: Tree)(trees: List[Tree]): Alternative = tree match { + def Alternative(tree: Tree)(trees: List[Tree])(implicit ctx: Context): Alternative = tree match { case tree: Alternative if trees eq tree.trees => tree case _ => finalize(tree, untpd.Alternative(trees)) } - def UnApply(tree: Tree)(fun: Tree, implicits: List[Tree], patterns: List[Tree]): UnApply = tree match { + def UnApply(tree: Tree)(fun: Tree, implicits: List[Tree], patterns: List[Tree])(implicit ctx: Context): UnApply = tree match { case tree: UnApply if (fun eq tree.fun) && (implicits eq tree.implicits) && (patterns eq tree.patterns) => tree case _ => finalize(tree, untpd.UnApply(fun, implicits, patterns)) } - def ValDef(tree: Tree)(name: TermName, tpt: Tree, rhs: LazyTree): ValDef = tree match { + def ValDef(tree: Tree)(name: TermName, tpt: Tree, rhs: LazyTree)(implicit ctx: Context): ValDef = tree match { case tree: ValDef if (name == tree.name) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) => tree case _ => finalize(tree, untpd.ValDef(name, tpt, rhs)) } - def DefDef(tree: Tree)(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree): DefDef = tree match { + def DefDef(tree: Tree)(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree)(implicit ctx: Context): DefDef = tree match { case tree: DefDef if (name == tree.name) && (tparams eq tree.tparams) && (vparamss eq tree.vparamss) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) => tree case _ => finalize(tree, untpd.DefDef(name, tparams, vparamss, tpt, rhs)) } - def TypeDef(tree: Tree)(name: TypeName, rhs: Tree): TypeDef = tree match { + def TypeDef(tree: Tree)(name: TypeName, rhs: Tree)(implicit ctx: Context): TypeDef = tree match { case tree: TypeDef if (name == tree.name) && (rhs eq tree.rhs) => tree case _ => finalize(tree, untpd.TypeDef(name, rhs)) } - def Template(tree: Tree)(constr: DefDef, parents: List[Tree], self: ValDef, body: LazyTreeList): Template = tree match { + def Template(tree: Tree)(constr: DefDef, parents: List[Tree], self: ValDef, body: LazyTreeList)(implicit ctx: Context): Template = tree match { case tree: Template if (constr eq tree.constr) && (parents eq tree.parents) && (self eq tree.self) && (body eq tree.unforcedBody) => tree case _ => finalize(tree, untpd.Template(constr, parents, self, body)) } - def Import(tree: Tree)(expr: Tree, selectors: List[untpd.Tree]): Import = tree match { + def Import(tree: Tree)(expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = tree match { case tree: Import if (expr eq tree.expr) && (selectors eq tree.selectors) => tree case _ => finalize(tree, untpd.Import(expr, selectors)) } - def PackageDef(tree: Tree)(pid: RefTree, stats: List[Tree]): PackageDef = tree match { + def PackageDef(tree: Tree)(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef = tree match { case tree: PackageDef if (pid eq tree.pid) && (stats eq tree.stats) => tree case _ => finalize(tree, untpd.PackageDef(pid, stats)) } @@ -1164,7 +1159,7 @@ object Trees { case tree: Annotated if (arg eq tree.arg) && (annot eq tree.annot) => tree case _ => finalize(tree, untpd.Annotated(arg, annot)) } - def Thicket(tree: Tree)(trees: List[Tree]): Thicket = tree match { + def Thicket(tree: Tree)(trees: List[Tree])(implicit ctx: Context): Thicket = tree match { case tree: Thicket if trees eq tree.trees => tree case _ => finalize(tree, untpd.Thicket(trees)) } @@ -1179,15 +1174,15 @@ object Trees { CaseDef(tree: Tree)(pat, guard, body) def Try(tree: Try)(expr: Tree = tree.expr, cases: List[CaseDef] = tree.cases, finalizer: Tree = tree.finalizer)(implicit ctx: Context): Try = Try(tree: Tree)(expr, cases, finalizer) - def UnApply(tree: UnApply)(fun: Tree = tree.fun, implicits: List[Tree] = tree.implicits, patterns: List[Tree] = tree.patterns): UnApply = + def UnApply(tree: UnApply)(fun: Tree = tree.fun, implicits: List[Tree] = tree.implicits, patterns: List[Tree] = tree.patterns)(implicit ctx: Context): UnApply = UnApply(tree: Tree)(fun, implicits, patterns) - def ValDef(tree: ValDef)(name: TermName = tree.name, tpt: Tree = tree.tpt, rhs: LazyTree = tree.unforcedRhs): ValDef = + def ValDef(tree: ValDef)(name: TermName = tree.name, tpt: Tree = tree.tpt, rhs: LazyTree = tree.unforcedRhs)(implicit ctx: Context): ValDef = ValDef(tree: Tree)(name, tpt, rhs) - def DefDef(tree: DefDef)(name: TermName = tree.name, tparams: List[TypeDef] = tree.tparams, vparamss: List[List[ValDef]] = tree.vparamss, tpt: Tree = tree.tpt, rhs: LazyTree = tree.unforcedRhs): DefDef = + def DefDef(tree: DefDef)(name: TermName = tree.name, tparams: List[TypeDef] = tree.tparams, vparamss: List[List[ValDef]] = tree.vparamss, tpt: Tree = tree.tpt, rhs: LazyTree = tree.unforcedRhs)(implicit ctx: Context): DefDef = DefDef(tree: Tree)(name, tparams, vparamss, tpt, rhs) - def TypeDef(tree: TypeDef)(name: TypeName = tree.name, rhs: Tree = tree.rhs): TypeDef = + def TypeDef(tree: TypeDef)(name: TypeName = tree.name, rhs: Tree = tree.rhs)(implicit ctx: Context): TypeDef = TypeDef(tree: Tree)(name, rhs) - def Template(tree: Template)(constr: DefDef = tree.constr, parents: List[Tree] = tree.parents, self: ValDef = tree.self, body: LazyTreeList = tree.unforcedBody): Template = + def Template(tree: Template)(constr: DefDef = tree.constr, parents: List[Tree] = tree.parents, self: ValDef = tree.self, body: LazyTreeList = tree.unforcedBody)(implicit ctx: Context): Template = Template(tree: Tree)(constr, parents, self, body) } diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index f56cdea95bc5..79c9b080a04f 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -14,7 +14,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { // ----- Tree cases that exist in untyped form only ------------------ - trait OpTree extends Tree { + abstract class OpTree(implicit ids: TreeIds) extends Tree { def op: Ident override def isTerm: Boolean = op.name.isTermName override def isType: Boolean = op.name.isTypeName @@ -23,7 +23,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { /** A typed subtree of an untyped tree needs to be wrapped in a TypedSplice * @param owner The current owner at the time the tree was defined */ - abstract case class TypedSplice(splice: tpd.Tree)(val owner: Symbol) extends ProxyTree { + abstract case class TypedSplice(splice: tpd.Tree)(val owner: Symbol)(implicit ids: TreeIds) extends ProxyTree { def forwardTo: tpd.Tree = splice } @@ -33,30 +33,32 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { } /** mods object name impl */ - case class ModuleDef(name: TermName, impl: Template) + case class ModuleDef(name: TermName, impl: Template)(implicit ids: TreeIds) extends MemberDef { type ThisTree[-T >: Untyped] <: Trees.NameTree[T] with Trees.MemberDef[T] with ModuleDef def withName(name: Name)(implicit ctx: Context): ModuleDef = cpy.ModuleDef(this)(name.toTermName, impl) } - case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree) extends TermTree + case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree)(implicit ids: TreeIds) extends Tree with TermTree - case class SymbolLit(str: String) extends TermTree + case class SymbolLit(str: String)(implicit ids: TreeIds) extends TermTree /** An interpolated string * @param segments a list of two element tickets consisting of string literal and argument tree, * possibly with a simple string literal as last element of the list */ - case class InterpolatedString(id: TermName, segments: List[Tree]) extends TermTree + case class InterpolatedString(id: TermName, segments: List[Tree])(implicit ids: TreeIds) + extends TermTree /** A function type */ - case class Function(args: List[Tree], body: Tree) extends Tree { + case class Function(args: List[Tree], body: Tree)(implicit ids: TreeIds) extends Tree { override def isTerm: Boolean = body.isTerm override def isType: Boolean = body.isType } /** A function type with `implicit` or `erased` modifiers */ - class FunctionWithMods(args: List[Tree], body: Tree, val mods: Modifiers) extends Function(args, body) + class FunctionWithMods(args: List[Tree], body: Tree, val mods: Modifiers)(implicit ids: TreeIds) + extends Function(args, body) /** A function created from a wildcard expression * @param placeholderParams a list of definitions of synthetic parameters. @@ -65,39 +67,40 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * This is equivalent to Function, except that forms a special case for the overlapping * positions tests. */ - class WildcardFunction(placeholderParams: List[ValDef], body: Tree) extends Function(placeholderParams, body) + class WildcardFunction(placeholderParams: List[ValDef], body: Tree)(implicit ids: TreeIds) + extends Function(placeholderParams, body) - case class InfixOp(left: Tree, op: Ident, right: Tree) extends OpTree - case class PostfixOp(od: Tree, op: Ident) extends OpTree - case class PrefixOp(op: Ident, od: Tree) extends OpTree { + case class InfixOp(left: Tree, op: Ident, right: Tree)(implicit ids: TreeIds) extends OpTree + case class PostfixOp(od: Tree, op: Ident)(implicit ids: TreeIds) extends OpTree + case class PrefixOp(op: Ident, od: Tree)(implicit ids: TreeIds) extends OpTree { override def isType: Boolean = op.isType override def isTerm: Boolean = op.isTerm } - case class Parens(t: Tree) extends ProxyTree { + case class Parens(t: Tree)(implicit ids: TreeIds) extends ProxyTree { def forwardTo: Tree = t } - case class Tuple(trees: List[Tree]) extends Tree { + case class Tuple(trees: List[Tree])(implicit ids: TreeIds) extends Tree { override def isTerm: Boolean = trees.isEmpty || trees.head.isTerm override def isType: Boolean = !isTerm } - case class Throw(expr: Tree) extends TermTree - case class Quote(expr: Tree) extends TermTree - case class DoWhile(body: Tree, cond: Tree) extends TermTree - case class ForYield(enums: List[Tree], expr: Tree) extends TermTree - case class ForDo(enums: List[Tree], body: Tree) extends TermTree - case class GenFrom(pat: Tree, expr: Tree) extends Tree - case class GenAlias(pat: Tree, expr: Tree) extends Tree - case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) extends TypTree - case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) extends DefTree - case class DependentTypeTree(tp: List[Symbol] => Type) extends Tree - - @sharable object EmptyTypeIdent extends Ident(tpnme.EMPTY) with WithoutTypeOrPos[Untyped] { + case class Throw(expr: Tree)(implicit ids: TreeIds) extends TermTree + case class Quote(expr: Tree)(implicit ids: TreeIds) extends TermTree + case class DoWhile(body: Tree, cond: Tree)(implicit ids: TreeIds) extends TermTree + case class ForYield(enums: List[Tree], expr: Tree)(implicit ids: TreeIds) extends TermTree + case class ForDo(enums: List[Tree], body: Tree)(implicit ids: TreeIds) extends TermTree + case class GenFrom(pat: Tree, expr: Tree)(implicit ids: TreeIds) extends Tree + case class GenAlias(pat: Tree, expr: Tree)(implicit ids: TreeIds) extends Tree + case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit ids: TreeIds) extends TypTree + case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit ids: TreeIds) extends DefTree + case class DependentTypeTree(tp: List[Symbol] => Type)(implicit ids: TreeIds) extends Tree + + @sharable object EmptyTypeIdent extends Ident(tpnme.EMPTY)(GlobalTreeIds) with WithoutTypeOrPos[Untyped] { override def isEmpty: Boolean = true } /** A block generated by the XML parser, only treated specially by * `Positioned#checkPos` */ - class XMLBlock(stats: List[Tree], expr: Tree) extends Block(stats, expr) + class XMLBlock(stats: List[Tree], expr: Tree)(implicit ids: TreeIds) extends Block(stats, expr) // ----- Modifiers ----------------------------------------------------- /** Mod is intended to record syntactic information about modifiers, it's @@ -105,7 +108,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * * For any query about semantic information, check `flags` instead. */ - sealed abstract class Mod(val flags: FlagSet) extends Positioned + sealed abstract class Mod(val flags: FlagSet) extends Positioned { + def cloned(implicit ids: TreeIds): Positioned = clone.asInstanceOf[Positioned] + } object Mod { case class Private() extends Mod(Flags.Private) @@ -136,8 +141,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { } /** Modifiers and annotations for definitions - * - * @param flags The set flags + * + * @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 @@ -202,6 +207,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def isEnumCase: Boolean = isEnum && is(Case) def isEnumClass: Boolean = isEnum && !is(Case) + + override def cloned(implicit ids: TreeIds): Modifiers = + clone.asInstanceOf[Modifiers] } @sharable val EmptyModifiers: Modifiers = new Modifiers() @@ -211,7 +219,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { /** A type tree that gets its type from some other tree's symbol. Enters the * type tree in the References attachment of the `from` tree as a side effect. */ - abstract class DerivedTypeTree extends TypeTree { + abstract class DerivedTypeTree(implicit ids: TreeIds) extends TypeTree { private[this] var myWatched: Tree = EmptyTree @@ -255,54 +263,54 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { // ------ Creation methods for untyped only ----------------- - def Ident(name: Name): Ident = new Ident(name) - def BackquotedIdent(name: Name): BackquotedIdent = new BackquotedIdent(name) - def SearchFailureIdent(name: Name): SearchFailureIdent = new SearchFailureIdent(name) - def Select(qualifier: Tree, name: Name): Select = new Select(qualifier, name) - def SelectWithSig(qualifier: Tree, name: Name, sig: Signature): Select = new SelectWithSig(qualifier, name, sig) - def This(qual: Ident): This = new This(qual) - def Super(qual: Tree, mix: Ident): Super = new Super(qual, mix) - def Apply(fun: Tree, args: List[Tree]): Apply = new Apply(fun, args) - def TypeApply(fun: Tree, args: List[Tree]): TypeApply = new TypeApply(fun, args) - def Literal(const: Constant): Literal = new Literal(const) - def New(tpt: Tree): New = new New(tpt) - def Typed(expr: Tree, tpt: Tree): Typed = new Typed(expr, tpt) - def NamedArg(name: Name, arg: Tree): NamedArg = new NamedArg(name, arg) - def Assign(lhs: Tree, rhs: Tree): Assign = new Assign(lhs, rhs) - def Block(stats: List[Tree], expr: Tree): Block = new Block(stats, expr) - def If(cond: Tree, thenp: Tree, elsep: Tree): If = new If(cond, thenp, elsep) - def InlineIf(cond: Tree, thenp: Tree, elsep: Tree): If = new InlineIf(cond, thenp, elsep) - def Closure(env: List[Tree], meth: Tree, tpt: Tree): Closure = new Closure(env, meth, tpt) - def Match(selector: Tree, cases: List[CaseDef]): Match = new Match(selector, cases) - def InlineMatch(selector: Tree, cases: List[CaseDef]): Match = new InlineMatch(selector, cases) - def CaseDef(pat: Tree, guard: Tree, body: Tree): CaseDef = new CaseDef(pat, guard, body) - def Labeled(bind: Bind, expr: Tree): Labeled = new Labeled(bind, expr) - def Return(expr: Tree, from: Tree): Return = new Return(expr, from) - def WhileDo(cond: Tree, body: Tree): WhileDo = new WhileDo(cond, body) - def Try(expr: Tree, cases: List[CaseDef], finalizer: Tree): Try = new Try(expr, cases, finalizer) - def SeqLiteral(elems: List[Tree], elemtpt: Tree): SeqLiteral = new SeqLiteral(elems, elemtpt) - def JavaSeqLiteral(elems: List[Tree], elemtpt: Tree): JavaSeqLiteral = new JavaSeqLiteral(elems, elemtpt) - def Inlined(call: tpd.Tree, bindings: List[MemberDef], expansion: Tree): Inlined = new Inlined(call, bindings, expansion) - def TypeTree(): TypeTree = new TypeTree() - def SingletonTypeTree(ref: Tree): SingletonTypeTree = new SingletonTypeTree(ref) - def AndTypeTree(left: Tree, right: Tree): AndTypeTree = new AndTypeTree(left, right) - def OrTypeTree(left: Tree, right: Tree): OrTypeTree = new OrTypeTree(left, right) - def RefinedTypeTree(tpt: Tree, refinements: List[Tree]): RefinedTypeTree = new RefinedTypeTree(tpt, refinements) - def AppliedTypeTree(tpt: Tree, args: List[Tree]): AppliedTypeTree = new AppliedTypeTree(tpt, args) - def LambdaTypeTree(tparams: List[TypeDef], body: Tree): LambdaTypeTree = new LambdaTypeTree(tparams, body) - def MatchTypeTree(bound: Tree, selector: Tree, cases: List[CaseDef]): MatchTypeTree = new MatchTypeTree(bound, selector, cases) - def ByNameTypeTree(result: Tree): ByNameTypeTree = new ByNameTypeTree(result) - def TypeBoundsTree(lo: Tree, hi: Tree): TypeBoundsTree = new TypeBoundsTree(lo, hi) - def Bind(name: Name, body: Tree): Bind = new Bind(name, body) - def Alternative(trees: List[Tree]): Alternative = new Alternative(trees) - def UnApply(fun: Tree, implicits: List[Tree], patterns: List[Tree]): UnApply = new UnApply(fun, implicits, patterns) - def ValDef(name: TermName, tpt: Tree, rhs: LazyTree): ValDef = new ValDef(name, tpt, rhs) - def DefDef(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree): DefDef = new DefDef(name, tparams, vparamss, tpt, rhs) - def TypeDef(name: TypeName, rhs: Tree): TypeDef = new TypeDef(name, rhs) - def Template(constr: DefDef, parents: List[Tree], self: ValDef, body: LazyTreeList): Template = new Template(constr, parents, self, body) - def Import(expr: Tree, selectors: List[Tree]): Import = new Import(expr, selectors) - def PackageDef(pid: RefTree, stats: List[Tree]): PackageDef = new PackageDef(pid, stats) - def Annotated(arg: Tree, annot: Tree): Annotated = new Annotated(arg, annot) + def Ident(name: Name)(implicit ids: TreeIds): Ident = new Ident(name) + def BackquotedIdent(name: Name)(implicit ids: TreeIds): BackquotedIdent = new BackquotedIdent(name) + def SearchFailureIdent(name: Name)(implicit ids: TreeIds): SearchFailureIdent = new SearchFailureIdent(name) + def Select(qualifier: Tree, name: Name)(implicit ids: TreeIds): Select = new Select(qualifier, name) + def SelectWithSig(qualifier: Tree, name: Name, sig: Signature)(implicit ids: TreeIds): Select = new SelectWithSig(qualifier, name, sig) + def This(qual: Ident)(implicit ids: TreeIds): This = new This(qual) + def Super(qual: Tree, mix: Ident)(implicit ids: TreeIds): Super = new Super(qual, mix) + def Apply(fun: Tree, args: List[Tree])(implicit ids: TreeIds): Apply = new Apply(fun, args) + def TypeApply(fun: Tree, args: List[Tree])(implicit ids: TreeIds): TypeApply = new TypeApply(fun, args) + def Literal(const: Constant)(implicit ids: TreeIds): Literal = new Literal(const) + def New(tpt: Tree)(implicit ids: TreeIds): New = new New(tpt) + def Typed(expr: Tree, tpt: Tree)(implicit ids: TreeIds): Typed = new Typed(expr, tpt) + def NamedArg(name: Name, arg: Tree)(implicit ids: TreeIds): NamedArg = new NamedArg(name, arg) + def Assign(lhs: Tree, rhs: Tree)(implicit ids: TreeIds): Assign = new Assign(lhs, rhs) + def Block(stats: List[Tree], expr: Tree)(implicit ids: TreeIds): Block = new Block(stats, expr) + def If(cond: Tree, thenp: Tree, elsep: Tree)(implicit ids: TreeIds): If = new If(cond, thenp, elsep) + def InlineIf(cond: Tree, thenp: Tree, elsep: Tree)(implicit ids: TreeIds): If = new InlineIf(cond, thenp, elsep) + def Closure(env: List[Tree], meth: Tree, tpt: Tree)(implicit ids: TreeIds): Closure = new Closure(env, meth, tpt) + def Match(selector: Tree, cases: List[CaseDef])(implicit ids: TreeIds): Match = new Match(selector, cases) + def InlineMatch(selector: Tree, cases: List[CaseDef])(implicit ids: TreeIds): Match = new InlineMatch(selector, cases) + def CaseDef(pat: Tree, guard: Tree, body: Tree)(implicit ids: TreeIds): CaseDef = new CaseDef(pat, guard, body) + def Labeled(bind: Bind, expr: Tree)(implicit ids: TreeIds): Labeled = new Labeled(bind, expr) + def Return(expr: Tree, from: Tree)(implicit ids: TreeIds): Return = new Return(expr, from) + def WhileDo(cond: Tree, body: Tree)(implicit ids: TreeIds): WhileDo = new WhileDo(cond, body) + def Try(expr: Tree, cases: List[CaseDef], finalizer: Tree)(implicit ids: TreeIds): Try = new Try(expr, cases, finalizer) + def SeqLiteral(elems: List[Tree], elemtpt: Tree)(implicit ids: TreeIds): SeqLiteral = new SeqLiteral(elems, elemtpt) + def JavaSeqLiteral(elems: List[Tree], elemtpt: Tree)(implicit ids: TreeIds): JavaSeqLiteral = new JavaSeqLiteral(elems, elemtpt) + def Inlined(call: tpd.Tree, bindings: List[MemberDef], expansion: Tree)(implicit ids: TreeIds): Inlined = new Inlined(call, bindings, expansion) + def TypeTree()(implicit ids: TreeIds): TypeTree = new TypeTree() + def SingletonTypeTree(ref: Tree)(implicit ids: TreeIds): SingletonTypeTree = new SingletonTypeTree(ref) + def AndTypeTree(left: Tree, right: Tree)(implicit ids: TreeIds): AndTypeTree = new AndTypeTree(left, right) + def OrTypeTree(left: Tree, right: Tree)(implicit ids: TreeIds): OrTypeTree = new OrTypeTree(left, right) + def RefinedTypeTree(tpt: Tree, refinements: List[Tree])(implicit ids: TreeIds): RefinedTypeTree = new RefinedTypeTree(tpt, refinements) + def AppliedTypeTree(tpt: Tree, args: List[Tree])(implicit ids: TreeIds): AppliedTypeTree = new AppliedTypeTree(tpt, args) + def LambdaTypeTree(tparams: List[TypeDef], body: Tree)(implicit ids: TreeIds): LambdaTypeTree = new LambdaTypeTree(tparams, body) + def MatchTypeTree(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit ids: TreeIds): MatchTypeTree = new MatchTypeTree(bound, selector, cases) + def ByNameTypeTree(result: Tree)(implicit ids: TreeIds): ByNameTypeTree = new ByNameTypeTree(result) + def TypeBoundsTree(lo: Tree, hi: Tree)(implicit ids: TreeIds): TypeBoundsTree = new TypeBoundsTree(lo, hi) + def Bind(name: Name, body: Tree)(implicit ids: TreeIds): Bind = new Bind(name, body) + def Alternative(trees: List[Tree])(implicit ids: TreeIds): Alternative = new Alternative(trees) + def UnApply(fun: Tree, implicits: List[Tree], patterns: List[Tree])(implicit ids: TreeIds): UnApply = new UnApply(fun, implicits, patterns) + def ValDef(name: TermName, tpt: Tree, rhs: LazyTree)(implicit ids: TreeIds): ValDef = new ValDef(name, tpt, rhs) + def DefDef(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree)(implicit ids: TreeIds): DefDef = new DefDef(name, tparams, vparamss, tpt, rhs) + def TypeDef(name: TypeName, rhs: Tree)(implicit ids: TreeIds): TypeDef = new TypeDef(name, rhs) + def Template(constr: DefDef, parents: List[Tree], self: ValDef, body: LazyTreeList)(implicit ids: TreeIds): Template = new Template(constr, parents, self, body) + def Import(expr: Tree, selectors: List[Tree])(implicit ids: TreeIds): Import = new Import(expr, selectors) + def PackageDef(pid: RefTree, stats: List[Tree])(implicit ids: TreeIds): PackageDef = new PackageDef(pid, stats) + def Annotated(arg: Tree, annot: Tree)(implicit ids: TreeIds): Annotated = new Annotated(arg, annot) // ------ Additional creation methods for untyped only ----------------- @@ -331,32 +339,32 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { ensureApplied((prefix /: argss)(Apply(_, _))) } - def Block(stat: Tree, expr: Tree): Block = + def Block(stat: Tree, expr: Tree)(implicit ids: TreeIds): Block = Block(stat :: Nil, expr) - def Apply(fn: Tree, arg: Tree): Apply = + def Apply(fn: Tree, arg: Tree)(implicit ids: TreeIds): Apply = Apply(fn, arg :: Nil) - def ensureApplied(tpt: Tree): Tree = tpt match { + def ensureApplied(tpt: Tree)(implicit ids: TreeIds): Tree = tpt match { case _: Apply => tpt case _ => Apply(tpt, Nil) } - def AppliedTypeTree(tpt: Tree, arg: Tree): AppliedTypeTree = + def AppliedTypeTree(tpt: Tree, arg: Tree)(implicit ids: TreeIds): AppliedTypeTree = AppliedTypeTree(tpt, arg :: Nil) def TypeTree(tpe: Type)(implicit ctx: Context): TypedSplice = TypedSplice(TypeTree().withTypeUnchecked(tpe)) - def unitLiteral: Literal = Literal(Constant(())) + def unitLiteral(implicit ids: TreeIds): Literal = Literal(Constant(())) def ref(tp: NamedType)(implicit ctx: Context): Tree = TypedSplice(tpd.ref(tp)) - def rootDot(name: Name): Select = Select(Ident(nme.ROOTPKG), name) - def scalaDot(name: Name): Select = Select(rootDot(nme.scala_), name) - def scalaUnit: Select = scalaDot(tpnme.Unit) - def scalaAny: Select = scalaDot(tpnme.Any) - def javaDotLangDot(name: Name): Select = Select(Select(Ident(nme.java), nme.lang), name) + def rootDot(name: Name)(implicit ids: TreeIds): Select = Select(Ident(nme.ROOTPKG), name) + def scalaDot(name: Name)(implicit ids: TreeIds): Select = Select(rootDot(nme.scala_), name) + def scalaUnit(implicit ids: TreeIds): Select = scalaDot(tpnme.Unit) + def scalaAny(implicit ids: TreeIds): Select = scalaDot(tpnme.Any) + def javaDotLangDot(name: Name)(implicit ids: TreeIds): Select = Select(Select(Ident(nme.java), nme.lang), name) def makeConstructor(tparams: List[TypeDef], vparamss: List[List[ValDef]], rhs: Tree = EmptyTree)(implicit ctx: Context): DefDef = DefDef(nme.CONSTRUCTOR, tparams, vparamss, TypeTree(), rhs) @@ -380,8 +388,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def makeParameter(pname: TermName, tpe: Tree, mods: Modifiers = EmptyModifiers)(implicit ctx: Context): ValDef = ValDef(pname, tpe, EmptyTree).withMods(mods | Param) - def makeSyntheticParameter(n: Int = 1, tpt: Tree = TypeTree())(implicit ctx: Context): ValDef = - ValDef(nme.syntheticParamName(n), tpt, EmptyTree).withFlags(SyntheticTermParam) + def makeSyntheticParameter(n: Int = 1, tpt: Tree = null)(implicit ctx: Context): ValDef = + ValDef(nme.syntheticParamName(n), if (tpt == null) TypeTree() else tpt, EmptyTree) + .withFlags(SyntheticTermParam) def lambdaAbstract(tparams: List[TypeDef], tpt: Tree)(implicit ctx: Context): Tree = if (tparams.isEmpty) tpt else LambdaTypeTree(tparams, tpt) @@ -421,80 +430,80 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { } }.asInstanceOf[copied.ThisTree[Untyped]] - def ModuleDef(tree: Tree)(name: TermName, impl: Template): ModuleDef = tree match { + def ModuleDef(tree: Tree)(name: TermName, impl: Template)(implicit ids: TreeIds): ModuleDef = tree match { case tree: ModuleDef if (name eq tree.name) && (impl eq tree.impl) => tree case _ => finalize(tree, untpd.ModuleDef(name, impl)) } - def ParsedTry(tree: Tree)(expr: Tree, handler: Tree, finalizer: Tree): TermTree = tree match { + def ParsedTry(tree: Tree)(expr: Tree, handler: Tree, finalizer: Tree)(implicit ids: TreeIds): TermTree = tree match { case tree: ParsedTry if (expr eq tree.expr) && (handler eq tree.handler) && (finalizer eq tree.finalizer) => tree case _ => finalize(tree, untpd.ParsedTry(expr, handler, finalizer)) } - def SymbolLit(tree: Tree)(str: String): TermTree = tree match { + def SymbolLit(tree: Tree)(str: String)(implicit ids: TreeIds): TermTree = tree match { case tree: SymbolLit if str == tree.str => tree case _ => finalize(tree, untpd.SymbolLit(str)) } - def InterpolatedString(tree: Tree)(id: TermName, segments: List[Tree]): TermTree = tree match { + def InterpolatedString(tree: Tree)(id: TermName, segments: List[Tree])(implicit ids: TreeIds): TermTree = tree match { case tree: InterpolatedString if (id eq tree.id) && (segments eq tree.segments) => tree case _ => finalize(tree, untpd.InterpolatedString(id, segments)) } - def Function(tree: Tree)(args: List[Tree], body: Tree): Tree = tree match { + def Function(tree: Tree)(args: List[Tree], body: Tree)(implicit ids: TreeIds): Tree = tree match { case tree: Function if (args eq tree.args) && (body eq tree.body) => tree case _ => finalize(tree, untpd.Function(args, body)) } - def InfixOp(tree: Tree)(left: Tree, op: Ident, right: Tree): Tree = tree match { + def InfixOp(tree: Tree)(left: Tree, op: Ident, right: Tree)(implicit ids: TreeIds): Tree = tree match { case tree: InfixOp if (left eq tree.left) && (op eq tree.op) && (right eq tree.right) => tree case _ => finalize(tree, untpd.InfixOp(left, op, right)) } - def PostfixOp(tree: Tree)(od: Tree, op: Ident): Tree = tree match { + def PostfixOp(tree: Tree)(od: Tree, op: Ident)(implicit ids: TreeIds): Tree = tree match { case tree: PostfixOp if (od eq tree.od) && (op eq tree.op) => tree case _ => finalize(tree, untpd.PostfixOp(od, op)) } - def PrefixOp(tree: Tree)(op: Ident, od: Tree): Tree = tree match { + def PrefixOp(tree: Tree)(op: Ident, od: Tree)(implicit ids: TreeIds): Tree = tree match { case tree: PrefixOp if (op eq tree.op) && (od eq tree.od) => tree case _ => finalize(tree, untpd.PrefixOp(op, od)) } - def Parens(tree: Tree)(t: Tree): ProxyTree = tree match { + def Parens(tree: Tree)(t: Tree)(implicit ids: TreeIds): ProxyTree = tree match { case tree: Parens if t eq tree.t => tree case _ => finalize(tree, untpd.Parens(t)) } - def Tuple(tree: Tree)(trees: List[Tree]): Tree = tree match { + def Tuple(tree: Tree)(trees: List[Tree])(implicit ids: TreeIds): Tree = tree match { case tree: Tuple if trees eq tree.trees => tree case _ => finalize(tree, untpd.Tuple(trees)) } - def Throw(tree: Tree)(expr: Tree): TermTree = tree match { + def Throw(tree: Tree)(expr: Tree)(implicit ids: TreeIds): TermTree = tree match { case tree: Throw if expr eq tree.expr => tree case _ => finalize(tree, untpd.Throw(expr)) } - def Quote(tree: Tree)(expr: Tree): TermTree = tree match { + def Quote(tree: Tree)(expr: Tree)(implicit ids: TreeIds): TermTree = tree match { case tree: Quote if expr eq tree.expr => tree case _ => finalize(tree, untpd.Quote(expr)) } - def DoWhile(tree: Tree)(body: Tree, cond: Tree): TermTree = tree match { + def DoWhile(tree: Tree)(body: Tree, cond: Tree)(implicit ids: TreeIds): TermTree = tree match { case tree: DoWhile if (body eq tree.body) && (cond eq tree.cond) => tree case _ => finalize(tree, untpd.DoWhile(body, cond)) } - def ForYield(tree: Tree)(enums: List[Tree], expr: Tree): TermTree = tree match { + def ForYield(tree: Tree)(enums: List[Tree], expr: Tree)(implicit ids: TreeIds): TermTree = tree match { case tree: ForYield if (enums eq tree.enums) && (expr eq tree.expr) => tree case _ => finalize(tree, untpd.ForYield(enums, expr)) } - def ForDo(tree: Tree)(enums: List[Tree], body: Tree): TermTree = tree match { + def ForDo(tree: Tree)(enums: List[Tree], body: Tree)(implicit ids: TreeIds): TermTree = tree match { case tree: ForDo if (enums eq tree.enums) && (body eq tree.body) => tree case _ => finalize(tree, untpd.ForDo(enums, body)) } - def GenFrom(tree: Tree)(pat: Tree, expr: Tree): Tree = tree match { + def GenFrom(tree: Tree)(pat: Tree, expr: Tree)(implicit ids: TreeIds): Tree = tree match { case tree: GenFrom if (pat eq tree.pat) && (expr eq tree.expr) => tree case _ => finalize(tree, untpd.GenFrom(pat, expr)) } - def GenAlias(tree: Tree)(pat: Tree, expr: Tree): Tree = tree match { + def GenAlias(tree: Tree)(pat: Tree, expr: Tree)(implicit ids: TreeIds): Tree = tree match { case tree: GenAlias if (pat eq tree.pat) && (expr eq tree.expr) => tree case _ => finalize(tree, untpd.GenAlias(pat, expr)) } - def ContextBounds(tree: Tree)(bounds: TypeBoundsTree, cxBounds: List[Tree]): TypTree = tree match { + def ContextBounds(tree: Tree)(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit ids: TreeIds): TypTree = tree match { case tree: ContextBounds if (bounds eq tree.bounds) && (cxBounds eq tree.cxBounds) => tree case _ => finalize(tree, untpd.ContextBounds(bounds, cxBounds)) } - def PatDef(tree: Tree)(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree): Tree = tree match { + def PatDef(tree: Tree)(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit ids: TreeIds): Tree = tree match { case tree: PatDef if (mods eq tree.mods) && (pats eq tree.pats) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree case _ => finalize(tree, untpd.PatDef(mods, pats, tpt, rhs)) } diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index b66a67b3224b..772096fabdb5 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -37,6 +37,15 @@ import plugins._ object Contexts { + /** A generator for tree ids */ + trait TreeIds { + def nextTreeId: Int + } + + object GlobalTreeIds extends TreeIds { + def nextTreeId = 0 + } + private val (compilerCallbackLoc, store1) = Store.empty.newLocation[CompilerCallback]() private val (sbtCallbackLoc, store2) = store1.newLocation[AnalysisCallback]() private val (printerFnLoc, store3) = store2.newLocation[Context => Printer](new RefinedPrinter(_)) @@ -76,6 +85,7 @@ object Contexts { with Reporting with NamerContextOps with Plugins + with TreeIds with Cloneable { thiscontext => implicit def ctx: Context = this @@ -456,6 +466,7 @@ object Contexts { def uniqueNamedTypes: Uniques.NamedTypeUniques = base.uniqueNamedTypes def uniques: util.HashSet[Type] = base.uniques def nextSymId: Int = base.nextSymId + def nextTreeId: Int = base.nextTreeId def initialize()(implicit ctx: Context): Unit = base.initialize()(ctx) } @@ -567,6 +578,7 @@ object Contexts { @sharable object NoContext extends Context { val base: ContextBase = null + override def nextTreeId = 0 override val implicits: ContextualImplicits = new ContextualImplicits(Nil, null)(this) } @@ -625,11 +637,13 @@ object Contexts { class ContextState { // Symbols state - /** A counter for unique ids */ + /** Counters for unique ids */ private[core] var _nextSymId: Int = 0 - def nextSymId: Int = { _nextSymId += 1; _nextSymId } + private[dotc] var _nextTreeId: Int = 0 + def nextTreeId: Int = { _nextTreeId += 1; _nextTreeId } + /** Sources that were loaded */ val sources: mutable.HashMap[AbstractFile, SourceFile] = new mutable.HashMap[AbstractFile, SourceFile] diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 950863fa565f..9f10d478b9a5 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -19,7 +19,7 @@ object TreePickler { val sectionName = "ASTs" - case class Hole(idx: Int, args: List[tpd.Tree]) extends tpd.Tree { + case class Hole(idx: Int, args: List[tpd.Tree])(implicit ids: TreeIds) extends tpd.Tree { override def fallbackToText(printer: Printer): Text = s"[[$idx|" ~~ printer.toTextGlobal(args, ", ") ~~ "]]" } @@ -331,6 +331,8 @@ class TreePickler(pickler: TastyPickler) { writeByte(SHAREDterm) writeRef(addr) } + //else if (tree.source `ne` ctx.source) + // pickleTree(tree)(ctx.withSource(tree.source)) else try tree match { case Ident(name) => diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index bc8a8cc53595..07946650e996 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -1385,7 +1385,7 @@ object TreeUnpickler { } /** A marker value used to detect cyclic reference while unpickling definitions. */ - @sharable val PoisonTree: tpd.Tree = Thicket(Nil) + @sharable val PoisonTree: tpd.Tree = new EmptyTree /** An enumeration indicating which subtrees should be added to an OwnerTree. */ type MemberDefMode = Int diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala index 0f0a0d36bf53..166dffd62549 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala @@ -11,6 +11,7 @@ import Parsers._ import util.Positions._ import core._ import Constants._ +import Contexts.TreeIds import Utility._ @@ -46,7 +47,7 @@ object MarkupParsers { override def getMessage: String = "input ended while parsing XML" } - class MarkupParser(parser: Parser, final val preserveWS: Boolean) extends MarkupParserCommon { + class MarkupParser(parser: Parser, final val preserveWS: Boolean)(implicit ids: TreeIds) extends MarkupParserCommon { import Tokens.{ LBRACE, RBRACE } diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/package.scala b/compiler/src/dotty/tools/dotc/tastyreflect/package.scala index d13dc0f322b0..52528720a93c 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/package.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/package.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc import dotty.tools.dotc.ast.Trees.{Tree, Untyped} -import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.core.Contexts.{Context, TreeIds} import dotty.tools.dotc.core.Symbols.Symbol import dotty.tools.dotc.core.Types.Type import dotty.tools.dotc.core.SymDenotations.SymDenotation @@ -11,7 +11,7 @@ package object tastyreflect { type PackageDefinition = PackageDefinitionImpl[Type] /** Represents the symbol of a definition in tree form */ - case class PackageDefinitionImpl[-T >: Untyped] private[tastyreflect] (sym: Symbol) extends Tree[T] { + case class PackageDefinitionImpl[-T >: Untyped] private[tastyreflect] (sym: Symbol)(implicit ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] = PackageDefinitionImpl[T] override def denot(implicit ctx: Context): SymDenotation = sym.denot diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 438249f89124..3cda46c96e07 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -189,7 +189,6 @@ object Applications { } } - trait Applications extends Compatibility { self: Typer with Dynamic => import Applications._ diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index aef040c5df78..20003b2d1dc0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -41,13 +41,6 @@ import scala.annotation.internal.sharable object Implicits { import tpd._ - /** A flag indicating that this an application of an extension method - * with the given name - */ - case class ExtMethodResult(app: Tree) extends tpd.Tree { - override def pos = app.pos - } - /** An implicit definition `implicitRef` that is visible under a different name, `alias`. * Gets generated if an implicit ref is imported via a renaming import. */ @@ -355,7 +348,7 @@ object Implicits { } object SearchFailure { - def apply(tpe: SearchFailureType): SearchFailure = { + def apply(tpe: SearchFailureType)(implicit ids: TreeIds): SearchFailure = { val id = if (tpe.isInstanceOf[AmbiguousImplicits]) "/* ambiguous */" else "/* missing */" @@ -394,7 +387,7 @@ object Implicits { @sharable object NoMatchingImplicits extends NoMatchingImplicits(NoType, EmptyTree) @sharable val NoMatchingImplicitsFailure: SearchFailure = - SearchFailure(NoMatchingImplicits) + SearchFailure(NoMatchingImplicits)(GlobalTreeIds) /** An ambiguous implicits failure */ class AmbiguousImplicits(val alt1: SearchSuccess, val alt2: SearchSuccess, val expectedType: Type, val argument: Tree) extends SearchFailureType { diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 9c3af1eef743..1397d19ae6a2 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -410,7 +410,7 @@ object ProtoTypes { } class UnapplyFunProto(argType: Type, typer: Typer)(implicit ctx: Context) extends FunProto( - untpd.TypedSplice(dummyTreeOfType(argType))(ctx) :: Nil, WildcardType)(typer) + untpd.TypedSplice(dummyTreeOfType(argType)(ctx))(ctx) :: Nil, WildcardType)(typer) /** A prototype for expressions [] that are type-parameterized: * @@ -652,7 +652,7 @@ object ProtoTypes { /** Dummy tree to be used as an argument of a FunProto or ViewProto type */ object dummyTreeOfType { - def apply(tp: Type): Tree = untpd.Literal(Constant(null)) withTypeUnchecked tp + def apply(tp: Type)(implicit ids: TreeIds): Tree = untpd.Literal(Constant(null)) withTypeUnchecked tp def unapply(tree: untpd.Tree): Option[Type] = tree match { case Literal(Constant(null)) => Some(tree.typeOpt) case _ => None From 1cdae05daa07dbb621534d6bb6e6e7cbefd9ad42 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 19 Dec 2018 10:52:13 +0100 Subject: [PATCH 03/75] Adapt refelect.TreeOps to new scheme --- compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala | 4 ++-- library/src/scala/tasty/reflect/TreeOps.scala | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala index 49b221a22947..fbcf34e3baa5 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala @@ -444,7 +444,7 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers def apply(cls: ClassSymbol)(implicit ctx: Context): This = tpd.This(cls) - def copy(original: Tree)(qual: Option[Id]): This = + def copy(original: Tree)(qual: Option[Id])(implicit ctx: Context): This = tpd.cpy.This(original)(qual.getOrElse(untpd.EmptyTypeIdent)) def unapply(x: Term)(implicit ctx: Context): Option[Option[Id]] = x match { @@ -555,7 +555,7 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers def apply(qual: Term, mix: Option[Id])(implicit ctx: Context): Super = tpd.Super(qual, mix.getOrElse(untpd.EmptyTypeIdent), false, NoSymbol) - def copy(original: Tree)(qual: Term, mix: Option[Id]): Super = + def copy(original: Tree)(qual: Term, mix: Option[Id])(implicit ctx: Context): Super = tpd.cpy.Super(original)(qual, mix.getOrElse(untpd.EmptyTypeIdent)) def unapply(x: Term)(implicit ctx: Context): Option[(Term, Option[Id])] = x match { diff --git a/library/src/scala/tasty/reflect/TreeOps.scala b/library/src/scala/tasty/reflect/TreeOps.scala index be45b19e8f02..5d0a40747907 100644 --- a/library/src/scala/tasty/reflect/TreeOps.scala +++ b/library/src/scala/tasty/reflect/TreeOps.scala @@ -320,7 +320,7 @@ trait TreeOps extends Core { /** Create a `this[` */ def apply(cls: ClassSymbol)(implicit ctx: Context): This - def copy(original: Tree)(qual: Option[Id]): This + def copy(original: Tree)(qual: Option[Id])(implicit ctx: Context): This /** Matches `this[` */ def unapply(tree: Tree)(implicit ctx: Context): Option[Option[Id]] @@ -444,7 +444,7 @@ trait TreeOps extends Core { /** Creates a `.super[` */ def apply(qual: Term, mix: Option[Id])(implicit ctx: Context): Super - def copy(original: Tree)(qual: Term, mix: Option[Id]): Super + def copy(original: Tree)(qual: Term, mix: Option[Id])(implicit ctx: Context): Super /** Matches a `.super[` */ def unapply(tree: Tree)(implicit ctx: Context): Option[(Term, Option[Id])] From 1b6a4711c5831cd577260c2e986bb15b6614dabe Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 19 Dec 2018 11:18:33 +0100 Subject: [PATCH 04/75] @transientParam annotation --- .../dotty/tools/dotc/core/Definitions.scala | 2 ++ .../tools/dotc/transform/Constructors.scala | 2 ++ .../src/scala/annotation/transientParam.scala | 20 +++++++++++++++++++ tests/neg/transient-param.scala | 14 +++++++++++++ 4 files changed, 38 insertions(+) create mode 100644 library/src/scala/annotation/transientParam.scala create mode 100644 tests/neg/transient-param.scala diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index a3f4191b7af1..1363b50b2965 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -794,6 +794,8 @@ class Definitions { def TASTYLongSignatureAnnot(implicit ctx: Context): ClassSymbol = TASTYLongSignatureAnnotType.symbol.asClass lazy val TailrecAnnotType: TypeRef = ctx.requiredClassRef("scala.annotation.tailrec") def TailrecAnnot(implicit ctx: Context): ClassSymbol = TailrecAnnotType.symbol.asClass + lazy val TransientParamAnnotType: TypeRef = ctx.requiredClassRef("scala.annotation.transientParam") + def TransientParamAnnot(implicit ctx: Context): ClassSymbol = TransientParamAnnotType.symbol.asClass lazy val SwitchAnnotType: TypeRef = ctx.requiredClassRef("scala.annotation.switch") def SwitchAnnot(implicit ctx: Context): ClassSymbol = SwitchAnnotType.symbol.asClass lazy val ThrowsAnnotType: TypeRef = ctx.requiredClassRef("scala.throws") diff --git a/compiler/src/dotty/tools/dotc/transform/Constructors.scala b/compiler/src/dotty/tools/dotc/transform/Constructors.scala index 78c440061db7..8ebb4976a9a1 100644 --- a/compiler/src/dotty/tools/dotc/transform/Constructors.scala +++ b/compiler/src/dotty/tools/dotc/transform/Constructors.scala @@ -224,6 +224,8 @@ class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase = dropped += acc Nil } else { + if (acc.hasAnnotation(defn.TransientParamAnnot)) + ctx.error(em"transient parameter $acc is retained as field in class ${acc.owner}", acc.pos) val target = if (acc.is(Method)) acc.field else acc if (!target.exists) Nil // this case arises when the parameter accessor is an alias else { diff --git a/library/src/scala/annotation/transientParam.scala b/library/src/scala/annotation/transientParam.scala new file mode 100644 index 000000000000..32b7a3b4f21d --- /dev/null +++ b/library/src/scala/annotation/transientParam.scala @@ -0,0 +1,20 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.annotation + +import scala.annotation.meta._ + +/** An annotation that goes on parameters of classes or traits. It asserts + * that the parameter is used only for initialization and is not kept in + * the class as a field. Violations of this assertion are flagged as + * compile errors. The annotatoon is particularly useful for implicit + * parameters since for these a textual scan is not sufficient to know + * where they are used. + */ +@param class transientParam extends scala.annotation.StaticAnnotation diff --git a/tests/neg/transient-param.scala b/tests/neg/transient-param.scala new file mode 100644 index 000000000000..188cd78f7baf --- /dev/null +++ b/tests/neg/transient-param.scala @@ -0,0 +1,14 @@ +import annotation.transientParam +class Context + +class Test1()(implicit @transientParam ctx: Context) { // error + def test1 = implicitly[Context] +} + +class Test2()(@transientParam ctx: Context) { // error + def test1 = ctx +} + +class Test3()(implicit @transientParam ctx: Context) { // OK + val foo = implicitly[Context] +} From 2cad64276fd5ae960c139cfd2d80663c227e61eb Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 19 Dec 2018 11:33:18 +0100 Subject: [PATCH 05/75] Apply @transientParam to compiler It's very important that tree nodes don't capture contexts. The @transientParam annotation makes sure they don't. --- .../src/dotty/tools/dotc/ast/Desugar.scala | 11 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 117 +++++++++--------- compiler/src/dotty/tools/dotc/ast/untpd.scala | 56 ++++----- .../tools/dotc/core/tasty/TreePickler.scala | 3 +- .../tools/dotc/tastyreflect/package.scala | 3 +- .../dotty/tools/dotc/typer/Applications.scala | 3 +- 6 files changed, 99 insertions(+), 94 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index d61d59e69693..e4135feb8103 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -12,6 +12,7 @@ import util.Property import collection.mutable.ListBuffer import reporting.diagnostic.messages._ import reporting.trace +import annotation.transientParam import scala.annotation.internal.sharable @@ -42,15 +43,15 @@ object desugar { // ----- DerivedTypeTrees ----------------------------------- - class SetterParamTree(implicit ids: TreeIds) extends DerivedTypeTree { + class SetterParamTree(implicit @transientParam ids: TreeIds) extends DerivedTypeTree { def derivedTree(sym: Symbol)(implicit ctx: Context): tpd.TypeTree = tpd.TypeTree(sym.info.resultType) } - class TypeRefTree(implicit ids: TreeIds) extends DerivedTypeTree { + class TypeRefTree(implicit @transientParam ids: TreeIds) extends DerivedTypeTree { def derivedTree(sym: Symbol)(implicit ctx: Context): tpd.TypeTree = tpd.TypeTree(sym.typeRef) } - class TermRefTree(implicit ids: TreeIds) extends DerivedTypeTree { + class TermRefTree(implicit @transientParam ids: TreeIds) extends DerivedTypeTree { def derivedTree(sym: Symbol)(implicit ctx: Context): tpd.Tree = tpd.ref(sym) } @@ -58,7 +59,7 @@ object desugar { * @param suffix String difference between existing parameter (call it `P`) and parameter owning the * DerivedTypeTree (call it `O`). We have: `O.name == P.name + suffix`. */ - class DerivedFromParamTree(suffix: String)(implicit ids: TreeIds) extends DerivedTypeTree { + class DerivedFromParamTree(suffix: String)(implicit @transientParam ids: TreeIds) extends DerivedTypeTree { /** Make sure that for all enclosing module classes their companion classes * are completed. Reason: We need the constructor of such companion classes to @@ -1389,6 +1390,6 @@ object desugar { buf.toList } - private class IrrefutableGenFrom(pat: Tree, expr: Tree)(implicit ids: TreeIds) + private class IrrefutableGenFrom(pat: Tree, expr: Tree)(implicit @transientParam ids: TreeIds) extends GenFrom(pat, expr) } diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 30b3e71f0eef..385a2dea2e21 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -13,6 +13,7 @@ import util.{Stats, Attachment, Property} import config.Config import annotation.internal.sharable import annotation.unchecked.uncheckedVariance +import annotation.transientParam object Trees { @@ -49,7 +50,7 @@ object Trees { * - Type checking an untyped tree should remove all embedded `TypedSplice` * nodes. */ - abstract class Tree[-T >: Untyped](implicit ids: TreeIds) + abstract class Tree[-T >: Untyped](implicit @transientParam ids: TreeIds) extends Positioned with Product with Attachment.Container @@ -269,7 +270,7 @@ object Trees { } /** Tree's denotation can be derived from its type */ - abstract class DenotingTree[-T >: Untyped](implicit ids: TreeIds) extends Tree[T] { + abstract class DenotingTree[-T >: Untyped](implicit @transientParam ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] <: DenotingTree[T] override def denot(implicit ctx: Context): Denotation = typeOpt match { case tpe: NamedType => tpe.denot @@ -286,7 +287,7 @@ object Trees { /** Tree's denot/isType/isTerm properties come from a subtree * identified by `forwardTo`. */ - abstract class ProxyTree[-T >: Untyped](implicit ids: TreeIds) extends Tree[T] { + abstract class ProxyTree[-T >: Untyped](implicit @transientParam ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] <: ProxyTree[T] def forwardTo: Tree[T] override def denot(implicit ctx: Context): Denotation = forwardTo.denot @@ -295,13 +296,13 @@ object Trees { } /** Tree has a name */ - abstract class NameTree[-T >: Untyped](implicit ids: TreeIds) extends DenotingTree[T] { + abstract class NameTree[-T >: Untyped](implicit @transientParam ids: TreeIds) extends DenotingTree[T] { type ThisTree[-T >: Untyped] <: NameTree[T] def name: Name } /** Tree refers by name to a denotation */ - abstract class RefTree[-T >: Untyped](implicit ids: TreeIds) extends NameTree[T] { + abstract class RefTree[-T >: Untyped](implicit @transientParam ids: TreeIds) extends NameTree[T] { type ThisTree[-T >: Untyped] <: RefTree[T] def qualifier: Tree[T] override def isType: Boolean = name.isTypeName @@ -320,7 +321,7 @@ object Trees { * The envelope of a MemberDef contains the whole definition and has its point * on the opening keyword (or the next token after that if keyword is missing). */ - abstract class MemberDef[-T >: Untyped](implicit ids: TreeIds) extends NameTree[T] with DefTree[T] { + abstract class MemberDef[-T >: Untyped](implicit @transientParam ids: TreeIds) extends NameTree[T] with DefTree[T] { type ThisTree[-T >: Untyped] <: MemberDef[T] private[this] var myMods: untpd.Modifiers = null @@ -362,7 +363,7 @@ object Trees { } /** A ValDef or DefDef tree */ - abstract class ValOrDefDef[-T >: Untyped](implicit ids: TreeIds) extends MemberDef[T] with WithLazyField[Tree[T]] { + abstract class ValOrDefDef[-T >: Untyped](implicit @transientParam ids: TreeIds) extends MemberDef[T] with WithLazyField[Tree[T]] { def name: TermName def tpt: Tree[T] def unforcedRhs: LazyTree = unforced @@ -372,7 +373,7 @@ object Trees { // ----------- Tree case classes ------------------------------------ /** name */ - case class Ident[-T >: Untyped] private[ast] (name: Name)(implicit ids: TreeIds) + case class Ident[-T >: Untyped] private[ast] (name: Name)(implicit @transientParam ids: TreeIds) extends RefTree[T] { type ThisTree[-T >: Untyped] = Ident[T] def qualifier: Tree[T] = genericEmptyTree @@ -381,31 +382,31 @@ object Trees { def isBackquoted: Boolean = false } - class BackquotedIdent[-T >: Untyped]private[ast] (name: Name)(implicit ids: TreeIds) + class BackquotedIdent[-T >: Untyped]private[ast] (name: Name)(implicit @transientParam ids: TreeIds) extends Ident[T](name) { override def isBackquoted: Boolean = true override def toString: String = s"BackquotedIdent($name)" } - class SearchFailureIdent[-T >: Untyped] private[ast] (name: Name)(implicit ids: TreeIds) + class SearchFailureIdent[-T >: Untyped] private[ast] (name: Name)(implicit @transientParam ids: TreeIds) extends Ident[T](name) { override def toString: String = s"SearchFailureIdent($name)" } /** qualifier.name, or qualifier#name, if qualifier is a type */ - case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name)(implicit ids: TreeIds) + case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name)(implicit @transientParam ids: TreeIds) extends RefTree[T] { type ThisTree[-T >: Untyped] = Select[T] } - class SelectWithSig[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name, val sig: Signature)(implicit ids: TreeIds) + class SelectWithSig[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name, val sig: Signature)(implicit @transientParam ids: TreeIds) extends Select[T](qualifier, name) { override def toString: String = s"SelectWithSig($qualifier, $name, $sig)" } /** qual.this */ - case class This[-T >: Untyped] private[ast] (qual: untpd.Ident)(implicit ids: TreeIds) + case class This[-T >: Untyped] private[ast] (qual: untpd.Ident)(implicit @transientParam ids: TreeIds) extends DenotingTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = This[T] // Denotation of a This tree is always the underlying class; needs correction for modules. @@ -420,13 +421,13 @@ object Trees { } /** C.super[mix], where qual = C.this */ - case class Super[-T >: Untyped] private[ast] (qual: Tree[T], mix: untpd.Ident)(implicit ids: TreeIds) + case class Super[-T >: Untyped] private[ast] (qual: Tree[T], mix: untpd.Ident)(implicit @transientParam ids: TreeIds) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Super[T] def forwardTo: Tree[T] = qual } - abstract class GenericApply[-T >: Untyped](implicit ids: TreeIds) extends ProxyTree[T] with TermTree[T] { + abstract class GenericApply[-T >: Untyped](implicit @transientParam ids: TreeIds) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] <: GenericApply[T] val fun: Tree[T] val args: List[Tree[T]] @@ -434,50 +435,50 @@ object Trees { } /** fun(args) */ - case class Apply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit ids: TreeIds) + case class Apply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit @transientParam ids: TreeIds) extends GenericApply[T] { type ThisTree[-T >: Untyped] = Apply[T] } /** fun[args] */ - case class TypeApply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit ids: TreeIds) + case class TypeApply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit @transientParam ids: TreeIds) extends GenericApply[T] { type ThisTree[-T >: Untyped] = TypeApply[T] } /** const */ - case class Literal[-T >: Untyped] private[ast] (const: Constant)(implicit ids: TreeIds) + case class Literal[-T >: Untyped] private[ast] (const: Constant)(implicit @transientParam ids: TreeIds) extends Tree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Literal[T] } /** new tpt, but no constructor call */ - case class New[-T >: Untyped] private[ast] (tpt: Tree[T])(implicit ids: TreeIds) + case class New[-T >: Untyped] private[ast] (tpt: Tree[T])(implicit @transientParam ids: TreeIds) extends Tree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = New[T] } /** expr : tpt */ - case class Typed[-T >: Untyped] private[ast] (expr: Tree[T], tpt: Tree[T])(implicit ids: TreeIds) + case class Typed[-T >: Untyped] private[ast] (expr: Tree[T], tpt: Tree[T])(implicit @transientParam ids: TreeIds) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Typed[T] def forwardTo: Tree[T] = expr } /** name = arg, in a parameter list */ - case class NamedArg[-T >: Untyped] private[ast] (name: Name, arg: Tree[T])(implicit ids: TreeIds) + case class NamedArg[-T >: Untyped] private[ast] (name: Name, arg: Tree[T])(implicit @transientParam ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] = NamedArg[T] } /** name = arg, outside a parameter list */ - case class Assign[-T >: Untyped] private[ast] (lhs: Tree[T], rhs: Tree[T])(implicit ids: TreeIds) + case class Assign[-T >: Untyped] private[ast] (lhs: Tree[T], rhs: Tree[T])(implicit @transientParam ids: TreeIds) extends TermTree[T] { type ThisTree[-T >: Untyped] = Assign[T] } /** { stats; expr } */ - case class Block[-T >: Untyped] private[ast] (stats: List[Tree[T]], expr: Tree[T])(implicit ids: TreeIds) + case class Block[-T >: Untyped] private[ast] (stats: List[Tree[T]], expr: Tree[T])(implicit @transientParam ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] = Block[T] override def isType: Boolean = expr.isType @@ -485,12 +486,12 @@ object Trees { } /** if cond then thenp else elsep */ - case class If[-T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit ids: TreeIds) + case class If[-T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit @transientParam ids: TreeIds) extends TermTree[T] { type ThisTree[-T >: Untyped] = If[T] def isInline = false } - class InlineIf[T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit ids: TreeIds) + class InlineIf[T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit @transientParam ids: TreeIds) extends If(cond, thenp, elsep) { override def isInline = true override def toString = s"InlineIf($cond, $thenp, $elsep)" @@ -505,32 +506,32 @@ object Trees { * of the closure is a function type, otherwise it is the type * given in `tpt`, which must be a SAM type. */ - case class Closure[-T >: Untyped] private[ast] (env: List[Tree[T]], meth: Tree[T], tpt: Tree[T])(implicit ids: TreeIds) + case class Closure[-T >: Untyped] private[ast] (env: List[Tree[T]], meth: Tree[T], tpt: Tree[T])(implicit @transientParam ids: TreeIds) extends TermTree[T] { type ThisTree[-T >: Untyped] = Closure[T] } /** selector match { cases } */ - case class Match[-T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit ids: TreeIds) + case class Match[-T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam ids: TreeIds) extends TermTree[T] { assert(cases.nonEmpty) type ThisTree[-T >: Untyped] = Match[T] def isInline = false } - class InlineMatch[T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit ids: TreeIds) + class InlineMatch[T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam ids: TreeIds) extends Match(selector, cases) { override def isInline = true override def toString = s"InlineMatch($selector, $cases)" } /** case pat if guard => body; only appears as child of a Match */ - case class CaseDef[-T >: Untyped] private[ast] (pat: Tree[T], guard: Tree[T], body: Tree[T])(implicit ids: TreeIds) + case class CaseDef[-T >: Untyped] private[ast] (pat: Tree[T], guard: Tree[T], body: Tree[T])(implicit @transientParam ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] = CaseDef[T] } /** label[tpt]: { expr } */ - case class Labeled[-T >: Untyped] private[ast] (bind: Bind[T], expr: Tree[T])(implicit ids: TreeIds) + case class Labeled[-T >: Untyped] private[ast] (bind: Bind[T], expr: Tree[T])(implicit @transientParam ids: TreeIds) extends NameTree[T] { type ThisTree[-T >: Untyped] = Labeled[T] def name: Name = bind.name @@ -541,13 +542,13 @@ object Trees { * After program transformations this is not necessarily the enclosing method, because * closures can intervene. */ - case class Return[-T >: Untyped] private[ast] (expr: Tree[T], from: Tree[T] = genericEmptyTree)(implicit ids: TreeIds) + case class Return[-T >: Untyped] private[ast] (expr: Tree[T], from: Tree[T] = genericEmptyTree)(implicit @transientParam ids: TreeIds) extends TermTree[T] { type ThisTree[-T >: Untyped] = Return[T] } /** while (cond) { body } */ - case class WhileDo[-T >: Untyped] private[ast] (cond: Tree[T], body: Tree[T])(implicit ids: TreeIds) + case class WhileDo[-T >: Untyped] private[ast] (cond: Tree[T], body: Tree[T])(implicit @transientParam ids: TreeIds) extends TermTree[T] { type ThisTree[-T >: Untyped] = WhileDo[T] } @@ -571,7 +572,7 @@ object Trees { * * Match(EmptyTree, $anonfun(x)>) */ - case class Try[-T >: Untyped] private[ast] (expr: Tree[T], cases: List[CaseDef[T]], finalizer: Tree[T])(implicit ids: TreeIds) + case class Try[-T >: Untyped] private[ast] (expr: Tree[T], cases: List[CaseDef[T]], finalizer: Tree[T])(implicit @transientParam ids: TreeIds) extends TermTree[T] { type ThisTree[-T >: Untyped] = Try[T] } @@ -579,13 +580,13 @@ object Trees { /** Seq(elems) * @param tpt The element type of the sequence. */ - case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit ids: TreeIds) + case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit @transientParam ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] = SeqLiteral[T] } /** Array(elems) */ - class JavaSeqLiteral[T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit ids: TreeIds) + class JavaSeqLiteral[T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit @transientParam ids: TreeIds) extends SeqLiteral(elems, elemtpt) { override def toString: String = s"JavaSeqLiteral($elems, $elemtpt)" } @@ -606,14 +607,14 @@ object Trees { * different context: `bindings` represent the arguments to the inlined * call, whereas `expansion` represents the body of the inlined function. */ - case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T])(implicit ids: TreeIds) + case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T])(implicit @transientParam ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] = Inlined[T] override def initialPos: Position = call.pos } /** A type tree that represents an existing or inferred type */ - case class TypeTree[-T >: Untyped]()(implicit ids: TreeIds) + case class TypeTree[-T >: Untyped]()(implicit @transientParam ids: TreeIds) extends DenotingTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = TypeTree[T] override def isEmpty: Boolean = !hasType @@ -624,66 +625,66 @@ object Trees { /** A type tree that defines a new type variable. Its type is always a TypeVar. * Every TypeVar is created as the type of one TypeVarBinder. */ - class TypeVarBinder[-T >: Untyped](implicit ids: TreeIds) extends TypeTree[T] + class TypeVarBinder[-T >: Untyped](implicit @transientParam ids: TreeIds) extends TypeTree[T] /** ref.type */ - case class SingletonTypeTree[-T >: Untyped] private[ast] (ref: Tree[T])(implicit ids: TreeIds) + case class SingletonTypeTree[-T >: Untyped] private[ast] (ref: Tree[T])(implicit @transientParam ids: TreeIds) extends DenotingTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = SingletonTypeTree[T] } /** left & right */ - case class AndTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])(implicit ids: TreeIds) + case class AndTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])(implicit @transientParam ids: TreeIds) extends TypTree[T] { type ThisTree[-T >: Untyped] = AndTypeTree[T] } /** left | right */ - case class OrTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])(implicit ids: TreeIds) + case class OrTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])(implicit @transientParam ids: TreeIds) extends TypTree[T] { type ThisTree[-T >: Untyped] = OrTypeTree[T] } /** tpt { refinements } */ - case class RefinedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], refinements: List[Tree[T]])(implicit ids: TreeIds) + case class RefinedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], refinements: List[Tree[T]])(implicit @transientParam ids: TreeIds) extends ProxyTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = RefinedTypeTree[T] def forwardTo: Tree[T] = tpt } /** tpt[args] */ - case class AppliedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], args: List[Tree[T]])(implicit ids: TreeIds) + case class AppliedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], args: List[Tree[T]])(implicit @transientParam ids: TreeIds) extends ProxyTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = AppliedTypeTree[T] def forwardTo: Tree[T] = tpt } /** [typeparams] -> tpt */ - case class LambdaTypeTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T])(implicit ids: TreeIds) + case class LambdaTypeTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T])(implicit @transientParam ids: TreeIds) extends TypTree[T] { type ThisTree[-T >: Untyped] = LambdaTypeTree[T] } /** [bound] selector match { cases } */ - case class MatchTypeTree[-T >: Untyped] private[ast] (bound: Tree[T], selector: Tree[T], cases: List[CaseDef[T]])(implicit ids: TreeIds) + case class MatchTypeTree[-T >: Untyped] private[ast] (bound: Tree[T], selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam ids: TreeIds) extends TypTree[T] { type ThisTree[-T >: Untyped] = MatchTypeTree[T] } /** => T */ - case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T])(implicit ids: TreeIds) + case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T])(implicit @transientParam ids: TreeIds) extends TypTree[T] { type ThisTree[-T >: Untyped] = ByNameTypeTree[T] } /** >: lo <: hi */ - case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T])(implicit ids: TreeIds) + case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T])(implicit @transientParam ids: TreeIds) extends TypTree[T] { type ThisTree[-T >: Untyped] = TypeBoundsTree[T] } /** name @ body */ - case class Bind[-T >: Untyped] private[ast] (name: Name, body: Tree[T])(implicit ids: TreeIds) + case class Bind[-T >: Untyped] private[ast] (name: Name, body: Tree[T])(implicit @transientParam ids: TreeIds) extends NameTree[T] with DefTree[T] with PatternTree[T] { type ThisTree[-T >: Untyped] = Bind[T] override def isType: Boolean = name.isTypeName @@ -691,7 +692,7 @@ object Trees { } /** tree_1 | ... | tree_n */ - case class Alternative[-T >: Untyped] private[ast] (trees: List[Tree[T]])(implicit ids: TreeIds) + case class Alternative[-T >: Untyped] private[ast] (trees: List[Tree[T]])(implicit @transientParam ids: TreeIds) extends PatternTree[T] { type ThisTree[-T >: Untyped] = Alternative[T] } @@ -710,13 +711,13 @@ object Trees { * val result = fun(sel)(implicits) * if (result.isDefined) "match patterns against result" */ - case class UnApply[-T >: Untyped] private[ast] (fun: Tree[T], implicits: List[Tree[T]], patterns: List[Tree[T]])(implicit ids: TreeIds) + case class UnApply[-T >: Untyped] private[ast] (fun: Tree[T], implicits: List[Tree[T]], patterns: List[Tree[T]])(implicit @transientParam ids: TreeIds) extends PatternTree[T] { type ThisTree[-T >: Untyped] = UnApply[T] } /** mods val name: tpt = rhs */ - case class ValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], private var preRhs: LazyTree)(implicit ids: TreeIds) + case class ValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], private var preRhs: LazyTree)(implicit @transientParam ids: TreeIds) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = ValDef[T] assert(isEmpty || tpt != genericEmptyTree) @@ -726,7 +727,7 @@ object Trees { /** mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs */ case class DefDef[-T >: Untyped] private[ast] (name: TermName, tparams: List[TypeDef[T]], - vparamss: List[List[ValDef[T]]], tpt: Tree[T], private var preRhs: LazyTree)(implicit ids: TreeIds) + vparamss: List[List[ValDef[T]]], tpt: Tree[T], private var preRhs: LazyTree)(implicit @transientParam ids: TreeIds) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = DefDef[T] assert(tpt != genericEmptyTree) @@ -739,7 +740,7 @@ object Trees { * mods type name = rhs or * mods type name >: lo <: hi, if rhs = TypeBoundsTree(lo, hi) & (lo ne hi) */ - case class TypeDef[-T >: Untyped] private[ast] (name: TypeName, rhs: Tree[T])(implicit ids: TreeIds) + case class TypeDef[-T >: Untyped] private[ast] (name: TypeName, rhs: Tree[T])(implicit @transientParam ids: TreeIds) extends MemberDef[T] { type ThisTree[-T >: Untyped] = TypeDef[T] @@ -748,7 +749,7 @@ object Trees { } /** extends parents { self => body } */ - case class Template[-T >: Untyped] private[ast] (constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], private var preBody: LazyTreeList)(implicit ids: TreeIds) + case class Template[-T >: Untyped] private[ast] (constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], private var preBody: LazyTreeList)(implicit @transientParam ids: TreeIds) extends DefTree[T] with WithLazyField[List[Tree[T]]] { type ThisTree[-T >: Untyped] = Template[T] def unforcedBody: LazyTreeList = unforced @@ -761,20 +762,20 @@ object Trees { * where a selector is either an untyped `Ident`, `name` or * an untyped thicket consisting of `name` and `rename`. */ - case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]])(implicit ids: TreeIds) + case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]])(implicit @transientParam ids: TreeIds) extends DenotingTree[T] { type ThisTree[-T >: Untyped] = Import[T] } /** package pid { stats } */ - case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]])(implicit ids: TreeIds) + case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]])(implicit @transientParam ids: TreeIds) extends ProxyTree[T] { type ThisTree[-T >: Untyped] = PackageDef[T] def forwardTo: RefTree[T] = pid } /** arg @annot */ - case class Annotated[-T >: Untyped] private[ast] (arg: Tree[T], annot: Tree[T])(implicit ids: TreeIds) + case class Annotated[-T >: Untyped] private[ast] (arg: Tree[T], annot: Tree[T])(implicit @transientParam ids: TreeIds) extends ProxyTree[T] { type ThisTree[-T >: Untyped] = Annotated[T] def forwardTo: Tree[T] = arg @@ -791,7 +792,7 @@ object Trees { * The contained trees will be integrated when transformed with * a `transform(List[Tree])` call. */ - case class Thicket[-T >: Untyped](trees: List[Tree[T]])(implicit ids: TreeIds) + case class Thicket[-T >: Untyped](trees: List[Tree[T]])(implicit @transientParam ids: TreeIds) extends Tree[T] with WithoutTypeOrPos[T] { myTpe = NoType.asInstanceOf[T] diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 79c9b080a04f..8abc5183e98e 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -7,14 +7,14 @@ import Types._, Contexts._, Constants._, Names._, Flags._ import Symbols._, StdNames._, Trees._ import util.Property import language.higherKinds - -import scala.annotation.internal.sharable +import annotation.transientParam +import annotation.internal.sharable object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { // ----- Tree cases that exist in untyped form only ------------------ - abstract class OpTree(implicit ids: TreeIds) extends Tree { + abstract class OpTree(implicit @transientParam ids: TreeIds) extends Tree { def op: Ident override def isTerm: Boolean = op.name.isTermName override def isType: Boolean = op.name.isTypeName @@ -23,7 +23,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { /** A typed subtree of an untyped tree needs to be wrapped in a TypedSplice * @param owner The current owner at the time the tree was defined */ - abstract case class TypedSplice(splice: tpd.Tree)(val owner: Symbol)(implicit ids: TreeIds) extends ProxyTree { + abstract case class TypedSplice(splice: tpd.Tree)(val owner: Symbol)(implicit @transientParam ids: TreeIds) extends ProxyTree { def forwardTo: tpd.Tree = splice } @@ -33,31 +33,31 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { } /** mods object name impl */ - case class ModuleDef(name: TermName, impl: Template)(implicit ids: TreeIds) + case class ModuleDef(name: TermName, impl: Template)(implicit @transientParam ids: TreeIds) extends MemberDef { type ThisTree[-T >: Untyped] <: Trees.NameTree[T] with Trees.MemberDef[T] with ModuleDef def withName(name: Name)(implicit ctx: Context): ModuleDef = cpy.ModuleDef(this)(name.toTermName, impl) } - case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree)(implicit ids: TreeIds) extends Tree with TermTree + case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree)(implicit @transientParam ids: TreeIds) extends Tree with TermTree - case class SymbolLit(str: String)(implicit ids: TreeIds) extends TermTree + case class SymbolLit(str: String)(implicit @transientParam ids: TreeIds) extends TermTree /** An interpolated string * @param segments a list of two element tickets consisting of string literal and argument tree, * possibly with a simple string literal as last element of the list */ - case class InterpolatedString(id: TermName, segments: List[Tree])(implicit ids: TreeIds) + case class InterpolatedString(id: TermName, segments: List[Tree])(implicit @transientParam ids: TreeIds) extends TermTree /** A function type */ - case class Function(args: List[Tree], body: Tree)(implicit ids: TreeIds) extends Tree { + case class Function(args: List[Tree], body: Tree)(implicit @transientParam ids: TreeIds) extends Tree { override def isTerm: Boolean = body.isTerm override def isType: Boolean = body.isType } /** A function type with `implicit` or `erased` modifiers */ - class FunctionWithMods(args: List[Tree], body: Tree, val mods: Modifiers)(implicit ids: TreeIds) + class FunctionWithMods(args: List[Tree], body: Tree, val mods: Modifiers)(implicit @transientParam ids: TreeIds) extends Function(args, body) /** A function created from a wildcard expression @@ -67,32 +67,32 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * This is equivalent to Function, except that forms a special case for the overlapping * positions tests. */ - class WildcardFunction(placeholderParams: List[ValDef], body: Tree)(implicit ids: TreeIds) + class WildcardFunction(placeholderParams: List[ValDef], body: Tree)(implicit @transientParam ids: TreeIds) extends Function(placeholderParams, body) - case class InfixOp(left: Tree, op: Ident, right: Tree)(implicit ids: TreeIds) extends OpTree - case class PostfixOp(od: Tree, op: Ident)(implicit ids: TreeIds) extends OpTree - case class PrefixOp(op: Ident, od: Tree)(implicit ids: TreeIds) extends OpTree { + case class InfixOp(left: Tree, op: Ident, right: Tree)(implicit @transientParam ids: TreeIds) extends OpTree + case class PostfixOp(od: Tree, op: Ident)(implicit @transientParam ids: TreeIds) extends OpTree + case class PrefixOp(op: Ident, od: Tree)(implicit @transientParam ids: TreeIds) extends OpTree { override def isType: Boolean = op.isType override def isTerm: Boolean = op.isTerm } - case class Parens(t: Tree)(implicit ids: TreeIds) extends ProxyTree { + case class Parens(t: Tree)(implicit @transientParam ids: TreeIds) extends ProxyTree { def forwardTo: Tree = t } - case class Tuple(trees: List[Tree])(implicit ids: TreeIds) extends Tree { + case class Tuple(trees: List[Tree])(implicit @transientParam ids: TreeIds) extends Tree { override def isTerm: Boolean = trees.isEmpty || trees.head.isTerm override def isType: Boolean = !isTerm } - case class Throw(expr: Tree)(implicit ids: TreeIds) extends TermTree - case class Quote(expr: Tree)(implicit ids: TreeIds) extends TermTree - case class DoWhile(body: Tree, cond: Tree)(implicit ids: TreeIds) extends TermTree - case class ForYield(enums: List[Tree], expr: Tree)(implicit ids: TreeIds) extends TermTree - case class ForDo(enums: List[Tree], body: Tree)(implicit ids: TreeIds) extends TermTree - case class GenFrom(pat: Tree, expr: Tree)(implicit ids: TreeIds) extends Tree - case class GenAlias(pat: Tree, expr: Tree)(implicit ids: TreeIds) extends Tree - case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit ids: TreeIds) extends TypTree - case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit ids: TreeIds) extends DefTree - case class DependentTypeTree(tp: List[Symbol] => Type)(implicit ids: TreeIds) extends Tree + case class Throw(expr: Tree)(implicit @transientParam ids: TreeIds) extends TermTree + case class Quote(expr: Tree)(implicit @transientParam ids: TreeIds) extends TermTree + case class DoWhile(body: Tree, cond: Tree)(implicit @transientParam ids: TreeIds) extends TermTree + case class ForYield(enums: List[Tree], expr: Tree)(implicit @transientParam ids: TreeIds) extends TermTree + case class ForDo(enums: List[Tree], body: Tree)(implicit @transientParam ids: TreeIds) extends TermTree + case class GenFrom(pat: Tree, expr: Tree)(implicit @transientParam ids: TreeIds) extends Tree + case class GenAlias(pat: Tree, expr: Tree)(implicit @transientParam ids: TreeIds) extends Tree + case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit @transientParam ids: TreeIds) extends TypTree + case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit @transientParam ids: TreeIds) extends DefTree + case class DependentTypeTree(tp: List[Symbol] => Type)(implicit @transientParam ids: TreeIds) extends Tree @sharable object EmptyTypeIdent extends Ident(tpnme.EMPTY)(GlobalTreeIds) with WithoutTypeOrPos[Untyped] { override def isEmpty: Boolean = true @@ -100,7 +100,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { /** A block generated by the XML parser, only treated specially by * `Positioned#checkPos` */ - class XMLBlock(stats: List[Tree], expr: Tree)(implicit ids: TreeIds) extends Block(stats, expr) + class XMLBlock(stats: List[Tree], expr: Tree)(implicit @transientParam ids: TreeIds) extends Block(stats, expr) // ----- Modifiers ----------------------------------------------------- /** Mod is intended to record syntactic information about modifiers, it's @@ -219,7 +219,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { /** A type tree that gets its type from some other tree's symbol. Enters the * type tree in the References attachment of the `from` tree as a side effect. */ - abstract class DerivedTypeTree(implicit ids: TreeIds) extends TypeTree { + abstract class DerivedTypeTree(implicit @transientParam ids: TreeIds) extends TypeTree { private[this] var myWatched: Tree = EmptyTree diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 9f10d478b9a5..747eb4865388 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -14,12 +14,13 @@ import TastyBuffer._ import transform.SymUtils._ import printing.Printer import printing.Texts._ +import annotation.transientParam object TreePickler { val sectionName = "ASTs" - case class Hole(idx: Int, args: List[tpd.Tree])(implicit ids: TreeIds) extends tpd.Tree { + case class Hole(idx: Int, args: List[tpd.Tree])(implicit @transientParam ids: TreeIds) extends tpd.Tree { override def fallbackToText(printer: Printer): Text = s"[[$idx|" ~~ printer.toTextGlobal(args, ", ") ~~ "]]" } diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/package.scala b/compiler/src/dotty/tools/dotc/tastyreflect/package.scala index 52528720a93c..543cb815a699 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/package.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/package.scala @@ -5,13 +5,14 @@ import dotty.tools.dotc.core.Contexts.{Context, TreeIds} import dotty.tools.dotc.core.Symbols.Symbol import dotty.tools.dotc.core.Types.Type import dotty.tools.dotc.core.SymDenotations.SymDenotation +import scala.annotation.transientParam package object tastyreflect { type PackageDefinition = PackageDefinitionImpl[Type] /** Represents the symbol of a definition in tree form */ - case class PackageDefinitionImpl[-T >: Untyped] private[tastyreflect] (sym: Symbol)(implicit ids: TreeIds) extends Tree[T] { + case class PackageDefinitionImpl[-T >: Untyped] private[tastyreflect] (sym: Symbol)(implicit @transientParam ids: TreeIds) extends Tree[T] { type ThisTree[-T >: Untyped] = PackageDefinitionImpl[T] override def denot(implicit ctx: Context): SymDenotation = sym.denot diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 3cda46c96e07..f2bc7d5b26e6 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -29,6 +29,7 @@ import reporting.trace import Constants.{Constant, IntTag, LongTag} import dotty.tools.dotc.reporting.diagnostic.messages.{NotAnExtractor, UnapplyInvalidNumberOfArguments} import Denotations.SingleDenotation +import annotation.transientParam object Applications { import tpd._ @@ -167,7 +168,7 @@ object Applications { /** A wrapper indicating that its argument is an application of an extension method. */ - class ExtMethodApply(val app: Tree) extends tpd.Tree { + class ExtMethodApply(app: Tree)(implicit @transientParam ids: TreeIds) extends tpd.Tree { override def pos = app.pos def canEqual(that: Any): Boolean = app.canEqual(that) From d4779f1114956da4cd1913b4b93f840615a796fd Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 19 Dec 2018 12:01:33 +0100 Subject: [PATCH 06/75] Produce tree ids in chunks Tree ids are now allocated in chunks. All ids in the same chunk were produced by contexts with the same source file. --- .../src/dotty/tools/dotc/core/Contexts.scala | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 772096fabdb5..d01a97894509 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -42,8 +42,18 @@ object Contexts { def nextTreeId: Int } + private final val TreeIdChunkSize = 1024 + + /** Id generator for compiler-global trees that are not created in a context. + * We reserve the first chunk of ids for these + */ object GlobalTreeIds extends TreeIds { - def nextTreeId = 0 + @sharable private var _nextTreeId: Int = 0 + def nextTreeId: Int = synchronized { + _nextTreeId += 1 + assert(_nextTreeId < TreeIdChunkSize) + _nextTreeId + } } private val (compilerCallbackLoc, store1) = Store.empty.newLocation[CompilerCallback]() @@ -236,6 +246,19 @@ object Contexts { implicitsCache } + def nextTreeId: Int = { + var id = base.nextTreeIdBySource.getOrElseUpdate(source, 0) + if (id % TreeIdChunkSize == 0) { + id = base.sourceOfChunk.length * TreeIdChunkSize + base.sourceOfChunk += source + } + base.nextTreeIdBySource(source) = id + 1 + id + } + + def sourceOfTreeId(id: Int): SourceFile = + base.sourceOfChunk(id / TreeIdChunkSize) + /** Sourcefile corresponding to given abstract file, memoized */ def getSource(file: AbstractFile, codec: => Codec = Codec(settings.encoding.value)) = base.sources.getOrElseUpdate(file, new SourceFile(file, codec)) @@ -466,7 +489,6 @@ object Contexts { def uniqueNamedTypes: Uniques.NamedTypeUniques = base.uniqueNamedTypes def uniques: util.HashSet[Type] = base.uniques def nextSymId: Int = base.nextSymId - def nextTreeId: Int = base.nextTreeId def initialize()(implicit ctx: Context): Unit = base.initialize()(ctx) } @@ -578,7 +600,6 @@ object Contexts { @sharable object NoContext extends Context { val base: ContextBase = null - override def nextTreeId = 0 override val implicits: ContextualImplicits = new ContextualImplicits(Nil, null)(this) } @@ -641,8 +662,8 @@ object Contexts { private[core] var _nextSymId: Int = 0 def nextSymId: Int = { _nextSymId += 1; _nextSymId } - private[dotc] var _nextTreeId: Int = 0 - def nextTreeId: Int = { _nextTreeId += 1; _nextTreeId } + private[core] var nextTreeIdBySource = new mutable.HashMap[SourceFile, Int] + private[core] var sourceOfChunk = mutable.ArrayBuffer[SourceFile](NoSource) /** Sources that were loaded */ val sources: mutable.HashMap[AbstractFile, SourceFile] = new mutable.HashMap[AbstractFile, SourceFile] @@ -720,6 +741,8 @@ object Contexts { for ((_, set) <- uniqueSets) set.clear() errorTypeMsg.clear() sources.clear() + nextTreeIdBySource.clear() + sourceOfChunk.clear() } // Test that access is single threaded From f0451af959d3c802f87f1f93fcd14ed516a8db47 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 19 Dec 2018 14:00:07 +0100 Subject: [PATCH 07/75] Set source field of context directly Inlined sources might not come from a compilation units that's currently compiled. --- .../src/dotty/tools/dotc/core/Contexts.scala | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index d01a97894509..2494b8307486 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -178,6 +178,11 @@ object Contexts { _typeComparer } + /** The current source file */ + private[this] var _source: SourceFile = _ + protected def source_=(source: SourceFile): Unit = _source = source + def source: SourceFile = _source + /** A map in which more contextual properties can be stored * Typically used for attributes that are read and written only in special situations. */ @@ -418,12 +423,6 @@ object Contexts { ctx.fresh.setImportInfo(new ImportInfo(implicit ctx => sym, imp.selectors, impNameOpt)) } - /** The current source file; will be derived from current - * compilation unit. - */ - def source: SourceFile = - if (compilationUnit == null) NoSource else compilationUnit.source - /** Does current phase use an erased types interpretation? */ def erasedTypes: Boolean = phase.erasedTypes @@ -453,6 +452,9 @@ object Contexts { final def withOwner(owner: Symbol): Context = if (owner ne this.owner) fresh.setOwner(owner) else this + final def withSource(source: SourceFile): Context = + if (source ne this.source) fresh.setSource(source) else this + final def withProperty[T](key: Key[T], value: Option[T]): Context = if (property(key) == value) this else value match { @@ -521,16 +523,21 @@ object Contexts { def setGadt(gadt: GADTMap): this.type = { this.gadt = gadt; this } def setFreshGADTBounds: this.type = setGadt(gadt.fresh) def setSearchHistory(searchHistory: SearchHistory): this.type = { this.searchHistory = searchHistory; this } + def setSource(source: SourceFile): this.type = { this.source = source; this } def setTypeComparerFn(tcfn: Context => TypeComparer): this.type = { this.typeComparer = tcfn(this); this } private def setMoreProperties(moreProperties: Map[Key[Any], Any]): this.type = { this.moreProperties = moreProperties; this } private def setStore(store: Store): this.type = { this.store = store; this } def setImplicits(implicits: ContextualImplicits): this.type = { this.implicitsCache = implicits; this } + def setCompilationUnit(compilationUnit: CompilationUnit): this.type = { + setSource(compilationUnit.source) + updateStore(compilationUnitLoc, compilationUnit) + } + def setCompilerCallback(callback: CompilerCallback): this.type = updateStore(compilerCallbackLoc, callback) def setSbtCallback(callback: AnalysisCallback): this.type = updateStore(sbtCallbackLoc, callback) def setPrinterFn(printer: Context => Printer): this.type = updateStore(printerFnLoc, printer) def setSettings(settingsState: SettingsState): this.type = updateStore(settingsStateLoc, settingsState) - def setCompilationUnit(compilationUnit: CompilationUnit): this.type = updateStore(compilationUnitLoc, compilationUnit) def setRun(run: Run): this.type = updateStore(runLoc, run) def setProfiler(profiler: Profiler): this.type = updateStore(profilerLoc, profiler) def setFreshNames(freshNames: FreshNameCreator): this.type = updateStore(freshNamesLoc, freshNames) @@ -592,6 +599,7 @@ object Contexts { tree = untpd.EmptyTree typeAssigner = TypeAssigner moreProperties = Map.empty + source = NoSource store = initialStore.updated(settingsStateLoc, settingsGroup.defaultState) typeComparer = new TypeComparer(this) searchHistory = new SearchRoot @@ -659,11 +667,12 @@ object Contexts { // Symbols state /** Counters for unique ids */ - private[core] var _nextSymId: Int = 0 + private[this] var _nextSymId: Int = 0 def nextSymId: Int = { _nextSymId += 1; _nextSymId } private[core] var nextTreeIdBySource = new mutable.HashMap[SourceFile, Int] private[core] var sourceOfChunk = mutable.ArrayBuffer[SourceFile](NoSource) + // first element reserved for GlobalTreeIds /** Sources that were loaded */ val sources: mutable.HashMap[AbstractFile, SourceFile] = new mutable.HashMap[AbstractFile, SourceFile] From 712adcccebcd7327e7cdae97a1dafa9e86522493 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 19 Dec 2018 22:38:21 +0100 Subject: [PATCH 08/75] Make TreeCopiers preserve source Copies should have the same source attribute as originals. --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 98 ++++++++++--------- compiler/src/dotty/tools/dotc/ast/untpd.scala | 78 +++++++-------- 2 files changed, 90 insertions(+), 86 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 385a2dea2e21..a2533dea1cd5 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -9,7 +9,7 @@ import language.higherKinds import collection.mutable.ListBuffer import printing.Printer import printing.Texts.Text -import util.{Stats, Attachment, Property} +import util.{Stats, Attachment, Property, SourceFile} import config.Config import annotation.internal.sharable import annotation.unchecked.uncheckedVariance @@ -66,6 +66,8 @@ object Trees { def uniqueId: Int = myUniqueId + def source(implicit ctx: Context): SourceFile = ctx.sourceOfTreeId(uniqueId) + /** The type constructor at the root of the tree */ type ThisTree[T >: Untyped] <: Tree[T] @@ -980,19 +982,21 @@ object Trees { protected def finalize(tree: Tree, copied: untpd.MemberDef)(implicit ids:TreeIds): copied.ThisTree[T] = postProcess(tree, copied.withPos(tree.pos).withAttachmentsFrom(tree)) + protected def srcCtx(tree: Tree)(implicit ctx: Context) = ctx.withSource(tree.source) + def Ident(tree: Tree)(name: Name)(implicit ctx: Context): Ident = tree match { case tree: BackquotedIdent => if (name == tree.name) tree - else finalize(tree, new BackquotedIdent(name)) + else finalize(tree, new BackquotedIdent(name)(srcCtx(tree))) case tree: Ident if name == tree.name => tree - case _ => finalize(tree, untpd.Ident(name)) + case _ => finalize(tree, untpd.Ident(name)(srcCtx(tree))) } def Select(tree: Tree)(qualifier: Tree, name: Name)(implicit ctx: Context): Select = tree match { case tree: SelectWithSig => if ((qualifier eq tree.qualifier) && (name == tree.name)) tree - else finalize(tree, new SelectWithSig(qualifier, name, tree.sig)) + else finalize(tree, new SelectWithSig(qualifier, name, tree.sig)(srcCtx(tree))) case tree: Select if (qualifier eq tree.qualifier) && (name == tree.name) => tree - case _ => finalize(tree, untpd.Select(qualifier, name)) + case _ => finalize(tree, untpd.Select(qualifier, name)(srcCtx(tree))) } /** Copy Ident or Select trees */ def Ref(tree: RefTree)(name: Name)(implicit ctx: Context): RefTree = tree match { @@ -1001,168 +1005,168 @@ object Trees { } def This(tree: Tree)(qual: untpd.Ident)(implicit ctx: Context): This = tree match { case tree: This if qual eq tree.qual => tree - case _ => finalize(tree, untpd.This(qual)) + case _ => finalize(tree, untpd.This(qual)(srcCtx(tree))) } def Super(tree: Tree)(qual: Tree, mix: untpd.Ident)(implicit ctx: Context): Super = tree match { case tree: Super if (qual eq tree.qual) && (mix eq tree.mix) => tree - case _ => finalize(tree, untpd.Super(qual, mix)) + case _ => finalize(tree, untpd.Super(qual, mix)(srcCtx(tree))) } def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply = tree match { case tree: Apply if (fun eq tree.fun) && (args eq tree.args) => tree - case _ => finalize(tree, untpd.Apply(fun, args)) + case _ => finalize(tree, untpd.Apply(fun, args)(srcCtx(tree))) } def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = tree match { case tree: TypeApply if (fun eq tree.fun) && (args eq tree.args) => tree - case _ => finalize(tree, untpd.TypeApply(fun, args)) + case _ => finalize(tree, untpd.TypeApply(fun, args)(srcCtx(tree))) } def Literal(tree: Tree)(const: Constant)(implicit ctx: Context): Literal = tree match { case tree: Literal if const == tree.const => tree - case _ => finalize(tree, untpd.Literal(const)) + case _ => finalize(tree, untpd.Literal(const)(srcCtx(tree))) } def New(tree: Tree)(tpt: Tree)(implicit ctx: Context): New = tree match { case tree: New if tpt eq tree.tpt => tree - case _ => finalize(tree, untpd.New(tpt)) + case _ => finalize(tree, untpd.New(tpt)(srcCtx(tree))) } def Typed(tree: Tree)(expr: Tree, tpt: Tree)(implicit ctx: Context): Typed = tree match { case tree: Typed if (expr eq tree.expr) && (tpt eq tree.tpt) => tree - case _ => finalize(tree, untpd.Typed(expr, tpt)) + case _ => finalize(tree, untpd.Typed(expr, tpt)(srcCtx(tree))) } def NamedArg(tree: Tree)(name: Name, arg: Tree)(implicit ctx: Context): NamedArg = tree match { case tree: NamedArg if (name == tree.name) && (arg eq tree.arg) => tree - case _ => finalize(tree, untpd.NamedArg(name, arg)) + case _ => finalize(tree, untpd.NamedArg(name, arg)(srcCtx(tree))) } def Assign(tree: Tree)(lhs: Tree, rhs: Tree)(implicit ctx: Context): Assign = tree match { case tree: Assign if (lhs eq tree.lhs) && (rhs eq tree.rhs) => tree - case _ => finalize(tree, untpd.Assign(lhs, rhs)) + case _ => finalize(tree, untpd.Assign(lhs, rhs)(srcCtx(tree))) } def Block(tree: Tree)(stats: List[Tree], expr: Tree)(implicit ctx: Context): Block = tree match { case tree: Block if (stats eq tree.stats) && (expr eq tree.expr) => tree - case _ => finalize(tree, untpd.Block(stats, expr)) + case _ => finalize(tree, untpd.Block(stats, expr)(srcCtx(tree))) } def If(tree: Tree)(cond: Tree, thenp: Tree, elsep: Tree)(implicit ctx: Context): If = tree match { case tree: If if (cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep) => tree - case tree: InlineIf => finalize(tree, untpd.InlineIf(cond, thenp, elsep)) - case _ => finalize(tree, untpd.If(cond, thenp, elsep)) + case tree: InlineIf => finalize(tree, untpd.InlineIf(cond, thenp, elsep)(srcCtx(tree))) + case _ => finalize(tree, untpd.If(cond, thenp, elsep)(srcCtx(tree))) } def Closure(tree: Tree)(env: List[Tree], meth: Tree, tpt: Tree)(implicit ctx: Context): Closure = tree match { case tree: Closure if (env eq tree.env) && (meth eq tree.meth) && (tpt eq tree.tpt) => tree - case _ => finalize(tree, untpd.Closure(env, meth, tpt)) + case _ => finalize(tree, untpd.Closure(env, meth, tpt)(srcCtx(tree))) } def Match(tree: Tree)(selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match = tree match { case tree: Match if (selector eq tree.selector) && (cases eq tree.cases) => tree - case tree: InlineMatch => finalize(tree, untpd.InlineMatch(selector, cases)) - case _ => finalize(tree, untpd.Match(selector, cases)) + case tree: InlineMatch => finalize(tree, untpd.InlineMatch(selector, cases)(srcCtx(tree))) + case _ => finalize(tree, untpd.Match(selector, cases)(srcCtx(tree))) } def CaseDef(tree: Tree)(pat: Tree, guard: Tree, body: Tree)(implicit ctx: Context): CaseDef = tree match { case tree: CaseDef if (pat eq tree.pat) && (guard eq tree.guard) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.CaseDef(pat, guard, body)) + case _ => finalize(tree, untpd.CaseDef(pat, guard, body)(srcCtx(tree))) } def Labeled(tree: Tree)(bind: Bind, expr: Tree)(implicit ctx: Context): Labeled = tree match { case tree: Labeled if (bind eq tree.bind) && (expr eq tree.expr) => tree - case _ => finalize(tree, untpd.Labeled(bind, expr)) + case _ => finalize(tree, untpd.Labeled(bind, expr)(srcCtx(tree))) } def Return(tree: Tree)(expr: Tree, from: Tree)(implicit ctx: Context): Return = tree match { case tree: Return if (expr eq tree.expr) && (from eq tree.from) => tree - case _ => finalize(tree, untpd.Return(expr, from)) + case _ => finalize(tree, untpd.Return(expr, from)(srcCtx(tree))) } def WhileDo(tree: Tree)(cond: Tree, body: Tree)(implicit ctx: Context): WhileDo = tree match { case tree: WhileDo if (cond eq tree.cond) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.WhileDo(cond, body)) + case _ => finalize(tree, untpd.WhileDo(cond, body)(srcCtx(tree))) } def Try(tree: Tree)(expr: Tree, cases: List[CaseDef], finalizer: Tree)(implicit ctx: Context): Try = tree match { case tree: Try if (expr eq tree.expr) && (cases eq tree.cases) && (finalizer eq tree.finalizer) => tree - case _ => finalize(tree, untpd.Try(expr, cases, finalizer)) + case _ => finalize(tree, untpd.Try(expr, cases, finalizer)(srcCtx(tree))) } def SeqLiteral(tree: Tree)(elems: List[Tree], elemtpt: Tree)(implicit ctx: Context): SeqLiteral = tree match { case tree: JavaSeqLiteral => if ((elems eq tree.elems) && (elemtpt eq tree.elemtpt)) tree else finalize(tree, new JavaSeqLiteral(elems, elemtpt)) case tree: SeqLiteral if (elems eq tree.elems) && (elemtpt eq tree.elemtpt) => tree - case _ => finalize(tree, untpd.SeqLiteral(elems, elemtpt)) + case _ => finalize(tree, untpd.SeqLiteral(elems, elemtpt)(srcCtx(tree))) } def Inlined(tree: Tree)(call: tpd.Tree, bindings: List[MemberDef], expansion: Tree)(implicit ctx: Context): Inlined = tree match { case tree: Inlined if (call eq tree.call) && (bindings eq tree.bindings) && (expansion eq tree.expansion) => tree - case _ => finalize(tree, untpd.Inlined(call, bindings, expansion)) + case _ => finalize(tree, untpd.Inlined(call, bindings, expansion)(srcCtx(tree))) } def SingletonTypeTree(tree: Tree)(ref: Tree)(implicit ctx: Context): SingletonTypeTree = tree match { case tree: SingletonTypeTree if ref eq tree.ref => tree - case _ => finalize(tree, untpd.SingletonTypeTree(ref)) + case _ => finalize(tree, untpd.SingletonTypeTree(ref)(srcCtx(tree))) } def AndTypeTree(tree: Tree)(left: Tree, right: Tree)(implicit ctx: Context): AndTypeTree = tree match { case tree: AndTypeTree if (left eq tree.left) && (right eq tree.right) => tree - case _ => finalize(tree, untpd.AndTypeTree(left, right)) + case _ => finalize(tree, untpd.AndTypeTree(left, right)(srcCtx(tree))) } def OrTypeTree(tree: Tree)(left: Tree, right: Tree)(implicit ctx: Context): OrTypeTree = tree match { case tree: OrTypeTree if (left eq tree.left) && (right eq tree.right) => tree - case _ => finalize(tree, untpd.OrTypeTree(left, right)) + case _ => finalize(tree, untpd.OrTypeTree(left, right)(srcCtx(tree))) } def RefinedTypeTree(tree: Tree)(tpt: Tree, refinements: List[Tree])(implicit ctx: Context): RefinedTypeTree = tree match { case tree: RefinedTypeTree if (tpt eq tree.tpt) && (refinements eq tree.refinements) => tree - case _ => finalize(tree, untpd.RefinedTypeTree(tpt, refinements)) + case _ => finalize(tree, untpd.RefinedTypeTree(tpt, refinements)(srcCtx(tree))) } def AppliedTypeTree(tree: Tree)(tpt: Tree, args: List[Tree])(implicit ctx: Context): AppliedTypeTree = tree match { case tree: AppliedTypeTree if (tpt eq tree.tpt) && (args eq tree.args) => tree - case _ => finalize(tree, untpd.AppliedTypeTree(tpt, args)) + case _ => finalize(tree, untpd.AppliedTypeTree(tpt, args)(srcCtx(tree))) } def LambdaTypeTree(tree: Tree)(tparams: List[TypeDef], body: Tree)(implicit ctx: Context): LambdaTypeTree = tree match { case tree: LambdaTypeTree if (tparams eq tree.tparams) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.LambdaTypeTree(tparams, body)) + case _ => finalize(tree, untpd.LambdaTypeTree(tparams, body)(srcCtx(tree))) } def MatchTypeTree(tree: Tree)(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit ctx: Context): MatchTypeTree = tree match { case tree: MatchTypeTree if (bound eq tree.bound) && (selector eq tree.selector) && (cases eq tree.cases) => tree - case _ => finalize(tree, untpd.MatchTypeTree(bound, selector, cases)) + case _ => finalize(tree, untpd.MatchTypeTree(bound, selector, cases)(srcCtx(tree))) } def ByNameTypeTree(tree: Tree)(result: Tree)(implicit ctx: Context): ByNameTypeTree = tree match { case tree: ByNameTypeTree if result eq tree.result => tree - case _ => finalize(tree, untpd.ByNameTypeTree(result)) + case _ => finalize(tree, untpd.ByNameTypeTree(result)(srcCtx(tree))) } def TypeBoundsTree(tree: Tree)(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree = tree match { case tree: TypeBoundsTree if (lo eq tree.lo) && (hi eq tree.hi) => tree - case _ => finalize(tree, untpd.TypeBoundsTree(lo, hi)) + case _ => finalize(tree, untpd.TypeBoundsTree(lo, hi)(srcCtx(tree))) } def Bind(tree: Tree)(name: Name, body: Tree)(implicit ctx: Context): Bind = tree match { case tree: Bind if (name eq tree.name) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.Bind(name, body)) + case _ => finalize(tree, untpd.Bind(name, body)(srcCtx(tree))) } def Alternative(tree: Tree)(trees: List[Tree])(implicit ctx: Context): Alternative = tree match { case tree: Alternative if trees eq tree.trees => tree - case _ => finalize(tree, untpd.Alternative(trees)) + case _ => finalize(tree, untpd.Alternative(trees)(srcCtx(tree))) } def UnApply(tree: Tree)(fun: Tree, implicits: List[Tree], patterns: List[Tree])(implicit ctx: Context): UnApply = tree match { case tree: UnApply if (fun eq tree.fun) && (implicits eq tree.implicits) && (patterns eq tree.patterns) => tree - case _ => finalize(tree, untpd.UnApply(fun, implicits, patterns)) + case _ => finalize(tree, untpd.UnApply(fun, implicits, patterns)(srcCtx(tree))) } def ValDef(tree: Tree)(name: TermName, tpt: Tree, rhs: LazyTree)(implicit ctx: Context): ValDef = tree match { case tree: ValDef if (name == tree.name) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) => tree - case _ => finalize(tree, untpd.ValDef(name, tpt, rhs)) + case _ => finalize(tree, untpd.ValDef(name, tpt, rhs)(srcCtx(tree))) } def DefDef(tree: Tree)(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree)(implicit ctx: Context): DefDef = tree match { case tree: DefDef if (name == tree.name) && (tparams eq tree.tparams) && (vparamss eq tree.vparamss) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) => tree - case _ => finalize(tree, untpd.DefDef(name, tparams, vparamss, tpt, rhs)) + case _ => finalize(tree, untpd.DefDef(name, tparams, vparamss, tpt, rhs)(srcCtx(tree))) } def TypeDef(tree: Tree)(name: TypeName, rhs: Tree)(implicit ctx: Context): TypeDef = tree match { case tree: TypeDef if (name == tree.name) && (rhs eq tree.rhs) => tree - case _ => finalize(tree, untpd.TypeDef(name, rhs)) + case _ => finalize(tree, untpd.TypeDef(name, rhs)(srcCtx(tree))) } def Template(tree: Tree)(constr: DefDef, parents: List[Tree], self: ValDef, body: LazyTreeList)(implicit ctx: Context): Template = tree match { case tree: Template if (constr eq tree.constr) && (parents eq tree.parents) && (self eq tree.self) && (body eq tree.unforcedBody) => tree - case _ => finalize(tree, untpd.Template(constr, parents, self, body)) + case _ => finalize(tree, untpd.Template(constr, parents, self, body)(srcCtx(tree))) } def Import(tree: Tree)(expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = tree match { case tree: Import if (expr eq tree.expr) && (selectors eq tree.selectors) => tree - case _ => finalize(tree, untpd.Import(expr, selectors)) + case _ => finalize(tree, untpd.Import(expr, selectors)(srcCtx(tree))) } def PackageDef(tree: Tree)(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef = tree match { case tree: PackageDef if (pid eq tree.pid) && (stats eq tree.stats) => tree - case _ => finalize(tree, untpd.PackageDef(pid, stats)) + case _ => finalize(tree, untpd.PackageDef(pid, stats)(srcCtx(tree))) } def Annotated(tree: Tree)(arg: Tree, annot: Tree)(implicit ctx: Context): Annotated = tree match { case tree: Annotated if (arg eq tree.arg) && (annot eq tree.annot) => tree - case _ => finalize(tree, untpd.Annotated(arg, annot)) + case _ => finalize(tree, untpd.Annotated(arg, annot)(srcCtx(tree))) } def Thicket(tree: Tree)(trees: List[Tree])(implicit ctx: Context): Thicket = tree match { case tree: Thicket if trees eq tree.trees => tree - case _ => finalize(tree, untpd.Thicket(trees)) + case _ => finalize(tree, untpd.Thicket(trees)(srcCtx(tree))) } // Copier methods with default arguments; these demand that the original tree diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 8abc5183e98e..c78925697edc 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -430,86 +430,86 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { } }.asInstanceOf[copied.ThisTree[Untyped]] - def ModuleDef(tree: Tree)(name: TermName, impl: Template)(implicit ids: TreeIds): ModuleDef = tree match { + def ModuleDef(tree: Tree)(name: TermName, impl: Template)(implicit ctx: Context): ModuleDef = tree match { case tree: ModuleDef if (name eq tree.name) && (impl eq tree.impl) => tree - case _ => finalize(tree, untpd.ModuleDef(name, impl)) + case _ => finalize(tree, untpd.ModuleDef(name, impl)(srcCtx(tree))) } - def ParsedTry(tree: Tree)(expr: Tree, handler: Tree, finalizer: Tree)(implicit ids: TreeIds): TermTree = tree match { + def ParsedTry(tree: Tree)(expr: Tree, handler: Tree, finalizer: Tree)(implicit ctx: Context): TermTree = tree match { case tree: ParsedTry if (expr eq tree.expr) && (handler eq tree.handler) && (finalizer eq tree.finalizer) => tree - case _ => finalize(tree, untpd.ParsedTry(expr, handler, finalizer)) + case _ => finalize(tree, untpd.ParsedTry(expr, handler, finalizer)(srcCtx(tree))) } - def SymbolLit(tree: Tree)(str: String)(implicit ids: TreeIds): TermTree = tree match { + def SymbolLit(tree: Tree)(str: String)(implicit ctx: Context): TermTree = tree match { case tree: SymbolLit if str == tree.str => tree - case _ => finalize(tree, untpd.SymbolLit(str)) + case _ => finalize(tree, untpd.SymbolLit(str)(srcCtx(tree))) } - def InterpolatedString(tree: Tree)(id: TermName, segments: List[Tree])(implicit ids: TreeIds): TermTree = tree match { + def InterpolatedString(tree: Tree)(id: TermName, segments: List[Tree])(implicit ctx: Context): TermTree = tree match { case tree: InterpolatedString if (id eq tree.id) && (segments eq tree.segments) => tree - case _ => finalize(tree, untpd.InterpolatedString(id, segments)) + case _ => finalize(tree, untpd.InterpolatedString(id, segments)(srcCtx(tree))) } - def Function(tree: Tree)(args: List[Tree], body: Tree)(implicit ids: TreeIds): Tree = tree match { + def Function(tree: Tree)(args: List[Tree], body: Tree)(implicit ctx: Context): Tree = tree match { case tree: Function if (args eq tree.args) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.Function(args, body)) + case _ => finalize(tree, untpd.Function(args, body)(srcCtx(tree))) } - def InfixOp(tree: Tree)(left: Tree, op: Ident, right: Tree)(implicit ids: TreeIds): Tree = tree match { + def InfixOp(tree: Tree)(left: Tree, op: Ident, right: Tree)(implicit ctx: Context): Tree = tree match { case tree: InfixOp if (left eq tree.left) && (op eq tree.op) && (right eq tree.right) => tree - case _ => finalize(tree, untpd.InfixOp(left, op, right)) + case _ => finalize(tree, untpd.InfixOp(left, op, right)(srcCtx(tree))) } - def PostfixOp(tree: Tree)(od: Tree, op: Ident)(implicit ids: TreeIds): Tree = tree match { + def PostfixOp(tree: Tree)(od: Tree, op: Ident)(implicit ctx: Context): Tree = tree match { case tree: PostfixOp if (od eq tree.od) && (op eq tree.op) => tree - case _ => finalize(tree, untpd.PostfixOp(od, op)) + case _ => finalize(tree, untpd.PostfixOp(od, op)(srcCtx(tree))) } - def PrefixOp(tree: Tree)(op: Ident, od: Tree)(implicit ids: TreeIds): Tree = tree match { + def PrefixOp(tree: Tree)(op: Ident, od: Tree)(implicit ctx: Context): Tree = tree match { case tree: PrefixOp if (op eq tree.op) && (od eq tree.od) => tree - case _ => finalize(tree, untpd.PrefixOp(op, od)) + case _ => finalize(tree, untpd.PrefixOp(op, od)(srcCtx(tree))) } - def Parens(tree: Tree)(t: Tree)(implicit ids: TreeIds): ProxyTree = tree match { + def Parens(tree: Tree)(t: Tree)(implicit ctx: Context): ProxyTree = tree match { case tree: Parens if t eq tree.t => tree - case _ => finalize(tree, untpd.Parens(t)) + case _ => finalize(tree, untpd.Parens(t)(srcCtx(tree))) } - def Tuple(tree: Tree)(trees: List[Tree])(implicit ids: TreeIds): Tree = tree match { + def Tuple(tree: Tree)(trees: List[Tree])(implicit ctx: Context): Tree = tree match { case tree: Tuple if trees eq tree.trees => tree - case _ => finalize(tree, untpd.Tuple(trees)) + case _ => finalize(tree, untpd.Tuple(trees)(srcCtx(tree))) } - def Throw(tree: Tree)(expr: Tree)(implicit ids: TreeIds): TermTree = tree match { + def Throw(tree: Tree)(expr: Tree)(implicit ctx: Context): TermTree = tree match { case tree: Throw if expr eq tree.expr => tree - case _ => finalize(tree, untpd.Throw(expr)) + case _ => finalize(tree, untpd.Throw(expr)(srcCtx(tree))) } - def Quote(tree: Tree)(expr: Tree)(implicit ids: TreeIds): TermTree = tree match { + def Quote(tree: Tree)(expr: Tree)(implicit ctx: Context): TermTree = tree match { case tree: Quote if expr eq tree.expr => tree - case _ => finalize(tree, untpd.Quote(expr)) + case _ => finalize(tree, untpd.Quote(expr)(srcCtx(tree))) } - def DoWhile(tree: Tree)(body: Tree, cond: Tree)(implicit ids: TreeIds): TermTree = tree match { + def DoWhile(tree: Tree)(body: Tree, cond: Tree)(implicit ctx: Context): TermTree = tree match { case tree: DoWhile if (body eq tree.body) && (cond eq tree.cond) => tree - case _ => finalize(tree, untpd.DoWhile(body, cond)) + case _ => finalize(tree, untpd.DoWhile(body, cond)(srcCtx(tree))) } - def ForYield(tree: Tree)(enums: List[Tree], expr: Tree)(implicit ids: TreeIds): TermTree = tree match { + def ForYield(tree: Tree)(enums: List[Tree], expr: Tree)(implicit ctx: Context): TermTree = tree match { case tree: ForYield if (enums eq tree.enums) && (expr eq tree.expr) => tree - case _ => finalize(tree, untpd.ForYield(enums, expr)) + case _ => finalize(tree, untpd.ForYield(enums, expr)(srcCtx(tree))) } - def ForDo(tree: Tree)(enums: List[Tree], body: Tree)(implicit ids: TreeIds): TermTree = tree match { + def ForDo(tree: Tree)(enums: List[Tree], body: Tree)(implicit ctx: Context): TermTree = tree match { case tree: ForDo if (enums eq tree.enums) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.ForDo(enums, body)) + case _ => finalize(tree, untpd.ForDo(enums, body)(srcCtx(tree))) } - def GenFrom(tree: Tree)(pat: Tree, expr: Tree)(implicit ids: TreeIds): Tree = tree match { + def GenFrom(tree: Tree)(pat: Tree, expr: Tree)(implicit ctx: Context): Tree = tree match { case tree: GenFrom if (pat eq tree.pat) && (expr eq tree.expr) => tree - case _ => finalize(tree, untpd.GenFrom(pat, expr)) + case _ => finalize(tree, untpd.GenFrom(pat, expr)(srcCtx(tree))) } - def GenAlias(tree: Tree)(pat: Tree, expr: Tree)(implicit ids: TreeIds): Tree = tree match { + def GenAlias(tree: Tree)(pat: Tree, expr: Tree)(implicit ctx: Context): Tree = tree match { case tree: GenAlias if (pat eq tree.pat) && (expr eq tree.expr) => tree - case _ => finalize(tree, untpd.GenAlias(pat, expr)) + case _ => finalize(tree, untpd.GenAlias(pat, expr)(srcCtx(tree))) } - def ContextBounds(tree: Tree)(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit ids: TreeIds): TypTree = tree match { + def ContextBounds(tree: Tree)(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit ctx: Context): TypTree = tree match { case tree: ContextBounds if (bounds eq tree.bounds) && (cxBounds eq tree.cxBounds) => tree - case _ => finalize(tree, untpd.ContextBounds(bounds, cxBounds)) + case _ => finalize(tree, untpd.ContextBounds(bounds, cxBounds)(srcCtx(tree))) } - def PatDef(tree: Tree)(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit ids: TreeIds): Tree = tree match { + def PatDef(tree: Tree)(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit ctx: Context): Tree = tree match { case tree: PatDef if (mods eq tree.mods) && (pats eq tree.pats) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree - case _ => finalize(tree, untpd.PatDef(mods, pats, tpt, rhs)) + case _ => finalize(tree, untpd.PatDef(mods, pats, tpt, rhs)(srcCtx(tree))) } def TypedSplice(tree: Tree)(splice: tpd.Tree)(implicit ctx: Context): ProxyTree = tree match { case tree: TypedSplice if splice `eq` tree.splice => tree - case _ => finalize(tree, untpd.TypedSplice(splice)) + case _ => finalize(tree, untpd.TypedSplice(splice)(srcCtx(tree))) } } From edaafd5c948f174752293c7db0ed76fc601621b9 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 19 Dec 2018 22:41:26 +0100 Subject: [PATCH 09/75] Refactor getSource and withSource --- compiler/src/dotty/tools/dotc/Run.scala | 18 ++---------- .../src/dotty/tools/dotc/core/Contexts.scala | 29 +++++++++++++++++-- .../dotty/tools/dotc/core/SymbolLoaders.scala | 2 +- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index 9067693e1168..21a4a65c7251 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -99,22 +99,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint /** Actions that need to be performed at the end of the current compilation run */ private[this] var finalizeActions = mutable.ListBuffer[() => Unit]() - def getSource(fileName: String): SourceFile = { - val f = new PlainFile(io.Path(fileName)) - if (f.isDirectory) { - ctx.error(s"expected file, received directory '$fileName'") - NoSource - } - else if (f.exists) - ctx.getSource(f) - else { - ctx.error(s"not found: $fileName") - NoSource - } - } - def compile(fileNames: List[String]): Unit = try { - val sources = fileNames map getSource + val sources = fileNames.map(ctx.getSource) compileSources(sources) } catch { case NonFatal(ex) => @@ -206,7 +192,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint def lateCompile(file: AbstractFile, typeCheck: Boolean)(implicit ctx: Context): Unit = if (!files.contains(file) && !lateFiles.contains(file)) { lateFiles += file - val unit = new CompilationUnit(getSource(file.path)) + val unit = new CompilationUnit(ctx.getSource(file.path)) def process()(implicit ctx: Context) = { unit.untpdTree = if (unit.isJava) new JavaParser(unit.source).parse() diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 2494b8307486..0dc1fa1297a7 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -20,7 +20,7 @@ import config.Settings._ import config.Config import reporting._ import reporting.diagnostic.Message -import io.AbstractFile +import io.{AbstractFile, PlainFile, Path} import scala.io.Codec import collection.mutable import printing._ @@ -268,6 +268,20 @@ object Contexts { def getSource(file: AbstractFile, codec: => Codec = Codec(settings.encoding.value)) = base.sources.getOrElseUpdate(file, new SourceFile(file, codec)) + def getSource(fileName: String): SourceFile = { + val f = new PlainFile(Path(fileName)) + if (f.isDirectory) { + error(s"expected file, received directory '$fileName'") + NoSource + } + else if (f.exists) + getSource(f) + else { + error(s"not found: $fileName") + NoSource + } + } + /** Those fields are used to cache phases created in withPhase. * phasedCtx is first phase with altered phase ever requested. * phasedCtxs is array that uses phaseId's as indexes, @@ -452,8 +466,19 @@ object Contexts { final def withOwner(owner: Symbol): Context = if (owner ne this.owner) fresh.setOwner(owner) else this + private[this] var sourceCtx: SimpleIdentityMap[SourceFile, Context] = SimpleIdentityMap.Empty + final def withSource(source: SourceFile): Context = - if (source ne this.source) fresh.setSource(source) else this + if (source `eq` this.source) this + else { + val prev = sourceCtx(source) + if (prev != null) prev + else { + val newCtx = fresh.setSource(source) + sourceCtx = sourceCtx.updated(source, newCtx) + newCtx + } + } final def withProperty[T](key: Key[T], value: Option[T]): Context = if (property(key) == value) this diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 1f849ccd3e65..8decb3ac28c2 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -159,7 +159,7 @@ object SymbolLoaders { Nil) } - val unit = new CompilationUnit(ctx.run.getSource(src.path)) + val unit = new CompilationUnit(ctx.getSource(src.path)) enterScanned(unit)(ctx.run.runContext.fresh.setCompilationUnit(unit)) } } From 1949b53f722fdfc9556a1547c904d5cb396f1696 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 20 Dec 2018 09:30:04 +0100 Subject: [PATCH 10/75] Serialize source file changes Serialize source file changes in positions section --- .../dotc/core/tasty/DottyUnpickler.scala | 2 +- .../dotc/core/tasty/PositionPickler.scala | 22 ++++-- .../dotc/core/tasty/PositionUnpickler.scala | 67 +++++++++++++------ .../tools/dotc/core/tasty/TastyFormat.scala | 19 ++++-- .../tools/dotc/core/tasty/TastyPrinter.scala | 2 +- .../tools/dotc/core/tasty/TreePickler.scala | 2 +- .../tools/dotc/core/tasty/TreeUnpickler.scala | 13 +++- 7 files changed, 88 insertions(+), 39 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala index 57125fed3e65..b53d6a0a3259 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala @@ -23,7 +23,7 @@ object DottyUnpickler { class PositionsSectionUnpickler extends SectionUnpickler[PositionUnpickler]("Positions") { def unpickle(reader: TastyReader, nameAtRef: NameTable): PositionUnpickler = - new PositionUnpickler(reader) + new PositionUnpickler(reader, nameAtRef) } class CommentsSectionUnpickler extends SectionUnpickler[CommentUnpickler]("Comments") { diff --git a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala index 2af9e393500b..7c74249c4a60 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala @@ -6,11 +6,13 @@ package tasty import ast._ import ast.Trees._ import ast.Trees.WithLazyField +import util.SourceFile import core._ -import Contexts._, Symbols._, Annotations._ +import Contexts._, Symbols._, Annotations._, Decorators._ import collection.mutable import TastyBuffer._ import util.Positions._ +import TastyFormat.SOURCE class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Addr]) { val buf: TastyBuffer = new TastyBuffer(5000) @@ -59,14 +61,20 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad case _ => false } - def traverse(x: Any): Unit = x match { + def traverse(x: Any, curSource: SourceFile): Unit = x match { case x: untpd.Tree => + var source = curSource val pos = if (x.isInstanceOf[untpd.MemberDef]) x.pos else x.pos.toSynthetic if (pos.exists && (pos != x.initialPos.toSynthetic || alwaysNeedsPos(x))) { addrOfTree(x) match { case Some(addr) if !pickledIndices.contains(addr.index) => //println(i"pickling $x with $pos at $addr") pickleDeltas(addr.index, pos) + if (x.source != curSource) { + buf.writeInt(SOURCE) + buf.writeInt(pickler.nameBuffer.nameIndex(x.source.path.toTermName).index) + source = curSource + } case _ => //println(i"no address for $x") } @@ -74,16 +82,16 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad //else if (x.pos.exists) println(i"skipping $x") x match { case x: untpd.MemberDef @unchecked => - for (ann <- x.symbol.annotations) traverse(ann.tree) + for (ann <- x.symbol.annotations) traverse(ann.tree, source) case _ => } - traverse(x.productIterator) + traverse(x.productIterator, source) case xs: TraversableOnce[_] => - xs.foreach(traverse) + xs.foreach(traverse(_, curSource)) case x: Annotation => - traverse(x.tree) + traverse(x.tree, curSource) case _ => } - traverse(roots) + for (root <- roots) traverse(root, root.source) } } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/PositionUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/PositionUnpickler.scala index 1e1031cb9e6f..0013a9d4c872 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/PositionUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/PositionUnpickler.scala @@ -5,34 +5,59 @@ package tasty import util.Positions._ import collection.{mutable, Map} -import TastyBuffer.Addr +import TastyBuffer.{Addr, NameRef} +import TastyFormat.SOURCE +import Names.TermName /** Unpickler for tree positions */ -class PositionUnpickler(reader: TastyReader) { +class PositionUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName) { import reader._ - private[tasty] lazy val positions: Map[Addr, Position] = { - val positions = new mutable.HashMap[Addr, Position] - var curIndex = 0 - var curStart = 0 - var curEnd = 0 - while (!isAtEnd) { - val header = readInt() - val addrDelta = header >> 3 - val hasStart = (header & 4) != 0 - val hasEnd = (header & 2) != 0 - val hasPoint = (header & 1) != 0 - curIndex += addrDelta - assert(curIndex >= 0) - if (hasStart) curStart += readInt() - if (hasEnd) curEnd += readInt() - positions(Addr(curIndex)) = - if (hasPoint) Position(curStart, curEnd, curStart + readInt()) - else Position(curStart, curEnd) + private var myPositions: mutable.HashMap[Addr, Position] = _ + private var mySourcePaths: mutable.HashMap[Addr, String] = _ + private var isDefined = false + + def ensureDefined(): Unit = + if (!isDefined) { + myPositions = new mutable.HashMap[Addr, Position] + mySourcePaths = new mutable.HashMap[Addr, String] + var curIndex = 0 + var curStart = 0 + var curEnd = 0 + while (!isAtEnd) { + val header = readInt() + if (header == SOURCE) { + val path = nameAtRef(readNameRef()).toString + mySourcePaths(Addr(curIndex)) = path + } + else { + val addrDelta = header >> 3 + val hasStart = (header & 4) != 0 + val hasEnd = (header & 2) != 0 + val hasPoint = (header & 1) != 0 + curIndex += addrDelta + assert(curIndex >= 0) + if (hasStart) curStart += readInt() + if (hasEnd) curEnd += readInt() + myPositions(Addr(curIndex)) = + if (hasPoint) Position(curStart, curEnd, curStart + readInt()) + else Position(curStart, curEnd) + } + } + isDefined = true } - positions + + private[tasty] def positions: Map[Addr, Position] = { + ensureDefined() + myPositions + } + + private[tasty] def sourcePaths: Map[Addr, String] = { + ensureDefined() + mySourcePaths } def posAt(addr: Addr): Position = positions.getOrElse(addr, NoPosition) + def sourcePathAt(addr: Addr): String = sourcePaths.getOrElse(addr, "") } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index 9172fc2049e9..00a453c65a28 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -218,14 +218,19 @@ Note: Tree tags are grouped into 5 categories that determine what follows, and t Standard Section: "Positions" Assoc* - Assoc = Header offset_Delta? offset_Delta? - Header = addr_Delta + // in one Nat: difference of address to last recorded node << 2 + - hasStartDiff + // one bit indicating whether there follows a start address delta << 1 - hasEndDiff // one bit indicating whether there follows an end address delta + Assoc = Header offset_Delta? offset_Delta? point_Delta? + | SOURCE nameref_Int + Header = addr_Delta + // in one Nat: difference of address to last recorded node << 3 + + hasStartDiff + // one bit indicating whether there follows a start address delta << 2 + hasEndDiff + // one bit indicating whether there follows an end address delta << 1 + hasPoint // one bit indicating whether the new position has a point (i.e ^ position) // Nodes which have the same positions as their parents are omitted. // offset_Deltas give difference of start/end offset wrt to the // same offset in the previously recorded node (or 0 for the first recorded node) Delta = Int // Difference between consecutive offsets, + SOURCE = 4 // Impossible as header + +All elements of a position section are serialized as Ints Standard Section: "Comments" Comment* @@ -272,7 +277,11 @@ object TastyFormat { } object NameTags extends NameTags - // AST tags + // Position header + + final val SOURCE = 4 + + // AST tags // Cat. 1: tag final val firstSimpleTreeTag = UNITconst diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala index 22ec8bfd8c74..54dbccc63ab2 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala @@ -5,7 +5,7 @@ package tasty import Contexts._, Decorators._ import Names.Name import TastyUnpickler._ -import TastyBuffer.NameRef +import TastyBuffer.{Addr, NameRef} import util.Positions.offsetToInt import printing.Highlighting._ diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 747eb4865388..14db02d123b8 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -64,7 +64,7 @@ class TreePickler(pickler: TastyPickler) { } } - private def pickleName(name: Name): Unit = writeNat(nameIndex(name).index) + def pickleName(name: Name): Unit = writeNat(nameIndex(name).index) private def pickleNameAndSig(name: Name, sig: Signature): Unit = pickleName( diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 07946650e996..6e32c012669f 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -19,6 +19,7 @@ import NameKinds._ import typer.ConstFold import typer.Checking.checkNonCyclic import util.Positions._ +import util.SourceFile import ast.{TreeTypeMap, Trees, tpd, untpd} import Trees._ import Decorators._ @@ -1250,7 +1251,7 @@ class TreeUnpickler(reader: TastyReader, def readLaterWithOwner[T <: AnyRef](end: Addr, op: TreeReader => Context => T)(implicit ctx: Context): Symbol => Trees.Lazy[T] = { val localReader = fork goto(end) - owner => new LazyReader(localReader, owner, ctx.mode, op) + owner => new LazyReader(localReader, owner, ctx.mode, ctx.source, op) } def readHole(end: Addr, isType: Boolean)(implicit ctx: Context): Tree = { @@ -1300,10 +1301,16 @@ class TreeUnpickler(reader: TastyReader, } } - class LazyReader[T <: AnyRef](reader: TreeReader, owner: Symbol, mode: Mode, op: TreeReader => Context => T) extends Trees.Lazy[T] { + class LazyReader[T <: AnyRef]( + reader: TreeReader, owner: Symbol, mode: Mode, source: SourceFile, + op: TreeReader => Context => T) extends Trees.Lazy[T] { def complete(implicit ctx: Context): T = { pickling.println(i"starting to read at ${reader.reader.currentAddr} with owner $owner") - op(reader)(ctx.withPhaseNoLater(ctx.picklerPhase).withOwner(owner).withModeBits(mode)) + op(reader)(ctx + .withPhaseNoLater(ctx.picklerPhase) + .withOwner(owner) + .withModeBits(mode) + .withSource(source)) } } From 454df0c462e0329e8031840de03ba45ad6be9ff7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 20 Dec 2018 19:01:16 +0100 Subject: [PATCH 11/75] Better caching of sources --- .../src/dotty/tools/dotc/core/Contexts.scala | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 0dc1fa1297a7..8c5339137e3b 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -270,15 +270,20 @@ object Contexts { def getSource(fileName: String): SourceFile = { val f = new PlainFile(Path(fileName)) - if (f.isDirectory) { - error(s"expected file, received directory '$fileName'") - NoSource - } - else if (f.exists) - getSource(f) - else { - error(s"not found: $fileName") - NoSource + base.sources.get(f) match { + case Some(source) => + source + case None => + if (f.isDirectory) { + error(s"expected file, received directory '$fileName'") + NoSource + } + else if (f.exists) + getSource(f) + else { + error(s"not found: $fileName") + NoSource + } } } @@ -466,10 +471,11 @@ object Contexts { final def withOwner(owner: Symbol): Context = if (owner ne this.owner) fresh.setOwner(owner) else this - private[this] var sourceCtx: SimpleIdentityMap[SourceFile, Context] = SimpleIdentityMap.Empty + private var sourceCtx: SimpleIdentityMap[SourceFile, Context] = SimpleIdentityMap.Empty final def withSource(source: SourceFile): Context = if (source `eq` this.source) this + else if ((source `eq` outer.source) && (outer.sourceCtx(this.source) `eq` this)) outer else { val prev = sourceCtx(source) if (prev != null) prev From 368a68d0000216c314d7ab3e40a16d544027c7a6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 20 Dec 2018 19:02:45 +0100 Subject: [PATCH 12/75] Allocate tree ids globally Tree ids survive compilation runs, need to be allocated globally. --- .../src/dotty/tools/dotc/ast/Desugar.scala | 12 +- .../dotty/tools/dotc/ast/DesugarEnums.scala | 2 +- .../src/dotty/tools/dotc/ast/Positioned.scala | 10 +- .../src/dotty/tools/dotc/ast/TreeIds.scala | 44 +++++ compiler/src/dotty/tools/dotc/ast/Trees.scala | 140 +++++++------- compiler/src/dotty/tools/dotc/ast/untpd.scala | 176 +++++++++--------- .../src/dotty/tools/dotc/core/Contexts.scala | 44 +---- .../tools/dotc/core/tasty/TreePickler.scala | 2 +- .../dotc/parsing/xml/MarkupParsers.scala | 4 +- .../tools/dotc/tastyreflect/package.scala | 4 +- .../dotty/tools/dotc/typer/Applications.scala | 2 +- .../dotty/tools/dotc/typer/Implicits.scala | 4 +- .../dotty/tools/dotc/typer/ProtoTypes.scala | 2 +- .../dotty/tools/dotc/util/SourceFile.scala | 2 +- 14 files changed, 231 insertions(+), 217 deletions(-) create mode 100644 compiler/src/dotty/tools/dotc/ast/TreeIds.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index e4135feb8103..1baf8ab75cdf 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -43,15 +43,15 @@ object desugar { // ----- DerivedTypeTrees ----------------------------------- - class SetterParamTree(implicit @transientParam ids: TreeIds) extends DerivedTypeTree { + class SetterParamTree(implicit @transientParam src: SourceInfo) extends DerivedTypeTree { def derivedTree(sym: Symbol)(implicit ctx: Context): tpd.TypeTree = tpd.TypeTree(sym.info.resultType) } - class TypeRefTree(implicit @transientParam ids: TreeIds) extends DerivedTypeTree { + class TypeRefTree(implicit @transientParam src: SourceInfo) extends DerivedTypeTree { def derivedTree(sym: Symbol)(implicit ctx: Context): tpd.TypeTree = tpd.TypeTree(sym.typeRef) } - class TermRefTree(implicit @transientParam ids: TreeIds) extends DerivedTypeTree { + class TermRefTree(implicit @transientParam src: SourceInfo) extends DerivedTypeTree { def derivedTree(sym: Symbol)(implicit ctx: Context): tpd.Tree = tpd.ref(sym) } @@ -59,7 +59,7 @@ object desugar { * @param suffix String difference between existing parameter (call it `P`) and parameter owning the * DerivedTypeTree (call it `O`). We have: `O.name == P.name + suffix`. */ - class DerivedFromParamTree(suffix: String)(implicit @transientParam ids: TreeIds) extends DerivedTypeTree { + class DerivedFromParamTree(suffix: String)(implicit @transientParam src: SourceInfo) extends DerivedTypeTree { /** Make sure that for all enclosing module classes their companion classes * are completed. Reason: We need the constructor of such companion classes to @@ -1026,7 +1026,7 @@ object desugar { mayNeedSetter } - private def derivedDefDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit ids: TreeIds) = + private def derivedDefDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit src: SourceInfo) = DefDef(named.name.asTermName, Nil, Nil, tpt, rhs) .withMods(mods) .withPos(original.pos.withPoint(named.pos.start)) @@ -1390,6 +1390,6 @@ object desugar { buf.toList } - private class IrrefutableGenFrom(pat: Tree, expr: Tree)(implicit @transientParam ids: TreeIds) + private class IrrefutableGenFrom(pat: Tree, expr: Tree)(implicit @transientParam src: SourceInfo) extends GenFrom(pat, expr) } diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index 0e9a8b4368c9..4fe8a7f38b53 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -73,7 +73,7 @@ object DesugarEnums { else if (isEnumCase(cdef)) cdef.withMods(cdef.mods.withFlags(cdef.mods.flags | Final)) else cdef - private def valuesDot(name: String)(implicit ids: TreeIds) = + private def valuesDot(name: String)(implicit src: SourceInfo) = Select(Ident(nme.DOLLAR_VALUES), name.toTermName) private def registerCall(implicit ctx: Context): List[Tree] = if (enumClass.typeParams.nonEmpty) Nil diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index 4daa2df3be35..0e98cb552d75 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package ast import util.Positions._ -import core.Contexts.{Context, TreeIds} +import core.Contexts.{Context, SourceInfo} import core.Decorators._ import core.Flags.{JavaDefined, Extension} import core.StdNames.nme @@ -27,26 +27,26 @@ abstract class Positioned extends Product { if (pos.exists) setChildPositions(pos.toSynthetic) } - def cloned(implicit ids: TreeIds): Positioned + def cloned(implicit src: SourceInfo): Positioned /** A positioned item like this one with the position set to `pos`. * if the positioned item is source-derived, a clone is returned. * If the positioned item is synthetic, the position is updated * destructively and the item itself is returned. */ - def withPos(pos: Position)(implicit ids: TreeIds): this.type = { + def withPos(pos: Position)(implicit src: SourceInfo): this.type = { val newpd = if (pos == curPos || curPos.isSynthetic) this else cloned newpd.setPos(pos) newpd.asInstanceOf[this.type] } - def withPos(posd: Positioned)(implicit ids: TreeIds): this.type = + def withPos(posd: Positioned)(implicit src: SourceInfo): this.type = if (posd == null) this else withPos(posd.pos) /** This item with a position that's the union of the given `pos` and the * current position. */ - def addPos(pos: Position)(implicit ids: TreeIds): this.type = withPos(pos union this.pos) + def addPos(pos: Position)(implicit src: SourceInfo): this.type = withPos(pos union this.pos) /** Set position of this tree only, without performing * any checks of consistency with - or updates of - other positions. diff --git a/compiler/src/dotty/tools/dotc/ast/TreeIds.scala b/compiler/src/dotty/tools/dotc/ast/TreeIds.scala new file mode 100644 index 000000000000..eafde3691ccc --- /dev/null +++ b/compiler/src/dotty/tools/dotc/ast/TreeIds.scala @@ -0,0 +1,44 @@ +package dotty.tools +package dotc +package ast + +import core.Contexts.SourceInfo +import io.AbstractFile +import scala.annotation.internal.sharable +import scala.collection.mutable +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.atomic.AtomicInteger + +object TreeIds { + + private final val ChunkSize = 1024 + + @sharable private[this] val counters = new ConcurrentHashMap[AbstractFile, AtomicInteger] + @sharable private[this] val fileOfChunk = mutable.ArrayBuffer[AbstractFile]() + + def nextId(implicit src: SourceInfo): Int = { + val file = src.source.file + var ctr = counters.get(file) + if (ctr == null) { + counters.putIfAbsent(file, new AtomicInteger) + ctr = counters.get(file) + } + def recur(): Int = { + val id = ctr.get + if (id % ChunkSize == 0) newChunk(file, ctr) + else if (ctr.compareAndSet(id, id + 1)) id + else recur() + } + recur() + } + + private def newChunk(file: AbstractFile, ctr: AtomicInteger): Int = synchronized { + val id = fileOfChunk.length * ChunkSize + fileOfChunk += file + ctr.set(id + 1) + id + } + + def fileOfId(id: Int): AbstractFile = + fileOfChunk(id / ChunkSize) +} \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index a2533dea1cd5..2f176529a3ca 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -50,7 +50,7 @@ object Trees { * - Type checking an untyped tree should remove all embedded `TypedSplice` * nodes. */ - abstract class Tree[-T >: Untyped](implicit @transientParam ids: TreeIds) + abstract class Tree[-T >: Untyped](implicit @transientParam src: SourceInfo) extends Positioned with Product with Attachment.Container @@ -62,7 +62,7 @@ object Trees { /** A unique identifier for this tree. Used for debugging, and potentially * tracking presentation compiler interactions. */ - @sharable private var myUniqueId: Int = ids.nextTreeId + @sharable private var myUniqueId: Int = TreeIds.nextId def uniqueId: Int = myUniqueId @@ -234,9 +234,9 @@ object Trees { override def hashCode(): Int = uniqueId // for debugging; was: System.identityHashCode(this) override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - override def cloned(implicit ids: TreeIds): Tree[T] = { + override def cloned(implicit src: SourceInfo): Tree[T] = { val tree = clone.asInstanceOf[Tree[T]] - tree.myUniqueId = ids.nextTreeId + tree.myUniqueId = TreeIds.nextId tree } } @@ -272,7 +272,7 @@ object Trees { } /** Tree's denotation can be derived from its type */ - abstract class DenotingTree[-T >: Untyped](implicit @transientParam ids: TreeIds) extends Tree[T] { + abstract class DenotingTree[-T >: Untyped](implicit @transientParam src: SourceInfo) extends Tree[T] { type ThisTree[-T >: Untyped] <: DenotingTree[T] override def denot(implicit ctx: Context): Denotation = typeOpt match { case tpe: NamedType => tpe.denot @@ -289,7 +289,7 @@ object Trees { /** Tree's denot/isType/isTerm properties come from a subtree * identified by `forwardTo`. */ - abstract class ProxyTree[-T >: Untyped](implicit @transientParam ids: TreeIds) extends Tree[T] { + abstract class ProxyTree[-T >: Untyped](implicit @transientParam src: SourceInfo) extends Tree[T] { type ThisTree[-T >: Untyped] <: ProxyTree[T] def forwardTo: Tree[T] override def denot(implicit ctx: Context): Denotation = forwardTo.denot @@ -298,13 +298,13 @@ object Trees { } /** Tree has a name */ - abstract class NameTree[-T >: Untyped](implicit @transientParam ids: TreeIds) extends DenotingTree[T] { + abstract class NameTree[-T >: Untyped](implicit @transientParam src: SourceInfo) extends DenotingTree[T] { type ThisTree[-T >: Untyped] <: NameTree[T] def name: Name } /** Tree refers by name to a denotation */ - abstract class RefTree[-T >: Untyped](implicit @transientParam ids: TreeIds) extends NameTree[T] { + abstract class RefTree[-T >: Untyped](implicit @transientParam src: SourceInfo) extends NameTree[T] { type ThisTree[-T >: Untyped] <: RefTree[T] def qualifier: Tree[T] override def isType: Boolean = name.isTypeName @@ -323,7 +323,7 @@ object Trees { * The envelope of a MemberDef contains the whole definition and has its point * on the opening keyword (or the next token after that if keyword is missing). */ - abstract class MemberDef[-T >: Untyped](implicit @transientParam ids: TreeIds) extends NameTree[T] with DefTree[T] { + abstract class MemberDef[-T >: Untyped](implicit @transientParam src: SourceInfo) extends NameTree[T] with DefTree[T] { type ThisTree[-T >: Untyped] <: MemberDef[T] private[this] var myMods: untpd.Modifiers = null @@ -365,7 +365,7 @@ object Trees { } /** A ValDef or DefDef tree */ - abstract class ValOrDefDef[-T >: Untyped](implicit @transientParam ids: TreeIds) extends MemberDef[T] with WithLazyField[Tree[T]] { + abstract class ValOrDefDef[-T >: Untyped](implicit @transientParam src: SourceInfo) extends MemberDef[T] with WithLazyField[Tree[T]] { def name: TermName def tpt: Tree[T] def unforcedRhs: LazyTree = unforced @@ -375,7 +375,7 @@ object Trees { // ----------- Tree case classes ------------------------------------ /** name */ - case class Ident[-T >: Untyped] private[ast] (name: Name)(implicit @transientParam ids: TreeIds) + case class Ident[-T >: Untyped] private[ast] (name: Name)(implicit @transientParam src: SourceInfo) extends RefTree[T] { type ThisTree[-T >: Untyped] = Ident[T] def qualifier: Tree[T] = genericEmptyTree @@ -384,31 +384,31 @@ object Trees { def isBackquoted: Boolean = false } - class BackquotedIdent[-T >: Untyped]private[ast] (name: Name)(implicit @transientParam ids: TreeIds) + class BackquotedIdent[-T >: Untyped]private[ast] (name: Name)(implicit @transientParam src: SourceInfo) extends Ident[T](name) { override def isBackquoted: Boolean = true override def toString: String = s"BackquotedIdent($name)" } - class SearchFailureIdent[-T >: Untyped] private[ast] (name: Name)(implicit @transientParam ids: TreeIds) + class SearchFailureIdent[-T >: Untyped] private[ast] (name: Name)(implicit @transientParam src: SourceInfo) extends Ident[T](name) { override def toString: String = s"SearchFailureIdent($name)" } /** qualifier.name, or qualifier#name, if qualifier is a type */ - case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name)(implicit @transientParam ids: TreeIds) + case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name)(implicit @transientParam src: SourceInfo) extends RefTree[T] { type ThisTree[-T >: Untyped] = Select[T] } - class SelectWithSig[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name, val sig: Signature)(implicit @transientParam ids: TreeIds) + class SelectWithSig[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name, val sig: Signature)(implicit @transientParam src: SourceInfo) extends Select[T](qualifier, name) { override def toString: String = s"SelectWithSig($qualifier, $name, $sig)" } /** qual.this */ - case class This[-T >: Untyped] private[ast] (qual: untpd.Ident)(implicit @transientParam ids: TreeIds) + case class This[-T >: Untyped] private[ast] (qual: untpd.Ident)(implicit @transientParam src: SourceInfo) extends DenotingTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = This[T] // Denotation of a This tree is always the underlying class; needs correction for modules. @@ -423,13 +423,13 @@ object Trees { } /** C.super[mix], where qual = C.this */ - case class Super[-T >: Untyped] private[ast] (qual: Tree[T], mix: untpd.Ident)(implicit @transientParam ids: TreeIds) + case class Super[-T >: Untyped] private[ast] (qual: Tree[T], mix: untpd.Ident)(implicit @transientParam src: SourceInfo) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Super[T] def forwardTo: Tree[T] = qual } - abstract class GenericApply[-T >: Untyped](implicit @transientParam ids: TreeIds) extends ProxyTree[T] with TermTree[T] { + abstract class GenericApply[-T >: Untyped](implicit @transientParam src: SourceInfo) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] <: GenericApply[T] val fun: Tree[T] val args: List[Tree[T]] @@ -437,50 +437,50 @@ object Trees { } /** fun(args) */ - case class Apply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit @transientParam ids: TreeIds) + case class Apply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit @transientParam src: SourceInfo) extends GenericApply[T] { type ThisTree[-T >: Untyped] = Apply[T] } /** fun[args] */ - case class TypeApply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit @transientParam ids: TreeIds) + case class TypeApply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit @transientParam src: SourceInfo) extends GenericApply[T] { type ThisTree[-T >: Untyped] = TypeApply[T] } /** const */ - case class Literal[-T >: Untyped] private[ast] (const: Constant)(implicit @transientParam ids: TreeIds) + case class Literal[-T >: Untyped] private[ast] (const: Constant)(implicit @transientParam src: SourceInfo) extends Tree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Literal[T] } /** new tpt, but no constructor call */ - case class New[-T >: Untyped] private[ast] (tpt: Tree[T])(implicit @transientParam ids: TreeIds) + case class New[-T >: Untyped] private[ast] (tpt: Tree[T])(implicit @transientParam src: SourceInfo) extends Tree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = New[T] } /** expr : tpt */ - case class Typed[-T >: Untyped] private[ast] (expr: Tree[T], tpt: Tree[T])(implicit @transientParam ids: TreeIds) + case class Typed[-T >: Untyped] private[ast] (expr: Tree[T], tpt: Tree[T])(implicit @transientParam src: SourceInfo) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Typed[T] def forwardTo: Tree[T] = expr } /** name = arg, in a parameter list */ - case class NamedArg[-T >: Untyped] private[ast] (name: Name, arg: Tree[T])(implicit @transientParam ids: TreeIds) + case class NamedArg[-T >: Untyped] private[ast] (name: Name, arg: Tree[T])(implicit @transientParam src: SourceInfo) extends Tree[T] { type ThisTree[-T >: Untyped] = NamedArg[T] } /** name = arg, outside a parameter list */ - case class Assign[-T >: Untyped] private[ast] (lhs: Tree[T], rhs: Tree[T])(implicit @transientParam ids: TreeIds) + case class Assign[-T >: Untyped] private[ast] (lhs: Tree[T], rhs: Tree[T])(implicit @transientParam src: SourceInfo) extends TermTree[T] { type ThisTree[-T >: Untyped] = Assign[T] } /** { stats; expr } */ - case class Block[-T >: Untyped] private[ast] (stats: List[Tree[T]], expr: Tree[T])(implicit @transientParam ids: TreeIds) + case class Block[-T >: Untyped] private[ast] (stats: List[Tree[T]], expr: Tree[T])(implicit @transientParam src: SourceInfo) extends Tree[T] { type ThisTree[-T >: Untyped] = Block[T] override def isType: Boolean = expr.isType @@ -488,12 +488,12 @@ object Trees { } /** if cond then thenp else elsep */ - case class If[-T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit @transientParam ids: TreeIds) + case class If[-T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit @transientParam src: SourceInfo) extends TermTree[T] { type ThisTree[-T >: Untyped] = If[T] def isInline = false } - class InlineIf[T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit @transientParam ids: TreeIds) + class InlineIf[T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit @transientParam src: SourceInfo) extends If(cond, thenp, elsep) { override def isInline = true override def toString = s"InlineIf($cond, $thenp, $elsep)" @@ -508,32 +508,32 @@ object Trees { * of the closure is a function type, otherwise it is the type * given in `tpt`, which must be a SAM type. */ - case class Closure[-T >: Untyped] private[ast] (env: List[Tree[T]], meth: Tree[T], tpt: Tree[T])(implicit @transientParam ids: TreeIds) + case class Closure[-T >: Untyped] private[ast] (env: List[Tree[T]], meth: Tree[T], tpt: Tree[T])(implicit @transientParam src: SourceInfo) extends TermTree[T] { type ThisTree[-T >: Untyped] = Closure[T] } /** selector match { cases } */ - case class Match[-T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam ids: TreeIds) + case class Match[-T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam src: SourceInfo) extends TermTree[T] { assert(cases.nonEmpty) type ThisTree[-T >: Untyped] = Match[T] def isInline = false } - class InlineMatch[T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam ids: TreeIds) + class InlineMatch[T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam src: SourceInfo) extends Match(selector, cases) { override def isInline = true override def toString = s"InlineMatch($selector, $cases)" } /** case pat if guard => body; only appears as child of a Match */ - case class CaseDef[-T >: Untyped] private[ast] (pat: Tree[T], guard: Tree[T], body: Tree[T])(implicit @transientParam ids: TreeIds) + case class CaseDef[-T >: Untyped] private[ast] (pat: Tree[T], guard: Tree[T], body: Tree[T])(implicit @transientParam src: SourceInfo) extends Tree[T] { type ThisTree[-T >: Untyped] = CaseDef[T] } /** label[tpt]: { expr } */ - case class Labeled[-T >: Untyped] private[ast] (bind: Bind[T], expr: Tree[T])(implicit @transientParam ids: TreeIds) + case class Labeled[-T >: Untyped] private[ast] (bind: Bind[T], expr: Tree[T])(implicit @transientParam src: SourceInfo) extends NameTree[T] { type ThisTree[-T >: Untyped] = Labeled[T] def name: Name = bind.name @@ -544,13 +544,13 @@ object Trees { * After program transformations this is not necessarily the enclosing method, because * closures can intervene. */ - case class Return[-T >: Untyped] private[ast] (expr: Tree[T], from: Tree[T] = genericEmptyTree)(implicit @transientParam ids: TreeIds) + case class Return[-T >: Untyped] private[ast] (expr: Tree[T], from: Tree[T] = genericEmptyTree)(implicit @transientParam src: SourceInfo) extends TermTree[T] { type ThisTree[-T >: Untyped] = Return[T] } /** while (cond) { body } */ - case class WhileDo[-T >: Untyped] private[ast] (cond: Tree[T], body: Tree[T])(implicit @transientParam ids: TreeIds) + case class WhileDo[-T >: Untyped] private[ast] (cond: Tree[T], body: Tree[T])(implicit @transientParam src: SourceInfo) extends TermTree[T] { type ThisTree[-T >: Untyped] = WhileDo[T] } @@ -574,7 +574,7 @@ object Trees { * * Match(EmptyTree, $anonfun(x)>) */ - case class Try[-T >: Untyped] private[ast] (expr: Tree[T], cases: List[CaseDef[T]], finalizer: Tree[T])(implicit @transientParam ids: TreeIds) + case class Try[-T >: Untyped] private[ast] (expr: Tree[T], cases: List[CaseDef[T]], finalizer: Tree[T])(implicit @transientParam src: SourceInfo) extends TermTree[T] { type ThisTree[-T >: Untyped] = Try[T] } @@ -582,13 +582,13 @@ object Trees { /** Seq(elems) * @param tpt The element type of the sequence. */ - case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit @transientParam ids: TreeIds) + case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit @transientParam src: SourceInfo) extends Tree[T] { type ThisTree[-T >: Untyped] = SeqLiteral[T] } /** Array(elems) */ - class JavaSeqLiteral[T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit @transientParam ids: TreeIds) + class JavaSeqLiteral[T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit @transientParam src: SourceInfo) extends SeqLiteral(elems, elemtpt) { override def toString: String = s"JavaSeqLiteral($elems, $elemtpt)" } @@ -609,14 +609,14 @@ object Trees { * different context: `bindings` represent the arguments to the inlined * call, whereas `expansion` represents the body of the inlined function. */ - case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T])(implicit @transientParam ids: TreeIds) + case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T])(implicit @transientParam src: SourceInfo) extends Tree[T] { type ThisTree[-T >: Untyped] = Inlined[T] override def initialPos: Position = call.pos } /** A type tree that represents an existing or inferred type */ - case class TypeTree[-T >: Untyped]()(implicit @transientParam ids: TreeIds) + case class TypeTree[-T >: Untyped]()(implicit @transientParam src: SourceInfo) extends DenotingTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = TypeTree[T] override def isEmpty: Boolean = !hasType @@ -627,66 +627,66 @@ object Trees { /** A type tree that defines a new type variable. Its type is always a TypeVar. * Every TypeVar is created as the type of one TypeVarBinder. */ - class TypeVarBinder[-T >: Untyped](implicit @transientParam ids: TreeIds) extends TypeTree[T] + class TypeVarBinder[-T >: Untyped](implicit @transientParam src: SourceInfo) extends TypeTree[T] /** ref.type */ - case class SingletonTypeTree[-T >: Untyped] private[ast] (ref: Tree[T])(implicit @transientParam ids: TreeIds) + case class SingletonTypeTree[-T >: Untyped] private[ast] (ref: Tree[T])(implicit @transientParam src: SourceInfo) extends DenotingTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = SingletonTypeTree[T] } /** left & right */ - case class AndTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])(implicit @transientParam ids: TreeIds) + case class AndTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])(implicit @transientParam src: SourceInfo) extends TypTree[T] { type ThisTree[-T >: Untyped] = AndTypeTree[T] } /** left | right */ - case class OrTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])(implicit @transientParam ids: TreeIds) + case class OrTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])(implicit @transientParam src: SourceInfo) extends TypTree[T] { type ThisTree[-T >: Untyped] = OrTypeTree[T] } /** tpt { refinements } */ - case class RefinedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], refinements: List[Tree[T]])(implicit @transientParam ids: TreeIds) + case class RefinedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], refinements: List[Tree[T]])(implicit @transientParam src: SourceInfo) extends ProxyTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = RefinedTypeTree[T] def forwardTo: Tree[T] = tpt } /** tpt[args] */ - case class AppliedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], args: List[Tree[T]])(implicit @transientParam ids: TreeIds) + case class AppliedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], args: List[Tree[T]])(implicit @transientParam src: SourceInfo) extends ProxyTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = AppliedTypeTree[T] def forwardTo: Tree[T] = tpt } /** [typeparams] -> tpt */ - case class LambdaTypeTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T])(implicit @transientParam ids: TreeIds) + case class LambdaTypeTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T])(implicit @transientParam src: SourceInfo) extends TypTree[T] { type ThisTree[-T >: Untyped] = LambdaTypeTree[T] } /** [bound] selector match { cases } */ - case class MatchTypeTree[-T >: Untyped] private[ast] (bound: Tree[T], selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam ids: TreeIds) + case class MatchTypeTree[-T >: Untyped] private[ast] (bound: Tree[T], selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam src: SourceInfo) extends TypTree[T] { type ThisTree[-T >: Untyped] = MatchTypeTree[T] } /** => T */ - case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T])(implicit @transientParam ids: TreeIds) + case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T])(implicit @transientParam src: SourceInfo) extends TypTree[T] { type ThisTree[-T >: Untyped] = ByNameTypeTree[T] } /** >: lo <: hi */ - case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T])(implicit @transientParam ids: TreeIds) + case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T])(implicit @transientParam src: SourceInfo) extends TypTree[T] { type ThisTree[-T >: Untyped] = TypeBoundsTree[T] } /** name @ body */ - case class Bind[-T >: Untyped] private[ast] (name: Name, body: Tree[T])(implicit @transientParam ids: TreeIds) + case class Bind[-T >: Untyped] private[ast] (name: Name, body: Tree[T])(implicit @transientParam src: SourceInfo) extends NameTree[T] with DefTree[T] with PatternTree[T] { type ThisTree[-T >: Untyped] = Bind[T] override def isType: Boolean = name.isTypeName @@ -694,7 +694,7 @@ object Trees { } /** tree_1 | ... | tree_n */ - case class Alternative[-T >: Untyped] private[ast] (trees: List[Tree[T]])(implicit @transientParam ids: TreeIds) + case class Alternative[-T >: Untyped] private[ast] (trees: List[Tree[T]])(implicit @transientParam src: SourceInfo) extends PatternTree[T] { type ThisTree[-T >: Untyped] = Alternative[T] } @@ -713,13 +713,13 @@ object Trees { * val result = fun(sel)(implicits) * if (result.isDefined) "match patterns against result" */ - case class UnApply[-T >: Untyped] private[ast] (fun: Tree[T], implicits: List[Tree[T]], patterns: List[Tree[T]])(implicit @transientParam ids: TreeIds) + case class UnApply[-T >: Untyped] private[ast] (fun: Tree[T], implicits: List[Tree[T]], patterns: List[Tree[T]])(implicit @transientParam src: SourceInfo) extends PatternTree[T] { type ThisTree[-T >: Untyped] = UnApply[T] } /** mods val name: tpt = rhs */ - case class ValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], private var preRhs: LazyTree)(implicit @transientParam ids: TreeIds) + case class ValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], private var preRhs: LazyTree)(implicit @transientParam src: SourceInfo) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = ValDef[T] assert(isEmpty || tpt != genericEmptyTree) @@ -729,7 +729,7 @@ object Trees { /** mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs */ case class DefDef[-T >: Untyped] private[ast] (name: TermName, tparams: List[TypeDef[T]], - vparamss: List[List[ValDef[T]]], tpt: Tree[T], private var preRhs: LazyTree)(implicit @transientParam ids: TreeIds) + vparamss: List[List[ValDef[T]]], tpt: Tree[T], private var preRhs: LazyTree)(implicit @transientParam src: SourceInfo) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = DefDef[T] assert(tpt != genericEmptyTree) @@ -742,7 +742,7 @@ object Trees { * mods type name = rhs or * mods type name >: lo <: hi, if rhs = TypeBoundsTree(lo, hi) & (lo ne hi) */ - case class TypeDef[-T >: Untyped] private[ast] (name: TypeName, rhs: Tree[T])(implicit @transientParam ids: TreeIds) + case class TypeDef[-T >: Untyped] private[ast] (name: TypeName, rhs: Tree[T])(implicit @transientParam src: SourceInfo) extends MemberDef[T] { type ThisTree[-T >: Untyped] = TypeDef[T] @@ -751,7 +751,7 @@ object Trees { } /** extends parents { self => body } */ - case class Template[-T >: Untyped] private[ast] (constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], private var preBody: LazyTreeList)(implicit @transientParam ids: TreeIds) + case class Template[-T >: Untyped] private[ast] (constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], private var preBody: LazyTreeList)(implicit @transientParam src: SourceInfo) extends DefTree[T] with WithLazyField[List[Tree[T]]] { type ThisTree[-T >: Untyped] = Template[T] def unforcedBody: LazyTreeList = unforced @@ -764,20 +764,20 @@ object Trees { * where a selector is either an untyped `Ident`, `name` or * an untyped thicket consisting of `name` and `rename`. */ - case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]])(implicit @transientParam ids: TreeIds) + case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]])(implicit @transientParam src: SourceInfo) extends DenotingTree[T] { type ThisTree[-T >: Untyped] = Import[T] } /** package pid { stats } */ - case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]])(implicit @transientParam ids: TreeIds) + case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]])(implicit @transientParam src: SourceInfo) extends ProxyTree[T] { type ThisTree[-T >: Untyped] = PackageDef[T] def forwardTo: RefTree[T] = pid } /** arg @annot */ - case class Annotated[-T >: Untyped] private[ast] (arg: Tree[T], annot: Tree[T])(implicit @transientParam ids: TreeIds) + case class Annotated[-T >: Untyped] private[ast] (arg: Tree[T], annot: Tree[T])(implicit @transientParam src: SourceInfo) extends ProxyTree[T] { type ThisTree[-T >: Untyped] = Annotated[T] def forwardTo: Tree[T] = arg @@ -794,7 +794,7 @@ object Trees { * The contained trees will be integrated when transformed with * a `transform(List[Tree])` call. */ - case class Thicket[-T >: Untyped](trees: List[Tree[T]])(implicit @transientParam ids: TreeIds) + case class Thicket[-T >: Untyped](trees: List[Tree[T]])(implicit @transientParam src: SourceInfo) extends Tree[T] with WithoutTypeOrPos[T] { myTpe = NoType.asInstanceOf[T] @@ -802,7 +802,7 @@ object Trees { override def isEmpty: Boolean = trees.isEmpty override def toList: List[Tree[T]] = flatten(trees) override def toString: String = if (isEmpty) "EmptyTree" else "Thicket(" + trees.mkString(", ") + ")" - override def withPos(pos: Position)(implicit ids: TreeIds): this.type = { + override def withPos(pos: Position)(implicit src: SourceInfo): this.type = { val newTrees = trees.mapConserve(_.withPos(pos)) if (trees eq newTrees) this @@ -814,10 +814,10 @@ object Trees { trees foreach (_.foreachInThicket(op)) } - class EmptyTree[T >: Untyped] extends Thicket(Nil)(GlobalTreeIds) + class EmptyTree[T >: Untyped] extends Thicket(Nil)(NoContext) class EmptyValDef[T >: Untyped] extends ValDef[T]( - nme.WILDCARD, genericEmptyTree[T], genericEmptyTree[T])(GlobalTreeIds) with WithoutTypeOrPos[T] { + nme.WILDCARD, genericEmptyTree[T], genericEmptyTree[T])(NoContext) with WithoutTypeOrPos[T] { myTpe = NoType.asInstanceOf[T] override def isEmpty: Boolean = true setMods(untpd.Modifiers(PrivateLocal)) @@ -952,11 +952,11 @@ object Trees { // ----- Auxiliary creation methods ------------------ - def Thicket(trees: List[Tree])(implicit ids:TreeIds): Thicket = new Thicket(trees) + def Thicket(trees: List[Tree])(implicit src: SourceInfo): Thicket = new Thicket(trees) def Thicket(): Thicket = EmptyTree - def Thicket(x1: Tree, x2: Tree)(implicit ids:TreeIds): Thicket = Thicket(x1 :: x2 :: Nil) - def Thicket(x1: Tree, x2: Tree, x3: Tree)(implicit ids:TreeIds): Thicket = Thicket(x1 :: x2 :: x3 :: Nil) - def flatTree(xs: List[Tree])(implicit ids:TreeIds): Tree = flatten(xs) match { + def Thicket(x1: Tree, x2: Tree)(implicit src: SourceInfo): Thicket = Thicket(x1 :: x2 :: Nil) + def Thicket(x1: Tree, x2: Tree, x3: Tree)(implicit src: SourceInfo): Thicket = Thicket(x1 :: x2 :: x3 :: Nil) + def flatTree(xs: List[Tree])(implicit src: SourceInfo): Tree = flatten(xs) match { case x :: Nil => x case ys => Thicket(ys) } @@ -976,10 +976,10 @@ object Trees { protected def postProcess(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] protected def postProcess(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T] - protected def finalize(tree: Tree, copied: untpd.Tree)(implicit ids:TreeIds): copied.ThisTree[T] = + protected def finalize(tree: Tree, copied: untpd.Tree)(implicit src: SourceInfo): copied.ThisTree[T] = postProcess(tree, copied.withPos(tree.pos).withAttachmentsFrom(tree)) - protected def finalize(tree: Tree, copied: untpd.MemberDef)(implicit ids:TreeIds): copied.ThisTree[T] = + protected def finalize(tree: Tree, copied: untpd.MemberDef)(implicit src: SourceInfo): copied.ThisTree[T] = postProcess(tree, copied.withPos(tree.pos).withAttachmentsFrom(tree)) protected def srcCtx(tree: Tree)(implicit ctx: Context) = ctx.withSource(tree.source) diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index c78925697edc..e89befd0b378 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -14,7 +14,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { // ----- Tree cases that exist in untyped form only ------------------ - abstract class OpTree(implicit @transientParam ids: TreeIds) extends Tree { + abstract class OpTree(implicit @transientParam src: SourceInfo) extends Tree { def op: Ident override def isTerm: Boolean = op.name.isTermName override def isType: Boolean = op.name.isTypeName @@ -23,7 +23,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { /** A typed subtree of an untyped tree needs to be wrapped in a TypedSplice * @param owner The current owner at the time the tree was defined */ - abstract case class TypedSplice(splice: tpd.Tree)(val owner: Symbol)(implicit @transientParam ids: TreeIds) extends ProxyTree { + abstract case class TypedSplice(splice: tpd.Tree)(val owner: Symbol)(implicit @transientParam src: SourceInfo) extends ProxyTree { def forwardTo: tpd.Tree = splice } @@ -33,31 +33,31 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { } /** mods object name impl */ - case class ModuleDef(name: TermName, impl: Template)(implicit @transientParam ids: TreeIds) + case class ModuleDef(name: TermName, impl: Template)(implicit @transientParam src: SourceInfo) extends MemberDef { type ThisTree[-T >: Untyped] <: Trees.NameTree[T] with Trees.MemberDef[T] with ModuleDef def withName(name: Name)(implicit ctx: Context): ModuleDef = cpy.ModuleDef(this)(name.toTermName, impl) } - case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree)(implicit @transientParam ids: TreeIds) extends Tree with TermTree + case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree)(implicit @transientParam src: SourceInfo) extends Tree with TermTree - case class SymbolLit(str: String)(implicit @transientParam ids: TreeIds) extends TermTree + case class SymbolLit(str: String)(implicit @transientParam src: SourceInfo) extends TermTree /** An interpolated string * @param segments a list of two element tickets consisting of string literal and argument tree, * possibly with a simple string literal as last element of the list */ - case class InterpolatedString(id: TermName, segments: List[Tree])(implicit @transientParam ids: TreeIds) + case class InterpolatedString(id: TermName, segments: List[Tree])(implicit @transientParam src: SourceInfo) extends TermTree /** A function type */ - case class Function(args: List[Tree], body: Tree)(implicit @transientParam ids: TreeIds) extends Tree { + case class Function(args: List[Tree], body: Tree)(implicit @transientParam src: SourceInfo) extends Tree { override def isTerm: Boolean = body.isTerm override def isType: Boolean = body.isType } /** A function type with `implicit` or `erased` modifiers */ - class FunctionWithMods(args: List[Tree], body: Tree, val mods: Modifiers)(implicit @transientParam ids: TreeIds) + class FunctionWithMods(args: List[Tree], body: Tree, val mods: Modifiers)(implicit @transientParam src: SourceInfo) extends Function(args, body) /** A function created from a wildcard expression @@ -67,40 +67,40 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * This is equivalent to Function, except that forms a special case for the overlapping * positions tests. */ - class WildcardFunction(placeholderParams: List[ValDef], body: Tree)(implicit @transientParam ids: TreeIds) + class WildcardFunction(placeholderParams: List[ValDef], body: Tree)(implicit @transientParam src: SourceInfo) extends Function(placeholderParams, body) - case class InfixOp(left: Tree, op: Ident, right: Tree)(implicit @transientParam ids: TreeIds) extends OpTree - case class PostfixOp(od: Tree, op: Ident)(implicit @transientParam ids: TreeIds) extends OpTree - case class PrefixOp(op: Ident, od: Tree)(implicit @transientParam ids: TreeIds) extends OpTree { + case class InfixOp(left: Tree, op: Ident, right: Tree)(implicit @transientParam src: SourceInfo) extends OpTree + case class PostfixOp(od: Tree, op: Ident)(implicit @transientParam src: SourceInfo) extends OpTree + case class PrefixOp(op: Ident, od: Tree)(implicit @transientParam src: SourceInfo) extends OpTree { override def isType: Boolean = op.isType override def isTerm: Boolean = op.isTerm } - case class Parens(t: Tree)(implicit @transientParam ids: TreeIds) extends ProxyTree { + case class Parens(t: Tree)(implicit @transientParam src: SourceInfo) extends ProxyTree { def forwardTo: Tree = t } - case class Tuple(trees: List[Tree])(implicit @transientParam ids: TreeIds) extends Tree { + case class Tuple(trees: List[Tree])(implicit @transientParam src: SourceInfo) extends Tree { override def isTerm: Boolean = trees.isEmpty || trees.head.isTerm override def isType: Boolean = !isTerm } - case class Throw(expr: Tree)(implicit @transientParam ids: TreeIds) extends TermTree - case class Quote(expr: Tree)(implicit @transientParam ids: TreeIds) extends TermTree - case class DoWhile(body: Tree, cond: Tree)(implicit @transientParam ids: TreeIds) extends TermTree - case class ForYield(enums: List[Tree], expr: Tree)(implicit @transientParam ids: TreeIds) extends TermTree - case class ForDo(enums: List[Tree], body: Tree)(implicit @transientParam ids: TreeIds) extends TermTree - case class GenFrom(pat: Tree, expr: Tree)(implicit @transientParam ids: TreeIds) extends Tree - case class GenAlias(pat: Tree, expr: Tree)(implicit @transientParam ids: TreeIds) extends Tree - case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit @transientParam ids: TreeIds) extends TypTree - case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit @transientParam ids: TreeIds) extends DefTree - case class DependentTypeTree(tp: List[Symbol] => Type)(implicit @transientParam ids: TreeIds) extends Tree - - @sharable object EmptyTypeIdent extends Ident(tpnme.EMPTY)(GlobalTreeIds) with WithoutTypeOrPos[Untyped] { + case class Throw(expr: Tree)(implicit @transientParam src: SourceInfo) extends TermTree + case class Quote(expr: Tree)(implicit @transientParam src: SourceInfo) extends TermTree + case class DoWhile(body: Tree, cond: Tree)(implicit @transientParam src: SourceInfo) extends TermTree + case class ForYield(enums: List[Tree], expr: Tree)(implicit @transientParam src: SourceInfo) extends TermTree + case class ForDo(enums: List[Tree], body: Tree)(implicit @transientParam src: SourceInfo) extends TermTree + case class GenFrom(pat: Tree, expr: Tree)(implicit @transientParam src: SourceInfo) extends Tree + case class GenAlias(pat: Tree, expr: Tree)(implicit @transientParam src: SourceInfo) extends Tree + case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit @transientParam src: SourceInfo) extends TypTree + case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit @transientParam src: SourceInfo) extends DefTree + case class DependentTypeTree(tp: List[Symbol] => Type)(implicit @transientParam src: SourceInfo) extends Tree + + @sharable object EmptyTypeIdent extends Ident(tpnme.EMPTY)(NoContext) with WithoutTypeOrPos[Untyped] { override def isEmpty: Boolean = true } /** A block generated by the XML parser, only treated specially by * `Positioned#checkPos` */ - class XMLBlock(stats: List[Tree], expr: Tree)(implicit @transientParam ids: TreeIds) extends Block(stats, expr) + class XMLBlock(stats: List[Tree], expr: Tree)(implicit @transientParam src: SourceInfo) extends Block(stats, expr) // ----- Modifiers ----------------------------------------------------- /** Mod is intended to record syntactic information about modifiers, it's @@ -109,7 +109,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * For any query about semantic information, check `flags` instead. */ sealed abstract class Mod(val flags: FlagSet) extends Positioned { - def cloned(implicit ids: TreeIds): Positioned = clone.asInstanceOf[Positioned] + def cloned(implicit src: SourceInfo): Positioned = clone.asInstanceOf[Positioned] } object Mod { @@ -208,7 +208,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def isEnumCase: Boolean = isEnum && is(Case) def isEnumClass: Boolean = isEnum && !is(Case) - override def cloned(implicit ids: TreeIds): Modifiers = + override def cloned(implicit src: SourceInfo): Modifiers = clone.asInstanceOf[Modifiers] } @@ -219,7 +219,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { /** A type tree that gets its type from some other tree's symbol. Enters the * type tree in the References attachment of the `from` tree as a side effect. */ - abstract class DerivedTypeTree(implicit @transientParam ids: TreeIds) extends TypeTree { + abstract class DerivedTypeTree(implicit @transientParam src: SourceInfo) extends TypeTree { private[this] var myWatched: Tree = EmptyTree @@ -263,54 +263,54 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { // ------ Creation methods for untyped only ----------------- - def Ident(name: Name)(implicit ids: TreeIds): Ident = new Ident(name) - def BackquotedIdent(name: Name)(implicit ids: TreeIds): BackquotedIdent = new BackquotedIdent(name) - def SearchFailureIdent(name: Name)(implicit ids: TreeIds): SearchFailureIdent = new SearchFailureIdent(name) - def Select(qualifier: Tree, name: Name)(implicit ids: TreeIds): Select = new Select(qualifier, name) - def SelectWithSig(qualifier: Tree, name: Name, sig: Signature)(implicit ids: TreeIds): Select = new SelectWithSig(qualifier, name, sig) - def This(qual: Ident)(implicit ids: TreeIds): This = new This(qual) - def Super(qual: Tree, mix: Ident)(implicit ids: TreeIds): Super = new Super(qual, mix) - def Apply(fun: Tree, args: List[Tree])(implicit ids: TreeIds): Apply = new Apply(fun, args) - def TypeApply(fun: Tree, args: List[Tree])(implicit ids: TreeIds): TypeApply = new TypeApply(fun, args) - def Literal(const: Constant)(implicit ids: TreeIds): Literal = new Literal(const) - def New(tpt: Tree)(implicit ids: TreeIds): New = new New(tpt) - def Typed(expr: Tree, tpt: Tree)(implicit ids: TreeIds): Typed = new Typed(expr, tpt) - def NamedArg(name: Name, arg: Tree)(implicit ids: TreeIds): NamedArg = new NamedArg(name, arg) - def Assign(lhs: Tree, rhs: Tree)(implicit ids: TreeIds): Assign = new Assign(lhs, rhs) - def Block(stats: List[Tree], expr: Tree)(implicit ids: TreeIds): Block = new Block(stats, expr) - def If(cond: Tree, thenp: Tree, elsep: Tree)(implicit ids: TreeIds): If = new If(cond, thenp, elsep) - def InlineIf(cond: Tree, thenp: Tree, elsep: Tree)(implicit ids: TreeIds): If = new InlineIf(cond, thenp, elsep) - def Closure(env: List[Tree], meth: Tree, tpt: Tree)(implicit ids: TreeIds): Closure = new Closure(env, meth, tpt) - def Match(selector: Tree, cases: List[CaseDef])(implicit ids: TreeIds): Match = new Match(selector, cases) - def InlineMatch(selector: Tree, cases: List[CaseDef])(implicit ids: TreeIds): Match = new InlineMatch(selector, cases) - def CaseDef(pat: Tree, guard: Tree, body: Tree)(implicit ids: TreeIds): CaseDef = new CaseDef(pat, guard, body) - def Labeled(bind: Bind, expr: Tree)(implicit ids: TreeIds): Labeled = new Labeled(bind, expr) - def Return(expr: Tree, from: Tree)(implicit ids: TreeIds): Return = new Return(expr, from) - def WhileDo(cond: Tree, body: Tree)(implicit ids: TreeIds): WhileDo = new WhileDo(cond, body) - def Try(expr: Tree, cases: List[CaseDef], finalizer: Tree)(implicit ids: TreeIds): Try = new Try(expr, cases, finalizer) - def SeqLiteral(elems: List[Tree], elemtpt: Tree)(implicit ids: TreeIds): SeqLiteral = new SeqLiteral(elems, elemtpt) - def JavaSeqLiteral(elems: List[Tree], elemtpt: Tree)(implicit ids: TreeIds): JavaSeqLiteral = new JavaSeqLiteral(elems, elemtpt) - def Inlined(call: tpd.Tree, bindings: List[MemberDef], expansion: Tree)(implicit ids: TreeIds): Inlined = new Inlined(call, bindings, expansion) - def TypeTree()(implicit ids: TreeIds): TypeTree = new TypeTree() - def SingletonTypeTree(ref: Tree)(implicit ids: TreeIds): SingletonTypeTree = new SingletonTypeTree(ref) - def AndTypeTree(left: Tree, right: Tree)(implicit ids: TreeIds): AndTypeTree = new AndTypeTree(left, right) - def OrTypeTree(left: Tree, right: Tree)(implicit ids: TreeIds): OrTypeTree = new OrTypeTree(left, right) - def RefinedTypeTree(tpt: Tree, refinements: List[Tree])(implicit ids: TreeIds): RefinedTypeTree = new RefinedTypeTree(tpt, refinements) - def AppliedTypeTree(tpt: Tree, args: List[Tree])(implicit ids: TreeIds): AppliedTypeTree = new AppliedTypeTree(tpt, args) - def LambdaTypeTree(tparams: List[TypeDef], body: Tree)(implicit ids: TreeIds): LambdaTypeTree = new LambdaTypeTree(tparams, body) - def MatchTypeTree(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit ids: TreeIds): MatchTypeTree = new MatchTypeTree(bound, selector, cases) - def ByNameTypeTree(result: Tree)(implicit ids: TreeIds): ByNameTypeTree = new ByNameTypeTree(result) - def TypeBoundsTree(lo: Tree, hi: Tree)(implicit ids: TreeIds): TypeBoundsTree = new TypeBoundsTree(lo, hi) - def Bind(name: Name, body: Tree)(implicit ids: TreeIds): Bind = new Bind(name, body) - def Alternative(trees: List[Tree])(implicit ids: TreeIds): Alternative = new Alternative(trees) - def UnApply(fun: Tree, implicits: List[Tree], patterns: List[Tree])(implicit ids: TreeIds): UnApply = new UnApply(fun, implicits, patterns) - def ValDef(name: TermName, tpt: Tree, rhs: LazyTree)(implicit ids: TreeIds): ValDef = new ValDef(name, tpt, rhs) - def DefDef(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree)(implicit ids: TreeIds): DefDef = new DefDef(name, tparams, vparamss, tpt, rhs) - def TypeDef(name: TypeName, rhs: Tree)(implicit ids: TreeIds): TypeDef = new TypeDef(name, rhs) - def Template(constr: DefDef, parents: List[Tree], self: ValDef, body: LazyTreeList)(implicit ids: TreeIds): Template = new Template(constr, parents, self, body) - def Import(expr: Tree, selectors: List[Tree])(implicit ids: TreeIds): Import = new Import(expr, selectors) - def PackageDef(pid: RefTree, stats: List[Tree])(implicit ids: TreeIds): PackageDef = new PackageDef(pid, stats) - def Annotated(arg: Tree, annot: Tree)(implicit ids: TreeIds): Annotated = new Annotated(arg, annot) + def Ident(name: Name)(implicit src: SourceInfo): Ident = new Ident(name) + def BackquotedIdent(name: Name)(implicit src: SourceInfo): BackquotedIdent = new BackquotedIdent(name) + def SearchFailureIdent(name: Name)(implicit src: SourceInfo): SearchFailureIdent = new SearchFailureIdent(name) + def Select(qualifier: Tree, name: Name)(implicit src: SourceInfo): Select = new Select(qualifier, name) + def SelectWithSig(qualifier: Tree, name: Name, sig: Signature)(implicit src: SourceInfo): Select = new SelectWithSig(qualifier, name, sig) + def This(qual: Ident)(implicit src: SourceInfo): This = new This(qual) + def Super(qual: Tree, mix: Ident)(implicit src: SourceInfo): Super = new Super(qual, mix) + def Apply(fun: Tree, args: List[Tree])(implicit src: SourceInfo): Apply = new Apply(fun, args) + def TypeApply(fun: Tree, args: List[Tree])(implicit src: SourceInfo): TypeApply = new TypeApply(fun, args) + def Literal(const: Constant)(implicit src: SourceInfo): Literal = new Literal(const) + def New(tpt: Tree)(implicit src: SourceInfo): New = new New(tpt) + def Typed(expr: Tree, tpt: Tree)(implicit src: SourceInfo): Typed = new Typed(expr, tpt) + def NamedArg(name: Name, arg: Tree)(implicit src: SourceInfo): NamedArg = new NamedArg(name, arg) + def Assign(lhs: Tree, rhs: Tree)(implicit src: SourceInfo): Assign = new Assign(lhs, rhs) + def Block(stats: List[Tree], expr: Tree)(implicit src: SourceInfo): Block = new Block(stats, expr) + def If(cond: Tree, thenp: Tree, elsep: Tree)(implicit src: SourceInfo): If = new If(cond, thenp, elsep) + def InlineIf(cond: Tree, thenp: Tree, elsep: Tree)(implicit src: SourceInfo): If = new InlineIf(cond, thenp, elsep) + def Closure(env: List[Tree], meth: Tree, tpt: Tree)(implicit src: SourceInfo): Closure = new Closure(env, meth, tpt) + def Match(selector: Tree, cases: List[CaseDef])(implicit src: SourceInfo): Match = new Match(selector, cases) + def InlineMatch(selector: Tree, cases: List[CaseDef])(implicit src: SourceInfo): Match = new InlineMatch(selector, cases) + def CaseDef(pat: Tree, guard: Tree, body: Tree)(implicit src: SourceInfo): CaseDef = new CaseDef(pat, guard, body) + def Labeled(bind: Bind, expr: Tree)(implicit src: SourceInfo): Labeled = new Labeled(bind, expr) + def Return(expr: Tree, from: Tree)(implicit src: SourceInfo): Return = new Return(expr, from) + def WhileDo(cond: Tree, body: Tree)(implicit src: SourceInfo): WhileDo = new WhileDo(cond, body) + def Try(expr: Tree, cases: List[CaseDef], finalizer: Tree)(implicit src: SourceInfo): Try = new Try(expr, cases, finalizer) + def SeqLiteral(elems: List[Tree], elemtpt: Tree)(implicit src: SourceInfo): SeqLiteral = new SeqLiteral(elems, elemtpt) + def JavaSeqLiteral(elems: List[Tree], elemtpt: Tree)(implicit src: SourceInfo): JavaSeqLiteral = new JavaSeqLiteral(elems, elemtpt) + def Inlined(call: tpd.Tree, bindings: List[MemberDef], expansion: Tree)(implicit src: SourceInfo): Inlined = new Inlined(call, bindings, expansion) + def TypeTree()(implicit src: SourceInfo): TypeTree = new TypeTree() + def SingletonTypeTree(ref: Tree)(implicit src: SourceInfo): SingletonTypeTree = new SingletonTypeTree(ref) + def AndTypeTree(left: Tree, right: Tree)(implicit src: SourceInfo): AndTypeTree = new AndTypeTree(left, right) + def OrTypeTree(left: Tree, right: Tree)(implicit src: SourceInfo): OrTypeTree = new OrTypeTree(left, right) + def RefinedTypeTree(tpt: Tree, refinements: List[Tree])(implicit src: SourceInfo): RefinedTypeTree = new RefinedTypeTree(tpt, refinements) + def AppliedTypeTree(tpt: Tree, args: List[Tree])(implicit src: SourceInfo): AppliedTypeTree = new AppliedTypeTree(tpt, args) + def LambdaTypeTree(tparams: List[TypeDef], body: Tree)(implicit src: SourceInfo): LambdaTypeTree = new LambdaTypeTree(tparams, body) + def MatchTypeTree(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit src: SourceInfo): MatchTypeTree = new MatchTypeTree(bound, selector, cases) + def ByNameTypeTree(result: Tree)(implicit src: SourceInfo): ByNameTypeTree = new ByNameTypeTree(result) + def TypeBoundsTree(lo: Tree, hi: Tree)(implicit src: SourceInfo): TypeBoundsTree = new TypeBoundsTree(lo, hi) + def Bind(name: Name, body: Tree)(implicit src: SourceInfo): Bind = new Bind(name, body) + def Alternative(trees: List[Tree])(implicit src: SourceInfo): Alternative = new Alternative(trees) + def UnApply(fun: Tree, implicits: List[Tree], patterns: List[Tree])(implicit src: SourceInfo): UnApply = new UnApply(fun, implicits, patterns) + def ValDef(name: TermName, tpt: Tree, rhs: LazyTree)(implicit src: SourceInfo): ValDef = new ValDef(name, tpt, rhs) + def DefDef(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree)(implicit src: SourceInfo): DefDef = new DefDef(name, tparams, vparamss, tpt, rhs) + def TypeDef(name: TypeName, rhs: Tree)(implicit src: SourceInfo): TypeDef = new TypeDef(name, rhs) + def Template(constr: DefDef, parents: List[Tree], self: ValDef, body: LazyTreeList)(implicit src: SourceInfo): Template = new Template(constr, parents, self, body) + def Import(expr: Tree, selectors: List[Tree])(implicit src: SourceInfo): Import = new Import(expr, selectors) + def PackageDef(pid: RefTree, stats: List[Tree])(implicit src: SourceInfo): PackageDef = new PackageDef(pid, stats) + def Annotated(arg: Tree, annot: Tree)(implicit src: SourceInfo): Annotated = new Annotated(arg, annot) // ------ Additional creation methods for untyped only ----------------- @@ -339,32 +339,32 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { ensureApplied((prefix /: argss)(Apply(_, _))) } - def Block(stat: Tree, expr: Tree)(implicit ids: TreeIds): Block = + def Block(stat: Tree, expr: Tree)(implicit src: SourceInfo): Block = Block(stat :: Nil, expr) - def Apply(fn: Tree, arg: Tree)(implicit ids: TreeIds): Apply = + def Apply(fn: Tree, arg: Tree)(implicit src: SourceInfo): Apply = Apply(fn, arg :: Nil) - def ensureApplied(tpt: Tree)(implicit ids: TreeIds): Tree = tpt match { + def ensureApplied(tpt: Tree)(implicit src: SourceInfo): Tree = tpt match { case _: Apply => tpt case _ => Apply(tpt, Nil) } - def AppliedTypeTree(tpt: Tree, arg: Tree)(implicit ids: TreeIds): AppliedTypeTree = + def AppliedTypeTree(tpt: Tree, arg: Tree)(implicit src: SourceInfo): AppliedTypeTree = AppliedTypeTree(tpt, arg :: Nil) def TypeTree(tpe: Type)(implicit ctx: Context): TypedSplice = TypedSplice(TypeTree().withTypeUnchecked(tpe)) - def unitLiteral(implicit ids: TreeIds): Literal = Literal(Constant(())) + def unitLiteral(implicit src: SourceInfo): Literal = Literal(Constant(())) def ref(tp: NamedType)(implicit ctx: Context): Tree = TypedSplice(tpd.ref(tp)) - def rootDot(name: Name)(implicit ids: TreeIds): Select = Select(Ident(nme.ROOTPKG), name) - def scalaDot(name: Name)(implicit ids: TreeIds): Select = Select(rootDot(nme.scala_), name) - def scalaUnit(implicit ids: TreeIds): Select = scalaDot(tpnme.Unit) - def scalaAny(implicit ids: TreeIds): Select = scalaDot(tpnme.Any) - def javaDotLangDot(name: Name)(implicit ids: TreeIds): Select = Select(Select(Ident(nme.java), nme.lang), name) + def rootDot(name: Name)(implicit src: SourceInfo): Select = Select(Ident(nme.ROOTPKG), name) + def scalaDot(name: Name)(implicit src: SourceInfo): Select = Select(rootDot(nme.scala_), name) + def scalaUnit(implicit src: SourceInfo): Select = scalaDot(tpnme.Unit) + def scalaAny(implicit src: SourceInfo): Select = scalaDot(tpnme.Any) + def javaDotLangDot(name: Name)(implicit src: SourceInfo): Select = Select(Select(Ident(nme.java), nme.lang), name) def makeConstructor(tparams: List[TypeDef], vparamss: List[List[ValDef]], rhs: Tree = EmptyTree)(implicit ctx: Context): DefDef = DefDef(nme.CONSTRUCTOR, tparams, vparamss, TypeTree(), rhs) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 8c5339137e3b..b974fcdbe6b4 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -12,7 +12,7 @@ import Symbols._ import Scopes._ import Uniques._ import ast.Trees._ -import ast.untpd +import ast.{untpd, TreeIds} import util.{FreshNameCreator, NoSource, SimpleIdentityMap, SourceFile} import typer.{Implicits, ImportInfo, Inliner, NamerContextOps, SearchHistory, SearchRoot, TypeAssigner, Typer} import Implicits.ContextualImplicits @@ -37,23 +37,8 @@ import plugins._ object Contexts { - /** A generator for tree ids */ - trait TreeIds { - def nextTreeId: Int - } - - private final val TreeIdChunkSize = 1024 - - /** Id generator for compiler-global trees that are not created in a context. - * We reserve the first chunk of ids for these - */ - object GlobalTreeIds extends TreeIds { - @sharable private var _nextTreeId: Int = 0 - def nextTreeId: Int = synchronized { - _nextTreeId += 1 - assert(_nextTreeId < TreeIdChunkSize) - _nextTreeId - } + trait SourceInfo { + def source: SourceFile } private val (compilerCallbackLoc, store1) = Store.empty.newLocation[CompilerCallback]() @@ -95,7 +80,7 @@ object Contexts { with Reporting with NamerContextOps with Plugins - with TreeIds + with SourceInfo with Cloneable { thiscontext => implicit def ctx: Context = this @@ -251,18 +236,8 @@ object Contexts { implicitsCache } - def nextTreeId: Int = { - var id = base.nextTreeIdBySource.getOrElseUpdate(source, 0) - if (id % TreeIdChunkSize == 0) { - id = base.sourceOfChunk.length * TreeIdChunkSize - base.sourceOfChunk += source - } - base.nextTreeIdBySource(source) = id + 1 - id - } - def sourceOfTreeId(id: Int): SourceFile = - base.sourceOfChunk(id / TreeIdChunkSize) + getSource(TreeIds.fileOfId(id)) /** Sourcefile corresponding to given abstract file, memoized */ def getSource(file: AbstractFile, codec: => Codec = Codec(settings.encoding.value)) = @@ -638,6 +613,7 @@ object Contexts { } @sharable object NoContext extends Context { + override def source = NoSource val base: ContextBase = null override val implicits: ContextualImplicits = new ContextualImplicits(Nil, null)(this) } @@ -697,14 +673,10 @@ object Contexts { class ContextState { // Symbols state - /** Counters for unique ids */ + /** Counter for unique symbol ids */ private[this] var _nextSymId: Int = 0 def nextSymId: Int = { _nextSymId += 1; _nextSymId } - private[core] var nextTreeIdBySource = new mutable.HashMap[SourceFile, Int] - private[core] var sourceOfChunk = mutable.ArrayBuffer[SourceFile](NoSource) - // first element reserved for GlobalTreeIds - /** Sources that were loaded */ val sources: mutable.HashMap[AbstractFile, SourceFile] = new mutable.HashMap[AbstractFile, SourceFile] @@ -781,8 +753,6 @@ object Contexts { for ((_, set) <- uniqueSets) set.clear() errorTypeMsg.clear() sources.clear() - nextTreeIdBySource.clear() - sourceOfChunk.clear() } // Test that access is single threaded diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 14db02d123b8..83b1633e6f63 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -20,7 +20,7 @@ object TreePickler { val sectionName = "ASTs" - case class Hole(idx: Int, args: List[tpd.Tree])(implicit @transientParam ids: TreeIds) extends tpd.Tree { + case class Hole(idx: Int, args: List[tpd.Tree])(implicit @transientParam src: SourceInfo) extends tpd.Tree { override def fallbackToText(printer: Printer): Text = s"[[$idx|" ~~ printer.toTextGlobal(args, ", ") ~~ "]]" } diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala index 166dffd62549..8d11b31fccd2 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala @@ -11,7 +11,7 @@ import Parsers._ import util.Positions._ import core._ import Constants._ -import Contexts.TreeIds +import Contexts.SourceInfo import Utility._ @@ -47,7 +47,7 @@ object MarkupParsers { override def getMessage: String = "input ended while parsing XML" } - class MarkupParser(parser: Parser, final val preserveWS: Boolean)(implicit ids: TreeIds) extends MarkupParserCommon { + class MarkupParser(parser: Parser, final val preserveWS: Boolean)(implicit src: SourceInfo) extends MarkupParserCommon { import Tokens.{ LBRACE, RBRACE } diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/package.scala b/compiler/src/dotty/tools/dotc/tastyreflect/package.scala index 543cb815a699..3fef58f370bc 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/package.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/package.scala @@ -1,7 +1,7 @@ package dotty.tools.dotc import dotty.tools.dotc.ast.Trees.{Tree, Untyped} -import dotty.tools.dotc.core.Contexts.{Context, TreeIds} +import dotty.tools.dotc.core.Contexts.{Context, SourceInfo} import dotty.tools.dotc.core.Symbols.Symbol import dotty.tools.dotc.core.Types.Type import dotty.tools.dotc.core.SymDenotations.SymDenotation @@ -12,7 +12,7 @@ package object tastyreflect { type PackageDefinition = PackageDefinitionImpl[Type] /** Represents the symbol of a definition in tree form */ - case class PackageDefinitionImpl[-T >: Untyped] private[tastyreflect] (sym: Symbol)(implicit @transientParam ids: TreeIds) extends Tree[T] { + case class PackageDefinitionImpl[-T >: Untyped] private[tastyreflect] (sym: Symbol)(implicit @transientParam src: SourceInfo) extends Tree[T] { type ThisTree[-T >: Untyped] = PackageDefinitionImpl[T] override def denot(implicit ctx: Context): SymDenotation = sym.denot diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index f2bc7d5b26e6..fa190d270354 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -168,7 +168,7 @@ object Applications { /** A wrapper indicating that its argument is an application of an extension method. */ - class ExtMethodApply(app: Tree)(implicit @transientParam ids: TreeIds) extends tpd.Tree { + class ExtMethodApply(val app: Tree)(implicit @transientParam src: SourceInfo) extends tpd.Tree { override def pos = app.pos def canEqual(that: Any): Boolean = app.canEqual(that) diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 20003b2d1dc0..f206068fd3a1 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -348,7 +348,7 @@ object Implicits { } object SearchFailure { - def apply(tpe: SearchFailureType)(implicit ids: TreeIds): SearchFailure = { + def apply(tpe: SearchFailureType)(implicit src: SourceInfo): SearchFailure = { val id = if (tpe.isInstanceOf[AmbiguousImplicits]) "/* ambiguous */" else "/* missing */" @@ -387,7 +387,7 @@ object Implicits { @sharable object NoMatchingImplicits extends NoMatchingImplicits(NoType, EmptyTree) @sharable val NoMatchingImplicitsFailure: SearchFailure = - SearchFailure(NoMatchingImplicits)(GlobalTreeIds) + SearchFailure(NoMatchingImplicits)(NoContext) /** An ambiguous implicits failure */ class AmbiguousImplicits(val alt1: SearchSuccess, val alt2: SearchSuccess, val expectedType: Type, val argument: Tree) extends SearchFailureType { diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 1397d19ae6a2..df165bfb0435 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -652,7 +652,7 @@ object ProtoTypes { /** Dummy tree to be used as an argument of a FunProto or ViewProto type */ object dummyTreeOfType { - def apply(tp: Type)(implicit ids: TreeIds): Tree = untpd.Literal(Constant(null)) withTypeUnchecked tp + def apply(tp: Type)(implicit src: SourceInfo): Tree = untpd.Literal(Constant(null)) withTypeUnchecked tp def unapply(tree: untpd.Tree): Option[Type] = tree match { case Literal(Constant(null)) => Some(tree.typeOpt) case _ => None diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index d200fae54df3..4ad599ccec71 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -148,7 +148,7 @@ case class SourceFile(file: AbstractFile, content: Array[Char]) extends interfac override def toString: String = file.toString } -@sharable object NoSource extends SourceFile("", "") { +@sharable object NoSource extends SourceFile(NoAbstractFile, Array[Char]()) { override def exists: Boolean = false override def atPos(pos: Position): SourcePosition = NoSourcePosition } From 03b3ac8f7fb3c361246f245e70e88376a5430721 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 21 Dec 2018 10:06:11 +0100 Subject: [PATCH 13/75] Follow source changes when unpickling --- .../tools/dotc/core/tasty/TreeUnpickler.scala | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 6e32c012669f..33e7e87ebb5f 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -742,6 +742,8 @@ class TreeUnpickler(reader: TastyReader, } private def readNewDef()(implicit ctx: Context): Tree = { + val sctx = sourceChangeContext + if (sctx `ne` ctx) return readNewDef()(sctx) val start = currentAddr val sym = symAtAddr(start) val tag = readByte() @@ -867,6 +869,7 @@ class TreeUnpickler(reader: TastyReader, private def readTemplate(implicit ctx: Context): Template = { val start = currentAddr + assert(sourcePathAt(start).isEmpty) val cls = ctx.owner.asClass val assumedSelfType = if (cls.is(Module) && cls.owner.isClass) TermRef(cls.owner.thisType, cls.name.sourceModuleName) @@ -952,6 +955,7 @@ class TreeUnpickler(reader: TastyReader, def readImport()(implicit ctx: Context): Tree = { val start = currentAddr + assert(sourcePathAt(start).isEmpty) readByte() readEnd() val expr = readTerm() @@ -961,6 +965,7 @@ class TreeUnpickler(reader: TastyReader, def readSelectors()(implicit ctx: Context): List[untpd.Tree] = nextByte match { case IMPORTED => val start = currentAddr + assert(sourcePathAt(start).isEmpty) readByte() val from = setPos(start, untpd.Ident(readName())) nextByte match { @@ -995,6 +1000,8 @@ class TreeUnpickler(reader: TastyReader, // ------ Reading trees ----------------------------------------------------- def readTerm()(implicit ctx: Context): Tree = { // TODO: rename to readTree + val sctx = sourceChangeContext + if (sctx `ne` ctx) return readTerm()(sctx) val start = currentAddr val tag = readByte() pickling.println(s"reading term ${astTagToString(tag)} at $start") @@ -1236,6 +1243,8 @@ class TreeUnpickler(reader: TastyReader, } def readCase()(implicit ctx: Context): CaseDef = { + val sctx = sourceChangeContext + if (sctx `ne` ctx) return readCase()(sctx) val start = currentAddr assert(readByte() == CASEDEF) val end = readEnd() @@ -1284,6 +1293,25 @@ class TreeUnpickler(reader: TastyReader, } } else NoPosition + /** Pickled source path at `addr`. */ + def sourcePathAt(addr: Addr)(implicit ctx: Context): String = + if (ctx.mode.is(Mode.ReadPositions)) { + posUnpicklerOpt match { + case Some(posUnpickler) => + posUnpickler.sourcePathAt(addr) + case _ => + "" + } + } else "" + + /** If currentAddr carries a source path, the current context with + * the source of that path, otherwise the current context itself. + */ + def sourceChangeContext(implicit ctx: Context): Context = { + val path = sourcePathAt(currentAddr) + if (path.nonEmpty) ctx.withSource(ctx.getSource(path)) else ctx + } + /** Coordinate for the symbol at `addr`. */ def coordAt(addr: Addr)(implicit ctx: Context): Coord = { val pos = posAt(addr) From 559defdb474f4834ca2d427adda400cd1800d875 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 23 Dec 2018 16:41:03 +0100 Subject: [PATCH 14/75] Remove unpickleTypeTree --- .../src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala | 3 --- .../src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 7 ------- 2 files changed, 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala index b53d6a0a3259..cccf6411652a 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala @@ -51,9 +51,6 @@ class DottyUnpickler(bytes: Array[Byte], mode: UnpickleMode = UnpickleMode.TopLe def enter(roots: Set[SymDenotation])(implicit ctx: Context): Unit = treeUnpickler.enter(roots) - def unpickleTypeTree()(implicit ctx: Context): Tree = - treeUnpickler.unpickleTypeTree() - protected def treeSectionUnpickler(posUnpicklerOpt: Option[PositionUnpickler], commentUnpicklerOpt: Option[CommentUnpickler]): TreeSectionUnpickler = { new TreeSectionUnpickler(posUnpicklerOpt, commentUnpicklerOpt) } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 33e7e87ebb5f..1dc04493d4f0 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -94,13 +94,6 @@ class TreeUnpickler(reader: TastyReader, rdr.indexStats(reader.endAddr) } - def unpickleTypeTree()(implicit ctx: Context): Tree = { - this.roots = Set(ctx.owner) - val rdr = new TreeReader(reader).fork - ownerTree = new OwnerTree(NoAddr, 0, rdr.fork, reader.endAddr) - rdr.readTpt() - } - /** The unpickled trees */ def unpickle(mode: UnpickleMode)(implicit ctx: Context): List[Tree] = { assert(roots != null, "unpickle without previous enterTopLevel") From 7f63293282e394c45218d8f43442eed6d4a677a6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 23 Dec 2018 16:55:51 +0100 Subject: [PATCH 15/75] Keep sourcefile info when pickling Pickle SOURCE position for roots, so that unpickler get the'right source when constructing trees. --- .../tools/dotc/core/tasty/PositionPickler.scala | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala index 7c74249c4a60..a11c521571ff 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala @@ -43,6 +43,11 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad pickledIndices += index } + def pickleSource(source: SourceFile): Unit = { + buf.writeInt(SOURCE) + buf.writeInt(pickler.nameBuffer.nameIndex(source.path.toTermName).index) + } + /** True if x's position shouldn't be reconstructed automatically from its initialPos */ def alwaysNeedsPos(x: Positioned) = x match { @@ -71,9 +76,8 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad //println(i"pickling $x with $pos at $addr") pickleDeltas(addr.index, pos) if (x.source != curSource) { - buf.writeInt(SOURCE) - buf.writeInt(pickler.nameBuffer.nameIndex(x.source.path.toTermName).index) - source = curSource + pickleSource(x.source) + source = x.source } case _ => //println(i"no address for $x") @@ -92,6 +96,10 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad traverse(x.tree, curSource) case _ => } - for (root <- roots) traverse(root, root.source) + pickleSource(ctx.source) + for (root <- roots) { + assert(root.source == ctx.source) + traverse(root, root.source) + } } } From 19f3bde39ecefdaf3a66ab8d8c1e56f49821e70c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 23 Dec 2018 19:23:12 +0100 Subject: [PATCH 16/75] Eliminate Decorators.sourcePos --- .../backend/jvm/CollectEntryPoints.scala | 16 +-- .../backend/jvm/DottyBackendInterface.scala | 23 ++-- .../dotty/tools/backend/jvm/GenBCode.scala | 2 +- .../dotty/tools/backend/sjs/JSCodeGen.scala | 4 +- .../src/dotty/tools/dotc/ast/Desugar.scala | 20 +-- .../dotty/tools/dotc/ast/DesugarEnums.scala | 2 +- .../src/dotty/tools/dotc/ast/Positioned.scala | 1 + compiler/src/dotty/tools/dotc/ast/Trees.scala | 9 +- .../src/dotty/tools/dotc/core/Comments.scala | 2 +- .../src/dotty/tools/dotc/core/Contexts.scala | 3 + .../tools/dotc/core/SymDenotations.scala | 2 +- .../dotty/tools/dotc/core/SymbolLoaders.scala | 2 +- .../src/dotty/tools/dotc/core/Symbols.scala | 21 ++- .../src/dotty/tools/dotc/core/TypeOps.scala | 3 +- .../dotc/core/tasty/PositionPickler.scala | 26 ++-- .../tools/dotc/core/tasty/TreePickler.scala | 2 +- .../tools/dotc/interactive/Interactive.scala | 2 +- .../tools/dotc/interactive/SourceTree.scala | 2 +- .../dotty/tools/dotc/parsing/Parsers.scala | 2 +- .../tools/dotc/printing/RefinedPrinter.scala | 12 +- .../dotc/reporting/diagnostic/messages.scala | 2 +- .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 2 +- .../tools/dotc/sbt/ExtractDependencies.scala | 2 +- .../tools/dotc/tastyreflect/IdOpsImpl.scala | 2 +- .../dotc/tastyreflect/PatternOpsImpl.scala | 2 +- .../dotc/tastyreflect/SymbolOpsImpl.scala | 2 +- .../tools/dotc/tastyreflect/TreeOpsImpl.scala | 4 +- .../TypeOrBoundsTreesOpsImpl.scala | 2 +- .../tools/dotc/transform/AccessProxies.scala | 2 +- .../dotty/tools/dotc/transform/Bridges.scala | 7 +- .../tools/dotc/transform/CheckStatic.scala | 14 +- .../dotc/transform/CollectEntryPoints.scala | 16 +-- .../tools/dotc/transform/Constructors.scala | 2 +- .../dotc/transform/ElimErasedValueType.scala | 2 +- .../dotty/tools/dotc/transform/Erasure.scala | 2 +- .../tools/dotc/transform/ExpandSAMs.scala | 14 +- .../tools/dotc/transform/ExplicitOuter.scala | 2 +- .../tools/dotc/transform/MacroTransform.scala | 2 +- .../tools/dotc/transform/MegaPhase.scala | 4 +- .../dotty/tools/dotc/transform/Mixin.scala | 2 +- .../dotc/transform/OverridingPairs.scala | 2 +- .../tools/dotc/transform/PatternMatcher.scala | 2 +- .../tools/dotc/transform/PostTyper.scala | 16 +-- .../dotc/transform/ProtectedAccessors.scala | 2 +- .../dotty/tools/dotc/transform/Splicer.scala | 2 +- .../dotty/tools/dotc/transform/Staging.scala | 35 ++--- .../tools/dotc/transform/SuperAccessors.scala | 13 +- .../dotty/tools/dotc/transform/TailRec.scala | 4 +- .../tools/dotc/transform/TreeChecker.scala | 2 +- .../tools/dotc/transform/TypeTestsCasts.scala | 10 +- .../tools/dotc/transform/patmat/Space.scala | 6 +- .../dotty/tools/dotc/typer/Applications.scala | 45 +++---- .../src/dotty/tools/dotc/typer/Checking.scala | 112 ++++++++-------- .../dotty/tools/dotc/typer/Docstrings.scala | 2 +- .../tools/dotc/typer/ErrorReporting.scala | 15 ++- .../dotty/tools/dotc/typer/Implicits.scala | 8 +- .../src/dotty/tools/dotc/typer/Inliner.scala | 14 +- .../src/dotty/tools/dotc/typer/Namer.scala | 27 ++-- .../tools/dotc/typer/PrepareInlineable.scala | 6 +- .../dotty/tools/dotc/typer/RefChecks.scala | 61 ++++----- .../dotty/tools/dotc/typer/TypeAssigner.scala | 38 +++--- .../src/dotty/tools/dotc/typer/Typer.scala | 120 +++++++++--------- .../tools/dotc/typer/VarianceChecker.scala | 17 ++- .../tools/dotc/util/SourcePosition.scala | 7 +- compiler/src/dotty/tools/io/VirtualFile.scala | 1 + tests/neg/quote-0.scala | 4 +- .../neg/divideZero-research/plugin_1.scala | 2 +- tests/plugins/neg/divideZero/plugin_1.scala | 2 +- 68 files changed, 434 insertions(+), 384 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala b/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala index a2d178e70c49..275a5614e47f 100644 --- a/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala +++ b/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala @@ -12,7 +12,7 @@ import SymDenotations._ import Contexts._ import Types._ import Symbols._ -import dotty.tools.dotc.util.Positions.Position +import dotty.tools.dotc.util.SourcePosition import Decorators._ import StdNames.nme @@ -47,10 +47,10 @@ object CollectEntryPoints{ def hasJavaMainMethod(sym: Symbol): Boolean = (toDenot(sym).info member nme.main).alternatives exists(x => isJavaMainMethod(x.symbol)) - def fail(msg: String, pos: Position = sym.pos) = { - ctx.warning( sym.name + - s" has a main method with parameter type Array[String], but ${toDenot(sym).fullName} will not be a runnable program.\n Reason: $msg", - sourcePos(sym.pos) + def fail(msg: String, pos: SourcePosition = sym.sourcePos) = { + ctx.warning( + i"""${sym.name} has a main method with parameter type Array[String], but ${sym.fullName} will not be a runnable program. + |Reason: $msg""", sym.sourcePos // TODO: make this next claim true, if possible // by generating valid main methods as static in module classes // not sure what the jvm allows here @@ -92,11 +92,11 @@ object CollectEntryPoints{ fail("main methods cannot be generic.") case MethodTpe(paramNames, paramTypes, resultType) => if (resultType :: paramTypes exists (_.typeSymbol.isAbstractType)) - fail("main methods cannot refer to type parameters or abstract types.", m.symbol.pos) + fail("main methods cannot refer to type parameters or abstract types.", m.symbol.sourcePos) else - isJavaMainMethod(m.symbol) || fail("main method must have exact signature (Array[String])Unit", m.symbol.pos) + isJavaMainMethod(m.symbol) || fail("main method must have exact signature (Array[String])Unit", m.symbol.sourcePos) case tp => - fail(s"don't know what this is: $tp", m.symbol.pos) + fail(s"don't know what this is: $tp", m.symbol.sourcePos) } } } diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 781885faec65..d334929d9bdf 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -21,7 +21,7 @@ import Types._ import Symbols._ import Phases._ -import dotty.tools.dotc.util.Positions +import dotty.tools.dotc.util.{SourcePosition, NoSourcePosition} import Decorators._ import tpd._ @@ -41,7 +41,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma type CompilationUnit = dotc.CompilationUnit type Constant = Constants.Constant type Literal = tpd.Literal - type Position = Positions.Position + type Position = SourcePosition type Name = Names.Name type ClassDef = tpd.TypeDef type TypeDef = tpd.TypeDef @@ -77,7 +77,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma type Closure = tpd.Closure val NoSymbol: Symbol = Symbols.NoSymbol - val NoPosition: Position = Positions.NoPosition + val NoPosition: Position = NoSourcePosition val EmptyTree: Tree = tpd.EmptyTree @@ -380,12 +380,11 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma ctx.requiredModule(className) } - def debuglog(msg: => String): Unit = ctx.debuglog(msg) def informProgress(msg: String): Unit = ctx.informProgress(msg) def log(msg: => String): Unit = ctx.log(msg) - def error(pos: Position, msg: String): Unit = ctx.error(msg, pos) - def warning(pos: Position, msg: String): Unit = ctx.warning(msg, pos) + def error(pos: SourcePosition, msg: String): Unit = ctx.error(msg, pos) + def warning(pos: SourcePosition, msg: String): Unit = ctx.warning(msg, pos) def abort(msg: String): Nothing = { ctx.error(msg) throw new RuntimeException(msg) @@ -502,7 +501,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma i"""|compiler bug: created invalid generic signature for $sym in ${sym.denot.owner.showFullName} |signature: $sig |if this is reproducible, please report bug at https://github.com/lampepfl/dotty/issues - """.trim, sym.pos) + """.trim, sym.sourcePos) } } @@ -563,7 +562,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma implicit def positionHelper(a: Position): PositionHelper = new PositionHelper { def isDefined: Boolean = a.exists - def line: Int = sourcePos(a).line + 1 + def line: Int = a.line + 1 def finalPosition: Position = a } @@ -587,7 +586,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma implicit def treeHelper(a: Tree): TreeHelper = new TreeHelper { def symbol: Symbol = a.symbol - def pos: Position = a.pos + def pos: Position = a.sourcePos def isEmpty: Boolean = a.isEmpty @@ -801,7 +800,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def freshLocal(cunit: CompilationUnit, name: String, tpe: Type, pos: Position, flags: Flags): Symbol = { - ctx.newSymbol(sym, name.toTermName, termFlagSet(flags), tpe, NoSymbol, pos) + ctx.newSymbol(sym, name.toTermName, termFlagSet(flags), tpe, NoSymbol, pos.pos) } def getter(clz: Symbol): Symbol = decorateSymbol(sym).getter @@ -809,7 +808,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def moduleSuffix: String = "" // todo: validate that names already have $ suffix def outputDirectory: AbstractFile = DottyBackendInterface.this.outputDirectory - def pos: Position = sym.pos + def pos: Position = sym.sourcePos def throwsAnnotations: List[Symbol] = Nil @@ -1105,7 +1104,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def _1: Type = field.tpe match { case JavaArrayType(elem) => elem case _ => - ctx.error(s"JavaSeqArray with type ${field.tpe} reached backend: $field", field.pos) + error(field.sourcePos, s"JavaSeqArray with type ${field.tpe} reached backend: $field") UnspecifiedErrorType } def _2: List[Tree] = field.elems diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index fe5d3c08aa8a..daabf824cead 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -163,7 +163,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter else (dupClassSym, classSymbol) ctx.atPhase(ctx.typerPhase) { implicit ctx => ctx.warning(s"${cl1.show} differs only in case from ${cl2.showLocated}. " + - "Such classes will overwrite one another on case-insensitive filesystems.", cl1.pos) + "Such classes will overwrite one another on case-insensitive filesystems.", cl1.sourcePos) } } } diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index 48c363ee65e0..ea248e766534 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -1608,7 +1608,7 @@ class JSCodeGen()(implicit ctx: Context) { def requireNotSuper(): Unit = { if (jsSuperClassValue.isDefined) - ctx.error("Illegal super call in Scala.js-defined JS class", tree.pos) + ctx.error("Illegal super call in Scala.js-defined JS class", tree.sourcePos) } def requireNotSpread(arg: js.TreeOrJSSpread): js.Tree = @@ -1984,7 +1984,7 @@ class JSCodeGen()(implicit ctx: Context) { if (sym.is(Trait)) { ctx.error( s"isInstanceOf[${sym.fullName}] not supported because it is a JS trait", - tree.pos) + tree.sourcePos) js.BooleanLiteral(true) } else { js.Unbox(js.JSBinaryOp( diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 1baf8ab75cdf..511a40c599ab 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -351,10 +351,10 @@ object desugar { val constrVparamss = if (originalVparamss.isEmpty) { // ensure parameter list is non-empty if (isCaseClass && originalTparams.isEmpty) - ctx.error(CaseClassMissingParamList(cdef), cdef.namePos) + ctx.error(CaseClassMissingParamList(cdef), cdef.sourcePos.withRange(cdef.namePos)) ListOfNil } else if (isCaseClass && originalVparamss.head.exists(_.mods.is(Implicit))) { - ctx.error("Case classes should have a non-implicit parameter list", cdef.namePos) + ctx.error("Case classes should have a non-implicit parameter list", cdef.sourcePos.withRange(cdef.namePos)) ListOfNil } else originalVparamss.nestedMap(toDefParam) @@ -433,7 +433,7 @@ object desugar { appliedRef(enumClassRef) else { ctx.error(i"explicit extends clause needed because both enum case and enum class have type parameters" - , cdef.pos.startPos) + , cdef.sourcePos.startPos) appliedTypeTree(enumClassRef, constrTparams map (_ => anyRef)) } @@ -637,15 +637,15 @@ object desugar { if (!isImplicit) Nil else if (ctx.owner is Package) { - ctx.error(TopLevelImplicitClass(cdef), cdef.pos) + ctx.error(TopLevelImplicitClass(cdef), cdef.sourcePos) Nil } else if (isCaseClass) { - ctx.error(ImplicitCaseClass(cdef), cdef.pos) + ctx.error(ImplicitCaseClass(cdef), cdef.sourcePos) Nil } else if (arity != 1) { - ctx.error(ImplicitClassPrimaryConstructorArity(), cdef.pos) + ctx.error(ImplicitClassPrimaryConstructorArity(), cdef.sourcePos) Nil } else @@ -713,7 +713,7 @@ object desugar { .withPos(mdef.pos.startPos) val ValDef(selfName, selfTpt, _) = impl.self val selfMods = impl.self.mods - if (!selfTpt.isEmpty) ctx.error(ObjectMayNotHaveSelfType(mdef), impl.self.pos) + if (!selfTpt.isEmpty) ctx.error(ObjectMayNotHaveSelfType(mdef), impl.self.sourcePos) val clsSelf = ValDef(selfName, SingletonTypeTree(Ident(moduleName)), impl.self.rhs) .withMods(selfMods) .withPos(impl.self.pos orElse impl.pos.startPos) @@ -740,7 +740,7 @@ object desugar { */ def opaqueAlias(tdef: TypeDef)(implicit ctx: Context): Tree = if (tdef.rhs.isInstanceOf[TypeBoundsTree]) { - ctx.error(em"opaque type ${tdef.name} must be an alias type", tdef.pos) + ctx.error(em"opaque type ${tdef.name} must be an alias type", tdef.sourcePos) tdef.withFlags(tdef.mods.flags &~ Opaque) } else { @@ -773,7 +773,7 @@ object desugar { val name = mdef.name if (ctx.owner == defn.ScalaPackageClass && defn.reservedScalaClassNames.contains(name.toTypeName)) { def kind = if (name.isTypeName) "class" else "object" - ctx.error(em"illegal redefinition of standard $kind $name", mdef.pos) + ctx.error(em"illegal redefinition of standard $kind $name", mdef.sourcePos) name.errorName } else name @@ -1366,7 +1366,7 @@ object desugar { elems foreach collect case Alternative(trees) => for (tree <- trees; (vble, _) <- getVariables(tree)) - ctx.error(IllegalVariableInPatternAlternative(), vble.pos) + ctx.error(IllegalVariableInPatternAlternative(), vble.sourcePos) case Annotated(arg, _) => collect(arg) case InterpolatedString(_, segments) => diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index 4fe8a7f38b53..3abdfa0799e4 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -57,7 +57,7 @@ object DesugarEnums { if (tparam.variance == 0) "is non variant" else "has bounds that depend on a type parameter in the same parameter list" errorType(i"""cannot determine type argument for enum parent $enumClass, - |type parameter $tparam $problem""", pos) + |type parameter $tparam $problem""", ctx.source.atPos(pos)) } } TypeTree(enumClass.typeRef.appliedTo(targs)).withPos(pos) diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index 0e98cb552d75..81244890f984 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -2,6 +2,7 @@ package dotty.tools.dotc package ast import util.Positions._ +import util.SourcePosition import core.Contexts.{Context, SourceInfo} import core.Decorators._ import core.Flags.{JavaDefined, Extension} diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 2f176529a3ca..b330a16ac73d 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -9,8 +9,9 @@ import language.higherKinds import collection.mutable.ListBuffer import printing.Printer import printing.Texts.Text -import util.{Stats, Attachment, Property, SourceFile} +import util.{Stats, Attachment, Property, SourceFile, SourcePosition} import config.Config +import io.AbstractFile import annotation.internal.sharable import annotation.unchecked.uncheckedVariance import annotation.transientParam @@ -66,7 +67,11 @@ object Trees { def uniqueId: Int = myUniqueId - def source(implicit ctx: Context): SourceFile = ctx.sourceOfTreeId(uniqueId) + def sourceFile(implicit ctx: Context): AbstractFile = TreeIds.fileOfId(uniqueId) + + def source(implicit ctx: Context): SourceFile = ctx.getSource(sourceFile) + + def sourcePos(implicit ctx: Context): SourcePosition = source.atPos(pos) /** The type constructor at the root of the tree */ type ThisTree[T >: Untyped] <: Tree[T] diff --git a/compiler/src/dotty/tools/dotc/core/Comments.scala b/compiler/src/dotty/tools/dotc/core/Comments.scala index 6bb489550012..c90a47408fe9 100644 --- a/compiler/src/dotty/tools/dotc/core/Comments.scala +++ b/compiler/src/dotty/tools/dotc/core/Comments.scala @@ -125,7 +125,7 @@ object Comments { val newName = ctx.freshNames.newName(tree.name, NameKinds.DocArtifactName) tree.copy(name = newName) case _ => - ctx.error(ProperDefinitionNotFound(), codePos) + ctx.error(ProperDefinitionNotFound(), ctx.source.atPos(codePos)) tree } } diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index b974fcdbe6b4..54129d191d69 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -461,6 +461,9 @@ object Contexts { } } + final def withSource(f: AbstractFile): Context = + if (f == null) this else withSource(getSource(f)) + final def withProperty[T](key: Key[T], value: Option[T]): Context = if (property(key) == value) this else value match { diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 9e08f4c4f821..c68079b05cc9 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -2108,7 +2108,7 @@ object SymDenotations { def complete(denot: SymDenotation)(implicit ctx: Context): Unit = { val sym = denot.symbol def errMsg = BadSymbolicReference(denot) - ctx.error(errMsg, sym.pos) + ctx.error(errMsg, sym.sourcePos) if (ctx.debug) throw new scala.Error() initializeToDefaults(denot, errMsg) } diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 8decb3ac28c2..6f40661e4edb 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -134,7 +134,7 @@ object SymbolLoaders { ctx.warning(i"""$what ${tree.name} is in the wrong directory. |It was declared to be in package ${path.reverse.mkString(".")} |But it is found in directory ${filePath.reverse.mkString(File.separator)}""", - tree.pos) + tree.sourcePos) ok } diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 62f3c1e90ec3..2c4f5f62ceae 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -26,7 +26,7 @@ import reporting.diagnostic.Message import collection.mutable import io.AbstractFile import language.implicitConversions -import util.{NoSource, Property} +import util.{SourceFile, NoSource, Property, SourcePosition} import scala.collection.JavaConverters._ import scala.annotation.internal.sharable import config.Printers.typr @@ -415,7 +415,8 @@ object Symbols { * @param coord The coordinates of the symbol (a position or an index) * @param id A unique identifier of the symbol (unique per ContextBase) */ - class Symbol private[Symbols] (private[this] var myCoord: Coord, val id: Int) extends Designator with ParamInfo with printing.Showable { + class Symbol private[Symbols] (private[this] var myCoord: Coord, val id: Int) + extends Designator with ParamInfo with printing.Showable { type ThisName <: Name @@ -626,9 +627,10 @@ object Symbols { final def sourceFile(implicit ctx: Context): AbstractFile = { val file = associatedFile if (file != null && file.extension != "class") file + else if (!defTree.isEmpty) defTree.sourceFile else { val topLevelCls = denot.topLevelClass(ctx.withPhaseNoLater(ctx.flattenPhase)) - topLevelCls.getAnnotation(defn.SourceFileAnnot) match { + topLevelCls.unforcedAnnotation(defn.SourceFileAnnot) match { case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match { case Some(Constant(path: String)) => AbstractFile.getFile(path) case none => null @@ -638,6 +640,8 @@ object Symbols { } } + def source(implicit ctx: Context): SourceFile = ctx.getSource(sourceFile) + /** A symbol related to `sym` that is defined in source code. * * @see enclosingSourceSymbols @@ -667,6 +671,17 @@ object Symbols { */ final def pos: Position = if (coord.isPosition) coord.toPosition else NoPosition + final def sourcePos(implicit ctx: Context): SourcePosition = { + val source = { + val f = sourceFile + if (f == null || f.isVirtual) + // don't trust virtual files for tree creation - replTest fails otherwise + ctx.source + else ctx.getSource(f) + } + source.atPos(pos) + } + // ParamInfo types and methods def isTypeParam(implicit ctx: Context): Boolean = denot.is(TypeParam) def paramName(implicit ctx: Context): ThisName = name.asInstanceOf[ThisName] diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index aa6ce6207706..345f6d2035d8 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -5,6 +5,7 @@ package core import Contexts._, Types._, Symbols._, Names._, Flags._ import SymDenotations._ import util.Positions._ +import util.SourcePosition import NameKinds.DepParamName import Decorators._ import StdNames._ @@ -320,7 +321,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object. def dynamicsEnabled: Boolean = featureEnabled(defn.LanguageModuleClass, nme.dynamics) - def testScala2Mode(msg: => Message, pos: Position, replace: => Unit = ()): Boolean = { + def testScala2Mode(msg: => Message, pos: SourcePosition, replace: => Unit = ()): Boolean = { if (scala2Mode) { migrationWarning(msg, pos) replace diff --git a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala index a11c521571ff..6910a8252444 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala @@ -6,7 +6,7 @@ package tasty import ast._ import ast.Trees._ import ast.Trees.WithLazyField -import util.SourceFile +import io.{AbstractFile, NoAbstractFile} import core._ import Contexts._, Symbols._, Annotations._, Decorators._ import collection.mutable @@ -43,7 +43,7 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad pickledIndices += index } - def pickleSource(source: SourceFile): Unit = { + def pickleSource(source: AbstractFile): Unit = { buf.writeInt(SOURCE) buf.writeInt(pickler.nameBuffer.nameIndex(source.path.toTermName).index) } @@ -66,18 +66,18 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad case _ => false } - def traverse(x: Any, curSource: SourceFile): Unit = x match { + def traverse(x: Any, current: AbstractFile): Unit = x match { case x: untpd.Tree => - var source = curSource + var sourceFile = current val pos = if (x.isInstanceOf[untpd.MemberDef]) x.pos else x.pos.toSynthetic if (pos.exists && (pos != x.initialPos.toSynthetic || alwaysNeedsPos(x))) { addrOfTree(x) match { case Some(addr) if !pickledIndices.contains(addr.index) => //println(i"pickling $x with $pos at $addr") pickleDeltas(addr.index, pos) - if (x.source != curSource) { - pickleSource(x.source) - source = x.source + if (x.source.file != current) { + pickleSource(x.source.file) + sourceFile = x.source.file } case _ => //println(i"no address for $x") @@ -86,20 +86,18 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad //else if (x.pos.exists) println(i"skipping $x") x match { case x: untpd.MemberDef @unchecked => - for (ann <- x.symbol.annotations) traverse(ann.tree, source) + for (ann <- x.symbol.annotations) traverse(ann.tree, sourceFile) case _ => } - traverse(x.productIterator, source) + traverse(x.productIterator, sourceFile) case xs: TraversableOnce[_] => - xs.foreach(traverse(_, curSource)) + xs.foreach(traverse(_, current)) case x: Annotation => - traverse(x.tree, curSource) + traverse(x.tree, current) case _ => } - pickleSource(ctx.source) for (root <- roots) { - assert(root.source == ctx.source) - traverse(root, root.source) + traverse(root, NoAbstractFile) } } } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 83b1633e6f63..38a440ae38dd 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -79,7 +79,7 @@ class TreePickler(pickler: TastyPickler) { // I believe it's a bug in typer: the type of an implicit argument refers // to a closure parameter outside the closure itself. TODO: track this down, so that we // can eliminate this case. - ctx.log(i"pickling reference to as yet undefined $sym in ${sym.owner}", sym.pos) + ctx.log(i"pickling reference to as yet undefined $sym in ${sym.owner}", sym.sourcePos) pickleForwardSymRef(sym) } diff --git a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala index 797bf77f1e8e..3a0fecc27c9e 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala @@ -6,7 +6,7 @@ import scala.annotation.tailrec import scala.collection._ import ast.{NavigateAST, Trees, tpd, untpd} -import core._, core.Decorators.{sourcePos => _, _} +import core._, core.Decorators._ import Contexts._, Flags._, Names._, NameOps._, Symbols._, Trees._, Types._ import transform.SymUtils.decorateSymbol import util.Positions._, util.SourceFile, util.SourcePosition diff --git a/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala b/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala index 3c8a51617723..aabfa0e2456c 100644 --- a/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala +++ b/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala @@ -5,7 +5,7 @@ package interactive import scala.io.Codec import ast.tpd -import core._, core.Decorators.{sourcePos => _} +import core._ import Contexts._, NameOps._, Symbols._, StdNames._ import util._, util.Positions._ diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 09c943697950..a47917be3da0 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -103,7 +103,7 @@ object Parsers { if (in.token == BACKQUOTED_IDENT) in.offset + 1 else in.offset def sourcePos(off: Int = in.offset): SourcePosition = - source atPos Position(off) + source.atPos(Position(off)) /* ------------- ERROR HANDLING ------------------------------------------- */ /** The offset where the last syntax error was reported, or if a skip to a diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 849c0c5d7826..c289172e7f01 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -311,7 +311,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { val txt = tree.typeOpt match { case tp: NamedType if name != nme.WILDCARD => val pre = if (tp.symbol is JavaStatic) tp.prefix.widen else tp.prefix - toTextPrefix(pre) ~ withPos(selectionString(tp), tree.pos) + toTextPrefix(pre) ~ withPos(selectionString(tp), tree.sourcePos) case _ => toText(name) } @@ -340,8 +340,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { typeApplyText(tree) case Literal(c) => tree.typeOpt match { - case ConstantType(tc) => withPos(toText(tc), tree.pos) - case _ => withPos(toText(c), tree.pos) + case ConstantType(tc) => withPos(toText(tc), tree.sourcePos) + case _ => withPos(toText(c), tree.sourcePos) } case New(tpt) => keywordStr("new ") ~ { @@ -506,7 +506,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { case SymbolLit(str) => "'" + str case InterpolatedString(id, segments) => - def strText(str: Literal) = withPos(escapedString(str.const.stringValue), tree.pos) + def strText(str: Literal) = withPos(escapedString(str.const.stringValue), tree.sourcePos) def segmentText(segment: Tree) = segment match { case Thicket(List(str: Literal, expr)) => strText(str) ~ "{" ~ toTextGlobal(expr) ~ "}" case str: Literal => strText(str) @@ -647,8 +647,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { if (tree.hasType && tree.symbol.exists) { val str: Text = nameString(tree.symbol) tree match { - case tree: RefTree => withPos(str, tree.pos) - case tree: MemberDef => withPos(str, tree.namePos) + case tree: RefTree => withPos(str, tree.sourcePos) + case tree: MemberDef => withPos(str, tree.sourcePos.withRange(tree.namePos)) case _ => str } } diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index d18d2c9a15ea..9714b1dc518a 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -2103,7 +2103,7 @@ object messages { case _ /* Signature.FullMatch */ => "\nThe definitions have matching type signatures after erasure." } } else "" - hl"${decl.showLocated} is already defined as ${previousDecl.showDcl} ${if (previousDecl.pos.exists) s"at line ${previousDecl.pos.line + 1}" else ""}." + details + hl"${decl.showLocated} is already defined as ${previousDecl.showDcl} ${if (previousDecl.pos.exists) s"at line ${previousDecl.sourcePos.line + 1}" else ""}." + details } val explanation: String = "" } diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 8634ad928920..00833d205d9e 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -246,7 +246,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder case ex: TypeError => // See neg/i1750a for an example where a cyclic error can arise. // The root cause in this example is an illegal "override" of an inner trait - ctx.error(ex.toMessage, csym.pos) + ctx.error(ex.toMessage, csym.sourcePos) defn.ObjectType :: Nil } if (ValueClasses.isDerivedValueClass(csym)) { diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 22b30e500e6e..8fb7a2cee309 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -235,7 +235,7 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT ctx.warning("""|No class, trait or object is defined in the compilation unit. |The incremental compiler cannot record the dependency information in such case. |Some errors like unused import referring to a non-existent class might not be reported. - |""".stripMargin, tree.pos) + |""".stripMargin, tree.sourcePos) } _responsibleForImports } diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/IdOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/IdOpsImpl.scala index e603babc3eb8..17330bae1a6b 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/IdOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/IdOpsImpl.scala @@ -5,7 +5,7 @@ import dotty.tools.dotc.core.Decorators._ trait IdOpsImpl extends scala.tasty.reflect.IdOps with CoreImpl { def IdDeco(id: Id): IdAPI = new IdAPI { - def pos(implicit ctx: Context): Position = id.pos + def pos(implicit ctx: Context): Position = id.sourcePos def name(implicit ctx: Context): String = id.name.toString } diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/PatternOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/PatternOpsImpl.scala index af972be8b896..88d6df9723dd 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/PatternOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/PatternOpsImpl.scala @@ -34,7 +34,7 @@ trait PatternOpsImpl extends scala.tasty.reflect.PatternOps with CoreImpl { // ----- Patterns ------------------------------------------------- def PatternDeco(pattern: Pattern): PatternAPI = new PatternAPI { - def pos(implicit ctx: Context): Position = pattern.pos + def pos(implicit ctx: Context): Position = pattern.sourcePos def tpe(implicit ctx: Context): Type = pattern.tpe.stripTypeVar } diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/SymbolOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/SymbolOpsImpl.scala index fcf3da51314a..9f57f543effe 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/SymbolOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/SymbolOpsImpl.scala @@ -26,7 +26,7 @@ trait SymbolOpsImpl extends scala.tasty.reflect.SymbolOps with CoreImpl { def name(implicit ctx: Context): String = symbol.name.toString def fullName(implicit ctx: Context): String = symbol.fullName.toString - def pos(implicit ctx: Context): Position = symbol.pos + def pos(implicit ctx: Context): Position = symbol.sourcePos def owner(implicit ctx: Context): Symbol = symbol.owner diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala index fbcf34e3baa5..69788d1efcb4 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TreeOpsImpl.scala @@ -10,7 +10,7 @@ import dotty.tools.dotc.tastyreflect.FromSymbol.{definitionFromSym, packageDefFr trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers { def TreeDeco(tree: Tree): TreeAPI = new TreeAPI { - def pos(implicit ctx: Context): Position = tree.pos + def pos(implicit ctx: Context): Position = tree.sourcePos def symbol(implicit ctx: Context): Symbol = tree.symbol } @@ -353,7 +353,7 @@ trait TreeOpsImpl extends scala.tasty.reflect.TreeOps with CoreImpl with Helpers def TermDeco(term: Term): TermAPI = new TermAPI { import tpd._ - def pos(implicit ctx: Context): Position = term.pos + def pos(implicit ctx: Context): Position = term.sourcePos def tpe(implicit ctx: Context): Type = term.tpe def underlyingArgument(implicit ctx: Context): Term = term.underlyingArgument def underlying(implicit ctx: Context): Term = term.underlying diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala index 2bf439ba3d28..cb3861c31af2 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala @@ -9,7 +9,7 @@ import dotty.tools.dotc.core.{Contexts, Types} trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps with CoreImpl { def TypeTreeDeco(tpt: TypeTree): TypeTreeAPI = new TypeTreeAPI { - def pos(implicit ctx: Context): Position = tpt.pos + def pos(implicit ctx: Context): Position = tpt.sourcePos def symbol(implicit ctx: Context): Symbol = tpt.symbol def tpe(implicit ctx: Context): Type = tpt.tpe.stripTypeVar } diff --git a/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala b/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala index 03782a0436bc..cfc03a0f31e6 100644 --- a/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala +++ b/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala @@ -143,7 +143,7 @@ abstract class AccessProxies { def accessorIfNeeded(tree: Tree)(implicit ctx: Context): Tree = tree match { case tree: RefTree if needsAccessor(tree.symbol) => if (tree.symbol.isConstructor) { - ctx.error("Implementation restriction: cannot use private constructors in inlineable methods", tree.pos) + ctx.error("Implementation restriction: cannot use private constructors in inlineable methods", tree.sourcePos) tree // TODO: create a proper accessor for the private constructor } else useAccessor(tree) diff --git a/compiler/src/dotty/tools/dotc/transform/Bridges.scala b/compiler/src/dotty/tools/dotc/transform/Bridges.scala index ca9550f09400..eba3b5f9a378 100644 --- a/compiler/src/dotty/tools/dotc/transform/Bridges.scala +++ b/compiler/src/dotty/tools/dotc/transform/Bridges.scala @@ -9,6 +9,7 @@ import ast.untpd import collection.{mutable, immutable} import ShortcutImplicits._ import util.Positions.Position +import util.SourcePosition /** A helper class for generating bridge methods in class `root`. */ class Bridges(root: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Context) { @@ -40,8 +41,8 @@ class Bridges(root: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont private val bridgesScope = newScope private val bridgeTarget = newMutableSymbolMap[Symbol] - def bridgePosFor(member: Symbol): Position = - if (member.owner == root && member.pos.exists) member.pos else root.pos + def bridgePosFor(member: Symbol): SourcePosition = + (if (member.owner == root && member.pos.exists) member else root).sourcePos /** Add a bridge between `member` and `other`, where `member` overrides `other` * before erasure, if the following conditions are satisfied. @@ -85,7 +86,7 @@ class Bridges(root: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont owner = root, flags = (member.flags | Method | Bridge | Artifact) &~ (Accessor | ParamAccessor | CaseAccessor | Deferred | Lazy | Module), - coord = bridgePosFor(member)).enteredAfter(thisPhase).asTerm + coord = bridgePosFor(member).pos).enteredAfter(thisPhase).asTerm ctx.debuglog( i"""generating bridge from ${other.showLocated}: ${other.info} diff --git a/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala b/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala index 32dc78e0a81c..bd109c251b52 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala @@ -33,26 +33,26 @@ class CheckStatic extends MiniPhase { for(defn <- defns) { if (defn.symbol.hasAnnotation(ctx.definitions.ScalaStaticAnnot)) { if(!ctx.owner.is(Module)) { - ctx.error(StaticFieldsOnlyAllowedInObjects(defn.symbol), defn.pos) + ctx.error(StaticFieldsOnlyAllowedInObjects(defn.symbol), defn.sourcePos) } if (defn.isInstanceOf[ValDef] && hadNonStaticField) { - ctx.error(StaticFieldsShouldPrecedeNonStatic(defn.symbol, defns), defn.pos) + ctx.error(StaticFieldsShouldPrecedeNonStatic(defn.symbol, defns), defn.sourcePos) } val companion = ctx.owner.companionClass def clashes = companion.asClass.membersNamed(defn.name) if (!companion.exists) { - ctx.error(MissingCompanionForStatic(defn.symbol), defn.pos) + ctx.error(MissingCompanionForStatic(defn.symbol), defn.sourcePos) } else if (clashes.exists) { - ctx.error(MemberWithSameNameAsStatic(), defn.pos) + ctx.error(MemberWithSameNameAsStatic(), defn.sourcePos) } else if (defn.symbol.is(Flags.Mutable) && companion.is(Flags.Trait)) { - ctx.error(TraitCompanionWithMutableStatic(), defn.pos) + ctx.error(TraitCompanionWithMutableStatic(), defn.sourcePos) } else if (defn.symbol.is(Flags.Lazy)) { - ctx.error(LazyStaticField(), defn.pos) + ctx.error(LazyStaticField(), defn.sourcePos) } else if (defn.symbol.allOverriddenSymbols.nonEmpty) { - ctx.error(StaticOverridingNonStaticMembers(), defn.pos) + ctx.error(StaticOverridingNonStaticMembers(), defn.sourcePos) } } else hadNonStaticField = hadNonStaticField || defn.isInstanceOf[ValDef] diff --git a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala index 8942d7ae6fcb..6679074bf0e3 100644 --- a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala +++ b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala @@ -11,7 +11,7 @@ import dotty.tools.dotc.core.Contexts.Context import Types._ import Decorators._ import StdNames._ -import dotty.tools.dotc.util.Positions.Position +import dotty.tools.dotc.util.SourcePosition import dotty.tools.dotc.config.JavaPlatform class CollectEntryPoints extends MiniPhase { @@ -38,10 +38,10 @@ class CollectEntryPoints extends MiniPhase { } def isJavaEntryPoint(sym: Symbol)(implicit ctx: Context): Boolean = { - def fail(msg: String, pos: Position = sym.pos) = { - ctx.warning(sym.name + - s" has a main method with parameter type Array[String], but ${sym.fullName} will not be a runnable program.\n Reason: $msg", - sourcePos(sym.pos) + def fail(msg: String, pos: SourcePosition = sym.sourcePos) = { + ctx.warning( + i"""${sym.name} has a main method with parameter type Array[String], but ${sym.fullName} will not be a runnable program. + |Reason: $msg""", sym.sourcePos // TODO: make this next claim true, if possible // by generating valid main methods as static in module classes // not sure what the jvm allows here @@ -80,11 +80,11 @@ class CollectEntryPoints extends MiniPhase { fail("main methods cannot be generic.") case t: MethodType => if (t.resultType :: t.paramInfos exists (_.typeSymbol.isAbstractType)) - fail("main methods cannot refer to type parameters or abstract types.", m.symbol.pos) + fail("main methods cannot refer to type parameters or abstract types.", m.symbol.sourcePos) else - ctx.platform.isMainMethod(m.symbol) || fail("main method must have exact signature (Array[String])Unit", m.symbol.pos) + ctx.platform.isMainMethod(m.symbol) || fail("main method must have exact signature (Array[String])Unit", m.symbol.sourcePos) case tp => - fail(s"don't know what this is: $tp", m.symbol.pos) + fail(s"don't know what this is: $tp", m.symbol.sourcePos) } } } diff --git a/compiler/src/dotty/tools/dotc/transform/Constructors.scala b/compiler/src/dotty/tools/dotc/transform/Constructors.scala index 8ebb4976a9a1..778eb842ad5b 100644 --- a/compiler/src/dotty/tools/dotc/transform/Constructors.scala +++ b/compiler/src/dotty/tools/dotc/transform/Constructors.scala @@ -225,7 +225,7 @@ class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase = Nil } else { if (acc.hasAnnotation(defn.TransientParamAnnot)) - ctx.error(em"transient parameter $acc is retained as field in class ${acc.owner}", acc.pos) + ctx.error(em"transient parameter $acc is retained as field in class ${acc.owner}", acc.sourcePos) val target = if (acc.is(Method)) acc.field else acc if (!target.exists) Nil // this case arises when the parameter accessor is an alias else { diff --git a/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala b/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala index d9327f53d145..ba9de3dacaaf 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala @@ -108,7 +108,7 @@ class ElimErasedValueType extends MiniPhase with InfoTransformer { |$sym1: $info1 in ${sym1.owner} and |$sym2: $info2 in ${sym2.owner} |have same type after erasure: $info""", - root.pos) + root.sourcePos) } val earlyCtx = ctx.withPhase(ctx.elimRepeatedPhase.next) while (opc.hasNext) { diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index bafea790faba..00da443666f3 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -322,7 +322,7 @@ object Erasure { private def checkNotErased(tree: Tree)(implicit ctx: Context): tree.type = { if (tree.symbol.isEffectivelyErased && !ctx.mode.is(Mode.Type)) - ctx.error(em"${tree.symbol} is declared as erased, but is in fact used", tree.pos) + ctx.error(em"${tree.symbol} is declared as erased, but is in fact used", tree.sourcePos) tree } diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala index 8e207d31ef5f..27bd533b49f5 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala @@ -39,13 +39,13 @@ class ExpandSAMs extends MiniPhase { case tpe if defn.isImplicitFunctionType(tpe) => tree case tpe @ SAMType(_) if tpe.isRef(defn.PartialFunctionClass) => - val tpe1 = checkRefinements(tpe, fn.pos) + val tpe1 = checkRefinements(tpe, fn) toPartialFunction(tree, tpe1) case tpe @ SAMType(_) if isPlatformSam(tpe.classSymbol.asClass) => - checkRefinements(tpe, fn.pos) + checkRefinements(tpe, fn) tree case tpe => - val tpe1 = checkRefinements(tpe, fn.pos) + val tpe1 = checkRefinements(tpe, fn) val Seq(samDenot) = tpe1.abstractTermMembers.filter(!_.symbol.isSuperAccessor) cpy.Block(tree)(stats, AnonClass(tpe1 :: Nil, fn.symbol.asTerm :: Nil, samDenot.symbol.asTerm.name :: Nil)) @@ -161,16 +161,16 @@ class ExpandSAMs extends MiniPhase { case _ => val found = tpe.baseType(defn.FunctionClass(1)) - ctx.error(TypeMismatch(found, tpe), tree.pos) + ctx.error(TypeMismatch(found, tpe), tree.sourcePos) tree } } - private def checkRefinements(tpe: Type, pos: Position)(implicit ctx: Context): Type = tpe.dealias match { + private def checkRefinements(tpe: Type, tree: Tree)(implicit ctx: Context): Type = tpe.dealias match { case RefinedType(parent, name, _) => if (name.isTermName && tpe.member(name).symbol.ownersIterator.isEmpty) // if member defined in the refinement - ctx.error("Lambda does not define " + name, pos) - checkRefinements(parent, pos) + ctx.error("Lambda does not define " + name, tree.sourcePos) + checkRefinements(parent, tree) case tpe => tpe } diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index 6a7e041e690a..f64a8ed55f37 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -118,7 +118,7 @@ class ExplicitOuter extends MiniPhase with InfoTransformer { thisPhase => if (tree.tpt ne EmptyTree) { val cls = tree.tpt.asInstanceOf[TypeTree].tpe.classSymbol if (cls.exists && hasOuter(cls.asClass)) - ctx.error("Not a single abstract method type, requires an outer pointer", tree.pos) + ctx.error("Not a single abstract method type, requires an outer pointer", tree.sourcePos) } tree } diff --git a/compiler/src/dotty/tools/dotc/transform/MacroTransform.scala b/compiler/src/dotty/tools/dotc/transform/MacroTransform.scala index e8bb69a12509..042e400bc3d0 100644 --- a/compiler/src/dotty/tools/dotc/transform/MacroTransform.scala +++ b/compiler/src/dotty/tools/dotc/transform/MacroTransform.scala @@ -63,7 +63,7 @@ abstract class MacroTransform extends Phase { } catch { case ex: TypeError => - ctx.error(ex.toMessage, tree.pos) + ctx.error(ex.toMessage, tree.sourcePos) tree } diff --git a/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala b/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala index 2af1f915265a..c6f0cebc876f 100644 --- a/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala +++ b/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala @@ -170,7 +170,7 @@ class MegaPhase(val miniPhases: Array[MiniPhase]) extends Phase { } catch { case ex: TypeError => - ctx.error(ex.toMessage, tree.pos) + ctx.error(ex.toMessage, tree.sourcePos) tree } def goUnnamed(tree: Tree, start: Int) = @@ -205,7 +205,7 @@ class MegaPhase(val miniPhases: Array[MiniPhase]) extends Phase { } catch { case ex: TypeError => - ctx.error(ex.toMessage, tree.pos) + ctx.error(ex.toMessage, tree.sourcePos) tree } if (tree.isInstanceOf[NameTree]) goNamed(tree, start) else goUnnamed(tree, start) diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala index 424b1fbab5b7..2da2f39d6bb0 100644 --- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala +++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala @@ -211,7 +211,7 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase => ctx.error( em"""parameterized $mixin is indirectly implemented, |needs to be implemented directly so that arguments can be passed""", - cls.pos) + cls.sourcePos) EmptyTree } diff --git a/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala b/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala index 9f73b4e53ae0..052216bcfb5e 100644 --- a/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala +++ b/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala @@ -134,7 +134,7 @@ object OverridingPairs { case ex: TypeError => // See neg/i1750a for an example where a cyclic error can arise. // The root cause in this example is an illegal "override" of an inner trait - ctx.error(ex.toMessage, base.pos) + ctx.error(ex.toMessage, base.sourcePos) } } else { curEntry = curEntry.prev diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index e470af9c43cb..60afd0a7b313 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -926,7 +926,7 @@ object PatternMatcher { patmatch.println(i"original types: ${typesInCases(original.cases)}%, %") patmatch.println(i"switch types : ${typesInCases(resultCases)}%, %") patmatch.println(i"tree = $result") - ctx.warning(UnableToEmitSwitch(numTypes(original.cases) < MinSwitchCases), original.pos) + ctx.warning(UnableToEmitSwitch(numTypes(original.cases) < MinSwitchCases), original.sourcePos) } case _ => } diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index 6cb00fad258f..0d2352372b29 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -199,7 +199,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase case tree @ Select(qual, name) => handleMeta(tree.symbol) if (name.isTypeName) { - Checking.checkRealizable(qual.tpe, qual.pos.focus) + Checking.checkRealizable(qual.tpe, qual.sourcePos.focus) super.transform(tree)(ctx.addMode(Mode.Type)) } else @@ -219,7 +219,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase case Select(nu: New, nme.CONSTRUCTOR) if isCheckable(nu) => // need to check instantiability here, because the type of the New itself // might be a type constructor. - Checking.checkInstantiable(tree.tpe, nu.pos) + Checking.checkInstantiable(tree.tpe, nu.sourcePos) withNoCheckNews(nu :: Nil)(super.transform(app)) case _ => super.transform(app) @@ -266,10 +266,10 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase } processMemberDef(super.transform(tree)) case tree: New if isCheckable(tree) => - Checking.checkInstantiable(tree.tpe, tree.pos) + Checking.checkInstantiable(tree.tpe, tree.sourcePos) super.transform(tree) case tree: Closure if !tree.tpt.isEmpty => - Checking.checkRealizable(tree.tpt.tpe, tree.pos, "SAM type") + Checking.checkRealizable(tree.tpt.tpe, tree.sourcePos, "SAM type") super.transform(tree) case tree @ Annotated(annotated, annot) => cpy.Annotated(tree)(transform(annotated), transformAnnot(annot)) @@ -277,7 +277,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase Checking.checkAppliedType(tree, boundsCheck = !ctx.mode.is(Mode.Pattern)) super.transform(tree) case SingletonTypeTree(ref) => - Checking.checkRealizable(ref.tpe, ref.pos.focus) + Checking.checkRealizable(ref.tpe, ref.sourcePos.focus) super.transform(tree) case tree: TypeTree => tree.withType( @@ -289,7 +289,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase case tree: AndTypeTree => // Ideally, this should be done by Typer, but we run into cyclic references // when trying to typecheck self types which are intersections. - Checking.checkNonCyclicInherited(tree.tpe, tree.left.tpe :: tree.right.tpe :: Nil, EmptyScope, tree.pos) + Checking.checkNonCyclicInherited(tree.tpe, tree.left.tpe :: tree.right.tpe :: Nil, EmptyScope, tree.sourcePos) super.transform(tree) case tree: LambdaTypeTree => VarianceChecker.checkLambda(tree) @@ -300,9 +300,9 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase def checkIdent(ident: untpd.Ident): Unit = { val name = ident.name.asTermName if (name != nme.WILDCARD && !exprTpe.member(name).exists && !exprTpe.member(name.toTypeName).exists) - ctx.error(NotAMember(exprTpe, name, "value"), ident.pos) + ctx.error(NotAMember(exprTpe, name, "value"), ident.sourcePos) if (seen(ident.name)) - ctx.error(ImportRenamedTwice(ident), ident.pos) + ctx.error(ImportRenamedTwice(ident), ident.sourcePos) seen += ident.name } selectors.foreach { diff --git a/compiler/src/dotty/tools/dotc/transform/ProtectedAccessors.scala b/compiler/src/dotty/tools/dotc/transform/ProtectedAccessors.scala index dadd92fb11a8..59e38f232d6e 100644 --- a/compiler/src/dotty/tools/dotc/transform/ProtectedAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/ProtectedAccessors.scala @@ -60,7 +60,7 @@ class ProtectedAccessors extends MiniPhase { val curCls = ctx.owner.enclosingClass transforms.println(i"${curCls.ownersIterator.toList}%, %") ctx.error(i"illegal access to protected ${reference.symbol.showLocated} from $curCls", - reference.pos) + reference.sourcePos) reference } } diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index 5bd039fb2629..74d8f2cf7a20 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicer.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicer.scala @@ -142,7 +142,7 @@ object Splicer { } protected def unexpectedTree(tree: Tree)(implicit env: Env): Object = - throw new StopInterpretation("Unexpected tree could not be interpreted: " + tree, tree.pos) + throw new StopInterpretation("Unexpected tree could not be interpreted: " + tree, tree.sourcePos) private def loadModule(sym: Symbol): Object = { if (sym.owner.is(Package)) { diff --git a/compiler/src/dotty/tools/dotc/transform/Staging.scala b/compiler/src/dotty/tools/dotc/transform/Staging.scala index 6a04d9bc01fa..cc194fc3c903 100644 --- a/compiler/src/dotty/tools/dotc/transform/Staging.scala +++ b/compiler/src/dotty/tools/dotc/transform/Staging.scala @@ -6,6 +6,7 @@ import Decorators._, Flags._, Types._, Contexts._, Symbols._, Constants._ import ast.Trees._ import ast.{TreeTypeMap, untpd} import util.Positions._ +import util.SourcePosition import tasty.TreePickler.Hole import SymUtils._ import NameKinds._ @@ -257,14 +258,14 @@ class Staging extends MacroTransformWithImplicits { * @return Some(msg) if unsuccessful where `msg` is a potentially empty error message * to be added to the "inconsistent phase" message. */ - def tryHeal(tp: Type, pos: Position)(implicit ctx: Context): Option[String] = tp match { + def tryHeal(tp: Type, pos: SourcePosition)(implicit ctx: Context): Option[String] = tp match { case tp: TypeRef => if (level == -1) { assert(ctx.inInlineMethod) None } else { val reqType = defn.QuotedTypeType.appliedTo(tp) - val tag = ctx.typer.inferImplicitArg(reqType, pos) + val tag = ctx.typer.inferImplicitArg(reqType, pos.pos) tag.tpe match { case fail: SearchFailureType => Some(i""" @@ -283,7 +284,7 @@ class Staging extends MacroTransformWithImplicits { /** Check reference to `sym` for phase consistency, where `tp` is the underlying type * by which we refer to `sym`. */ - def check(sym: Symbol, tp: Type, pos: Position)(implicit ctx: Context): Unit = { + def check(sym: Symbol, tp: Type, pos: SourcePosition)(implicit ctx: Context): Unit = { val isThis = tp.isInstanceOf[ThisType] def symStr = if (!isThis) sym.show @@ -301,7 +302,7 @@ class Staging extends MacroTransformWithImplicits { } /** Check all named types and this-types in a given type for phase consistency. */ - def checkType(pos: Position)(implicit ctx: Context): TypeAccumulator[Unit] = new TypeAccumulator[Unit] { + def checkType(pos: SourcePosition)(implicit ctx: Context): TypeAccumulator[Unit] = new TypeAccumulator[Unit] { def apply(acc: Unit, tp: Type): Unit = reporting.trace(i"check type level $tp at $level") { tp match { case tp: TypeRef if tp.symbol.isSplice => @@ -314,11 +315,11 @@ class Staging extends MacroTransformWithImplicits { tp } case tp: NamedType => - check(tp.symbol, tp, pos) + check(tp.symbol, tp, tp.symbol.sourcePos) if (!tp.symbol.is(Param)) foldOver(acc, tp) case tp: ThisType => - check(tp.cls, tp, pos) + check(tp.cls, tp, tp.cls.sourcePos) foldOver(acc, tp) case _ => foldOver(acc, tp) @@ -342,15 +343,15 @@ class Staging extends MacroTransformWithImplicits { private def checkLevel(tree: Tree)(implicit ctx: Context): Tree = { tree match { case (_: Ident) | (_: This) => - check(tree.symbol, tree.tpe, tree.pos) + check(tree.symbol, tree.tpe, tree.sourcePos) case (_: UnApply) | (_: TypeTree) => - checkType(tree.pos).apply((), tree.tpe) + checkType(tree.sourcePos).apply((), tree.tpe) case Select(qual, OuterSelectName(_, levels)) => - checkType(tree.pos).apply((), tree.tpe.widen) + checkType(tree.sourcePos).apply((), tree.tpe.widen) case _: Bind => - checkType(tree.pos).apply((), tree.symbol.info) + checkType(tree.sourcePos).apply((), tree.symbol.info) case _: Template => - checkType(tree.pos).apply((), tree.symbol.owner.asClass.givenSelfType) + checkType(tree.sourcePos).apply((), tree.symbol.owner.asClass.givenSelfType) case _ => } tree @@ -441,19 +442,19 @@ class Staging extends MacroTransformWithImplicits { val hole = makeHole(body1, quotes, tpe).withPos(splice.pos) // We do not place add the inline marker for trees that where lifted as they come from the same file as their // enclosing quote. Any intemediate splice will add it's own Inlined node and cancel it before splicig the lifted tree. - // Note that lifted trees are not necessarily expressions and that Inlined nodes are expected to be expressions. + // Note that lifted trees are not necessarily expressions and that Inlined nodes are expected to be expressions. // For example we can have a lifted tree containing the LHS of an assignment (see tests/run-with-compiler/quote-var.scala). if (splice.isType || outer.embedded.isLiftedSymbol(splice.qualifier.symbol)) hole else Inlined(EmptyTree, Nil, hole) } else if (enclosingInlineds.nonEmpty) { // level 0 in an inlined call val spliceCtx = ctx.outer // drop the last `inlineContext` - val pos: SourcePosition = Decorators.sourcePos(enclosingInlineds.head.pos)(spliceCtx) + val pos: SourcePosition = spliceCtx.source.atPos(enclosingInlineds.head.pos) val evaluatedSplice = Splicer.splice(splice.qualifier, pos, macroClassLoader)(spliceCtx).withPos(splice.pos) if (ctx.reporter.hasErrors) splice else transform(evaluatedSplice) } else if (!ctx.owner.isInlineMethod) { // level 0 outside an inline method - ctx.error(i"splice outside quotes or inline method", splice.pos) + ctx.error(i"splice outside quotes or inline method", splice.sourcePos) splice } else if (Splicer.canBeSpliced(splice.qualifier)) { // level 0 inside an inline definition @@ -461,7 +462,9 @@ class Staging extends MacroTransformWithImplicits { splice } else { // level 0 inside an inline definition - ctx.error("Malformed macro call. The contents of the ~ must call a static method and arguments must be quoted or inline.".stripMargin, splice.pos) + ctx.error( + "Malformed macro call. The contents of the ~ must call a static method and arguments must be quoted or inline.".stripMargin, + splice.sourcePos) splice } } @@ -617,7 +620,7 @@ class Staging extends MacroTransformWithImplicits { | | * The contents of the splice must call a static method | * All arguments must be quoted or inline - """.stripMargin, tree.rhs.pos) + """.stripMargin, tree.rhs.sourcePos) EmptyTree } case _ => diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index d647127a68c3..b9061df6ca83 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -81,7 +81,9 @@ class SuperAccessors(thisPhase: DenotTransformer) { superInfo, coord = accPos).enteredAfter(thisPhase) // Diagnostic for SI-7091 if (!accDefs.contains(clazz)) - ctx.error(s"Internal error: unable to store accessor definition in ${clazz}. clazz.hasPackageFlag=${clazz is Package}. Accessor required for ${sel} (${sel.show})", sel.pos) + ctx.error( + s"Internal error: unable to store accessor definition in ${clazz}. clazz.hasPackageFlag=${clazz is Package}. Accessor required for ${sel} (${sel.show})", + sel.sourcePos) else accDefs(clazz) += DefDef(acc, EmptyTree).withPos(accPos) acc } @@ -100,9 +102,9 @@ class SuperAccessors(thisPhase: DenotTransformer) { if (sym.isTerm && !sym.is(Method, butNot = Accessor) && !ctx.owner.is(ParamForwarder)) // ParamForwaders as installed ParamForwarding.scala do use super calls to vals - ctx.error(s"super may be not be used on ${sym.underlyingSymbol}", sel.pos) + ctx.error(s"super may be not be used on ${sym.underlyingSymbol}", sel.sourcePos) else if (isDisallowed(sym)) - ctx.error(s"super not allowed here: use this.${sel.name} instead", sel.pos) + ctx.error(s"super not allowed here: use this.${sel.name} instead", sel.sourcePos) else if (sym is Deferred) { val member = sym.overridingSymbol(clazz.asClass) if (!mix.name.isEmpty || @@ -110,7 +112,7 @@ class SuperAccessors(thisPhase: DenotTransformer) { !((member is AbsOverride) && member.isIncompleteIn(clazz))) ctx.error( i"${sym.showLocated} is accessed from super. It may not be abstract unless it is overridden by a member declared `abstract' and `override'", - sel.pos) + sel.sourcePos) else ctx.log(i"ok super $sel ${sym.showLocated} $member $clazz ${member.isIncompleteIn(clazz)}") } else if (mix.name.isEmpty && !(sym.owner is Trait)) @@ -120,8 +122,7 @@ class SuperAccessors(thisPhase: DenotTransformer) { if ((overriding is (Deferred, butNot = AbsOverride)) && !(overriding.owner is Trait)) ctx.error( s"${sym.showLocated} cannot be directly accessed from ${clazz} because ${overriding.owner} redeclares it as abstract", - sel.pos) - + sel.sourcePos) } if (name.isTermName && mix.name.isEmpty && ((clazz is Trait) || clazz != ctx.owner.enclosingClass || !validCurrentClass)) diff --git a/compiler/src/dotty/tools/dotc/transform/TailRec.scala b/compiler/src/dotty/tools/dotc/transform/TailRec.scala index bc3a251065cf..2c4a70294ad2 100644 --- a/compiler/src/dotty/tools/dotc/transform/TailRec.scala +++ b/compiler/src/dotty/tools/dotc/transform/TailRec.scala @@ -123,7 +123,7 @@ class TailRec extends MiniPhase { // We don't report a new error if failures were reported // during the transformation. if (mandatory && !failureReported) - ctx.error(TailrecNotApplicable(method), method.pos) + ctx.error(TailrecNotApplicable(method), method.sourcePos) tree } @@ -282,7 +282,7 @@ class TailRec extends MiniPhase { def fail(reason: String) = { if (isMandatory) { failureReported = true - ctx.error(s"Cannot rewrite recursive call: $reason", tree.pos) + ctx.error(s"Cannot rewrite recursive call: $reason", tree.sourcePos) } else tailrec.println("Cannot rewrite recursive call at: " + tree.pos + " because: " + reason) diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index 07b71670c5d4..0ec7aa5217e5 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -180,7 +180,7 @@ class TreeChecker extends Phase with SymTransformer { def assertDefined(tree: untpd.Tree)(implicit ctx: Context): Unit = if (tree.symbol.maybeOwner.isTerm) - assert(nowDefinedSyms contains tree.symbol, i"undefined symbol ${tree.symbol} at line " + tree.pos.line) + assert(nowDefinedSyms contains tree.symbol, i"undefined symbol ${tree.symbol} at line " + tree.sourcePos.line) /** assert Java classes are not used as objects */ def assertIdentNotJavaClass(tree: Tree)(implicit ctx: Context): Unit = tree match { diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index da67a64e60ad..22839f9d0ef9 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -165,8 +165,8 @@ object TypeTestsCasts { def unreachable(why: => String) = if (flagUnrelated) - if (inMatch) ctx.error(em"this case is unreachable since $why", expr.pos) - else ctx.warning(em"this will always yield false since $why", expr.pos) + if (inMatch) ctx.error(em"this case is unreachable since $why", expr.sourcePos) + else ctx.warning(em"this will always yield false since $why", expr.sourcePos) /** Are `foundCls` and `testCls` classes that allow checks * whether a test would be always false? @@ -186,7 +186,7 @@ object TypeTestsCasts { def checkSensical: Boolean = if (!isCheckable) true else if (foundCls.isPrimitiveValueClass && !testCls.isPrimitiveValueClass) { - ctx.error("cannot test if value types are references", tree.pos) + ctx.error("cannot test if value types are references", tree.sourcePos) false } else if (!foundCls.derivesFrom(testCls)) { @@ -206,7 +206,7 @@ object TypeTestsCasts { if (expr.tpe <:< testType) if (expr.tpe.isNotNull) { - ctx.warning(TypeTestAlwaysSucceeds(foundCls, testCls), tree.pos) + ctx.warning(TypeTestAlwaysSucceeds(foundCls, testCls), tree.sourcePos) constant(expr, Literal(Constant(true))) } else expr.testNotNull @@ -274,7 +274,7 @@ object TypeTestsCasts { if (sym.isTypeTest) { val argType = tree.args.head.tpe if (!checkable(expr.tpe, argType, tree.pos)) - ctx.warning(i"the type test for $argType cannot be checked at runtime", tree.pos) + ctx.warning(i"the type test for $argType cannot be checked at runtime", tree.sourcePos) transformTypeTest(expr, tree.args.head.tpe, flagUnrelated = true) } else if (sym eq defn.Any_asInstanceOf) diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 42c2580f78c4..57ab59897e73 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -924,7 +924,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { } if (uncovered.nonEmpty) - ctx.warning(PatternMatchExhaustivity(show(Or(uncovered))), sel.pos) + ctx.warning(PatternMatchExhaustivity(show(Or(uncovered))), sel.sourcePos) } private def redundancyCheckable(sel: Tree): Boolean = @@ -973,14 +973,14 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { if (covered == Empty) covered = curr if (isSubspace(covered, prevs)) { - ctx.warning(MatchCaseUnreachable(), pat.pos) + ctx.warning(MatchCaseUnreachable(), pat.sourcePos) } // if last case is `_` and only matches `null`, produce a warning if (i == cases.length - 1 && !isNull(pat) ) { simplify(minus(covered, prevs)) match { case Typ(`nullType`, _) => - ctx.warning(MatchCaseOnlyNullWarning(), pat.pos) + ctx.warning(MatchCaseOnlyNullWarning(), pat.sourcePos) case _ => } diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index fa190d270354..b8def0006d3c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -6,6 +6,7 @@ import core._ import ast.{Trees, tpd, untpd} import util.Positions._ import util.Stats.track +import util.{SourcePosition, NoSourcePosition} import Trees.Untyped import Contexts._ import Flags._ @@ -37,7 +38,7 @@ object Applications { def extractorMember(tp: Type, name: Name)(implicit ctx: Context): SingleDenotation = tp.member(name).suchThat(_.info.isParameterless) - def extractorMemberType(tp: Type, name: Name, errorPos: Position = NoPosition)(implicit ctx: Context): Type = { + def extractorMemberType(tp: Type, name: Name, errorPos: SourcePosition)(implicit ctx: Context): Type = { val ref = extractorMember(tp, name) if (ref.isOverloaded) errorType(i"Overloaded reference to $ref is not allowed in extractor", errorPos) @@ -48,18 +49,18 @@ object Applications { * for a pattern with `numArgs` subpatterns? * This is the case of `tp` has members `_1` to `_N` where `N == numArgs`. */ - def isProductMatch(tp: Type, numArgs: Int)(implicit ctx: Context): Boolean = - numArgs > 0 && productArity(tp) == numArgs + def isProductMatch(tp: Type, numArgs: Int, errorPos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Boolean = + numArgs > 0 && productArity(tp, errorPos) == numArgs /** Does `tp` fit the "get match" conditions as an unapply result type? * This is the case of `tp` has a `get` member as well as a * parameterless `isEmpty` member of result type `Boolean`. */ - def isGetMatch(tp: Type, errorPos: Position = NoPosition)(implicit ctx: Context): Boolean = + def isGetMatch(tp: Type, errorPos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Boolean = extractorMemberType(tp, nme.isEmpty, errorPos).isRef(defn.BooleanClass) && extractorMemberType(tp, nme.get, errorPos).exists - def productSelectorTypes(tp: Type, errorPos: Position = NoPosition)(implicit ctx: Context): List[Type] = { + def productSelectorTypes(tp: Type, errorPos: SourcePosition)(implicit ctx: Context): List[Type] = { def tupleSelectors(n: Int, tp: Type): List[Type] = { val sel = extractorMemberType(tp, nme.selectorName(n), errorPos) // extractorMemberType will return NoType if this is the tail of tuple with an unknown tail @@ -75,8 +76,8 @@ object Applications { genTupleSelectors(0, tp) } - def productArity(tp: Type)(implicit ctx: Context): Int = - if (defn.isProductSubType(tp)) productSelectorTypes(tp).size else -1 + def productArity(tp: Type, errorPos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Int = + if (defn.isProductSubType(tp)) productSelectorTypes(tp, errorPos).size else -1 def productSelectors(tp: Type)(implicit ctx: Context): List[Symbol] = { val sels = for (n <- Iterator.from(0)) yield @@ -84,14 +85,14 @@ object Applications { sels.takeWhile(_.exists).toList } - def getUnapplySelectors(tp: Type, args: List[untpd.Tree], pos: Position = NoPosition)(implicit ctx: Context): List[Type] = + def getUnapplySelectors(tp: Type, args: List[untpd.Tree], pos: SourcePosition)(implicit ctx: Context): List[Type] = if (args.length > 1 && !(tp.derivesFrom(defn.SeqClass))) { val sels = productSelectorTypes(tp, pos) if (sels.length == args.length) sels else tp :: Nil } else tp :: Nil - def unapplyArgs(unapplyResult: Type, unapplyFn: Tree, args: List[untpd.Tree], pos: Position = NoPosition)(implicit ctx: Context): List[Type] = { + def unapplyArgs(unapplyResult: Type, unapplyFn: Tree, args: List[untpd.Tree], pos: SourcePosition)(implicit ctx: Context): List[Type] = { val unapplyName = unapplyFn.symbol.name def seqSelector = defn.RepeatedParamType.appliedTo(unapplyResult.elemType :: Nil) @@ -149,14 +150,14 @@ object Applications { } else { assert(unapplyName == nme.unapply) - if (isProductMatch(unapplyResult, args.length)) - productSelectorTypes(unapplyResult) + if (isProductMatch(unapplyResult, args.length, pos)) + productSelectorTypes(unapplyResult, pos) else if (isGetMatch(unapplyResult, pos)) getUnapplySelectors(getTp, args, pos) else if (unapplyResult.widenSingleton isRef defn.BooleanClass) Nil else if (defn.isProductSubType(unapplyResult)) - productSelectorTypes(unapplyResult) + productSelectorTypes(unapplyResult, pos) // this will cause a "wrong number of arguments in pattern" error later on, // which is better than the message in `fail`. else fail @@ -239,7 +240,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => /** Signal failure with given message at position of the application itself */ protected def fail(msg: => Message): Unit - protected def appPos: Position + protected def appPos: SourcePosition /** The current function part, which might be affected by lifting. */ @@ -588,7 +589,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => ok = false def fail(msg: => Message): Unit = ok = false - def appPos: Position = NoPosition + def appPos: SourcePosition = NoSourcePosition lazy val normalizedFun: Tree = ref(methRef) init() } @@ -647,15 +648,15 @@ trait Applications extends Compatibility { self: Typer with Dynamic => def harmonizeArgs(args: List[TypedArg]): List[Tree] = harmonize(args) - override def appPos: Position = app.pos + override def appPos: SourcePosition = app.sourcePos def fail(msg: => Message, arg: Trees.Tree[T]): Unit = { - ctx.error(msg, arg.pos) + ctx.error(msg, arg.sourcePos) ok = false } def fail(msg: => Message): Unit = { - ctx.error(msg, app.pos) + ctx.error(msg, app.sourcePos) ok = false } @@ -906,7 +907,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => if (typedArgs.length <= pt.paramInfos.length && !isNamed) if (typedFn.symbol == defn.Predef_classOf && typedArgs.nonEmpty) { val arg = typedArgs.head - checkClassType(arg.tpe, arg.pos, traitReq = false, stablePrefixReq = false) + checkClassType(arg.tpe, arg.sourcePos, traitReq = false, stablePrefixReq = false) } case _ => } @@ -1065,7 +1066,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => unapp.println(TypeComparer.explained(implicit ctx => unapplyArgType <:< selType)) errorType( ex"Pattern type $unapplyArgType is neither a subtype nor a supertype of selector type $selType", - tree.pos) + tree.sourcePos) } val dummyArg = dummyTreeOfType(ownType) val unapplyApp = typedExpr(untpd.TypedSplice(Apply(unapplyFn, dummyArg :: Nil))) @@ -1076,7 +1077,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => case _ => Nil.assertingErrorsReported } - var argTypes = unapplyArgs(unapplyApp.tpe, unapplyFn, args, tree.pos) + var argTypes = unapplyArgs(unapplyApp.tpe, unapplyFn, args, tree.sourcePos) for (argType <- argTypes) assert(!argType.isInstanceOf[TypeBounds], unapplyApp.tpe.show) val bunchedArgs = if (argTypes.nonEmpty && argTypes.last.isRepeatedParam) @@ -1092,7 +1093,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => else args if (argTypes.length != bunchedArgs.length) { - ctx.error(UnapplyInvalidNumberOfArguments(qual, argTypes), tree.pos) + ctx.error(UnapplyInvalidNumberOfArguments(qual, argTypes), tree.sourcePos) argTypes = argTypes.take(args.length) ++ List.fill(argTypes.length - args.length)(WildcardType) } @@ -1678,7 +1679,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => typed(untpd.Apply(core, untpd.TypedSplice(receiver) :: Nil), pt1, ctx.typerState.ownedVars)( ctx.addMode(Mode.FixedQualifier)) if (!app.symbol.is(Extension)) - ctx.error(em"not an extension method: $methodRef", receiver.pos) + ctx.error(em"not an extension method: $methodRef", receiver.sourcePos) app } } diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 8293e0a99ee0..6591339ab949 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -17,7 +17,7 @@ import Scopes._ import CheckRealizable._ import ErrorReporting.errorTree -import util.Positions._ +import util.SourcePosition import transform.SymUtils._ import Decorators._ import ErrorReporting.{err, errorType} @@ -41,13 +41,13 @@ object Checking { (args, boundss).zipped.foreach { (arg, bound) => if (!bound.isLambdaSub && !arg.tpe.hasSimpleKind) { // see MissingTypeParameterFor - ctx.error(ex"missing type parameter(s) for $arg", arg.pos) + ctx.error(ex"missing type parameter(s) for $arg", arg.sourcePos) } } for ((arg, which, bound) <- ctx.boundsViolations(args, boundss, instantiate)) ctx.error( DoesNotConformToBound(arg.tpe, which, bound)(err), - arg.pos.focus) + arg.sourcePos.focus) } /** Check that type arguments `args` conform to corresponding bounds in `tl` @@ -79,7 +79,7 @@ object Checking { HKTypeLambda.fromParams(tparams, bound).appliedTo(args) if (boundsCheck) checkBounds(orderedArgs, bounds, instantiate) - def checkWildcardApply(tp: Type, pos: Position): Unit = tp match { + def checkWildcardApply(tp: Type, pos: SourcePosition): Unit = tp match { case tp @ AppliedType(tycon, args) => if (tycon.isLambdaSub && args.exists(_.isInstanceOf[TypeBounds])) ctx.errorOrMigrationWarning( @@ -88,7 +88,7 @@ object Checking { case _ => } def checkValidIfApply(implicit ctx: Context): Unit = - checkWildcardApply(tycon.tpe.appliedTo(args.map(_.tpe)), tree.pos) + checkWildcardApply(tycon.tpe.appliedTo(args.map(_.tpe)), tree.sourcePos) checkValidIfApply(ctx.addMode(Mode.AllowLambdaWildcardApply)) } @@ -118,7 +118,7 @@ object Checking { /** Check that `tp` refers to a nonAbstract class * and that the instance conforms to the self type of the created class. */ - def checkInstantiable(tp: Type, pos: Position)(implicit ctx: Context): Unit = + def checkInstantiable(tp: Type, pos: SourcePosition)(implicit ctx: Context): Unit = tp.underlyingClassRef(refinementOK = false) match { case tref: TypeRef => val cls = tref.symbol @@ -136,7 +136,7 @@ object Checking { } /** Check that type `tp` is realizable. */ - def checkRealizable(tp: Type, pos: Position, what: String = "path")(implicit ctx: Context): Unit = { + def checkRealizable(tp: Type, pos: SourcePosition, what: String = "path")(implicit ctx: Context): Unit = { val rstatus = realizability(tp) if (rstatus ne Realizable) ctx.errorOrMigrationWarning(em"$tp is not a legal $what\nsince it${rstatus.msg}", pos) @@ -270,7 +270,7 @@ object Checking { catch { case ex: CyclicReference => if (reportErrors) { - errorType(i"illegal cyclic reference: ${checker.where} ${checker.lastChecked} of $sym refers back to the type itself", sym.pos) + errorType(i"illegal cyclic reference: ${checker.where} ${checker.lastChecked} of $sym refers back to the type itself", sym.sourcePos) } else info } @@ -288,7 +288,7 @@ object Checking { def checkRefinementNonCyclic(refinement: Tree, refineCls: ClassSymbol, seen: mutable.Set[Symbol]) (implicit ctx: Context): Unit = { def flag(what: String, tree: Tree) = - ctx.warning(i"$what reference in refinement is deprecated", tree.pos) + ctx.warning(i"$what reference in refinement is deprecated", tree.sourcePos) def forwardRef(tree: Tree) = flag("forward", tree) def selfRef(tree: Tree) = flag("self", tree) val checkTree = new TreeAccumulator[Unit] { @@ -332,7 +332,7 @@ object Checking { * unless a type with the same name aleadry appears in `decls`. * @return true iff no cycles were detected */ - def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, pos: Position)(implicit ctx: Context): Unit = { + def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, pos: SourcePosition)(implicit ctx: Context): Unit = { def qualifies(sym: Symbol) = sym.name.isTypeName && !sym.is(Private) val abstractTypeNames = for (parent <- parents; mbr <- parent.abstractTypeMembers if qualifies(mbr.symbol)) @@ -357,7 +357,7 @@ object Checking { /** Check that symbol's definition is well-formed. */ def checkWellFormed(sym: Symbol)(implicit ctx: Context): Unit = { - def fail(msg: Message) = ctx.error(msg, sym.pos) + def fail(msg: Message) = ctx.error(msg, sym.sourcePos) def checkWithDeferred(flag: FlagSet) = if (sym.is(flag)) @@ -442,7 +442,7 @@ object Checking { * * @return The `info` of `sym`, with problematic aliases expanded away. */ - def checkNoPrivateLeaks(sym: Symbol, pos: Position)(implicit ctx: Context): Type = { + def checkNoPrivateLeaks(sym: Symbol, pos: SourcePosition)(implicit ctx: Context): Type = { class NotPrivate extends TypeMap { var errors: List[() => String] = Nil @@ -511,25 +511,25 @@ object Checking { def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context): Unit = { def checkValueClassMember(stat: Tree) = stat match { case _: TypeDef if stat.symbol.isClass => - ctx.error(ValueClassesMayNotDefineInner(clazz, stat.symbol), stat.pos) + ctx.error(ValueClassesMayNotDefineInner(clazz, stat.symbol), stat.sourcePos) case _: ValDef if !stat.symbol.is(ParamAccessor) => - ctx.error(ValueClassesMayNotDefineNonParameterField(clazz, stat.symbol), stat.pos) + ctx.error(ValueClassesMayNotDefineNonParameterField(clazz, stat.symbol), stat.sourcePos) case _: DefDef if stat.symbol.isConstructor => - ctx.error(ValueClassesMayNotDefineASecondaryConstructor(clazz, stat.symbol), stat.pos) + ctx.error(ValueClassesMayNotDefineASecondaryConstructor(clazz, stat.symbol), stat.sourcePos) case _: MemberDef | _: Import | EmptyTree => // ok case _ => - ctx.error(ValueClassesMayNotContainInitalization(clazz), stat.pos) + ctx.error(ValueClassesMayNotContainInitalization(clazz), stat.sourcePos) } if (isDerivedValueClass(clazz)) { if (clazz.is(Trait)) - ctx.error(CannotExtendAnyVal(clazz), clazz.pos) + ctx.error(CannotExtendAnyVal(clazz), clazz.sourcePos) if (clazz.is(Abstract)) - ctx.error(ValueClassesMayNotBeAbstract(clazz), clazz.pos) + ctx.error(ValueClassesMayNotBeAbstract(clazz), clazz.sourcePos) if (!clazz.isStatic) - ctx.error(ValueClassesMayNotBeContainted(clazz), clazz.pos) + ctx.error(ValueClassesMayNotBeContainted(clazz), clazz.sourcePos) if (isCyclic(clazz.asClass)) - ctx.error(ValueClassesMayNotWrapItself(clazz), clazz.pos) + ctx.error(ValueClassesMayNotWrapItself(clazz), clazz.sourcePos) else { val clParamAccessors = clazz.asClass.paramAccessors.filter { param => param.isTerm && !param.is(Flags.Accessor) @@ -537,17 +537,17 @@ object Checking { clParamAccessors match { case param :: params => if (param.is(Mutable)) - ctx.error(ValueClassParameterMayNotBeAVar(clazz, param), param.pos) + ctx.error(ValueClassParameterMayNotBeAVar(clazz, param), param.sourcePos) if (param.info.isInstanceOf[ExprType]) - ctx.error(ValueClassParameterMayNotBeCallByName(clazz, param), param.pos) + ctx.error(ValueClassParameterMayNotBeCallByName(clazz, param), param.sourcePos) if (param.is(Erased)) - ctx.error("value class first parameter cannot be `erased`", param.pos) + ctx.error("value class first parameter cannot be `erased`", param.sourcePos) else { for (p <- params if !p.is(Erased)) - ctx.error("value class can only have one non `erased` parameter", p.pos) + ctx.error("value class can only have one non `erased` parameter", p.sourcePos) } case Nil => - ctx.error(ValueClassNeedsOneValParam(clazz), clazz.pos) + ctx.error(ValueClassNeedsOneValParam(clazz), clazz.sourcePos) } } stats.foreach(checkValueClassMember) @@ -562,7 +562,7 @@ trait Checking { def checkNonCyclic(sym: Symbol, info: TypeBounds, reportErrors: Boolean)(implicit ctx: Context): Type = Checking.checkNonCyclic(sym, info, reportErrors) - def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, pos: Position)(implicit ctx: Context): Unit = + def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, pos: SourcePosition)(implicit ctx: Context): Unit = Checking.checkNonCyclicInherited(joint, parents, decls, pos) /** Check that Java statics and packages can only be used in selections. @@ -572,17 +572,17 @@ trait Checking { val sym = tree.tpe.termSymbol // The check is avoided inside Java compilation units because it always fails // on the singleton type Module.type. - if ((sym is Package) || ((sym is JavaModule) && !ctx.compilationUnit.isJava)) ctx.error(JavaSymbolIsNotAValue(sym), tree.pos) + if ((sym is Package) || ((sym is JavaModule) && !ctx.compilationUnit.isJava)) ctx.error(JavaSymbolIsNotAValue(sym), tree.sourcePos) } tree } /** Check that type `tp` is stable. */ - def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit = + def checkStable(tp: Type, pos: SourcePosition)(implicit ctx: Context): Unit = if (!tp.isStable) ctx.error(ex"$tp is not stable", pos) /** Check that all type members of `tp` have realizable bounds */ - def checkRealizableBounds(cls: Symbol, pos: Position)(implicit ctx: Context): Unit = { + def checkRealizableBounds(cls: Symbol, pos: SourcePosition)(implicit ctx: Context): Unit = { val rstatus = boundsRealizability(cls.thisType) if (rstatus ne Realizable) ctx.error(ex"$cls cannot be instantiated since it${rstatus.msg}", pos) @@ -594,7 +594,7 @@ trait Checking { * check that class prefix is stable. * @return `tp` itself if it is a class or trait ref, ObjectType if not. */ - def checkClassType(tp: Type, pos: Position, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type = + def checkClassType(tp: Type, pos: SourcePosition, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type = tp.underlyingClassRef(refinementOK = false) match { case tref: TypeRef => if (traitReq && !(tref.symbol is Trait)) ctx.error(TraitIsExpected(tref.symbol), pos) @@ -614,7 +614,7 @@ trait Checking { defn.LanguageModuleClass, nme.implicitConversions, i"Definition of implicit conversion $sym", ctx.owner.topLevelClass, - sym.pos) + sym.sourcePos) } sym.info.stripPoly match { @@ -634,7 +634,7 @@ trait Checking { * - it is defined in Predef * - it is the scala.reflect.Selectable.reflectiveSelectable conversion */ - def checkImplicitConversionUseOK(sym: Symbol, pos: Position)(implicit ctx: Context): Unit = { + def checkImplicitConversionUseOK(sym: Symbol, pos: SourcePosition)(implicit ctx: Context): Unit = { val conversionOK = !sym.exists || sym.is(Synthetic) || @@ -651,7 +651,7 @@ trait Checking { name: TermName, description: => String, featureUseSite: Symbol, - pos: Position)(implicit ctx: Context): Unit = + pos: SourcePosition)(implicit ctx: Context): Unit = if (!ctx.featureEnabled(base, name)) ctx.featureWarning(name.toString, description, isScala2Feature = base.isContainedIn(defn.LanguageModuleClass), @@ -661,7 +661,7 @@ trait Checking { * are feasible, i.e. that their lower bound conforms to their upper bound. If a type * argument is infeasible, issue and error and continue with upper bound. */ - def checkFeasibleParent(tp: Type, pos: Position, where: => String = "")(implicit ctx: Context): Type = { + def checkFeasibleParent(tp: Type, pos: SourcePosition, where: => String = "")(implicit ctx: Context): Type = { def checkGoodBounds(tp: Type) = tp match { case tp @ TypeBounds(lo, hi) if !(lo <:< hi) => ctx.error(ex"no type exists between low bound $lo and high bound $hi$where", pos) @@ -711,7 +711,7 @@ trait Checking { (tree.symbol.isStatic && isCaseObject(tree.symbol) || isCaseClassApply(tree.symbol)) || isCaseClassNew(tree.symbol) - if (!allow) ctx.error(em"$what must be a known value", tree.pos) + if (!allow) ctx.error(em"$what must be a known value", tree.sourcePos) else { def checkArgs(tree: Tree): Unit = tree match { case Apply(fn, args) => @@ -741,12 +741,12 @@ trait Checking { if (decl.matches(other)) { def doubleDefError(decl: Symbol, other: Symbol): Unit = if (!decl.info.isErroneous && !other.info.isErroneous) - ctx.error(DoubleDeclaration(decl, other), decl.pos) + ctx.error(DoubleDeclaration(decl, other), decl.sourcePos) if (decl is Synthetic) doubleDefError(other, decl) else doubleDefError(decl, other) } if ((decl is HasDefaultParams) && (other is HasDefaultParams)) { - ctx.error(em"two or more overloaded variants of $decl have default arguments", decl.pos) + ctx.error(em"two or more overloaded variants of $decl have default arguments", decl.sourcePos) decl resetFlag HasDefaultParams } } @@ -765,10 +765,10 @@ trait Checking { if (!ctx.isAfterTyper) { val called = call.tpe.classSymbol if (caller is Trait) - ctx.error(i"$caller may not call constructor of $called", call.pos) + ctx.error(i"$caller may not call constructor of $called", call.sourcePos) else if (called.is(Trait) && !caller.mixins.contains(called)) ctx.error(i"""$called is already implemented by super${caller.superClass}, - |its constructor cannot be called again""", call.pos) + |its constructor cannot be called again""", call.sourcePos) } /** Check that `tpt` does not define a higher-kinded type */ @@ -800,7 +800,7 @@ trait Checking { * * The standard library relies on this idiom. */ - def checkTraitInheritance(parent: Symbol, cls: ClassSymbol, pos: Position)(implicit ctx: Context): Unit = + def checkTraitInheritance(parent: Symbol, cls: ClassSymbol, pos: SourcePosition)(implicit ctx: Context): Unit = parent match { case parent: ClassSymbol if parent is Trait => val psuper = parent.superClass @@ -815,7 +815,7 @@ trait Checking { /** Check that case classes are not inherited by case classes. */ - def checkCaseInheritance(parent: Symbol, caseCls: ClassSymbol, pos: Position)(implicit ctx: Context): Unit = + def checkCaseInheritance(parent: Symbol, caseCls: ClassSymbol, pos: SourcePosition)(implicit ctx: Context): Unit = parent match { case parent: ClassSymbol => if (parent is Case) @@ -833,7 +833,7 @@ trait Checking { val check = new TreeTraverser { def traverse(tree: Tree)(implicit ctx: Context) = tree match { case id: Ident if vparams.exists(_.symbol == id.symbol) => - ctx.error("illegal forward reference to method parameter", id.pos) + ctx.error("illegal forward reference to method parameter", id.sourcePos) case _ => traverseChildren(tree) } @@ -849,7 +849,7 @@ trait Checking { * of the self type, yet is no longer visible once the `this` has been replaced * by some other prefix. See neg/i3083.scala */ - def checkMembersOK(tp: Type, pos: Position)(implicit ctx: Context): Type = { + def checkMembersOK(tp: Type, pos: SourcePosition)(implicit ctx: Context): Type = { var ok = true val check: Type => Unit = { case ref: NamedType => @@ -876,7 +876,7 @@ trait Checking { if (t.pos.isSourceDerived && owner == badOwner) t match { case t: RefTree if allowed(t.name, checkedSym) => - case _ => ctx.error(i"illegal reference to $checkedSym from $where", t.pos) + case _ => ctx.error(i"illegal reference to $checkedSym from $where", t.sourcePos) } val sym = t.symbol t match { @@ -890,7 +890,7 @@ trait Checking { } /** Check that we are in an inline context (inside an inline method or in inline code) */ - def checkInInlineContext(what: String, pos: Position)(implicit ctx: Context): Unit = + def checkInInlineContext(what: String, pos: SourcePosition)(implicit ctx: Context): Unit = if (!ctx.inInlineMethod && !ctx.isInlineContext) { val inInlineUnapply = ctx.owner.ownersIterator.exists(owner => owner.name == nme.unapply && owner.is(Inline) && owner.is(Method)) @@ -908,7 +908,7 @@ trait Checking { cls.owner.isTerm && (cls.owner.flagsUNSAFE.is(Case) || cls.owner.name == nme.DOLLAR_NEW) if (!cdef.mods.isEnumCase && !isEnumAnonCls) - ctx.error(CaseClassCannotExtendEnum(cls, parent), cdef.pos) + ctx.error(CaseClassCannotExtendEnum(cls, parent), cdef.sourcePos) } /** Check that all references coming from enum cases in an enum companion object @@ -994,23 +994,23 @@ trait ReChecking extends Checking { trait NoChecking extends ReChecking { import tpd._ override def checkNonCyclic(sym: Symbol, info: TypeBounds, reportErrors: Boolean)(implicit ctx: Context): Type = info - override def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, pos: Position)(implicit ctx: Context): Unit = () + override def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, pos: SourcePosition)(implicit ctx: Context): Unit = () override def checkValue(tree: Tree, proto: Type)(implicit ctx: Context): tree.type = tree - override def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit = () - override def checkClassType(tp: Type, pos: Position, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type = tp + override def checkStable(tp: Type, pos: SourcePosition)(implicit ctx: Context): Unit = () + override def checkClassType(tp: Type, pos: SourcePosition, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type = tp override def checkImplicitConversionDefOK(sym: Symbol)(implicit ctx: Context): Unit = () - override def checkImplicitConversionUseOK(sym: Symbol, pos: Position)(implicit ctx: Context): Unit = () - override def checkFeasibleParent(tp: Type, pos: Position, where: => String = "")(implicit ctx: Context): Type = tp + override def checkImplicitConversionUseOK(sym: Symbol, pos: SourcePosition)(implicit ctx: Context): Unit = () + override def checkFeasibleParent(tp: Type, pos: SourcePosition, where: => String = "")(implicit ctx: Context): Type = tp override def checkInlineConformant(tree: Tree, isFinal: Boolean, what: => String)(implicit ctx: Context): Unit = () override def checkNoDoubleDeclaration(cls: Symbol)(implicit ctx: Context): Unit = () override def checkParentCall(call: Tree, caller: ClassSymbol)(implicit ctx: Context): Unit = () override def checkSimpleKinded(tpt: Tree)(implicit ctx: Context): Tree = tpt override def checkNotSingleton(tpt: Tree, where: String)(implicit ctx: Context): Tree = tpt override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context): Unit = () - override def checkTraitInheritance(parentSym: Symbol, cls: ClassSymbol, pos: Position)(implicit ctx: Context): Unit = () - override def checkCaseInheritance(parentSym: Symbol, caseCls: ClassSymbol, pos: Position)(implicit ctx: Context): Unit = () + override def checkTraitInheritance(parentSym: Symbol, cls: ClassSymbol, pos: SourcePosition)(implicit ctx: Context): Unit = () + override def checkCaseInheritance(parentSym: Symbol, caseCls: ClassSymbol, pos: SourcePosition)(implicit ctx: Context): Unit = () override def checkNoForwardDependencies(vparams: List[ValDef])(implicit ctx: Context): Unit = () - override def checkMembersOK(tp: Type, pos: Position)(implicit ctx: Context): Type = tp - override def checkInInlineContext(what: String, pos: Position)(implicit ctx: Context): Unit = () - override def checkFeature(base: ClassSymbol, name: TermName, description: => String, featureUseSite: Symbol, pos: Position)(implicit ctx: Context): Unit = () + override def checkMembersOK(tp: Type, pos: SourcePosition)(implicit ctx: Context): Type = tp + override def checkInInlineContext(what: String, pos: SourcePosition)(implicit ctx: Context): Unit = () + override def checkFeature(base: ClassSymbol, name: TermName, description: => String, featureUseSite: Symbol, pos: SourcePosition)(implicit ctx: Context): Unit = () } diff --git a/compiler/src/dotty/tools/dotc/typer/Docstrings.scala b/compiler/src/dotty/tools/dotc/typer/Docstrings.scala index 65e68a1df4e4..2d4232f5f888 100644 --- a/compiler/src/dotty/tools/dotc/typer/Docstrings.scala +++ b/compiler/src/dotty/tools/dotc/typer/Docstrings.scala @@ -38,7 +38,7 @@ object Docstrings { case List(df: tpd.DefDef) => usecase.typed(df) case _ => - ctx.error("`@usecase` was not a valid definition", usecase.codePos) + ctx.error("`@usecase` was not a valid definition", ctx.source.atPos(usecase.codePos)) usecase } } diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index e9f9d6d5ea50..819947f2c513 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -7,6 +7,7 @@ import core._ import Types._, ProtoTypes._, Contexts._, Decorators._, Denotations._, Symbols._ import Implicits._, Flags._ import util.Positions._ +import util.SourcePosition import java.util.regex.Matcher.quoteReplacement import reporting.diagnostic.Message import reporting.diagnostic.messages._ @@ -15,18 +16,18 @@ object ErrorReporting { import tpd._ - def errorTree(tree: untpd.Tree, msg: => Message, pos: Position)(implicit ctx: Context): tpd.Tree = - tree withType errorType(msg, pos) + def errorTree(tree: untpd.Tree, msg: => Message, pos: SourcePosition)(implicit ctx: Context): tpd.Tree = + tree.withType(errorType(msg, pos)) def errorTree(tree: untpd.Tree, msg: => Message)(implicit ctx: Context): tpd.Tree = - errorTree(tree, msg, tree.pos) + errorTree(tree, msg, tree.sourcePos) - def errorType(msg: => Message, pos: Position)(implicit ctx: Context): ErrorType = { + def errorType(msg: => Message, pos: SourcePosition)(implicit ctx: Context): ErrorType = { ctx.error(msg, pos) ErrorType(msg) } - def wrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[ParamInfo], actual: List[untpd.Tree], pos: Position)(implicit ctx: Context): ErrorType = + def wrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[ParamInfo], actual: List[untpd.Tree], pos: SourcePosition)(implicit ctx: Context): ErrorType = errorType(WrongNumberOfTypeArgs(fntpe, expectedArgs, actual)(ctx), pos) class Errors(implicit ctx: Context) { @@ -79,8 +80,10 @@ object ErrorReporting { def takesNoParamsStr(tree: Tree, kind: String): String = if (tree.tpe.widen.exists) i"${exprStr(tree)} does not take ${kind}parameters" - else + else { + new FatalError("").printStackTrace() i"undefined: $tree # ${tree.uniqueId}: ${tree.tpe.toString} at ${ctx.phase}" + } def patternConstrStr(tree: Tree): String = ??? diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index f206068fd3a1..949f142bb12c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -738,7 +738,8 @@ trait Implicits { self: Typer => /** Search an implicit argument and report error if not found */ def implicitArgTree(formal: Type, pos: Position)(implicit ctx: Context): Tree = { val arg = inferImplicitArg(formal, pos) - if (arg.tpe.isInstanceOf[SearchFailureType]) ctx.error(missingArgMsg(arg, formal, ""), pos) + if (arg.tpe.isInstanceOf[SearchFailureType]) + ctx.error(missingArgMsg(arg, formal, ""), ctx.source.atPos(pos)) arg } @@ -909,7 +910,7 @@ trait Implicits { self: Typer => case altResult: SearchSuccess => ctx.migrationWarning( s"According to new implicit resolution rules, this will be ambiguous:\n${result.reason.explanation}", - pos) + ctx.source.atPos(pos)) altResult case _ => result @@ -1152,7 +1153,8 @@ trait Implicits { self: Typer => |According to the new implicit resolution rules this is no longer possible; |the search will fail with a global ambiguity error instead. | - |Consider using the scala.implicits.Not class to implement similar functionality.""", pos) + |Consider using the scala.implicits.Not class to implement similar functionality.""", + ctx.source.atPos(pos)) /** A relation that imfluences the order in which implicits are tried. * We prefer (in order of importance) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index d27a6199f957..def087ee645c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -25,6 +25,8 @@ import dotty.tools.dotc.util.{SimpleIdentityMap, SimpleIdentitySet} import collection.mutable import reporting.trace import util.Positions.Position +import util.SourcePosition +import ast.TreeInfo object Inliner { import tpd._ @@ -112,7 +114,7 @@ object Inliner { i"""|Maximal number of successive inlines (${ctx.settings.XmaxInlines.value}) exceeded, |Maybe this is caused by a recursive inline method? |You can use -Xmax-inlines to change the limit.""", - (tree :: enclosingInlineds).last.pos + (tree :: enclosingInlineds).last.sourcePos ) } @@ -362,7 +364,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { if (inlinedMethod == defn.Typelevel_constValue) { val constVal = tryConstValue if (!constVal.isEmpty) return constVal - ctx.error(i"not a constant type: ${callTypeArgs.head}; cannot take constValue", call.pos) + ctx.error(i"not a constant type: ${callTypeArgs.head}; cannot take constValue", call.sourcePos) } else if (inlinedMethod == defn.Typelevel_constValueOpt) { val constVal = tryConstValue @@ -449,7 +451,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { case _ => arg.show } } - ctx.error(s"$msg${rest.map(decompose).mkString(", ")}", callToReport.pos) + ctx.error(s"$msg${rest.map(decompose).mkString(", ")}", callToReport.sourcePos) } issueInCtx(ctxToReport) case _ => @@ -709,7 +711,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { val evidence = evTyper.inferImplicitArg(tpt.tpe, tpt.pos)(ctx.fresh.setTyper(evTyper)) evidence.tpe match { case fail: Implicits.AmbiguousImplicits => - ctx.error(evTyper.missingArgMsg(evidence, tpt.tpe, ""), tpt.pos) + ctx.error(evTyper.missingArgMsg(evidence, tpt.tpe, ""), tpt.sourcePos) true // hard error: return true to stop implicit search here case fail: Implicits.SearchFailureType => false @@ -903,7 +905,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { class InlineTyper extends ReTyper { import reducer._ - override def ensureAccessible(tpe: Type, superAccess: Boolean, pos: Position)(implicit ctx: Context): Type = { + override def ensureAccessible(tpe: Type, superAccess: Boolean, pos: SourcePosition)(implicit ctx: Context): Type = { tpe match { case tpe: NamedType if tpe.symbol.exists && !tpe.symbol.isAccessibleFrom(tpe.prefix, superAccess) => tpe.info match { @@ -923,7 +925,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { assert(tree.hasType, tree) val qual1 = typed(tree.qualifier, selectionProto(tree.name, pt, this)) val res = untpd.cpy.Select(tree)(qual1, tree.name).withType(tree.typeOpt) - ensureAccessible(res.tpe, tree.qualifier.isInstanceOf[untpd.Super], tree.pos) + ensureAccessible(res.tpe, tree.qualifier.isInstanceOf[untpd.Super], tree.sourcePos) res } diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index fa881495dcf9..1f3e5060164d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -247,7 +247,8 @@ class Namer { typer: Typer => if (name.isEmpty) NoSymbol else { val cls = ctx.owner.enclosingClassNamed(name) - if (!cls.exists) ctx.error(s"no enclosing class or object is named $name", pos) + if (!cls.exists) + ctx.error(s"no enclosing class or object is named $name", ctx.source.atPos(pos)) cls } } @@ -279,7 +280,7 @@ class Namer { typer: Typer => case _ => (flags.isTermFlags, flags.toTermFlags, "value") } if (!ok) - ctx.error(i"modifier(s) `$flags' incompatible with $kind definition", tree.pos) + ctx.error(i"modifier(s) `$flags' incompatible with $kind definition", tree.sourcePos) adapted } @@ -292,7 +293,7 @@ class Namer { typer: Typer => def checkNoConflict(name: Name): Name = { def errorName(msg: => String) = { - ctx.error(msg, tree.pos) + ctx.error(msg, tree.sourcePos) name.freshened } def preExisting = ctx.effectiveScope.lookup(name) @@ -404,7 +405,7 @@ class Namer { typer: Typer => /** If there's already an existing type, then the package is a dup of this type */ val existingType = pkgOwner.info.decls.lookup(pid.name.toTypeName) if (existingType.exists) { - ctx.error(PkgDuplicateSymbol(existingType), pid.pos) + ctx.error(PkgDuplicateSymbol(existingType), pid.sourcePos) ctx.newCompletePackageSymbol(pkgOwner, (pid.name ++ "$_error_").toTermName).entered } else ctx.newCompletePackageSymbol(pkgOwner, pid.name.asTermName).entered @@ -693,7 +694,7 @@ class Namer { typer: Typer => } def missingType(sym: Symbol, modifier: String)(implicit ctx: Context): Unit = { - ctx.error(s"${modifier}type of implicit definition needs to be given explicitly", sym.pos) + ctx.error(s"${modifier}type of implicit definition needs to be given explicitly", sym.sourcePos) sym.resetFlag(Implicit) } @@ -796,7 +797,7 @@ class Namer { typer: Typer => denot.info = typeSig(sym) invalidateIfClashingSynthetic(denot) Checking.checkWellFormed(sym) - denot.info = avoidPrivateLeaks(sym, sym.pos) + denot.info = avoidPrivateLeaks(sym, sym.sourcePos) } } @@ -886,7 +887,7 @@ class Namer { typer: Typer => val ptype = parentType(parent)(ctx.superCallContext).dealiasKeepAnnots if (cls.isRefinementClass) ptype else { - val pt = checkClassType(ptype, parent.pos, + val pt = checkClassType(ptype, parent.sourcePos, traitReq = parent ne parents.head, stablePrefixReq = true) if (pt.derivesFrom(cls)) { val addendum = parent match { @@ -894,15 +895,15 @@ class Namer { typer: Typer => "\n(Note that inheriting a class of the same name is no longer allowed)" case _ => "" } - ctx.error(CyclicInheritance(cls, addendum), parent.pos) + ctx.error(CyclicInheritance(cls, addendum), parent.sourcePos) defn.ObjectType } else { val pclazz = pt.typeSymbol if (pclazz.is(Final)) - ctx.error(ExtendFinalClass(cls, pclazz), cls.pos) + ctx.error(ExtendFinalClass(cls, pclazz), cls.sourcePos) if (pclazz.is(Sealed) && pclazz.associatedFile != cls.associatedFile) - ctx.error(UnableToExtendSealedClass(pclazz), cls.pos) + ctx.error(UnableToExtendSealedClass(pclazz), cls.sourcePos) pt } } @@ -970,7 +971,7 @@ class Namer { typer: Typer => Checking.checkWellFormed(cls) if (isDerivedValueClass(cls)) cls.setFlag(Final) - cls.info = avoidPrivateLeaks(cls, cls.pos) + cls.info = avoidPrivateLeaks(cls, cls.sourcePos) cls.baseClasses.foreach(_.invalidateBaseTypeCache()) // we might have looked before and found nothing cls.setNoInitsFlags(parentsKind(parents), bodyKind(rest)) if (cls.isNoInitsClass) cls.primaryConstructor.setFlag(Stable) @@ -1155,7 +1156,7 @@ class Namer { typer: Typer => case _: untpd.DerivedTypeTree => WildcardType case TypeTree() => - checkMembersOK(inferredType, mdef.pos) + checkMembersOK(inferredType, mdef.sourcePos) case DependentTypeTree(tpFun) => val tpe = tpFun(paramss.head) if (isFullyDefined(tpe, ForceDegree.none)) tpe @@ -1167,7 +1168,7 @@ class Namer { typer: Typer => val hygienicType = avoid(rhsType, paramss.flatten) if (!hygienicType.isValueType || !(hygienicType <:< tpt.tpe)) ctx.error(i"return type ${tpt.tpe} of lambda cannot be made hygienic;\n" + - i"it is not a supertype of the hygienic type $hygienicType", mdef.pos) + i"it is not a supertype of the hygienic type $hygienicType", mdef.sourcePos) //println(i"lifting $rhsType over $paramss -> $hygienicType = ${tpt.tpe}") //println(TypeComparer.explained { implicit ctx => hygienicType <:< tpt.tpe }) case _ => diff --git a/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala b/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala index ef8e4b42c06d..d073e16c373d 100644 --- a/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala +++ b/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala @@ -84,7 +84,7 @@ object PrepareInlineable { def preTransform(tree: Tree)(implicit ctx: Context): Tree = tree match { case tree: RefTree if needsAccessor(tree.symbol) => if (tree.symbol.isConstructor) { - ctx.error("Implementation restriction: cannot use private constructors in inlineinline methods", tree.pos) + ctx.error("Implementation restriction: cannot use private constructors in inlineinline methods", tree.sourcePos) tree // TODO: create a proper accessor for the private constructor } else useAccessor(tree) @@ -243,10 +243,10 @@ object PrepareInlineable { def checkInlineMethod(inlined: Symbol, body: Tree)(implicit ctx: Context): Unit = { if (ctx.outer.inInlineMethod) - ctx.error(ex"implementation restriction: nested inline methods are not supported", inlined.pos) + ctx.error(ex"implementation restriction: nested inline methods are not supported", inlined.sourcePos) if (inlined.name == nme.unapply && tupleArgs(body).isEmpty) ctx.warning( em"inline unapply method can be rewritten only if its right hand side is a tuple (e1, ..., eN)", - body.pos) + body.sourcePos) } } diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 1d84c3478d33..151fe8cfbe6d 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -8,7 +8,7 @@ import StdNames._, Denotations._, SymUtils._ import NameKinds.DefaultGetterName import Annotations._ import util.Positions._ -import util.Store +import util.{Store, SourcePosition} import scala.collection.{ mutable, immutable } import ast._ import Trees._ @@ -59,7 +59,7 @@ object RefChecks { " define default arguments" + ( if (owners.forall(_ == clazz)) "." else ".\nThe members with defaults are defined in " + owners.map(_.showLocated).mkString("", " and ", ".")), - clazz.pos) + clazz.sourcePos) } } } @@ -68,7 +68,7 @@ object RefChecks { if (clazz derivesFrom defn.DynamicClass) { for ((_, m1 :: m2 :: _) <- (clazz.info member nme.applyDynamic).alternatives groupBy (_.symbol.typeParams.length)) { ctx.error("implementation restriction: applyDynamic cannot be overloaded except by methods with different numbers of type parameters, e.g. applyDynamic[T1](method: String)(arg: T1) and applyDynamic[T1, T2](method: String)(arg1: T1, arg2: T2)", - m1.symbol.pos) + m1.symbol.sourcePos) } } } @@ -98,7 +98,7 @@ object RefChecks { val otherSelf = other.givenSelfType.asSeenFrom(cls.thisType, other.classSymbol) if (otherSelf.exists && !(cinfo.selfType <:< otherSelf)) ctx.error(DoesNotConformToSelfType(category, cinfo.selfType, cls, otherSelf, relation, other.classSymbol), - cls.pos) + cls.sourcePos) } for (parent <- cinfo.classParents) checkSelfConforms(parent.classSymbol.asClass, "illegal inheritance", "parent") @@ -117,7 +117,7 @@ object RefChecks { case TypeRef(ref: TermRef, _) => val paramRefs = ref.namedPartsWith(ntp => ntp.symbol.enclosingClass == cls) if (paramRefs.nonEmpty) - ctx.error("trait parameters cannot be used as parent prefixes", parent.pos) + ctx.error("trait parameters cannot be used as parent prefixes", parent.sourcePos) case _ => } @@ -132,7 +132,7 @@ object RefChecks { val others = cls.owner.linkedClass.info.decls.filter(clashes) others.foreach { other => - ctx.error(ClassAndCompanionNameClash(cls, other), cls.pos) + ctx.error(ClassAndCompanionNameClash(cls, other), cls.sourcePos) } } @@ -182,7 +182,7 @@ object RefChecks { mixinOverrideErrors.toList match { case List() => case List(MixinOverrideError(_, msg)) => - ctx.error(msg, clazz.pos) + ctx.error(msg, clazz.sourcePos) case MixinOverrideError(member, msg) :: others => val others1 = others.map(_.member).filter(_.name != member.name).distinct def othersMsg = { @@ -192,7 +192,7 @@ object RefChecks { if (others1.isEmpty) "" else i";\nother members with override errors are:: $others1%, %" } - ctx.error(msg + othersMsg, clazz.pos) + ctx.error(msg + othersMsg, clazz.sourcePos) } } @@ -244,7 +244,7 @@ object RefChecks { if (!(hasErrors && member.is(Synthetic) && member.is(Module))) { // suppress errors relating toi synthetic companion objects if other override // errors (e.g. relating to the companion class) have already been reported. - if (member.owner == clazz) ctx.error(fullmsg, member.pos) + if (member.owner == clazz) ctx.error(fullmsg, member.sourcePos) else mixinOverrideErrors += new MixinOverrideError(member, fullmsg) hasErrors = true } @@ -283,7 +283,7 @@ object RefChecks { memberTp.overrides(otherTp, member.matchNullaryLoosely || other.matchNullaryLoosely || ctx.testScala2Mode(overrideErrorMsg("no longer has compatible type"), - (if (member.owner == clazz) member else clazz).pos)) + (if (member.owner == clazz) member else clazz).sourcePos)) catch { case ex: MissingType => // can happen when called with upwardsSelf as qualifier of memberTp and otherTp, @@ -355,7 +355,8 @@ object RefChecks { // Also exclusion for implicit shortcut methods // Also excluded under Scala2 mode are overrides of default methods of Java traits. if (autoOverride(member) || - other.owner.is(JavaTrait) && ctx.testScala2Mode("`override' modifier required when a Java 8 default method is re-implemented", member.pos)) + other.owner.is(JavaTrait) && + ctx.testScala2Mode("`override' modifier required when a Java 8 default method is re-implemented", member.sourcePos)) member.setFlag(Override) else if (member.isType && self.memberInfo(member) =:= self.memberInfo(other)) () // OK, don't complain about type aliases which are equal @@ -386,7 +387,7 @@ object RefChecks { } else if (member.is(ModuleVal) && !other.isRealMethod && !other.is(Deferred | Lazy)) { overrideError("may not override a concrete non-lazy value") } else if (member.is(Lazy, butNot = Module) && !other.isRealMethod && !other.is(Lazy) && - !ctx.testScala2Mode("may not override a non-lazy value", member.pos)) { + !ctx.testScala2Mode("may not override a non-lazy value", member.sourcePos)) { overrideError("may not override a non-lazy value") } else if (other.is(Lazy) && !other.isRealMethod && !member.is(Lazy)) { overrideError("must be declared lazy to override a lazy value") @@ -431,7 +432,7 @@ object RefChecks { "\n(Note that having same-named member classes in types of a mixin composition is no longer allowed)" case _ => "" } - ctx.error(ex.getMessage + addendum, clazz.pos) + ctx.error(ex.getMessage + addendum, clazz.sourcePos) } printMixinOverrideErrors() @@ -659,7 +660,7 @@ object RefChecks { em"""${mbr.showLocated} is not a legal implementation of `$name' in $clazz | its type $mbrType | does not conform to ${mbrd.info}""", - (if (mbr.owner == clazz) mbr else clazz).pos) + (if (mbr.owner == clazz) mbr else clazz).sourcePos) } } } @@ -673,14 +674,14 @@ object RefChecks { for (baseCls <- caseCls.info.baseClasses.tail) if (baseCls.typeParams.exists(_.paramVariance != 0)) for (problem <- variantInheritanceProblems(baseCls, caseCls, "non-variant", "case ")) - ctx.errorOrMigrationWarning(problem(), clazz.pos) + ctx.errorOrMigrationWarning(problem(), clazz.sourcePos) } checkNoAbstractMembers() if (abstractErrors.isEmpty) checkNoAbstractDecls(clazz) if (abstractErrors.nonEmpty) - ctx.error(abstractErrorMessage, clazz.pos) + ctx.error(abstractErrorMessage, clazz.sourcePos) checkMemberTypesOK() checkCaseClassInheritanceInvariant() @@ -693,7 +694,7 @@ object RefChecks { // override a concrete method in Object. The jvm, however, does not. val overridden = decl.matchingDecl(defn.ObjectClass, defn.ObjectType) if (overridden.is(Final)) - ctx.error(TraitRedefinedFinalMethodFromAnyRef(overridden), decl.pos) + ctx.error(TraitRedefinedFinalMethodFromAnyRef(overridden), decl.sourcePos) } } @@ -715,7 +716,7 @@ object RefChecks { cls <- clazz.info.baseClasses.tail if cls.paramAccessors.nonEmpty && !mixins.contains(cls) problem <- variantInheritanceProblems(cls, clazz.asClass.superClass, "parameterized", "super") - } ctx.error(problem(), clazz.pos) + } ctx.error(problem(), clazz.sourcePos) } checkParameterizedTraitsOK() @@ -794,9 +795,9 @@ object RefChecks { val nonMatching = clazz.info.member(member.name).altsWith(alt => alt.owner != clazz) nonMatching match { case Nil => - ctx.error(OverridesNothing(member), member.pos) + ctx.error(OverridesNothing(member), member.sourcePos) case ms => - ctx.error(OverridesNothingButNameExists(member, ms), member.pos) + ctx.error(OverridesNothingButNameExists(member, ms), member.sourcePos) } member.resetFlag(Override) member.resetFlag(AbsOverride) @@ -808,7 +809,7 @@ object RefChecks { // I assume that's a consequence of some code trying to avoid noise by suppressing // warnings after the first, but I think it'd be better if we didn't have to // arbitrarily choose one as more important than the other. - private def checkUndesiredProperties(sym: Symbol, pos: Position)(implicit ctx: Context): Unit = { + private def checkUndesiredProperties(sym: Symbol, pos: SourcePosition)(implicit ctx: Context): Unit = { // If symbol is deprecated, and the point of reference is not enclosed // in either a deprecated member or a scala bridge method, issue a warning. if (sym.isDeprecated && !ctx.owner.ownersIterator.exists(_.isDeprecated)) { @@ -852,7 +853,7 @@ object RefChecks { if (!concrOvers.isEmpty) ctx.deprecationWarning( symbol.toString + " overrides concrete, non-deprecated symbol(s):" + - concrOvers.map(_.name).mkString(" ", ", ", ""), tree.pos) + concrOvers.map(_.name).mkString(" ", ", ", ""), tree.sourcePos) } } @@ -951,13 +952,14 @@ class RefChecks extends MiniPhase { thisPhase => val sym = tree.symbol if (sym.exists && sym.owner.isTerm) { tree.rhs match { - case Ident(nme.WILDCARD) => ctx.error(UnboundPlaceholderParameter(), sym.pos) + case Ident(nme.WILDCARD) => ctx.error(UnboundPlaceholderParameter(), sym.sourcePos) case _ => } if (!sym.is(Lazy)) { currentLevel.levelAndIndex.get(sym) match { case Some((level, symIdx)) if symIdx <= level.maxIndex => - ctx.error(ForwardReferenceExtendsOverDefinition(sym, level.refSym), level.refPos) + ctx.error(ForwardReferenceExtendsOverDefinition(sym, level.refSym), + ctx.source.atPos(level.refPos)) case _ => } } @@ -980,18 +982,18 @@ class RefChecks extends MiniPhase { thisPhase => tree } catch { case ex: TypeError => - ctx.error(ex.getMessage, tree.pos) + ctx.error(ex.getMessage, tree.sourcePos) tree } override def transformIdent(tree: Ident)(implicit ctx: Context): Ident = { - checkUndesiredProperties(tree.symbol, tree.pos) + checkUndesiredProperties(tree.symbol, tree.sourcePos) currentLevel.enterReference(tree.symbol, tree.pos) tree } override def transformSelect(tree: Select)(implicit ctx: Context): Select = { - checkUndesiredProperties(tree.symbol, tree.pos) + checkUndesiredProperties(tree.symbol, tree.sourcePos) tree } @@ -1002,7 +1004,8 @@ class RefChecks extends MiniPhase { thisPhase => if (level.maxIndex > 0) { // An implementation restriction to avoid VerifyErrors and lazyvals mishaps; see SI-4717 ctx.debuglog("refsym = " + level.refSym) - ctx.error("forward reference not allowed from self constructor invocation", level.refPos) + ctx.error("forward reference not allowed from self constructor invocation", + ctx.source.atPos(level.refPos)) } } tree @@ -1011,7 +1014,7 @@ class RefChecks extends MiniPhase { thisPhase => override def transformNew(tree: New)(implicit ctx: Context): New = { val tpe = tree.tpe val sym = tpe.typeSymbol - checkUndesiredProperties(sym, tree.pos) + checkUndesiredProperties(sym, tree.sourcePos) currentLevel.enterReference(sym, tree.pos) tpe.dealias.foreachPart { case TermRef(_, s: Symbol) => currentLevel.enterReference(s, tree.pos) diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 317d3f762696..d6a8e6bbe420 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -7,6 +7,7 @@ import ast._ import Contexts._, Constants._, Types._, Symbols._, Names._, Flags._, Decorators._ import ErrorReporting._, Annotations._, Denotations._, SymDenotations._, StdNames._ import util.Positions._ +import util.SourcePosition import config.Printers.typr import ast.Trees._ import NameOps._ @@ -32,7 +33,7 @@ trait TypeAssigner { case _ => ctx.error( if (qual.isEmpty) tree.show + " can be used only in a class, object, or template" - else qual.show + " is not an enclosing class", tree.pos) + else qual.show + " is not an enclosing class", tree.sourcePos) NoSymbol } } @@ -149,7 +150,7 @@ trait TypeAssigner { def avoidingType(expr: Tree, bindings: List[Tree])(implicit ctx: Context): Type = avoid(expr.tpe, localSyms(bindings).filter(_.isTerm)) - def avoidPrivateLeaks(sym: Symbol, pos: Position)(implicit ctx: Context): Type = + def avoidPrivateLeaks(sym: Symbol, pos: SourcePosition)(implicit ctx: Context): Type = if (!sym.is(SyntheticOrPrivate) && sym.owner.isClass) checkNoPrivateLeaks(sym, pos) else sym.info @@ -184,7 +185,7 @@ trait TypeAssigner { * (2) if the owner of the denotation is a package object, it is assured * that the package object shows up as the prefix. */ - def ensureAccessible(tpe: Type, superAccess: Boolean, pos: Position)(implicit ctx: Context): Type = { + def ensureAccessible(tpe: Type, superAccess: Boolean, pos: SourcePosition)(implicit ctx: Context): Type = { def test(tpe: Type, firstTry: Boolean): Type = tpe match { case tpe: NamedType => val pre = tpe.prefix @@ -235,7 +236,7 @@ trait TypeAssigner { /** The type of a selection with `name` of a tree with type `site`. */ - def selectionType(site: Type, name: Name, pos: Position)(implicit ctx: Context): Type = { + def selectionType(site: Type, name: Name, pos: SourcePosition)(implicit ctx: Context): Type = { val mbr = site.member(name) if (reallyExists(mbr)) site.select(name, mbr) @@ -261,11 +262,12 @@ trait TypeAssigner { var qualType = qual1.tpe.widenIfUnstable if (!qualType.hasSimpleKind && tree.name != nme.CONSTRUCTOR) // constructors are selected on typeconstructor, type arguments are passed afterwards - qualType = errorType(em"$qualType takes type parameters", qual1.pos) - else if (!qualType.isInstanceOf[TermType]) qualType = errorType(em"$qualType is illegal as a selection prefix", qual1.pos) - val ownType = selectionType(qualType, tree.name, tree.pos) + qualType = errorType(em"$qualType takes type parameters", qual1.sourcePos) + else if (!qualType.isInstanceOf[TermType]) + qualType = errorType(em"$qualType is illegal as a selection prefix", qual1.sourcePos) + val ownType = selectionType(qualType, tree.name, tree.sourcePos) if (tree.getAttachment(desugar.SuppressAccessCheck).isDefined) ownType - else ensureAccessible(ownType, qual1.isInstanceOf[Super], tree.pos) + else ensureAccessible(ownType, qual1.isInstanceOf[Super], tree.sourcePos) } /** Type assignment method. Each method takes as parameters @@ -316,7 +318,7 @@ trait TypeAssigner { val cls = qualifyingClass(tree, tree.qual.name, packageOK = false) tree.withType( if (cls.isClass) cls.thisType - else errorType("not a legal qualifying class for this", tree.pos)) + else errorType("not a legal qualifying class for this", tree.sourcePos)) } def assignType(tree: untpd.Super, qual: Tree, inConstrCall: Boolean, mixinClass: Symbol = NoSymbol)(implicit ctx: Context): Super = { @@ -329,9 +331,9 @@ trait TypeAssigner { case p :: Nil => p.typeConstructor case Nil => - errorType(SuperQualMustBeParent(mix, cls), tree.pos) + errorType(SuperQualMustBeParent(mix, cls), tree.sourcePos) case p :: q :: _ => - errorType("ambiguous parent class qualifier", tree.pos) + errorType("ambiguous parent class qualifier", tree.sourcePos) } val owntype = if (mixinClass.exists) mixinClass.appliedRef @@ -373,15 +375,15 @@ trait TypeAssigner { if (fntpe.isResultDependent) safeSubstParams(fntpe.resultType, fntpe.paramRefs, args.tpes) else fntpe.resultType else - errorType(i"wrong number of arguments at ${ctx.phase.prev} for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.pos) + errorType(i"wrong number of arguments at ${ctx.phase.prev} for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.sourcePos) case t => - errorType(err.takesNoParamsStr(fn, ""), tree.pos) + errorType(err.takesNoParamsStr(fn, ""), tree.sourcePos) } ConstFold(tree.withType(ownType)) } def assignType(tree: untpd.TypeApply, fn: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = { - def fail = tree.withType(errorType(err.takesNoParamsStr(fn, "type "), tree.pos)) + def fail = tree.withType(errorType(err.takesNoParamsStr(fn, "type "), tree.sourcePos)) fn.tpe.widen match { case pt: TypeLambda => tree.withType { @@ -393,9 +395,9 @@ trait TypeAssigner { val namedArgMap = new mutable.HashMap[Name, Type] for (NamedArg(name, arg) <- args) if (namedArgMap.contains(name)) - ctx.error(DuplicateNamedTypeParameter(name), arg.pos) + ctx.error(DuplicateNamedTypeParameter(name), arg.sourcePos) else if (!paramNames.contains(name)) - ctx.error(UndefinedNamedTypeParameter(name, paramNames), arg.pos) + ctx.error(UndefinedNamedTypeParameter(name, paramNames), arg.sourcePos) else namedArgMap(name) = arg.tpe @@ -432,7 +434,7 @@ trait TypeAssigner { else { val argTypes = args.tpes if (sameLength(argTypes, paramNames)) pt.instantiate(argTypes) - else wrongNumberOfTypeArgs(fn.tpe, pt.typeParams, args, tree.pos) + else wrongNumberOfTypeArgs(fn.tpe, pt.typeParams, args, tree.sourcePos) } } case err: ErrorType => @@ -544,7 +546,7 @@ trait TypeAssigner { val tparams = tycon.tpe.typeParams val ownType = if (sameLength(tparams, args)) tycon.tpe.appliedTo(args.tpes) - else wrongNumberOfTypeArgs(tycon.tpe, tparams, args, tree.pos) + else wrongNumberOfTypeArgs(tycon.tpe, tparams, args, tree.sourcePos) tree.withType(ownType) } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index e35b0c9bba68..3c3e7cb5d14b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -114,7 +114,7 @@ class Typer extends Namer * @param required flags the result's symbol must have * @param pos position to use for error reporting */ - def findRef(name: Name, pt: Type, required: FlagConjunction, pos: Position)(implicit ctx: Context): Type = { + def findRef(name: Name, pt: Type, required: FlagConjunction, tree: untpd.Tree)(implicit ctx: Context): Type = { val refctx = ctx val noImports = ctx.mode.is(Mode.InPackageClauseName) @@ -164,14 +164,14 @@ class Typer extends Namer } else { if (!scala2pkg && !previous.isError && !found.isError) { - refctx.error(AmbiguousImport(name, newPrec, prevPrec, prevCtx), pos) + refctx.error(AmbiguousImport(name, newPrec, prevPrec, prevCtx), tree.sourcePos) } previous } def selection(imp: ImportInfo, name: Name) = if (imp.sym.isCompleting) { - ctx.warning(i"cyclic ${imp.sym}, ignored", pos) + ctx.warning(i"cyclic ${imp.sym}, ignored", tree.sourcePos) NoType } else if (unimported.nonEmpty && unimported.contains(imp.site.termSymbol)) NoType @@ -193,7 +193,7 @@ class Typer extends Namer def checkUnambiguous(found: Type) = { val other = recur(selectors.tail) if (other.exists && found.exists && (found != other)) - refctx.error(em"reference to `$name` is ambiguous; it is imported twice", pos) + refctx.error(em"reference to `$name` is ambiguous; it is imported twice", tree.sourcePos) found } @@ -362,12 +362,12 @@ class Typer extends Namer unimported = Set.empty foundUnderScala2 = NoType try { - var found = findRef(name, pt, EmptyFlagConjunction, tree.pos) + var found = findRef(name, pt, EmptyFlagConjunction, tree) if (foundUnderScala2.exists && !(foundUnderScala2 =:= found)) { ctx.migrationWarning( ex"""Name resolution will change. | currently selected : $foundUnderScala2 - | in the future, without -language:Scala2: $found""", tree.pos) + | in the future, without -language:Scala2: $found""", tree.sourcePos) found = foundUnderScala2 } found @@ -380,7 +380,7 @@ class Typer extends Namer val ownType = if (rawType.exists) - ensureAccessible(rawType, superAccess = false, tree.pos) + ensureAccessible(rawType, superAccess = false, tree.sourcePos) else if (name == nme._scope) { // gross hack to support current xml literals. // awaiting a better implicits based solution for library-supported xml @@ -392,9 +392,9 @@ class Typer extends Namer ctx.owner.owner.unforcedDecls.lookup(tree.name).exists) { // When InSuperCall mode and in a constructor we are in the arguments // of a this(...) constructor call - errorType(ex"$tree is not accessible from constructor arguments", tree.pos) + errorType(ex"$tree is not accessible from constructor arguments", tree.sourcePos) } else - errorType(new MissingIdent(tree, kind, name.show), tree.pos) + errorType(new MissingIdent(tree, kind, name.show), tree.sourcePos) val tree1 = ownType match { case ownType: NamedType if !prefixIsElidable(ownType) => @@ -415,7 +415,7 @@ class Typer extends Namer !pt.isInstanceOf[ApplyingProto] && !tree.tpe.isStable && !isWildcardArg(tree)) - ctx.error(StableIdentPattern(tree, pt), tree.pos) + ctx.error(StableIdentPattern(tree, pt), tree.sourcePos) tree } @@ -433,7 +433,7 @@ class Typer extends Namer case _ => app } case qual1 => - if (tree.name.isTypeName) checkStable(qual1.tpe, qual1.pos) + if (tree.name.isTypeName) checkStable(qual1.tpe, qual1.sourcePos) val select = typedSelect(tree, pt, qual1) if (select.tpe ne TryDynamicCallType) ConstFold(checkStableIdentPattern(select, pt)) else if (pt.isInstanceOf[FunOrPolyProto] || pt == AssignProto) select @@ -476,7 +476,7 @@ class Typer extends Namer } val enclosingInlineable = ctx.owner.ownersIterator.findSymbol(_.isInlineMethod) if (enclosingInlineable.exists && !PrepareInlineable.isLocal(qual1.symbol, enclosingInlineable)) - ctx.error(SuperCallsNotAllowedInlineable(enclosingInlineable), tree.pos) + ctx.error(SuperCallsNotAllowedInlineable(enclosingInlineable), tree.sourcePos) pt match { case pt: SelectionProto if pt.name.isTypeName => qual1 // don't do super references for types; they are meaningless anyway @@ -511,18 +511,18 @@ class Typer extends Namer typed(cpy.Block(tree)(clsDef :: Nil, New(Ident(x), Nil)), pt) case _ => var tpt1 = typedType(tree.tpt) - tpt1 = tpt1.withType(ensureAccessible(tpt1.tpe, superAccess = false, tpt1.pos)) + tpt1 = tpt1.withType(ensureAccessible(tpt1.tpe, superAccess = false, tpt1.sourcePos)) tpt1.tpe.dealias match { case TypeApplications.EtaExpansion(tycon) => tpt1 = tpt1.withType(tycon) case _ => } - if (checkClassType(tpt1.tpe, tpt1.pos, traitReq = false, stablePrefixReq = true) eq defn.ObjectType) + if (checkClassType(tpt1.tpe, tpt1.sourcePos, traitReq = false, stablePrefixReq = true) eq defn.ObjectType) tpt1 = TypeTree(defn.ObjectType).withPos(tpt1.pos) tpt1 match { case AppliedTypeTree(_, targs) => for (targ @ TypeBoundsTree(_, _) <- targs) - ctx.error(WildcardOnTypeArgumentNotAllowedOnNew(), targ.pos) + ctx.error(WildcardOnTypeArgumentNotAllowedOnNew(), targ.sourcePos) case _ => } @@ -661,7 +661,7 @@ class Typer extends Namer lhsCore match { case lhsCore: RefTree if setter.exists => val setterTypeRaw = pre.select(setterName, setter) - val setterType = ensureAccessible(setterTypeRaw, isSuperSelection(lhsCore), tree.pos) + val setterType = ensureAccessible(setterTypeRaw, isSuperSelection(lhsCore), tree.sourcePos) val lhs2 = untpd.rename(lhsCore, setterName).withType(setterType) typedUnadapted(untpd.Apply(untpd.TypedSplice(lhs2), tree.rhs :: Nil), WildcardType, locked) case _ => @@ -725,7 +725,7 @@ class Typer extends Namer } def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context): Tree = track("typedIf") { - if (tree.isInline) checkInInlineContext("inline if", tree.pos) + if (tree.isInline) checkInInlineContext("inline if", tree.sourcePos) val cond1 = typed(tree.cond, defn.BooleanType) val thenp2 :: elsep2 :: Nil = harmonic(harmonize, pt) { val thenp1 = typed(tree.thenp, pt.notApplied) @@ -780,7 +780,7 @@ class Typer extends Namer val isImplicit = tree.mods.is(Implicit) var isErased = tree.mods.is(Erased) if (isErased && args.isEmpty) { - ctx.error("An empty function cannot not be erased", tree.pos) + ctx.error("An empty function cannot not be erased", tree.sourcePos) isErased = false } (isImplicit, isErased) @@ -797,7 +797,7 @@ class Typer extends Namer val companion = MethodType.maker(isImplicit = isImplicit, isErased = isErased) val mt = companion.fromSymbols(params1.map(_.symbol), resultTpt.tpe) if (mt.isParamDependent) - ctx.error(i"$mt is an illegal function type because it has inter-parameter dependencies", tree.pos) + ctx.error(i"$mt is an illegal function type because it has inter-parameter dependencies", tree.sourcePos) val resTpt = TypeTree(mt.nonDependentResultApprox).withPos(body.pos) val typeArgs = params1.map(_.tpt) :+ resTpt val tycon = TypeTree(funCls.typeRef) @@ -916,18 +916,18 @@ class Typer extends Namer } case _ => } - errorType(AnonymousFunctionMissingParamType(param, params, tree, pt), param.pos) + errorType(AnonymousFunctionMissingParamType(param, params, tree, pt), param.sourcePos) } def protoFormal(i: Int): Type = if (protoFormals.length == params.length) protoFormals(i) - else errorType(WrongNumberOfParameters(protoFormals.length), tree.pos) + else errorType(WrongNumberOfParameters(protoFormals.length), tree.sourcePos) /** Is `formal` a product type which is elementwise compatible with `params`? */ def ptIsCorrectProduct(formal: Type) = { isFullyDefined(formal, ForceDegree.noBottom) && (defn.isProductSubType(formal) || formal.derivesFrom(defn.PairClass)) && - productSelectorTypes(formal).corresponds(params) { + productSelectorTypes(formal, tree.sourcePos).corresponds(params) { (argType, param) => param.tpt.isEmpty || argType <:< typedAheadType(param.tpt).tpe } @@ -961,7 +961,7 @@ class Typer extends Namer case SAMType(sam) if !defn.isFunctionType(pt) && mt <:< sam => if (!isFullyDefined(pt, ForceDegree.all)) - ctx.error(ex"result type of closure is an underspecified SAM type $pt", tree.pos) + ctx.error(ex"result type of closure is an underspecified SAM type $pt", tree.sourcePos) TypeTree(pt) case _ => if (mt.isParamDependent) { @@ -988,7 +988,7 @@ class Typer extends Namer tree.selector match { case EmptyTree => if (tree.isInline) { - checkInInlineContext("implicit match", tree.pos) + checkInInlineContext("implicit match", tree.sourcePos) val cases1 = tree.cases.mapconserve { case cdef @ CaseDef(pat @ Typed(Ident(nme.WILDCARD), _), _, _) => // case _ : T --> case evidence$n : T @@ -1003,7 +1003,7 @@ class Typer extends Namer typed(desugar.makeCaseLambda(tree.cases, protoFormals.length, unchecked) withPos tree.pos, pt) } case _ => - if (tree.isInline) checkInInlineContext("inline match", tree.pos) + if (tree.isInline) checkInInlineContext("inline match", tree.sourcePos) val sel1 = typedExpr(tree.selector) val selType = fullyDefinedType(sel1.tpe, "pattern selector", tree.pos).widen typedMatchFinish(tree, sel1, selType, tree.cases, pt) @@ -1064,7 +1064,7 @@ class Typer extends Namer val sym = b.symbol if (sym.name != tpnme.WILDCARD) if (ctx.scope.lookup(b.name) == NoSymbol) ctx.enter(sym) - else ctx.error(new DuplicateBind(b, cdef), b.pos) + else ctx.error(new DuplicateBind(b, cdef), b.sourcePos) if (!ctx.isAfterTyper) { val bounds = ctx.gadt.bounds(sym) if (bounds != null) sym.info = bounds @@ -1127,14 +1127,14 @@ class Typer extends Namer def enclMethInfo(cx: Context): (Tree, Type) = { val owner = cx.owner if (owner.isType) { - ctx.error(ReturnOutsideMethodDefinition(owner), tree.pos) + ctx.error(ReturnOutsideMethodDefinition(owner), tree.sourcePos) (EmptyTree, WildcardType) } else if (owner != cx.outer.owner && owner.isRealMethod) { if (owner.isInlineMethod) - (EmptyTree, errorType(NoReturnFromInlineable(owner), tree.pos)) + (EmptyTree, errorType(NoReturnFromInlineable(owner), tree.sourcePos)) else if (!owner.isCompleted) - (EmptyTree, errorType(MissingReturnTypeWithReturnStatement(owner), tree.pos)) + (EmptyTree, errorType(MissingReturnTypeWithReturnStatement(owner), tree.sourcePos)) else { val from = Ident(TermRef(NoPrefix, owner.asTerm)) val proto = returnProto(owner, cx.scope) @@ -1235,13 +1235,13 @@ class Typer extends Namer tree.withType( if (isFullyDefined(pt, ForceDegree.noBottom)) pt else if (ctx.reporter.errorsReported) UnspecifiedErrorType - else errorType(i"cannot infer type; expected type $pt is not fully defined", tree.pos)) + else errorType(i"cannot infer type; expected type $pt is not fully defined", tree.sourcePos)) } } def typedSingletonTypeTree(tree: untpd.SingletonTypeTree)(implicit ctx: Context): SingletonTypeTree = track("typedSingletonTypeTree") { val ref1 = typedExpr(tree.ref) - checkStable(ref1.tpe, tree.pos) + checkStable(ref1.tpe, tree.sourcePos) assignType(cpy.SingletonTypeTree(tree)(ref1), ref1) } @@ -1271,11 +1271,11 @@ class Typer extends Namer checkRefinementNonCyclic(refinement, refineCls, seen) val rsym = refinement.symbol if (rsym.info.isInstanceOf[PolyType] && rsym.allOverriddenSymbols.isEmpty) - ctx.error(PolymorphicMethodMissingTypeInParent(rsym, tpt1.symbol), refinement.pos) + ctx.error(PolymorphicMethodMissingTypeInParent(rsym, tpt1.symbol), refinement.sourcePos) val member = refineCls.info.member(rsym.name) if (member.isOverloaded) { - ctx.error(OverloadInRefinement(rsym), refinement.pos) + ctx.error(OverloadInRefinement(rsym), refinement.sourcePos) } } assignType(cpy.RefinedTypeTree(tree)(tpt1, refinements1), tpt1, refinements1, refineCls) @@ -1285,14 +1285,14 @@ class Typer extends Namer val tpt1 = typed(tree.tpt, AnyTypeConstructorProto)(ctx.retractMode(Mode.Pattern)) val tparams = tpt1.tpe.typeParams if (tparams.isEmpty) { - ctx.error(TypeDoesNotTakeParameters(tpt1.tpe, tree.args), tree.pos) + ctx.error(TypeDoesNotTakeParameters(tpt1.tpe, tree.args), tree.sourcePos) tpt1 } else { var args = tree.args val args1 = { if (args.length != tparams.length) { - wrongNumberOfTypeArgs(tpt1.tpe, tparams, args, tree.pos) + wrongNumberOfTypeArgs(tpt1.tpe, tparams, args, tree.sourcePos) args = args.take(tparams.length) } def typedArg(arg: untpd.Tree, tparam: ParamInfo) = { @@ -1413,7 +1413,7 @@ class Typer extends Namer val sym = ctx.newPatternBoundSymbol(tree.name, symTp, tree.pos) if (pt == defn.ImplicitScrutineeTypeRef) sym.setFlag(Implicit) if (ctx.mode.is(Mode.InPatternAlternative)) - ctx.error(i"Illegal variable ${sym.name} in pattern alternative", tree.pos) + ctx.error(i"Illegal variable ${sym.name} in pattern alternative", tree.sourcePos) assignType(cpy.Bind(tree)(tree.name, body1), sym) } } @@ -1576,7 +1576,7 @@ class Typer extends Namer case cinfo: MethodType => if (!ctx.erasedTypes) { // after constructors arguments are passed in super call. typr.println(i"constr type: $cinfo") - ctx.error(ParameterizedTypeLacksArguments(psym), ref.pos) + ctx.error(ParameterizedTypeLacksArguments(psym), ref.sourcePos) } ref case _ => @@ -1589,7 +1589,7 @@ class Typer extends Namer var result = if (tree.isType) typedType(tree)(superCtx) else typedExpr(tree)(superCtx) val psym = result.tpe.dealias.typeSymbol if (seenParents.contains(psym) && !cls.isRefinementClass) { - if (!ctx.isAfterTyper) ctx.error(i"$psym is extended twice", tree.pos) + if (!ctx.isAfterTyper) ctx.error(i"$psym is extended twice", tree.sourcePos) } else seenParents += psym if (tree.isType) { @@ -1597,8 +1597,8 @@ class Typer extends Namer result = maybeCall(result, psym, psym.primaryConstructor.info) } else checkParentCall(result, cls) - checkTraitInheritance(psym, cls, tree.pos) - if (cls is Case) checkCaseInheritance(psym, cls, tree.pos) + checkTraitInheritance(psym, cls, tree.sourcePos) + if (cls is Case) checkCaseInheritance(psym, cls, tree.sourcePos) result } @@ -1613,7 +1613,7 @@ class Typer extends Namer val other = memberInSelfButNotThis(decl) if (other.exists) { val msg = CannotHaveSameNameAs(decl, other, CannotHaveSameNameAs.DefinedInSelf(self)) - ctx.error(msg, decl.pos) + ctx.error(msg, decl.sourcePos) } foundRedef || other.exists } @@ -1641,7 +1641,7 @@ class Typer extends Namer val impl1 = cpy.Template(impl)(constr1, parents1, self1, body1) .withType(dummy.termRef) if (!cls.is(AbstractOrTrait) && !ctx.isAfterTyper) - checkRealizableBounds(cls, cdef.namePos) + checkRealizableBounds(cls, cdef.sourcePos.withRange(cdef.namePos)) if (cls.is(Case) && cls.derivesFrom(defn.EnumClass)) { val firstParent = parents1.head.tpe.dealias.typeSymbol checkEnum(cdef, cls, firstParent) @@ -1657,10 +1657,10 @@ class Typer extends Namer if (reportDynamicInheritance) { val isRequired = parents1.exists(_.tpe.isRef(defn.DynamicClass)) ctx.featureWarning(nme.dynamics.toString, "extension of type scala.Dynamic", isScala2Feature = true, - cls, isRequired, cdef.pos) + cls, isRequired, cdef.sourcePos) } - checkNonCyclicInherited(cls.thisType, cls.classParents, cls.info.decls, cdef.pos) + checkNonCyclicInherited(cls.thisType, cls.classParents, cls.info.decls, cdef.sourcePos) // check value class constraints checkDerivedValueClass(cls, body1) @@ -1713,7 +1713,7 @@ class Typer extends Namer val pcls = (defn.ObjectClass /: parents)(improve) typr.println(i"ensure first is class $parents%, % --> ${parents map (_ baseType pcls)}%, %") val first = ctx.typeComparer.glb(defn.ObjectType :: parents.map(_.baseType(pcls))) - checkFeasibleParent(first, pos, em" in inferred superclass $first") :: parents + checkFeasibleParent(first, ctx.source.atPos(pos), em" in inferred superclass $first") :: parents } } @@ -1741,8 +1741,8 @@ class Typer extends Namer def typedImport(imp: untpd.Import, sym: Symbol)(implicit ctx: Context): Import = track("typedImport") { val expr1 = typedExpr(imp.expr, AnySelectionProto) - checkStable(expr1.tpe, imp.expr.pos) - if (!ctx.isAfterTyper) checkRealizable(expr1.tpe, imp.expr.pos) + checkStable(expr1.tpe, imp.expr.sourcePos) + if (!ctx.isAfterTyper) checkRealizable(expr1.tpe, imp.expr.sourcePos) assignType(cpy.Import(imp)(expr1, imp.selectors), sym) } @@ -1751,7 +1751,7 @@ class Typer extends Namer val pkg = pid1.symbol pid1 match { case pid1: RefTree if pkg.exists => - if (!pkg.is(Package)) ctx.error(PackageNameAlreadyDefined(pkg), tree.pos) + if (!pkg.is(Package)) ctx.error(PackageNameAlreadyDefined(pkg), tree.sourcePos) val packageCtx = ctx.packageContext(tree, pkg) val stats1 = typedStats(tree.stats, pkg.moduleClass)(packageCtx) cpy.PackageDef(tree)(pid1, stats1).withType(pkg.termRef) @@ -1791,7 +1791,7 @@ class Typer extends Namer case closure(_, _, _) => case _ => val recovered = typed(qual)(ctx.fresh.setExploreTyperState()) - ctx.errorOrMigrationWarning(OnlyFunctionsCanBeFollowedByUnderscore(recovered.tpe.widen), tree.pos) + ctx.errorOrMigrationWarning(OnlyFunctionsCanBeFollowedByUnderscore(recovered.tpe.widen), tree.sourcePos) if (ctx.scala2Mode) { // Under -rewrite, patch `x _` to `(() => x)` patch(Position(tree.pos.start), "(() => ") @@ -1812,7 +1812,7 @@ class Typer extends Namer if ((prefix ++ suffix).isEmpty) "simply leave out the trailing ` _`" else s"use `$prefix$suffix` instead" ctx.errorOrMigrationWarning(i"""The syntax ` _` is no longer supported; - |you can $remedy""", tree.pos) + |you can $remedy""", tree.sourcePos) if (ctx.scala2Mode) { patch(Position(tree.pos.start), prefix) patch(Position(qual.pos.end, tree.pos.end), suffix) @@ -2015,7 +2015,7 @@ class Typer extends Namer try adapt(typedUnadapted(tree, pt, locked), pt, locked) catch { case ex: TypeError => - errorTree(tree, ex.toMessage, tree.pos.focus) + errorTree(tree, ex.toMessage, tree.sourcePos.focus) // This uses tree.pos.focus instead of the default tree.pos, because: // - since tree can be a top-level definition, tree.pos can point to the whole definition // - that would in turn hide all other type errors inside tree. @@ -2259,8 +2259,8 @@ class Typer extends Namer def missingArgs(mt: MethodType) = { val meth = methPart(tree).symbol - if (mt.paramNames.length == 0) ctx.error(MissingEmptyArgumentList(meth), tree.pos) - else ctx.error(em"missing arguments for $meth", tree.pos) + if (mt.paramNames.length == 0) ctx.error(MissingEmptyArgumentList(meth), tree.sourcePos) + else ctx.error(em"missing arguments for $meth", tree.sourcePos) tree.withType(mt.resultType) } @@ -2398,7 +2398,7 @@ class Typer extends Namer case failure: SearchFailureType => ctx.error( missingArgMsg(arg, formal, implicitParamString(paramName, methodStr, tree)), - tree.pos.endPos) + tree.sourcePos.endPos) case _ => } } @@ -2467,7 +2467,7 @@ class Typer extends Namer def isAutoApplied(sym: Symbol): Boolean = { sym.isConstructor || sym.matchNullaryLoosely || - ctx.testScala2Mode(MissingEmptyArgumentList(sym), tree.pos, + ctx.testScala2Mode(MissingEmptyArgumentList(sym), tree.sourcePos, patch(tree.pos.endPos, "()")) } @@ -2633,14 +2633,14 @@ class Typer extends Namer case SelectionProto(name, mbrType, _, _) => def tryExtension(implicit ctx: Context): Tree = try { - findRef(name, WildcardType, ExtensionMethod, tree.pos) match { + findRef(name, WildcardType, ExtensionMethod, tree) match { case ref: TermRef => extMethodApply(untpd.ref(ref).withPos(tree.pos), tree, mbrType) case _ => EmptyTree } } catch { - case ex: TypeError => errorTree(tree, ex.toMessage, tree.pos) + case ex: TypeError => errorTree(tree, ex.toMessage, tree.sourcePos) } val nestedCtx = ctx.fresh.setNewTyperState() val app = tryExtension(nestedCtx) @@ -2663,7 +2663,7 @@ class Typer extends Namer case SearchSuccess(inferred: ExtMethodApply, _, _) => inferred // nothing to check or adapt for extension method applications case SearchSuccess(inferred, _, _) => - checkImplicitConversionUseOK(inferred.symbol, tree.pos) + checkImplicitConversionUseOK(inferred.symbol, tree.sourcePos) readapt(inferred)(ctx.retractMode(Mode.ImplicitsEnabled)) case failure: SearchFailure => if (pt.isInstanceOf[ProtoType] && !failure.isAmbiguous) @@ -2703,7 +2703,7 @@ class Typer extends Namer * tree that went unreported. A scenario where this happens is i1802.scala. */ def ensureReported(tp: Type) = tp match { - case err: ErrorType if !ctx.reporter.errorsReported => ctx.error(err.msg, tree.pos) + case err: ErrorType if !ctx.reporter.errorsReported => ctx.error(err.msg, tree.sourcePos) case _ => } @@ -2774,6 +2774,6 @@ class Typer extends Namer private def checkStatementPurity(tree: tpd.Tree)(original: untpd.Tree, exprOwner: Symbol)(implicit ctx: Context): Unit = { if (!ctx.isAfterTyper && isPureExpr(tree) && !tree.tpe.isRef(defn.UnitClass) && !isSelfOrSuperConstrCall(tree)) - ctx.warning(PureExpressionInStatementPosition(original, exprOwner), original.pos) + ctx.warning(PureExpressionInStatementPosition(original, exprOwner), original.sourcePos) } } diff --git a/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala b/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala index fe59723ed3c0..688a0cda3557 100644 --- a/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala +++ b/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala @@ -9,6 +9,7 @@ import Variances._ import NameKinds._ import TypeApplications.varianceConforms import util.Positions._ +import util.SourcePosition import config.Printers.variances import reporting.trace @@ -38,8 +39,8 @@ object VarianceChecker { } val pos = tree.tparams .find(_.name.toTermName == paramName) - .map(_.pos) - .getOrElse(tree.pos) + .map(_.sourcePos) + .getOrElse(tree.sourcePos) ctx.error(em"${paramVarianceStr}variant type parameter $paramName occurs in ${occursStr}variant position in ${tl.resType}", pos) } def apply(x: Boolean, t: Type) = x && { @@ -151,12 +152,14 @@ class VarianceChecker()(implicit ctx: Context) { } private object Traverser extends TreeTraverser { - def checkVariance(sym: Symbol, pos: Position) = Validator.validateDefinition(sym) match { + def checkVariance(sym: Symbol, pos: SourcePosition) = Validator.validateDefinition(sym) match { case Some(VarianceError(tvar, required)) => def msg = i"${varianceString(tvar.flags)} $tvar occurs in ${varianceString(required)} position in type ${sym.info} of $sym" if (ctx.scala2Mode && (sym.owner.isConstructor || sym.ownersIterator.exists(_.is(ProtectedLocal)))) { - ctx.migrationWarning(s"According to new variance rules, this is no longer accepted; need to annotate with @uncheckedVariance:\n$msg", pos) + ctx.migrationWarning( + s"According to new variance rules, this is no longer accepted; need to annotate with @uncheckedVariance:\n$msg", + pos) // patch(Position(pos.end), " @scala.annotation.unchecked.uncheckedVariance") // Patch is disabled until two TODOs are solved: // TODO use an import or shorten if possible @@ -178,15 +181,15 @@ class VarianceChecker()(implicit ctx: Context) { case defn: MemberDef if skip => ctx.debuglog(s"Skipping variance check of ${sym.showDcl}") case tree: TypeDef => - checkVariance(sym, tree.pos) + checkVariance(sym, tree.sourcePos) tree.rhs match { case rhs: Template => traverseChildren(rhs) case _ => } case tree: ValDef => - checkVariance(sym, tree.pos) + checkVariance(sym, tree.sourcePos) case DefDef(_, tparams, vparamss, _, _) => - checkVariance(sym, tree.pos) + checkVariance(sym, tree.sourcePos) tparams foreach traverse vparamss foreach (_ foreach traverse) case _ => diff --git a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala index 2731551c501a..6385aa6c73c1 100644 --- a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala +++ b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala @@ -55,7 +55,12 @@ extends interfaces.SourcePosition with Showable { def endLine: Int = source.offsetToLine(end) def endColumn: Int = source.column(end) - def withOuter(outer: SourcePosition): SourcePosition = new SourcePosition(source, pos, outer) + def withOuter(outer: SourcePosition): SourcePosition = SourcePosition(source, pos, outer) + def withRange(range: Position) = SourcePosition(source, range, outer) + + def startPos: SourcePosition = withRange(pos.startPos) + def endPos : SourcePosition = withRange(pos.endPos) + def focus : SourcePosition = withRange(pos.focus) override def toString: String = s"${if (source.exists) source.file.toString else "(no source)"}:$pos" diff --git a/compiler/src/dotty/tools/io/VirtualFile.scala b/compiler/src/dotty/tools/io/VirtualFile.scala index 8206e50baaf2..a790fc02a3d3 100644 --- a/compiler/src/dotty/tools/io/VirtualFile.scala +++ b/compiler/src/dotty/tools/io/VirtualFile.scala @@ -15,6 +15,7 @@ import java.io.{ ByteArrayInputStream, ByteArrayOutputStream, InputStream, Outpu * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class VirtualFile(val name: String, override val path: String) extends AbstractFile { + /** * Initializes this instance with the specified name and an * identical path. diff --git a/tests/neg/quote-0.scala b/tests/neg/quote-0.scala index 6ee4c560c1a4..3e4231281300 100644 --- a/tests/neg/quote-0.scala +++ b/tests/neg/quote-0.scala @@ -14,8 +14,8 @@ class Test { '((y: Expr[Int]) => ~y ) // error: wrong staging level - def f[T](t: Type[T], x: Expr[T]) = '{ - val z2 = ~x // error: wrong staging level + def f[T](t: Type[T], x: Expr[T]) = '{ // error: wrong staging level + val z2 = ~x } def g[T](implicit t: Type[T], x: Expr[T]) = '{ diff --git a/tests/plugins/neg/divideZero-research/plugin_1.scala b/tests/plugins/neg/divideZero-research/plugin_1.scala index 4b255faa1266..45ef30a41150 100644 --- a/tests/plugins/neg/divideZero-research/plugin_1.scala +++ b/tests/plugins/neg/divideZero-research/plugin_1.scala @@ -30,7 +30,7 @@ class DivideZero extends MiniPhase with ResearchPlugin { override def transformApply(tree: tpd.Apply)(implicit ctx: Context): tpd.Tree = tree match { case tpd.Apply(fun, tpd.Literal(Constants.Constant(v)) :: Nil) if isNumericDivide(fun.symbol) && v == 0 => - ctx.error("divide by zero", tree.pos) + ctx.error("divide by zero", tree.sourcePos) tree case _ => tree diff --git a/tests/plugins/neg/divideZero/plugin_1.scala b/tests/plugins/neg/divideZero/plugin_1.scala index 97b3dfa22ee2..fb27821f59e7 100644 --- a/tests/plugins/neg/divideZero/plugin_1.scala +++ b/tests/plugins/neg/divideZero/plugin_1.scala @@ -31,7 +31,7 @@ class DivideZero extends PluginPhase with StandardPlugin { override def transformApply(tree: tpd.Apply)(implicit ctx: Context): tpd.Tree = tree match { case tpd.Apply(fun, tpd.Literal(Constants.Constant(v)) :: Nil) if isNumericDivide(fun.symbol) && v == 0 => - ctx.error("divide by zero", tree.pos) + ctx.error("divide by zero", tree.sourcePos) tree case _ => tree From 8d9f3caeaba1fc442c8d89d6be7c586f81af0eaf Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 25 Dec 2018 19:11:17 +0100 Subject: [PATCH 17/75] Fix position of inline bodies in unpickler. --- .../src/dotty/tools/dotc/core/Contexts.scala | 4 ++- .../tools/dotc/core/tasty/TreeUnpickler.scala | 34 ++++++++++++------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 54129d191d69..4ab293659d7a 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -435,6 +435,7 @@ object Contexts { this.implicitsCache = null this.phasedCtx = this this.phasedCtxs = null + this.sourceCtx = null // See comment related to `creationTrace` in this file // setCreationTrace() this @@ -446,12 +447,13 @@ object Contexts { final def withOwner(owner: Symbol): Context = if (owner ne this.owner) fresh.setOwner(owner) else this - private var sourceCtx: SimpleIdentityMap[SourceFile, Context] = SimpleIdentityMap.Empty + private var sourceCtx: SimpleIdentityMap[SourceFile, Context] = null final def withSource(source: SourceFile): Context = if (source `eq` this.source) this else if ((source `eq` outer.source) && (outer.sourceCtx(this.source) `eq` this)) outer else { + if (sourceCtx == null) sourceCtx = SimpleIdentityMap.Empty val prev = sourceCtx(source) if (prev != null) prev else { diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 1dc04493d4f0..b469e0ebc275 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -20,6 +20,7 @@ import typer.ConstFold import typer.Checking.checkNonCyclic import util.Positions._ import util.SourceFile +import io.AbstractFile import ast.{TreeTypeMap, Trees, tpd, untpd} import Trees._ import Decorators._ @@ -35,6 +36,7 @@ import core.quoted.PickledQuotes import scala.quoted import scala.quoted.Types.TreeType import scala.quoted.Exprs.TastyTreeExpr +import scala.annotation.transientParam import scala.annotation.internal.sharable /** Unpickler for typed trees @@ -105,12 +107,14 @@ class TreeUnpickler(reader: TastyReader, } } - class Completer(owner: Symbol, reader: TastyReader) extends LazyType { + class Completer(reader: TastyReader)(implicit @transientParam ctx: Context) extends LazyType { import reader._ + val owner = ctx.owner + val source = ctx.source def complete(denot: SymDenotation)(implicit ctx: Context): Unit = { treeAtAddr(currentAddr) = new TreeReader(reader).readIndexedDef()( - ctx.withPhaseNoLater(ctx.picklerPhase).withOwner(owner)) + ctx.withPhaseNoLater(ctx.picklerPhase).withOwner(owner).withSource(source)) } } @@ -541,13 +545,13 @@ class TreeUnpickler(reader: TastyReader, pickling.println(i"overwriting ${rootd.symbol} # ${rootd.hashCode}") rootd.symbol.coord = coord rootd.info = adjustIfModule( - new Completer(ctx.owner, subReader(start, end)) with SymbolLoaders.SecondCompleter) + new Completer(subReader(start, end)) with SymbolLoaders.SecondCompleter) rootd.flags = flags &~ Touched // allow one more completion rootd.privateWithin = privateWithin seenRoots += rootd.symbol rootd.symbol case _ => - val completer = adjustIfModule(new Completer(ctx.owner, subReader(start, end))) + val completer = adjustIfModule(new Completer(subReader(start, end))) if (isClass) ctx.newClassSymbol(ctx.owner, name.asTypeName, flags, completer, privateWithin, coord) else @@ -565,7 +569,8 @@ class TreeUnpickler(reader: TastyReader, } else if (sym.isInlineMethod) sym.addAnnotation(LazyBodyAnnotation { ctx0 => - implicit val ctx: Context = localContext(sym)(ctx0).addMode(Mode.ReadPositions) + val ctx1 = localContext(sym)(ctx0).addMode(Mode.ReadPositions) + implicit val ctx: Context = sourceChangeContext(Addr(0))(ctx1) // avoids space leaks by not capturing the current context forkAt(rhsStart).readTerm() }) @@ -690,9 +695,11 @@ class TreeUnpickler(reader: TastyReader, /** Process package with given operation `op`. The operation takes as arguments * - a `RefTree` representing the `pid` of the package, * - an end address, - * - a context which has the processd package as owner + * - a context which has the processed package as owner */ def processPackage[T](op: (RefTree, Addr) => Context => T)(implicit ctx: Context): T = { + val sctx = sourceChangeContext() + if (sctx `ne` ctx) return processPackage(op)(sctx) readByte() val end = readEnd() val pid = ref(readTermRef()).asInstanceOf[RefTree] @@ -735,7 +742,7 @@ class TreeUnpickler(reader: TastyReader, } private def readNewDef()(implicit ctx: Context): Tree = { - val sctx = sourceChangeContext + val sctx = sourceChangeContext() if (sctx `ne` ctx) return readNewDef()(sctx) val start = currentAddr val sym = symAtAddr(start) @@ -843,7 +850,7 @@ class TreeUnpickler(reader: TastyReader, goto(end) setPos(start, tree) if (!sym.isType) { // Only terms might have leaky aliases, see the documentation of `checkNoPrivateLeaks` - sym.info = ta.avoidPrivateLeaks(sym, tree.pos) + sym.info = ta.avoidPrivateLeaks(sym, tree.sourcePos) } sym.defTree = tree @@ -993,7 +1000,7 @@ class TreeUnpickler(reader: TastyReader, // ------ Reading trees ----------------------------------------------------- def readTerm()(implicit ctx: Context): Tree = { // TODO: rename to readTree - val sctx = sourceChangeContext + val sctx = sourceChangeContext() if (sctx `ne` ctx) return readTerm()(sctx) val start = currentAddr val tag = readByte() @@ -1236,7 +1243,7 @@ class TreeUnpickler(reader: TastyReader, } def readCase()(implicit ctx: Context): CaseDef = { - val sctx = sourceChangeContext + val sctx = sourceChangeContext() if (sctx `ne` ctx) return readCase()(sctx) val start = currentAddr assert(readByte() == CASEDEF) @@ -1300,9 +1307,10 @@ class TreeUnpickler(reader: TastyReader, /** If currentAddr carries a source path, the current context with * the source of that path, otherwise the current context itself. */ - def sourceChangeContext(implicit ctx: Context): Context = { - val path = sourcePathAt(currentAddr) - if (path.nonEmpty) ctx.withSource(ctx.getSource(path)) else ctx + def sourceChangeContext(addr: Addr = currentAddr)(implicit ctx: Context): Context = { + val path = sourcePathAt(addr) + if (path.nonEmpty) ctx.withSource(ctx.getSource(path)) + else ctx } /** Coordinate for the symbol at `addr`. */ From 1ce8b59b6058f41a44627774cb6270b95aa092c9 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 31 Dec 2018 10:44:40 +0100 Subject: [PATCH 18/75] Lazy load contents of source position --- compiler/src/dotty/tools/dotc/CompilationUnit.scala | 4 ++-- compiler/src/dotty/tools/dotc/ast/Trees.scala | 4 +--- compiler/src/dotty/tools/dotc/core/Symbols.scala | 2 +- compiler/src/dotty/tools/dotc/util/SourceFile.scala | 7 ++++++- doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/CompilationUnit.scala b/compiler/src/dotty/tools/dotc/CompilationUnit.scala index 00527db565a8..cdd92078d1db 100644 --- a/compiler/src/dotty/tools/dotc/CompilationUnit.scala +++ b/compiler/src/dotty/tools/dotc/CompilationUnit.scala @@ -34,9 +34,9 @@ class CompilationUnit(val source: SourceFile) { object CompilationUnit { - /** Make a compilation unit for top class `clsd` with the contends of the `unpickled` */ + /** Make a compilation unit for top class `clsd` with the contents of the `unpickled` tree */ def mkCompilationUnit(clsd: ClassDenotation, unpickled: Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit = - mkCompilationUnit(SourceFile(clsd.symbol.associatedFile, Array.empty), unpickled, forceTrees) + mkCompilationUnit(new SourceFile(clsd.symbol.associatedFile, Array.empty[Char]), unpickled, forceTrees) /** Make a compilation unit, given picked bytes and unpickled tree */ def mkCompilationUnit(source: SourceFile, unpickled: Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit = { diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index b330a16ac73d..d2849900a9d5 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -67,9 +67,7 @@ object Trees { def uniqueId: Int = myUniqueId - def sourceFile(implicit ctx: Context): AbstractFile = TreeIds.fileOfId(uniqueId) - - def source(implicit ctx: Context): SourceFile = ctx.getSource(sourceFile) + def source(implicit ctx: Context): SourceFile = ctx.getSource(TreeIds.fileOfId(uniqueId)) def sourcePos(implicit ctx: Context): SourcePosition = source.atPos(pos) diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 2c4f5f62ceae..71abe1cffbc7 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -627,7 +627,7 @@ object Symbols { final def sourceFile(implicit ctx: Context): AbstractFile = { val file = associatedFile if (file != null && file.extension != "class") file - else if (!defTree.isEmpty) defTree.sourceFile + else if (!defTree.isEmpty) defTree.source.file else { val topLevelCls = denot.topLevelClass(ctx.withPhaseNoLater(ctx.flattenPhase)) topLevelCls.unforcedAnnotation(defn.SourceFileAnnot) match { diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index 4ad599ccec71..00258f7a5d29 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -34,7 +34,9 @@ object ScriptSourceFile { } } -case class SourceFile(file: AbstractFile, content: Array[Char]) extends interfaces.SourceFile { +class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends interfaces.SourceFile { + + lazy val content = computeContent def this(file: AbstractFile, codec: Codec) = this(file, new String(file.toByteArray, codec.charSet).toCharArray) def this(name: String, content: String) = this(new VirtualFile(name), content.toCharArray) @@ -147,6 +149,9 @@ case class SourceFile(file: AbstractFile, content: Array[Char]) extends interfac override def toString: String = file.toString } +object SourceFile { + implicit def eqSurce: Eq[SourceFile, SourceFile] = Eq +} @sharable object NoSource extends SourceFile(NoAbstractFile, Array[Char]()) { override def exists: Boolean = false diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala index 1e656ee4f37d..89c6ca0f7e96 100644 --- a/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala +++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala @@ -415,7 +415,7 @@ case class Site( } private def toSourceFile(f: JFile): SourceFile = - SourceFile(AbstractFile.getFile(new File(f.toPath)), Source.fromFile(f, "UTF-8").toArray) + new SourceFile(AbstractFile.getFile(new File(f.toPath)), Source.fromFile(f, "UTF-8").toArray) private def collectFiles(dir: JFile, includes: String => Boolean): Array[JFile] = dir From 3c56fa6d752a6d0571ad86338b5be51ea2d7bf77 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 31 Dec 2018 11:00:59 +0100 Subject: [PATCH 19/75] Print full source positions in trees --- compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala | 2 +- compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 4255a8a175f7..2dc13277ed38 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -502,7 +502,7 @@ class PlainPrinter(_ctx: Context) extends Printer { else Text() - nodeName ~ "(" ~ elems ~ tpSuffix ~ ")" ~ (Str(tree.pos.toString) provided ctx.settings.YprintPos.value) + nodeName ~ "(" ~ elems ~ tpSuffix ~ ")" ~ (Str(tree.sourcePos.toString) provided ctx.settings.YprintPos.value) }.close // todo: override in refined printer def toText(pos: SourcePosition): Text = diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index c289172e7f01..fc3ebda70944 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -604,8 +604,10 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { if (!suppressPositions) { if (printPos) { val pos = - if (homogenizedView && !tree.isInstanceOf[MemberDef]) tree.pos.toSynthetic - else tree.pos + if (homogenizedView) + if (tree.isInstanceOf[MemberDef]) tree.pos + else tree.pos.toSynthetic + else tree.sourcePos val clsStr = ""//if (tree.isType) tree.getClass.toString else "" txt = (txt ~ "@" ~ pos.toString ~ clsStr).close } From 4a5d09aec43be6de1d9c4b934582b38ae8ccfe10 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 31 Dec 2018 11:11:10 +0100 Subject: [PATCH 20/75] Fix dropInlined --- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index def087ee645c..893d4ebe0119 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -123,7 +123,7 @@ object Inliner { if (enclosingInlineds.nonEmpty) inlined // Remove in the outer most inlined call else { val inlinedAtPos = inlined.call.pos - val callSourceFile = ctx.source.file + val callSourceFile = ctx.compilationUnit.source.file /** Removes all Inlined trees, replacing them with blocks. * Repositions all trees directly inside an inlined expansion of a non empty call to the position of the call. From 9f54f736e101af1e03458f396ed50c36a8570eed Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 31 Dec 2018 12:22:48 +0100 Subject: [PATCH 21/75] Check sources correspond under -Ytest-pickler --- .../dotty/tools/dotc/printing/RefinedPrinter.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index fc3ebda70944..7a351f800d20 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -603,17 +603,17 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { } if (!suppressPositions) { if (printPos) { - val pos = + val posStr = if (homogenizedView) - if (tree.isInstanceOf[MemberDef]) tree.pos - else tree.pos.toSynthetic - else tree.sourcePos + if (tree.isInstanceOf[MemberDef]) s"${tree.source}${tree.pos}" + else s"${tree.source}${tree.pos.toSynthetic}" + else tree.sourcePos.toString val clsStr = ""//if (tree.isType) tree.getClass.toString else "" - txt = (txt ~ "@" ~ pos.toString ~ clsStr).close + txt = (txt ~ "@" ~ posStr ~ clsStr).close } if (ctx.settings.YprintPosSyms.value && tree.isDef) txt = (txt ~ - s"@@(${tree.symbol.name}=" ~ tree.symbol.pos.toString ~ ")").close + s"@@(${tree.symbol.name}=" ~ tree.symbol.sourcePos.toString ~ ")").close } if (ctx.settings.YshowTreeIds.value) txt = (txt ~ "#" ~ tree.uniqueId.toString).close From 30008ae507104cdd8aabaf007ef6ad3722688506 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 31 Dec 2018 18:10:44 +0100 Subject: [PATCH 22/75] Fix PositionPickler Generate a position entry if sourcefiles change. --- .../src/dotty/tools/dotc/core/tasty/PositionPickler.scala | 5 ++++- compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala index 6910a8252444..b06b585b7dae 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala @@ -70,7 +70,10 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad case x: untpd.Tree => var sourceFile = current val pos = if (x.isInstanceOf[untpd.MemberDef]) x.pos else x.pos.toSynthetic - if (pos.exists && (pos != x.initialPos.toSynthetic || alwaysNeedsPos(x))) { + if (pos.exists && ( + pos != x.initialPos.toSynthetic || + x.source.file != current || + alwaysNeedsPos(x))) { addrOfTree(x) match { case Some(addr) if !pickledIndices.contains(addr.index) => //println(i"pickling $x with $pos at $addr") diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index b469e0ebc275..98d57f7a153c 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -276,7 +276,7 @@ class TreeUnpickler(reader: TastyReader, def readType()(implicit ctx: Context): Type = { val start = currentAddr val tag = readByte() - pickling.println(s"reading type ${astTagToString(tag)} at $start") + pickling.println(s"reading type ${astTagToString(tag)} at $start, ${ctx.source}") def registeringType[T](tp: Type, op: => T): T = { typeAtAddr(start) = tp @@ -1004,7 +1004,7 @@ class TreeUnpickler(reader: TastyReader, if (sctx `ne` ctx) return readTerm()(sctx) val start = currentAddr val tag = readByte() - pickling.println(s"reading term ${astTagToString(tag)} at $start") + pickling.println(s"reading term ${astTagToString(tag)} at $start, ${ctx.source}") def readPathTerm(): Tree = { goto(start) From ed27a4e13e7e49a329f0a4b851c78282525d3d79 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 31 Dec 2018 18:13:13 +0100 Subject: [PATCH 23/75] Make Inliner source-position aware --- .../src/dotty/tools/dotc/ast/Positioned.scala | 3 -- compiler/src/dotty/tools/dotc/ast/Trees.scala | 29 ++++++++++++- .../src/dotty/tools/dotc/typer/Inliner.scala | 43 ++++++++++--------- .../tools/dotc/util/SourcePosition.scala | 2 +- 4 files changed, 51 insertions(+), 26 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index 81244890f984..1af06b453a29 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -41,9 +41,6 @@ abstract class Positioned extends Product { newpd.asInstanceOf[this.type] } - def withPos(posd: Positioned)(implicit src: SourceInfo): this.type = - if (posd == null) this else withPos(posd.pos) - /** This item with a position that's the union of the given `pos` and the * current position. */ diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index d2849900a9d5..9dd81fb137f9 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -71,6 +71,26 @@ object Trees { def sourcePos(implicit ctx: Context): SourcePosition = source.atPos(pos) + def withPos(posd: Tree[_])(implicit ctx: Context): this.type = { + val tree1 = + if (posd.source == source && (posd.pos == pos || posd.pos.isSynthetic)) this + else cloned(ctx.withSource(posd.source)) + tree1.setPos(sourcePos.pos) + tree1.asInstanceOf[this.type] + } + + def withSource(source: SourceFile)(implicit ctx: Context): Tree[T] = + if (source == this.source) this + else cloned(ctx.withSource(source)) + + def withSourcePos(sourcePos: SourcePosition)(implicit ctx: Context): this.type = { + val tree1 = + if (sourcePos.source == source && (sourcePos.pos == pos || pos.isSynthetic)) this + else cloned(ctx.withSource(sourcePos.source)) + tree1.setPos(sourcePos.pos) + tree1.asInstanceOf[this.type] + } + /** The type constructor at the root of the tree */ type ThisTree[T >: Untyped] <: Tree[T] @@ -790,6 +810,8 @@ object Trees { override def withTypeUnchecked(tpe: Type): ThisTree[Type] = this.asInstanceOf[ThisTree[Type]] override def pos: Position = NoPosition override def setPos(pos: Position): Unit = {} + override def withSource(source: SourceFile)(implicit ctx: Context): Tree[T] = this + override def withSourcePos(sourcePos: SourcePosition)(implicit ctx: Context): this.type = this } /** Temporary class that results from translation of ModuleDefs @@ -817,7 +839,9 @@ object Trees { trees foreach (_.foreachInThicket(op)) } - class EmptyTree[T >: Untyped] extends Thicket(Nil)(NoContext) + class EmptyTree[T >: Untyped] extends Thicket(Nil)(NoContext) { + assert(uniqueId != 1492) + } class EmptyValDef[T >: Untyped] extends ValDef[T]( nme.WILDCARD, genericEmptyTree[T], genericEmptyTree[T])(NoContext) with WithoutTypeOrPos[T] { @@ -1032,7 +1056,8 @@ object Trees { } def Typed(tree: Tree)(expr: Tree, tpt: Tree)(implicit ctx: Context): Typed = tree match { case tree: Typed if (expr eq tree.expr) && (tpt eq tree.tpt) => tree - case _ => finalize(tree, untpd.Typed(expr, tpt)(srcCtx(tree))) + case tree => finalize(tree, untpd.Typed(expr, tpt)(srcCtx(tree))) + //.ensuring(res => res.uniqueId != 1471, s"source = $tree, ${tree.uniqueId}") } def NamedArg(tree: Tree)(name: Name, arg: Tree)(implicit ctx: Context): NamedArg = tree match { case tree: NamedArg if (name == tree.name) && (arg eq tree.arg) => tree diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 893d4ebe0119..9ae61c1fd4b3 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -63,15 +63,15 @@ object Inliner { */ def inlineCall(tree: Tree, pt: Type)(implicit ctx: Context): Tree = { - /** Set the position of all trees logically contained in the expansion of - * inlined call `call` to the position of `call`. This transform is necessary - * when lifting bindings from the expansion to the outside of the call. - */ + /** Set the position of all trees logically contained in the expansion of + * inlined call `call` to the position of `call`. This transform is necessary + * when lifting bindings from the expansion to the outside of the call. + */ def liftFromInlined(call: Tree) = new TreeMap { override def transform(t: Tree)(implicit ctx: Context) = { t match { case Inlined(t, Nil, expr) if t.isEmpty => expr - case _ => super.transform(t.withPos(call.pos)) + case _ => super.transform(t.withSourcePos(call.sourcePos)) } } } @@ -122,8 +122,8 @@ object Inliner { def dropInlined(inlined: Inlined)(implicit ctx: Context): Tree = { if (enclosingInlineds.nonEmpty) inlined // Remove in the outer most inlined call else { - val inlinedAtPos = inlined.call.pos - val callSourceFile = ctx.compilationUnit.source.file + val inlinedAtPos = inlined.call.sourcePos + val curSourceFile = ctx.compilationUnit.source.file /** Removes all Inlined trees, replacing them with blocks. * Repositions all trees directly inside an inlined expansion of a non empty call to the position of the call. @@ -136,10 +136,10 @@ object Inliner { case _ => val transformed = super.transform(tree) enclosingInlineds match { - case call :: _ if call.symbol.sourceFile != callSourceFile => + case call :: _ if call.symbol.sourceFile != curSourceFile => // Until we implement JSR-45, we cannot represent in output positions in other source files. // So, reposition inlined code from other files with the call position: - transformed.withPos(inlinedAtPos) + transformed.withSourcePos(inlinedAtPos) case _ => transformed } } @@ -159,8 +159,8 @@ object Inliner { * in the call field of an Inlined node. * The trace has enough info to completely reconstruct positions. */ - def inlineCallTrace(callSym: Symbol, pos: Position)(implicit ctx: Context): Tree = - Ident(callSym.topLevelClass.typeRef).withPos(pos) + def inlineCallTrace(callSym: Symbol, pos: SourcePosition)(implicit ctx: Context): Tree = + Ident(callSym.topLevelClass.typeRef).withSourcePos(pos) } /** Produces an inlined version of `call` via its `inlined` method. @@ -235,7 +235,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { val binding = { if (isByName) DefDef(boundSym, arg.changeOwner(ctx.owner, boundSym)) else ValDef(boundSym, arg) - }.withPos(boundSym.pos) + }.withSourcePos(boundSym.sourcePos) boundSym.defTree = binding bindingsBuf += binding binding @@ -289,7 +289,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { ref(rhsClsSym.sourceModule) else inlineCallPrefix - val binding = ValDef(selfSym.asTerm, rhs).withPos(selfSym.pos) + val binding = ValDef(selfSym.asTerm, rhs).withSourcePos(selfSym.sourcePos) bindingsBuf += binding selfSym.defTree = binding inlining.println(i"proxy at $level: $selfSym = ${bindingsBuf.last}") @@ -347,13 +347,14 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { */ def integrate(tree: Tree, originalOwner: Symbol)(implicit ctx: Context): Tree = { val result = tree.changeOwner(originalOwner, ctx.owner) - if (!originalOwner.isContainedIn(inlinedMethod)) Inlined(EmptyTree, Nil, result) + if (!originalOwner.isContainedIn(inlinedMethod)) + Inlined(EmptyTree, Nil, result)(ctx.withSource(tree.source)).withPos(tree.pos) else result } def tryConstValue: Tree = ctx.typeComparer.constValue(callTypeArgs.head.tpe) match { - case Some(c) => Literal(c).withPos(call.pos) + case Some(c) => Literal(c)(ctx.withSource(call.source)).withPos(call.pos) case _ => EmptyTree } @@ -410,15 +411,17 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { tree.tpe match { case thistpe: ThisType => thisProxy.get(thistpe.cls) match { - case Some(t) => ref(t).withPos(tree.pos) + case Some(t) => ref(t).withSourcePos(tree.sourcePos) case None => tree } case _ => tree } case tree: Ident => paramProxy.get(tree.tpe) match { - case Some(t) if tree.isTerm && t.isSingleton => singleton(t.dealias).withPos(tree.pos) - case Some(t) if tree.isType => TypeTree(t).withPos(tree.pos) + case Some(t) if tree.isTerm && t.isSingleton => + singleton(t.dealias).withSourcePos(tree.sourcePos) + case Some(t) if tree.isType => + TypeTree(t).withSourcePos(tree.sourcePos) case _ => tree } case tree => tree @@ -429,7 +432,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { // Apply inliner to `rhsToInline`, split off any implicit bindings from result, and // make them part of `bindingsBuf`. The expansion is then the tree that remains. - val expansion = inliner.transform(rhsToInline.withPos(call.pos)) + val expansion = inliner.transform(rhsToInline.withSourcePos(call.sourcePos)) def issueError() = callValueArgss match { case (msgArg :: rest) :: Nil => @@ -595,7 +598,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { case _ => binding } - binding1.withPos(call.pos) + binding1.withSourcePos(call.sourcePos) } /** An extractor for references to inlineable arguments. These are : diff --git a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala index 6385aa6c73c1..f536d1d16266 100644 --- a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala +++ b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala @@ -5,7 +5,6 @@ package util import printing.{Showable, Printer} import printing.Texts._ import Positions.{Position, NoPosition} - import scala.annotation.internal.sharable /** A source position is comprised of a position in a source file */ @@ -61,6 +60,7 @@ extends interfaces.SourcePosition with Showable { def startPos: SourcePosition = withRange(pos.startPos) def endPos : SourcePosition = withRange(pos.endPos) def focus : SourcePosition = withRange(pos.focus) + def toSynthetic: SourcePosition = withRange(pos.toSynthetic) override def toString: String = s"${if (source.exists) source.file.toString else "(no source)"}:$pos" From a1e367bd442e3016c0abd9103c8545788bdd7f60 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 1 Jan 2019 11:36:44 +0100 Subject: [PATCH 24/75] Fix Symbol#sourceFile defTree should take precedence over associated files. This matters for inlined code. --- .../src/dotty/tools/dotc/core/Symbols.scala | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 71abe1cffbc7..cf1db9803f81 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -624,21 +624,22 @@ object Symbols { type DontUseSymbolOnSymbol /** The source file from which this class was generated, null if not applicable. */ - final def sourceFile(implicit ctx: Context): AbstractFile = { - val file = associatedFile - if (file != null && file.extension != "class") file - else if (!defTree.isEmpty) defTree.source.file + final def sourceFile(implicit ctx: Context): AbstractFile = + if (!defTree.isEmpty) defTree.source.file else { - val topLevelCls = denot.topLevelClass(ctx.withPhaseNoLater(ctx.flattenPhase)) - topLevelCls.unforcedAnnotation(defn.SourceFileAnnot) match { - case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match { - case Some(Constant(path: String)) => AbstractFile.getFile(path) + val file = associatedFile + if (file != null && file.extension != "class") file + else { + val topLevelCls = denot.topLevelClass(ctx.withPhaseNoLater(ctx.flattenPhase)) + topLevelCls.unforcedAnnotation(defn.SourceFileAnnot) match { + case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match { + case Some(Constant(path: String)) => AbstractFile.getFile(path) + case none => null + } case none => null } - case none => null } } - } def source(implicit ctx: Context): SourceFile = ctx.getSource(sourceFile) From 56b313ae5e84a44dc70a6ae03baa384ad7f850db Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 1 Jan 2019 11:59:31 +0100 Subject: [PATCH 25/75] Make PositionPickler work for shared trees --- .../dotty/tools/dotc/core/tasty/PositionPickler.scala | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala index b06b585b7dae..f480e4ea2ee3 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala @@ -70,12 +70,13 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad case x: untpd.Tree => var sourceFile = current val pos = if (x.isInstanceOf[untpd.MemberDef]) x.pos else x.pos.toSynthetic - if (pos.exists && ( - pos != x.initialPos.toSynthetic || - x.source.file != current || - alwaysNeedsPos(x))) { + val sourceChange = x.source.file != current + if (pos.exists && (pos != x.initialPos.toSynthetic || sourceChange || alwaysNeedsPos(x))) { addrOfTree(x) match { - case Some(addr) if !pickledIndices.contains(addr.index) => + case Some(addr) if !pickledIndices.contains(addr.index) || sourceChange => + // we currently do not share trees when unpickling, so if one path to a tree contains + // a source change while another does not, we have to record the position of the tree twice + // in order not to miss the source change. Test case is t3232a.scala. //println(i"pickling $x with $pos at $addr") pickleDeltas(addr.index, pos) if (x.source.file != current) { From b8e23f40b7a4e85de82a92d9bdfcc404ebde90c4 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 2 Jan 2019 16:04:59 +0100 Subject: [PATCH 26/75] Make Modifiers not extend from Positioned Modifiers was made a subclass of Positioned since it contains elements that are Positioned: source modifiers and annotations. That way, we got the navigation logic to get to the elements for free. However, a lot of modifiers are synthetic, and seems artificial to give these a position. With the addition of a source component to position the balance swings the other way. It now seems preferable to have Modifiers not extend Positions and to consider modifier as a as a separate case for navigation instead. --- .../dotty/tools/dotc/ast/NavigateAST.scala | 1 + .../src/dotty/tools/dotc/ast/Positioned.scala | 12 ++++- compiler/src/dotty/tools/dotc/ast/untpd.scala | 2 +- .../tools/dotc/parsing/JavaParsers.scala | 4 +- .../dotty/tools/dotc/parsing/Parsers.scala | 47 +++++++++---------- .../src/dotty/tools/dotc/typer/Namer.scala | 2 +- 6 files changed, 38 insertions(+), 30 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala b/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala index f180b34e3aa3..d2b34d4b9122 100644 --- a/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala +++ b/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala @@ -72,6 +72,7 @@ object NavigateAST { while (it.hasNext) { val path1 = it.next() match { case p: Positioned => singlePath(p, path) + case m: untpd.Modifiers => childPath(m.productIterator, path) case xs: List[_] => childPath(xs.iterator, path) case _ => path } diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index 1af06b453a29..f523d1bff6d3 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -105,6 +105,8 @@ abstract class Positioned extends Product { end = p.pos.start } else outstanding = p :: outstanding + case m: untpd.Modifiers => + elems = elems ::: m.mods.reverse ::: m.annotations.reverse case xs: List[_] => elems = elems ::: xs.reverse case _ => @@ -121,6 +123,7 @@ abstract class Positioned extends Product { n -= 1 productElement(n) match { case p: Positioned => pos = pos union p.pos + case m: untpd.Modifiers => pos = unionPos(unionPos(pos, m.mods), m.annotations) case xs: List[_] => pos = unionPos(pos, xs) case _ => } @@ -138,9 +141,11 @@ abstract class Positioned extends Product { def contains(that: Positioned): Boolean = { def isParent(x: Any): Boolean = x match { case x: Positioned => - x contains that + x.contains(that) + case m: untpd.Modifiers => + m.mods.exists(isParent) || m.annotations.exists(isParent) case xs: List[_] => - xs exists isParent + xs.exists(isParent) case _ => false } @@ -198,6 +203,9 @@ abstract class Positioned extends Product { lastPos = p.pos } p.checkPos(nonOverlapping) + case m: untpd.Modifiers => + m.annotations.foreach(check) + m.mods.foreach(check) case xs: List[_] => xs.foreach(check) case _ => diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index e89befd0b378..58baa1433945 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -151,7 +151,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { flags: FlagSet = EmptyFlags, privateWithin: TypeName = tpnme.EMPTY, annotations: List[Tree] = Nil, - mods: List[Mod] = Nil) extends Positioned with Cloneable { + mods: List[Mod] = Nil) extends Cloneable { def is(fs: FlagSet): Boolean = flags is fs def is(fc: FlagConjunction): Boolean = flags is fc diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala index e16d27ce06af..6346f25c2500 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -732,7 +732,7 @@ object JavaParsers { val members = new ListBuffer[Tree] while (in.token != RBRACE && in.token != EOF) { val start = in.offset - var mods = atPos(start) { modifiers(inInterface) } + var mods = modifiers(inInterface) if (in.token == LBRACE) { skipAhead() // skip init block, we just assume we have seen only static accept(RBRACE) @@ -895,7 +895,7 @@ object JavaParsers { while (in.token == SEMI) in.nextToken() if (in.token != EOF) { val start = in.offset - val mods = atPos(start) { modifiers(inInterface = false) } + val mods = modifiers(inInterface = false) buf ++= typeDecl(start, mods) } } diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index a47917be3da0..20ce5940002c 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1935,7 +1935,7 @@ object Parsers { def typeParam(): TypeDef = { val isConcreteOwner = ownerKind == ParamOwner.Class || ownerKind == ParamOwner.Def val start = in.offset - val mods = atPos(start) { + val mods = annotsAsMods() | { if (ownerKind == ParamOwner.Class) Param | PrivateLocal else Param @@ -1946,7 +1946,6 @@ object Parsers { else EmptyFlags else EmptyFlags } - } atPos(start, nameStart) { val name = if (isConcreteOwner || in.token != USCORE) ident().toTypeName @@ -1992,27 +1991,25 @@ object Parsers { if (ofClass) { mods = addFlag(modifiers(start = mods), ParamAccessor) mods = - atPos(start, in.offset) { - if (in.token == VAL) { - in.nextToken() - mods - } - else if (in.token == VAR) { - val mod = atPos(in.skipToken()) { Mod.Var() } - addMod(mods, mod) - } - else { - if (!(mods.flags &~ (ParamAccessor | Inline | impliedMods.flags)).isEmpty) - syntaxError("`val' or `var' expected") - if (firstClause && ofCaseClass) mods - else mods | PrivateLocal - } + if (in.token == VAL) { + in.nextToken() + mods + } + else if (in.token == VAR) { + val mod = atPos(in.skipToken()) { Mod.Var() } + addMod(mods, mod) + } + else { + if (!(mods.flags &~ (ParamAccessor | Inline | impliedMods.flags)).isEmpty) + syntaxError("`val' or `var' expected") + if (firstClause && ofCaseClass) mods + else mods | PrivateLocal } } else { if (isIdent(nme.inline) && in.isSoftModifierInParamModifierPosition) mods = addModifier(mods) - mods = atPos(start) { mods | Param } + mods |= Param } atPos(start, nameStart) { val name = ident() @@ -2024,7 +2021,7 @@ object Parsers { if (in.token == EQUALS) { in.nextToken(); expr() } else EmptyTree if (implicitOffset >= 0) { - mods = mods.withPos(mods.pos.union(Position(implicitOffset, implicitOffset))) + //mods = mods.withPos(mods.pos.union(Position(implicitOffset, implicitOffset))) implicitOffset = -1 } ValDef(name, tpt, default).withMods(mods) @@ -2165,9 +2162,8 @@ object Parsers { } def posMods(start: Int, mods: Modifiers): Modifiers = { - val mods1 = atPos(start)(mods) in.nextToken() - mods1 + mods } /** Def ::= val PatDef @@ -2557,8 +2553,10 @@ object Parsers { setLastStatOffset() if (in.token == PACKAGE) { val start = in.skipToken() - if (in.token == OBJECT) - stats += objectDef(start, atPos(start, in.skipToken()) { Modifiers(Package) }) + if (in.token == OBJECT) { + in.nextToken() + stats += objectDef(start, Modifiers(Package)) + } else stats += packaging(start) } else if (in.token == IMPORT) @@ -2718,7 +2716,8 @@ object Parsers { if (in.token == PACKAGE) { in.nextToken() if (in.token == OBJECT) { - ts += objectDef(start, atPos(start, in.skipToken()) { Modifiers(Package) }) + in.nextToken() + ts += objectDef(start, Modifiers(Package)) if (in.token != EOF) { acceptStatSep() ts ++= topStatSeq() diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 1f3e5060164d..fdc7dca7c457 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -266,7 +266,7 @@ class Namer { typer: Typer => def createSymbol(tree: Tree)(implicit ctx: Context): Symbol = { def privateWithinClass(mods: Modifiers) = - enclosingClassNamed(mods.privateWithin, mods.pos) + enclosingClassNamed(mods.privateWithin, tree.pos) /** Check that flags are OK for symbol. This is done early to avoid * catastrophic failure when we create a TermSymbol with TypeFlags, or vice versa. From 9f86d2fe879c0e5ffeec57af810887296610a2fc Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 2 Jan 2019 18:31:55 +0100 Subject: [PATCH 27/75] Temporary hack to circumvent missing sourcefile info Will be no longer necessary once bootstrap library uses new Tasty format. --- .../src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 98d57f7a153c..844e4048b05f 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -112,9 +112,16 @@ class TreeUnpickler(reader: TastyReader, val owner = ctx.owner val source = ctx.source def complete(denot: SymDenotation)(implicit ctx: Context): Unit = { + val sourceToUse = if (source.exists) source else ctx.source + // TODO: remove. This is a hack to get pickling tests (notable tuple-cons-2.scala + // to pass. The problem is that without a bootstrapped library some unpicked + // files are lacking a source, and if these are completed from Definitions + // there's also no external source given in `context`. In that case we switch + // late and pick the calling context's source. We can drop this hack once + // all Tasty trees have a SOURCE entry, which will determine the context source treeAtAddr(currentAddr) = new TreeReader(reader).readIndexedDef()( - ctx.withPhaseNoLater(ctx.picklerPhase).withOwner(owner).withSource(source)) + ctx.withPhaseNoLater(ctx.picklerPhase).withOwner(owner).withSource(sourceToUse)) } } From e22d702ca7a8142f056d454b104b839eab8a66d5 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 2 Jan 2019 18:56:42 +0100 Subject: [PATCH 28/75] Add source component to Positioned --- .../src/dotty/tools/dotc/ast/Positioned.scala | 108 ++++++++++++++---- .../src/dotty/tools/dotc/ast/TreeIds.scala | 5 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 49 +------- compiler/src/dotty/tools/dotc/ast/untpd.scala | 36 +++--- .../src/dotty/tools/dotc/core/Contexts.scala | 1 + .../tools/dotc/transform/ByNameClosures.scala | 2 +- .../dotc/transform/TransformByNameApply.scala | 3 +- .../src/dotty/tools/dotc/typer/Typer.scala | 2 +- 8 files changed, 115 insertions(+), 91 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index f523d1bff6d3..bb172249e124 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -1,44 +1,78 @@ -package dotty.tools.dotc +package dotty.tools +package dotc package ast import util.Positions._ -import util.SourcePosition +import util.{SourceFile, SourcePosition} import core.Contexts.{Context, SourceInfo} import core.Decorators._ import core.Flags.{JavaDefined, Extension} import core.StdNames.nme +import io.AbstractFile +import annotation.transientParam +import annotation.internal.sharable /** A base class for things that have positions (currently: modifiers and trees) */ -abstract class Positioned extends Product { +abstract class Positioned(implicit @transientParam src: SourceInfo) extends Product with Cloneable { + /** A unique identifier. Among other things, used for determining the source file + * component of the position. + */ + private var myUniqueId: Int = _ private[this] var curPos: Position = _ - setPos(initialPos) - - /** The item's position. - */ + /** The item's position */ def pos: Position = curPos - /** Destructively update `curPos` to given position. Also, set any missing + /** item's id */ + def uniqueId: Int = myUniqueId + + protected def srcfile: AbstractFile = TreeIds.fileOfId(uniqueId) + def source(implicit ctx: Context): SourceFile = ctx.getSource(srcfile) + def sourcePos(implicit ctx: Context): SourcePosition = source.atPos(pos) + + setId(TreeIds.nextIdFor(initialFile(src))) + setPos(initialPos, srcfile) + + protected def setId(id: Int): Unit = myUniqueId = id + + /** Destructively update `curPos` to given position. Also, set any missing * positions in children. */ - protected def setPos(pos: Position): Unit = { - setPosUnchecked(pos) - if (pos.exists) setChildPositions(pos.toSynthetic) + protected def setPos(pos: Position, file: AbstractFile): Unit = { + setPosUnchecked(pos, file) + if (pos.exists) setChildPositions(pos.toSynthetic, file) } - def cloned(implicit src: SourceInfo): Positioned - /** A positioned item like this one with the position set to `pos`. * if the positioned item is source-derived, a clone is returned. * If the positioned item is synthetic, the position is updated * destructively and the item itself is returned. */ def withPos(pos: Position)(implicit src: SourceInfo): this.type = { - val newpd = if (pos == curPos || curPos.isSynthetic) this else cloned - newpd.setPos(pos) - newpd.asInstanceOf[this.type] + val ownPos = this.pos + val newpd: this.type = if (pos == ownPos || ownPos.isSynthetic) this else cloneIn(srcfile) + newpd.setPos(pos, srcfile) + newpd + } + + def withPos(posd: Positioned)(implicit ctx: Context): this.type = { + val ownPos = this.pos + val newpd: this.type = + if (posd.source == source && posd.pos == ownPos || ownPos.isSynthetic) this + else cloneIn(posd.srcfile) + newpd.setPos(posd.pos, posd.srcfile) + newpd + } + + def withSourcePos(sourcePos: SourcePosition)(implicit ctx: Context): this.type = { + val ownPos = this.pos + val newpd: this.type = + if (sourcePos.source == source && sourcePos.pos == ownPos || ownPos.isSynthetic) this + else cloneIn(sourcePos.source.file) + newpd.setPos(sourcePos.pos, sourcePos.source.file) + newpd } /** This item with a position that's the union of the given `pos` and the @@ -50,7 +84,10 @@ abstract class Positioned extends Product { * any checks of consistency with - or updates of - other positions. * Called from Unpickler when entering positions. */ - private[dotc] def setPosUnchecked(pos: Position): Unit = curPos = pos + private[dotc] def setPosUnchecked(pos: Position, file: AbstractFile = this.srcfile): Unit = { + if (file != this.srcfile) setId(TreeIds.nextIdFor(file)) + curPos = pos + } /** If any children of this node do not have positions, * fit their positions between the positions of the known subtrees @@ -63,7 +100,7 @@ abstract class Positioned extends Product { * But since mutual tail recursion is not supported in Scala, we express it instead * as a while loop with a termination by return in the middle. */ - private def setChildPositions(pos: Position): Unit = { + private def setChildPositions(pos: Position, file: AbstractFile): Unit = { var n = productArity // subnodes are analyzed right to left var elems: List[Any] = Nil // children in lists still to be considered, from right to left var end = pos.end // the last defined offset, fill in positions up to this offset @@ -75,10 +112,10 @@ abstract class Positioned extends Product { // synthetic. We can preserve this invariant by always setting a // zero-extent position for these trees here. if (!p.pos.exists || p.pos.isZeroExtent) { - p.setPos(Position(start, start)) + p.setPos(Position(start, start), file) fillIn(ps1, start, end) } else { - p.setPos(Position(start, end)) + p.setPos(Position(start, end), file) fillIn(ps1, end, end) } case nil => @@ -114,6 +151,31 @@ abstract class Positioned extends Product { } } + protected def cloneIn(file: AbstractFile): this.type = { + val newpd: this.type = clone.asInstanceOf[this.type] + newpd.setId(TreeIds.nextIdFor(file)) + newpd + } + + def initialFile(src: SourceInfo): AbstractFile = { + def firstFile(x: Any): AbstractFile = x match { + case x: Positioned if x.pos.exists => + x.srcfile + case x1 :: xs1 => + val f = firstFile(x1) + if (f != null) f else firstFile(xs1) + case _ => + null + } + def firstElemFile(n: Int): AbstractFile = + if (n == productArity) src.source.file + else { + val f = firstFile(productElement(n)) + if (f != null) f else firstElemFile(n + 1) + } + firstElemFile(0) + } + /** The initial, synthetic position. This is usually the union of all positioned children's positions. */ def initialPos: Position = { @@ -122,7 +184,7 @@ abstract class Positioned extends Product { while (n > 0) { n -= 1 productElement(n) match { - case p: Positioned => pos = pos union p.pos + case p: Positioned if sameSource(p) => pos = pos union p.pos case m: untpd.Modifiers => pos = unionPos(unionPos(pos, m.mods), m.annotations) case xs: List[_] => pos = unionPos(pos, xs) case _ => @@ -132,12 +194,14 @@ abstract class Positioned extends Product { } private def unionPos(pos: Position, xs: List[_]): Position = xs match { - case (p: Positioned) :: xs1 => unionPos(pos union p.pos, xs1) + case (p: Positioned) :: xs1 if sameSource(p) => unionPos(pos union p.pos, xs1) case (xs0: List[_]) :: xs1 => unionPos(unionPos(pos, xs0), xs1) case _ :: xs1 => unionPos(pos, xs1) case _ => pos } + private def sameSource(that: Positioned) = srcfile == that.srcfile + def contains(that: Positioned): Boolean = { def isParent(x: Any): Boolean = x match { case x: Positioned => diff --git a/compiler/src/dotty/tools/dotc/ast/TreeIds.scala b/compiler/src/dotty/tools/dotc/ast/TreeIds.scala index eafde3691ccc..091e074487fe 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeIds.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeIds.scala @@ -16,8 +16,9 @@ object TreeIds { @sharable private[this] val counters = new ConcurrentHashMap[AbstractFile, AtomicInteger] @sharable private[this] val fileOfChunk = mutable.ArrayBuffer[AbstractFile]() - def nextId(implicit src: SourceInfo): Int = { - val file = src.source.file + def nextId(implicit src: SourceInfo): Int = nextIdFor(src.source.file) + + def nextIdFor(file: AbstractFile): Int = { var ctr = counters.get(file) if (ctr == null) { counters.putIfAbsent(file, new AtomicInteger) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 9dd81fb137f9..2b1c68625ef8 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -15,6 +15,7 @@ import io.AbstractFile import annotation.internal.sharable import annotation.unchecked.uncheckedVariance import annotation.transientParam +import Decorators._ object Trees { @@ -55,42 +56,10 @@ object Trees { extends Positioned with Product with Attachment.Container - with printing.Showable - with Cloneable { + with printing.Showable { if (Stats.enabled) ntrees += 1 - /** A unique identifier for this tree. Used for debugging, and potentially - * tracking presentation compiler interactions. - */ - @sharable private var myUniqueId: Int = TreeIds.nextId - - def uniqueId: Int = myUniqueId - - def source(implicit ctx: Context): SourceFile = ctx.getSource(TreeIds.fileOfId(uniqueId)) - - def sourcePos(implicit ctx: Context): SourcePosition = source.atPos(pos) - - def withPos(posd: Tree[_])(implicit ctx: Context): this.type = { - val tree1 = - if (posd.source == source && (posd.pos == pos || posd.pos.isSynthetic)) this - else cloned(ctx.withSource(posd.source)) - tree1.setPos(sourcePos.pos) - tree1.asInstanceOf[this.type] - } - - def withSource(source: SourceFile)(implicit ctx: Context): Tree[T] = - if (source == this.source) this - else cloned(ctx.withSource(source)) - - def withSourcePos(sourcePos: SourcePosition)(implicit ctx: Context): this.type = { - val tree1 = - if (sourcePos.source == source && (sourcePos.pos == pos || pos.isSynthetic)) this - else cloned(ctx.withSource(sourcePos.source)) - tree1.setPos(sourcePos.pos) - tree1.asInstanceOf[this.type] - } - /** The type constructor at the root of the tree */ type ThisTree[T >: Untyped] <: Tree[T] @@ -160,7 +129,7 @@ object Trees { val tree = (if (myTpe == null || (myTpe.asInstanceOf[AnyRef] eq tpe.asInstanceOf[AnyRef])) this - else clone).asInstanceOf[Tree[Type]] + else cloneIn(srcfile)).asInstanceOf[Tree[Type]] tree overwriteType tpe tree.asInstanceOf[ThisTree[Type]] } @@ -256,12 +225,6 @@ object Trees { override def hashCode(): Int = uniqueId // for debugging; was: System.identityHashCode(this) override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - - override def cloned(implicit src: SourceInfo): Tree[T] = { - val tree = clone.asInstanceOf[Tree[T]] - tree.myUniqueId = TreeIds.nextId - tree - } } class UnAssignedTypeException[T >: Untyped](tree: Tree[T]) extends RuntimeException { @@ -357,7 +320,7 @@ object Trees { def rawComment: Option[Comment] = getAttachment(DocComment) def withMods(mods: untpd.Modifiers): ThisTree[Untyped] = { - val tree = if (myMods == null || (myMods == mods)) this else clone.asInstanceOf[MemberDef[Untyped]] + val tree = if (myMods == null || (myMods == mods)) this else cloneIn(srcfile) tree.setMods(mods) tree.asInstanceOf[ThisTree[Untyped]] } @@ -809,9 +772,7 @@ object Trees { trait WithoutTypeOrPos[-T >: Untyped] extends Tree[T] { override def withTypeUnchecked(tpe: Type): ThisTree[Type] = this.asInstanceOf[ThisTree[Type]] override def pos: Position = NoPosition - override def setPos(pos: Position): Unit = {} - override def withSource(source: SourceFile)(implicit ctx: Context): Tree[T] = this - override def withSourcePos(sourcePos: SourcePosition)(implicit ctx: Context): this.type = this + override def setPos(pos: Position, file: AbstractFile): Unit = {} } /** Temporary class that results from translation of ModuleDefs diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 58baa1433945..6808b6fa0da9 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -108,36 +108,35 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * * For any query about semantic information, check `flags` instead. */ - sealed abstract class Mod(val flags: FlagSet) extends Positioned { - def cloned(implicit src: SourceInfo): Positioned = clone.asInstanceOf[Positioned] - } + sealed abstract class Mod(val flags: FlagSet)(implicit @transientParam src: SourceInfo) + extends Positioned object Mod { - case class Private() extends Mod(Flags.Private) + case class Private()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Private) - case class Protected() extends Mod(Flags.Protected) + case class Protected()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Protected) - case class Var() extends Mod(Flags.Mutable) + case class Var()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Mutable) - case class Implicit() extends Mod(Flags.ImplicitCommon) + case class Implicit()(implicit @transientParam src: SourceInfo) extends Mod(Flags.ImplicitCommon) - case class Erased() extends Mod(Flags.Erased) + case class Erased()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Erased) - case class Final() extends Mod(Flags.Final) + case class Final()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Final) - case class Sealed() extends Mod(Flags.Sealed) + case class Sealed()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Sealed) - case class Opaque() extends Mod(Flags.Opaque) + case class Opaque()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Opaque) - case class Override() extends Mod(Flags.Override) + case class Override()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Override) - case class Abstract() extends Mod(Flags.Abstract) + case class Abstract()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Abstract) - case class Lazy() extends Mod(Flags.Lazy) + case class Lazy()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Lazy) - case class Inline() extends Mod(Flags.Inline) + case class Inline()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Inline) - case class Enum() extends Mod(Flags.Enum) + case class Enum()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Enum) } /** Modifiers and annotations for definitions @@ -151,7 +150,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { flags: FlagSet = EmptyFlags, privateWithin: TypeName = tpnme.EMPTY, annotations: List[Tree] = Nil, - mods: List[Mod] = Nil) extends Cloneable { + mods: List[Mod] = Nil) { def is(fs: FlagSet): Boolean = flags is fs def is(fc: FlagConjunction): Boolean = flags is fc @@ -207,9 +206,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def isEnumCase: Boolean = isEnum && is(Case) def isEnumClass: Boolean = isEnum && !is(Case) - - override def cloned(implicit src: SourceInfo): Modifiers = - clone.asInstanceOf[Modifiers] } @sharable val EmptyModifiers: Modifiers = new Modifiers() diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 4ab293659d7a..9fdb44b0d5f3 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -39,6 +39,7 @@ object Contexts { trait SourceInfo { def source: SourceFile + def withSource(file: AbstractFile): SourceInfo } private val (compilerCallbackLoc, store1) = Store.empty.newLocation[CompilerCallback]() diff --git a/compiler/src/dotty/tools/dotc/transform/ByNameClosures.scala b/compiler/src/dotty/tools/dotc/transform/ByNameClosures.scala index 8356539f9000..e1301916ff78 100644 --- a/compiler/src/dotty/tools/dotc/transform/ByNameClosures.scala +++ b/compiler/src/dotty/tools/dotc/transform/ByNameClosures.scala @@ -28,7 +28,7 @@ class ByNameClosures extends TransformByNameApply with IdentityDenotTransformer override def mkByNameClosure(arg: Tree, argType: Type)(implicit ctx: Context): Tree = { val meth = ctx.newSymbol( ctx.owner, nme.ANON_FUN, Synthetic | Method, MethodType(Nil, Nil, argType)) - Closure(meth, _ => arg.changeOwnerAfter(ctx.owner, meth, thisPhase)) + Closure(meth, _ => arg.changeOwnerAfter(ctx.owner, meth, thisPhase)).withPos(arg) } } diff --git a/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala b/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala index dc9317f0028a..360d03452fdc 100644 --- a/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala +++ b/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala @@ -43,7 +43,8 @@ abstract class TransformByNameApply extends MiniPhase { thisPhase: DenotTransfor case formalExpr: ExprType => var argType = arg.tpe.widenIfUnstable if (defn.isBottomType(argType)) argType = formal.widenExpr - def wrap(arg: Tree) = ref(defn.cbnArg).appliedToType(argType).appliedTo(arg) + def wrap(arg: Tree) = + ref(defn.cbnArg).appliedToType(argType).appliedTo(arg).withPos(arg) arg match { case Apply(Select(qual, nme.apply), Nil) if qual.tpe.derivesFrom(defn.FunctionClass(0)) && isPureExpr(qual) => diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 3c3e7cb5d14b..9c85baf48d7d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -58,7 +58,7 @@ object Typer { /** Assert tree has a position, unless it is empty or a typed splice */ def assertPositioned(tree: untpd.Tree)(implicit ctx: Context): Unit = if (!tree.isEmpty && !tree.isInstanceOf[untpd.TypedSplice] && ctx.typerState.isGlobalCommittable) - assert(tree.pos.exists, s"position not set for $tree # ${tree.uniqueId}") + assert(tree.pos.exists, s"position not set for $tree # ${tree.uniqueId} in ${tree.source}") /** A context property that indicates the owner of any expressions to be typed in the context * if that owner is different from the context's owner. Typically, a context with a class From 27a7a776ce0a9e9517286187453c8da50aadf82e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 2 Jan 2019 19:19:30 +0100 Subject: [PATCH 29/75] Inliner tweaks Needed to make all pickling tests pass --- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 9ae61c1fd4b3..6496dd3b0ce3 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -411,7 +411,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { tree.tpe match { case thistpe: ThisType => thisProxy.get(thistpe.cls) match { - case Some(t) => ref(t).withSourcePos(tree.sourcePos) + case Some(t) => ref(t) case None => tree } case _ => tree @@ -419,7 +419,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { case tree: Ident => paramProxy.get(tree.tpe) match { case Some(t) if tree.isTerm && t.isSingleton => - singleton(t.dealias).withSourcePos(tree.sourcePos) + singleton(t.dealias) case Some(t) if tree.isType => TypeTree(t).withSourcePos(tree.sourcePos) case _ => tree @@ -432,7 +432,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { // Apply inliner to `rhsToInline`, split off any implicit bindings from result, and // make them part of `bindingsBuf`. The expansion is then the tree that remains. - val expansion = inliner.transform(rhsToInline.withSourcePos(call.sourcePos)) + val expansion = inliner.transform(rhsToInline).withSourcePos(call.sourcePos) def issueError() = callValueArgss match { case (msgArg :: rest) :: Nil => From 91af81a71e255303baa78683f347a6a32e420512 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 3 Jan 2019 11:18:23 +0100 Subject: [PATCH 30/75] withPos(Positioned) -> withPosOf --- compiler/src/dotty/tools/dotc/ast/Positioned.scala | 5 +++-- .../dotty/tools/dotc/transform/ByNameClosures.scala | 2 +- .../tools/dotc/transform/TransformByNameApply.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 10 +++++----- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index bb172249e124..39e34a4a5391 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -52,12 +52,13 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod */ def withPos(pos: Position)(implicit src: SourceInfo): this.type = { val ownPos = this.pos - val newpd: this.type = if (pos == ownPos || ownPos.isSynthetic) this else cloneIn(srcfile) + val newpd: this.type = + if (pos == ownPos || ownPos.isSynthetic) this else cloneIn(srcfile) newpd.setPos(pos, srcfile) newpd } - def withPos(posd: Positioned)(implicit ctx: Context): this.type = { + def withPosOf(posd: Positioned)(implicit ctx: Context): this.type = { val ownPos = this.pos val newpd: this.type = if (posd.source == source && posd.pos == ownPos || ownPos.isSynthetic) this diff --git a/compiler/src/dotty/tools/dotc/transform/ByNameClosures.scala b/compiler/src/dotty/tools/dotc/transform/ByNameClosures.scala index e1301916ff78..01e52707c872 100644 --- a/compiler/src/dotty/tools/dotc/transform/ByNameClosures.scala +++ b/compiler/src/dotty/tools/dotc/transform/ByNameClosures.scala @@ -28,7 +28,7 @@ class ByNameClosures extends TransformByNameApply with IdentityDenotTransformer override def mkByNameClosure(arg: Tree, argType: Type)(implicit ctx: Context): Tree = { val meth = ctx.newSymbol( ctx.owner, nme.ANON_FUN, Synthetic | Method, MethodType(Nil, Nil, argType)) - Closure(meth, _ => arg.changeOwnerAfter(ctx.owner, meth, thisPhase)).withPos(arg) + Closure(meth, _ => arg.changeOwnerAfter(ctx.owner, meth, thisPhase)).withPosOf(arg) } } diff --git a/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala b/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala index 360d03452fdc..9a4e89f5b6a6 100644 --- a/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala +++ b/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala @@ -44,7 +44,7 @@ abstract class TransformByNameApply extends MiniPhase { thisPhase: DenotTransfor var argType = arg.tpe.widenIfUnstable if (defn.isBottomType(argType)) argType = formal.widenExpr def wrap(arg: Tree) = - ref(defn.cbnArg).appliedToType(argType).appliedTo(arg).withPos(arg) + ref(defn.cbnArg).appliedToType(argType).appliedTo(arg).withPosOf(arg) arg match { case Apply(Select(qual, nme.apply), Nil) if qual.tpe.derivesFrom(defn.FunctionClass(0)) && isPureExpr(qual) => diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 6496dd3b0ce3..06debba4df04 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -71,7 +71,7 @@ object Inliner { override def transform(t: Tree)(implicit ctx: Context) = { t match { case Inlined(t, Nil, expr) if t.isEmpty => expr - case _ => super.transform(t.withSourcePos(call.sourcePos)) + case _ => super.transform(t.withPosOf(call)) } } } @@ -139,7 +139,7 @@ object Inliner { case call :: _ if call.symbol.sourceFile != curSourceFile => // Until we implement JSR-45, we cannot represent in output positions in other source files. // So, reposition inlined code from other files with the call position: - transformed.withSourcePos(inlinedAtPos) + transformed.withPosOf(inlined.call) case _ => transformed } } @@ -421,7 +421,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { case Some(t) if tree.isTerm && t.isSingleton => singleton(t.dealias) case Some(t) if tree.isType => - TypeTree(t).withSourcePos(tree.sourcePos) + TypeTree(t).withPosOf(tree) case _ => tree } case tree => tree @@ -432,7 +432,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { // Apply inliner to `rhsToInline`, split off any implicit bindings from result, and // make them part of `bindingsBuf`. The expansion is then the tree that remains. - val expansion = inliner.transform(rhsToInline).withSourcePos(call.sourcePos) + val expansion = inliner.transform(rhsToInline).withPosOf(call) def issueError() = callValueArgss match { case (msgArg :: rest) :: Nil => @@ -598,7 +598,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { case _ => binding } - binding1.withSourcePos(call.sourcePos) + binding1.withPosOf(call) } /** An extractor for references to inlineable arguments. These are : From 2907634e473fe38f56114d1ce9ccc8b1ebf25812 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 3 Jan 2019 12:09:56 +0100 Subject: [PATCH 31/75] Unpickler always takes source from context ... when setting positions --- .../src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 844e4048b05f..80e1f9037570 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -1316,7 +1316,10 @@ class TreeUnpickler(reader: TastyReader, */ def sourceChangeContext(addr: Addr = currentAddr)(implicit ctx: Context): Context = { val path = sourcePathAt(addr) - if (path.nonEmpty) ctx.withSource(ctx.getSource(path)) + if (path.nonEmpty) { + pickling.println(i"source change at $addr: $path") + ctx.withSource(ctx.getSource(path)) + } else ctx } @@ -1332,7 +1335,7 @@ class TreeUnpickler(reader: TastyReader, /** Set position of `tree` at given `addr`. */ def setPos[T <: untpd.Tree](addr: Addr, tree: T)(implicit ctx: Context): tree.type = { val pos = posAt(addr) - if (pos.exists) tree.setPosUnchecked(pos) + if (pos.exists) tree.setPosUnchecked(pos, ctx.source.file) tree } } From 14d2c5a478bd7abcb08a948c6b423a1b85fc650f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 3 Jan 2019 12:26:42 +0100 Subject: [PATCH 32/75] withPos -> withSpan --- .../src/dotty/tools/dotc/ast/Desugar.scala | 36 ++++++++-------- .../dotty/tools/dotc/ast/DesugarEnums.scala | 6 +-- .../src/dotty/tools/dotc/ast/Positioned.scala | 20 ++++----- .../dotty/tools/dotc/ast/TreeTypeMap.scala | 4 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 29 ++++++++----- compiler/src/dotty/tools/dotc/ast/tpd.scala | 14 +++---- compiler/src/dotty/tools/dotc/ast/untpd.scala | 2 +- .../dotc/core/quoted/PickledQuotes.scala | 2 +- .../tools/dotc/core/tasty/TreeUnpickler.scala | 2 +- .../tools/dotc/parsing/JavaParsers.scala | 8 ++-- .../dotty/tools/dotc/parsing/Parsers.scala | 26 ++++++------ .../dotc/parsing/TreeBuilder.scala.unused | 2 +- .../dotc/parsing/xml/SymbolicXMLBuilder.scala | 2 +- .../tools/dotc/printing/RefinedPrinter.scala | 2 +- .../tools/dotc/quoted/QuoteCompiler.scala | 2 +- .../TypeOrBoundsTreesOpsImpl.scala | 2 +- .../tools/dotc/transform/AccessProxies.scala | 4 +- .../dotty/tools/dotc/transform/Bridges.scala | 2 +- .../tools/dotc/transform/CapturedVars.scala | 2 +- .../dotty/tools/dotc/transform/ClassOf.scala | 2 +- .../tools/dotc/transform/Constructors.scala | 6 +-- .../dotty/tools/dotc/transform/Erasure.scala | 7 ++-- .../tools/dotc/transform/ExplicitOuter.scala | 4 +- .../tools/dotc/transform/ExplicitSelf.scala | 2 +- .../tools/dotc/transform/FirstTransform.scala | 4 +- .../dotc/transform/FullParameterization.scala | 2 +- .../dotty/tools/dotc/transform/GetClass.scala | 2 +- .../dotty/tools/dotc/transform/Getters.scala | 4 +- .../tools/dotc/transform/LambdaLift.scala | 10 ++--- .../dotty/tools/dotc/transform/LazyVals.scala | 2 +- .../dotc/transform/LinkScala2Impls.scala | 2 +- .../dotty/tools/dotc/transform/Mixin.scala | 4 +- .../dotty/tools/dotc/transform/MixinOps.scala | 2 +- .../dotc/transform/NonLocalReturns.scala | 2 +- .../dotc/transform/ParamForwarding.scala | 2 +- .../tools/dotc/transform/PatternMatcher.scala | 2 +- .../tools/dotc/transform/PostTyper.scala | 4 +- .../dotty/tools/dotc/transform/Staging.scala | 8 ++-- .../tools/dotc/transform/SuperAccessors.scala | 8 ++-- .../dotc/transform/SyntheticMethods.scala | 2 +- .../dotty/tools/dotc/transform/TailRec.scala | 4 +- .../dotc/transform/TryCatchPatterns.scala | 4 +- .../tools/dotc/transform/TypeTestsCasts.scala | 4 +- .../dotty/tools/dotc/typer/Applications.scala | 8 ++-- .../src/dotty/tools/dotc/typer/Dynamic.scala | 4 +- .../dotty/tools/dotc/typer/EtaExpansion.scala | 8 ++-- .../dotty/tools/dotc/typer/Implicits.scala | 25 ++++++----- .../src/dotty/tools/dotc/typer/Inliner.scala | 6 +-- .../tools/dotc/typer/PrepareInlineable.scala | 4 +- .../dotty/tools/dotc/typer/ProtoTypes.scala | 2 +- .../src/dotty/tools/dotc/typer/Typer.scala | 42 +++++++++---------- .../tools/dotc/util/SourcePosition.scala | 10 ++--- .../src/dotty/tools/repl/ReplCompiler.scala | 8 ++-- 53 files changed, 191 insertions(+), 186 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 511a40c599ab..cca27179b354 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -113,7 +113,7 @@ object desugar { def derivedTypeParam(tdef: TypeDef, suffix: String = "")(implicit ctx: Context): TypeDef = cpy.TypeDef(tdef)( name = tdef.name ++ suffix, - rhs = new DerivedFromParamTree(suffix).withPos(tdef.rhs.pos).watching(tdef) + rhs = new DerivedFromParamTree(suffix).withPosOf(tdef.rhs).watching(tdef) ) /** A derived type definition watching `sym` */ @@ -123,7 +123,7 @@ object desugar { /** A value definition copied from `vdef` with a tpt typetree derived from it */ def derivedTermParam(vdef: ValDef)(implicit ctx: Context): ValDef = cpy.ValDef(vdef)( - tpt = new DerivedFromParamTree("").withPos(vdef.tpt.pos).watching(vdef)) + tpt = new DerivedFromParamTree("").withPosOf(vdef.tpt).watching(vdef)) // ----- Desugar methods ------------------------------------------------- @@ -351,10 +351,10 @@ object desugar { val constrVparamss = if (originalVparamss.isEmpty) { // ensure parameter list is non-empty if (isCaseClass && originalTparams.isEmpty) - ctx.error(CaseClassMissingParamList(cdef), cdef.sourcePos.withRange(cdef.namePos)) + ctx.error(CaseClassMissingParamList(cdef), cdef.sourcePos.withSpan(cdef.namePos)) ListOfNil } else if (isCaseClass && originalVparamss.head.exists(_.mods.is(Implicit))) { - ctx.error("Case classes should have a non-implicit parameter list", cdef.sourcePos.withRange(cdef.namePos)) + ctx.error("Case classes should have a non-implicit parameter list", cdef.sourcePos.withSpan(cdef.namePos)) ListOfNil } else originalVparamss.nestedMap(toDefParam) @@ -398,7 +398,7 @@ object desugar { def appliedTypeTree(tycon: Tree, args: List[Tree]) = (if (args.isEmpty) tycon else AppliedTypeTree(tycon, args)) - .withPos(cdef.pos.startPos) + .withSpan(cdef.pos.startPos) def isHK(tparam: Tree): Boolean = tparam match { case TypeDef(_, LambdaTypeTree(tparams, body)) => true @@ -564,7 +564,7 @@ object desugar { ModuleDef( className.toTermName, Template(emptyConstructor, parentTpt :: Nil, EmptyValDef, defs)) .withMods(companionMods | Synthetic)) - .withPos(cdef.pos).toList + .withPosOf(cdef).toList val companionMembers = defaultGetters ::: eqInstances ::: enumCases @@ -653,7 +653,7 @@ object desugar { // we can reuse the constructor parameters; no derived params are needed. DefDef(className.toTermName, constrTparams, constrVparamss, classTypeRef, creatorExpr) .withMods(companionMods | Synthetic | Implicit) - .withPos(cdef.pos) :: Nil + .withPosOf(cdef) :: Nil val self1 = { val selfType = if (self.tpt.isEmpty) classTypeRef else self.tpt @@ -710,17 +710,17 @@ object desugar { val clsRef = Ident(clsName) val modul = ValDef(moduleName, clsRef, New(clsRef, Nil)) .withMods(mods.toTermFlags & RetainedModuleValFlags | ModuleValCreationFlags) - .withPos(mdef.pos.startPos) + .withSpan(mdef.pos.startPos) val ValDef(selfName, selfTpt, _) = impl.self val selfMods = impl.self.mods if (!selfTpt.isEmpty) ctx.error(ObjectMayNotHaveSelfType(mdef), impl.self.sourcePos) val clsSelf = ValDef(selfName, SingletonTypeTree(Ident(moduleName)), impl.self.rhs) .withMods(selfMods) - .withPos(impl.self.pos orElse impl.pos.startPos) + .withSpan(impl.self.pos.orElse(impl.pos.startPos)) val clsTmpl = cpy.Template(impl)(self = clsSelf, body = impl.body) val cls = TypeDef(clsName, clsTmpl) .withMods(mods.toTypeFlags & RetainedModuleClassFlags | ModuleClassCreationFlags) - Thicket(modul, classDef(cls).withPos(mdef.pos)) + Thicket(modul, classDef(cls).withPosOf(mdef)) } } @@ -842,7 +842,7 @@ object desugar { mods & Lazy | Synthetic | (if (ctx.owner.isClass) PrivateLocal else EmptyFlags) val firstDef = ValDef(tmpName, TypeTree(), matchExpr) - .withPos(pat.pos.union(rhs.pos)).withMods(patMods) + .withSpan(pat.pos.union(rhs.pos)).withMods(patMods) def selector(n: Int) = Select(Ident(tmpName), nme.selectorName(n)) val restDefs = for (((named, tpt), n) <- vars.zipWithIndex) @@ -856,7 +856,7 @@ object desugar { /** Expand variable identifier x to x @ _ */ def patternVar(tree: Tree)(implicit ctx: Context): Bind = { val Ident(name) = tree - Bind(name, Ident(nme.WILDCARD)).withPos(tree.pos) + Bind(name, Ident(nme.WILDCARD)).withPosOf(tree) } def defTree(tree: Tree)(implicit ctx: Context): Tree = tree match { @@ -879,7 +879,7 @@ object desugar { def block(tree: Block)(implicit ctx: Context): Block = tree.expr match { case EmptyTree => cpy.Block(tree)(tree.stats, - unitLiteral withPos (if (tree.stats.isEmpty) tree.pos else tree.pos.endPos)) + unitLiteral.withSpan(if (tree.stats.isEmpty) tree.pos else tree.pos.endPos)) case _ => tree } @@ -900,7 +900,7 @@ object desugar { case Tuple(args) => args.mapConserve(assignToNamedArg) case _ => arg :: Nil } - Apply(Select(fn, op.name).withPos(selectPos), args) + Apply(Select(fn, op.name).withSpan(selectPos), args) } if (isLeftAssoc(op.name)) @@ -985,7 +985,7 @@ object desugar { val vdefs = params.zipWithIndex.map{ case (param, idx) => - DefDef(param.name, Nil, Nil, TypeTree(), selector(idx)).withPos(param.pos) + DefDef(param.name, Nil, Nil, TypeTree(), selector(idx)).withPosOf(param) } Function(param :: Nil, Block(vdefs, body)) } @@ -1021,7 +1021,7 @@ object desugar { private def derivedValDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit ctx: Context) = { val vdef = ValDef(named.name.asTermName, tpt, rhs) .withMods(mods) - .withPos(original.pos.withPoint(named.pos.start)) + .withSpan(original.pos.withPoint(named.pos.start)) val mayNeedSetter = valDef(vdef) mayNeedSetter } @@ -1029,7 +1029,7 @@ object desugar { private def derivedDefDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit src: SourceInfo) = DefDef(named.name.asTermName, Nil, Nil, tpt, rhs) .withMods(mods) - .withPos(original.pos.withPoint(named.pos.start)) + .withSpan(original.pos.withPoint(named.pos.start)) /** Main desugaring method */ def apply(tree: Tree)(implicit ctx: Context): Tree = { @@ -1279,7 +1279,7 @@ object desugar { finalizer) } } - desugared.withPos(tree.pos) + desugared.withPosOf(tree) } /** Create a class definition with the same info as the refined type given by `parent` diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index 3abdfa0799e4..09f60855d3db 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -60,7 +60,7 @@ object DesugarEnums { |type parameter $tparam $problem""", ctx.source.atPos(pos)) } } - TypeTree(enumClass.typeRef.appliedTo(targs)).withPos(pos) + TypeTree(enumClass.typeRef.appliedTo(targs)).withSpan(pos) } /** A type tree referring to `enumClass` */ @@ -207,7 +207,7 @@ object DesugarEnums { val (tagMeth, scaffolding) = enumTagMeth(CaseKind.Object) val impl1 = cpy.Template(impl)(body = List(tagMeth, toStringMeth) ++ registerCall) val vdef = ValDef(name, TypeTree(), New(impl1)).withMods(mods | Final) - flatTree(scaffolding ::: vdef :: Nil).withPos(pos) + flatTree(scaffolding ::: vdef :: Nil).withSpan(pos) } } @@ -223,6 +223,6 @@ object DesugarEnums { val (tag, scaffolding) = nextEnumTag(CaseKind.Simple) val creator = Apply(Ident(nme.DOLLAR_NEW), List(Literal(Constant(tag)), Literal(Constant(name.toString)))) val vdef = ValDef(name, enumClassRef, creator).withMods(mods | Final) - flatTree(scaffolding ::: vdef :: Nil).withPos(pos) + flatTree(scaffolding ::: vdef :: Nil).withSpan(pos) } } diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index 39e34a4a5391..8539812a3767 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -35,7 +35,10 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod setId(TreeIds.nextIdFor(initialFile(src))) setPos(initialPos, srcfile) - protected def setId(id: Int): Unit = myUniqueId = id + protected def setId(id: Int): Unit = { + myUniqueId = id + //assert(id != 2067, getClass) + } /** Destructively update `curPos` to given position. Also, set any missing * positions in children. @@ -50,7 +53,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod * If the positioned item is synthetic, the position is updated * destructively and the item itself is returned. */ - def withPos(pos: Position)(implicit src: SourceInfo): this.type = { + def withSpan(pos: Position): this.type = { val ownPos = this.pos val newpd: this.type = if (pos == ownPos || ownPos.isSynthetic) this else cloneIn(srcfile) @@ -58,29 +61,24 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod newpd } - def withPosOf(posd: Positioned)(implicit ctx: Context): this.type = { + def withPosOf(posd: Positioned): this.type = { val ownPos = this.pos val newpd: this.type = - if (posd.source == source && posd.pos == ownPos || ownPos.isSynthetic) this + if (posd.srcfile == srcfile && posd.pos == ownPos || ownPos.isSynthetic) this else cloneIn(posd.srcfile) newpd.setPos(posd.pos, posd.srcfile) newpd } - def withSourcePos(sourcePos: SourcePosition)(implicit ctx: Context): this.type = { + def withSourcePos(sourcePos: SourcePosition): this.type = { val ownPos = this.pos val newpd: this.type = - if (sourcePos.source == source && sourcePos.pos == ownPos || ownPos.isSynthetic) this + if (sourcePos.source.file == srcfile && sourcePos.pos == ownPos || ownPos.isSynthetic) this else cloneIn(sourcePos.source.file) newpd.setPos(sourcePos.pos, sourcePos.source.file) newpd } - /** This item with a position that's the union of the given `pos` and the - * current position. - */ - def addPos(pos: Position)(implicit src: SourceInfo): this.type = withPos(pos union this.pos) - /** Set position of this tree only, without performing * any checks of consistency with - or updates of - other positions. * Called from Unpickler when entering positions. diff --git a/compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala b/compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala index 25269c17e863..9f3cc17aaf54 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala @@ -89,7 +89,7 @@ class TreeTypeMap( case tree1 => tree1.withType(mapType(tree1.tpe)) match { case id: Ident if tpd.needsSelect(id.tpe) => - ref(id.tpe.asInstanceOf[TermRef]).withPos(id.pos) + ref(id.tpe.asInstanceOf[TermRef]).withPosOf(id) case ddef @ DefDef(name, tparams, vparamss, tpt, _) => val (tmap1, tparams1) = transformDefs(ddef.tparams) val (tmap2, vparamss1) = tmap1.transformVParamss(vparamss) @@ -122,7 +122,7 @@ class TreeTypeMap( val expr1 = tmap.transform(expr) cpy.Labeled(labeled)(bind1, expr1) case Hole(n, args) => - Hole(n, args.mapConserve(transform)).withPos(tree.pos).withType(mapType(tree.tpe)) + Hole(n, args.mapConserve(transform)).withPosOf(tree).withType(mapType(tree.tpe)) case tree1 => super.transform(tree1) } diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 2b1c68625ef8..537e696f0647 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -85,7 +85,7 @@ object Trees { /** Copy `tpe` attribute from tree `from` into this tree, independently * whether it is null or not. final def copyAttr[U >: Untyped](from: Tree[U]): ThisTree[T] = { - val t1 = this.withPos(from.pos) + val t1 = this.withPosOf(from) val t2 = if (from.myTpe != null) t1.withType(from.myTpe.asInstanceOf[Type]) else t1 @@ -783,21 +783,30 @@ object Trees { case class Thicket[-T >: Untyped](trees: List[Tree[T]])(implicit @transientParam src: SourceInfo) extends Tree[T] with WithoutTypeOrPos[T] { myTpe = NoType.asInstanceOf[T] - type ThisTree[-T >: Untyped] = Thicket[T] - override def isEmpty: Boolean = trees.isEmpty - override def toList: List[Tree[T]] = flatten(trees) - override def toString: String = if (isEmpty) "EmptyTree" else "Thicket(" + trees.mkString(", ") + ")" - override def withPos(pos: Position)(implicit src: SourceInfo): this.type = { - val newTrees = trees.mapConserve(_.withPos(pos)) + + def mapElems(op: Tree[T] => Tree[T] @uncheckedVariance): Thicket[T] = { + val newTrees = trees.mapConserve(op) if (trees eq newTrees) this else Thicket[T](newTrees).asInstanceOf[this.type] } - override def pos: Position = (NoPosition /: trees) ((pos, t) => pos union t.pos) + override def foreachInThicket(op: Tree[T] => Unit): Unit = trees foreach (_.foreachInThicket(op)) + + override def isEmpty: Boolean = trees.isEmpty + override def toList: List[Tree[T]] = flatten(trees) + override def toString: String = if (isEmpty) "EmptyTree" else "Thicket(" + trees.mkString(", ") + ")" + override def pos: Position = (NoPosition /: trees) ((pos, t) => pos union t.pos) + + override def withSpan(pos: Position): this.type = + mapElems(_.withSpan(pos)).asInstanceOf[this.type] + override def withPosOf(posd: Positioned): this.type = + mapElems(_.withPosOf(posd)).asInstanceOf[this.type] + override def withSourcePos(sourcePos: SourcePosition): this.type = + mapElems(_.withSourcePos(sourcePos)).asInstanceOf[this.type] } class EmptyTree[T >: Untyped] extends Thicket(Nil)(NoContext) { @@ -965,10 +974,10 @@ object Trees { protected def postProcess(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T] protected def finalize(tree: Tree, copied: untpd.Tree)(implicit src: SourceInfo): copied.ThisTree[T] = - postProcess(tree, copied.withPos(tree.pos).withAttachmentsFrom(tree)) + postProcess(tree, copied.withPosOf(tree).withAttachmentsFrom(tree)) protected def finalize(tree: Tree, copied: untpd.MemberDef)(implicit src: SourceInfo): copied.ThisTree[T] = - postProcess(tree, copied.withPos(tree.pos).withAttachmentsFrom(tree)) + postProcess(tree, copied.withPosOf(tree).withAttachmentsFrom(tree)) protected def srcCtx(tree: Tree)(implicit ctx: Context) = ctx.withSource(tree.source) diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 3fce069dd475..d50ea2e8eb54 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -404,13 +404,13 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def newArray(elemTpe: Type, returnTpe: Type, pos: Position, dims: JavaSeqLiteral)(implicit ctx: Context): Tree = { val elemClass = elemTpe.classSymbol def newArr = - ref(defn.DottyArraysModule).select(defn.newArrayMethod).withPos(pos) + ref(defn.DottyArraysModule).select(defn.newArrayMethod).withSpan(pos) if (!ctx.erasedTypes) { assert(!TypeErasure.isGeneric(elemTpe)) //needs to be done during typer. See Applications.convertNewGenericArray - newArr.appliedToTypeTrees(TypeTree(returnTpe) :: Nil).appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withPos(pos) + newArr.appliedToTypeTrees(TypeTree(returnTpe) :: Nil).appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withSpan(pos) } else // after erasure - newArr.appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withPos(pos) + newArr.appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withSpan(pos) } /** The wrapped array method name for an array of type elemtp */ @@ -1012,7 +1012,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { tree else { ctx.warning(i"conversion from ${tree.tpe.widen} to ${numericCls.typeRef} will always fail at runtime.") - Throw(New(defn.ClassCastExceptionClass.typeRef, Nil)) withPos tree.pos + Throw(New(defn.ClassCastExceptionClass.typeRef, Nil)).withPosOf(tree) } } @@ -1204,7 +1204,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { // Give a zero-extent position to the qualifier to prevent it from being included several // times in results in the language server. val noPosExpr = focusPositions(imp.expr) - val selectTree = Select(noPosExpr, sym.name).withPos(id.pos) + val selectTree = Select(noPosExpr, sym.name).withPosOf(id) rename match { case None => selectTree :: Nil @@ -1213,7 +1213,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { // node with the new name and the type of the real symbol. val name = if (sym.name.isTypeName) rename.name.toTypeName else rename.name val actual = Select(noPosExpr, sym.name) - val renameTree = Select(noPosExpr, name).withPos(rename.pos).withType(actual.tpe) + val renameTree = Select(noPosExpr, name).withPosOf(rename).withType(actual.tpe) selectTree :: renameTree :: Nil } } @@ -1236,7 +1236,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { private def focusPositions(tree: Tree)(implicit ctx: Context): Tree = { val transformer = new tpd.TreeMap { override def transform(tree: Tree)(implicit ctx: Context): Tree = { - super.transform(tree).withPos(tree.pos.focus) + super.transform(tree).withSpan(tree.pos.focus) } } transformer.transform(tree) diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 6808b6fa0da9..d18c8f8f7045 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -325,7 +325,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { (tycon, targs) case TypedSplice(tpt1: tpd.Tree) => val argTypes = tpt1.tpe.dealias.argTypesLo - def wrap(tpe: Type) = TypeTree(tpe).withPos(tpt.pos) + def wrap(tpe: Type) = TypeTree(tpe).withPosOf(tpt) (tpt, argTypes.map(wrap)) case _ => (tpt, Nil) diff --git a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala index 585d4129734a..385ef8e7b55b 100644 --- a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala +++ b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala @@ -140,7 +140,7 @@ object PickledQuotes { new TreeTypeMap( oldOwners = ddef.symbol :: Nil, newOwners = ctx.owner :: Nil, - treeMap = tree => paramToVals.get(tree.symbol).map(_.withPos(tree.pos)).getOrElse(tree) + treeMap = tree => paramToVals.get(tree.symbol).map(_.withPosOf(tree)).getOrElse(tree) ).transform(ddef.rhs) case Block(stats, expr) => seq(stats, rec(expr)) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 80e1f9037570..9e53f85c4922 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -1032,7 +1032,7 @@ class TreeUnpickler(reader: TastyReader, def readQualId(): (untpd.Ident, TypeRef) = { val qual = readTerm().asInstanceOf[untpd.Ident] - (untpd.Ident(qual.name).withPos(qual.pos), qual.tpe.asInstanceOf[TypeRef]) + (untpd.Ident(qual.name).withPosOf(qual), qual.tpe.asInstanceOf[TypeRef]) } def accessibleDenot(pre: Type, name: Name, sig: Signature) = { diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala index 6346f25c2500..1736d7b905ec 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -87,7 +87,7 @@ object JavaParsers { skip() } - def errorTypeTree: TypeTree = TypeTree().withType(UnspecifiedErrorType) withPos Position(in.offset) + def errorTypeTree: TypeTree = TypeTree().withType(UnspecifiedErrorType).withSpan(Position(in.offset)) // --------- tree building ----------------------------- @@ -225,7 +225,7 @@ object JavaParsers { /** Convert (qual)ident to type identifier */ def convertToTypeId(tree: Tree): Tree = convertToTypeName(tree) match { - case Some(t) => t withPos tree.pos + case Some(t) => t.withPosOf(tree) case _ => tree match { case AppliedTypeTree(_, _) | Select(_, _) => tree @@ -603,7 +603,7 @@ object JavaParsers { } def importCompanionObject(cdef: TypeDef): Tree = - Import(Ident(cdef.name.toTermName).withPos(NoPosition), Ident(nme.WILDCARD) :: Nil) + Import(Ident(cdef.name.toTermName).withSpan(NoPosition), Ident(nme.WILDCARD) :: Nil) // Importing the companion object members cannot be done uncritically: see // ticket #2377 wherein a class contains two static inner classes, each of which @@ -660,7 +660,7 @@ object JavaParsers { } else { val qual = ((Ident(names.head): Tree) /: names.tail.init) (Select(_, _)) val lastname = names.last - val ident = Ident(lastname) withPos Position(lastnameOffset) + val ident = Ident(lastname).withSpan(Position(lastnameOffset)) // val selector = lastname match { // case nme.WILDCARD => Pair(ident, Ident(null) withPos Position(-1)) // case _ => Pair(ident, ident) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 20ce5940002c..971752892886 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -72,7 +72,7 @@ object Parsers { * If `t` does not have a position yet, set its position to the given one. */ def atPos[T <: Positioned](pos: Position)(t: T): T = - if (t.pos.isSourceDerived) t else t.withPos(pos) + if (t.pos.isSourceDerived) t else t.withSpan(pos) def atPos[T <: Positioned](start: Offset, point: Offset, end: Offset)(t: T): T = atPos(Position(start, end, point))(t) @@ -367,9 +367,9 @@ object Parsers { */ def convertToParam(tree: Tree, mods: Modifiers = Modifiers(), expected: String = "formal parameter"): ValDef = tree match { case Ident(name) => - makeParameter(name.asTermName, TypeTree(), mods) withPos tree.pos + makeParameter(name.asTermName, TypeTree(), mods).withPosOf(tree) case Typed(Ident(name), tpt) => - makeParameter(name.asTermName, tpt, mods) withPos tree.pos + makeParameter(name.asTermName, tpt, mods).withPosOf(tree) case _ => syntaxError(s"not a legal $expected", tree.pos) makeParameter(nme.ERROR, tree, mods) @@ -903,7 +903,7 @@ object Parsers { else if (isSimpleLiteral) { SingletonTypeTree(literal()) } else if (in.token == USCORE) { val start = in.skipToken() - typeBounds().withPos(Position(start, in.lastOffset, start)) + typeBounds().withSpan(Position(start, in.lastOffset, start)) } else if (isIdent(nme.raw.TILDE) && in.lookaheadIn(BitSet(IDENTIFIER, BACKQUOTED_IDENT))) atPos(in.offset) { PrefixOp(typeIdent(), path(thisOK = true)) } @@ -1030,7 +1030,7 @@ object Parsers { def typedOpt(): Tree = if (in.token == COLON) { in.nextToken(); toplevelTyp() } - else TypeTree().withPos(Position(in.lastOffset)) + else TypeTree().withSpan(Position(in.lastOffset)) def typeDependingOn(location: Location.Value): Tree = if (location == Location.InParens) typ() @@ -1270,7 +1270,7 @@ object Parsers { if (isWildcard(t) && location != Location.InPattern) { val vd :: rest = placeholderParams placeholderParams = - cpy.ValDef(vd)(tpt = tpt).withPos(vd.pos union tpt.pos) :: rest + cpy.ValDef(vd)(tpt = tpt).withSpan(vd.pos.union(tpt.pos)) :: rest } Typed(t, tpt) } @@ -1425,7 +1425,7 @@ object Parsers { val start = in.skipToken() val pname = WildcardParamName.fresh() val param = ValDef(pname, TypeTree(), EmptyTree).withFlags(SyntheticTermParam) - .withPos(Position(start)) + .withSpan(Position(start)) placeholderParams = param :: placeholderParams atPos(start) { Ident(pname) } case LPAREN => @@ -1449,9 +1449,9 @@ object Parsers { impl.parents match { case parent :: Nil if missingBody => if (parent.isType) ensureApplied(wrapNew(parent)) - else parent.withPos(Position(start, in.lastOffset)) + else parent.withSpan(Position(start, in.lastOffset)) case _ => - New(impl.withPos(Position(start, in.lastOffset))) + New(impl.withSpan(Position(start, in.lastOffset))) } case _ => if (isLiteral) literal() @@ -1893,7 +1893,7 @@ object Parsers { case _ => tree } if (tree1.pos.exists && start < tree1.pos.start) - tree1.withPos(tree1.pos.withStart(start)) + tree1.withSpan(tree1.pos.withStart(start)) else tree1 } @@ -2101,7 +2101,7 @@ object Parsers { val firstPos = if (t.pos.exists) t.pos.withStart(offset) else Position(offset, in.lastOffset) - t.withPos(firstPos) :: rest + t.withSpan(firstPos) :: rest case nil => nil } } @@ -2593,11 +2593,11 @@ object Parsers { if (in.token == ARROW) { first match { case Typed(tree @ This(EmptyTypeIdent), tpt) => - self = makeSelfDef(nme.WILDCARD, tpt).withPos(first.pos) + self = makeSelfDef(nme.WILDCARD, tpt).withPosOf(first) case _ => val ValDef(name, tpt, _) = convertToParam(first, EmptyModifiers, "self type clause") if (name != nme.ERROR) - self = makeSelfDef(name, tpt).withPos(first.pos) + self = makeSelfDef(name, tpt).withPosOf(first) } in.nextToken() } else { diff --git a/compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused b/compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused index 672c85179ff2..5293368402c9 100644 --- a/compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused +++ b/compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused @@ -42,7 +42,7 @@ class TreeBuilder(implicit ctx: Context) { case Ident(name) if isVarPattern(tree) && name != nme.WILDCARD => Bind( name, Ident(nme.WILDCARD).withPos(tree.pos.focus) - ).withPos(tree.pos) + ).withPosOf(tree) case Typed(id @ Ident(name), tpt) if isVarPattern(id) && name != nme.WILDCARD => Bind( name, diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala b/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala index 32a2bbbc714e..3c33450fab57 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala @@ -147,7 +147,7 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont def parseAttribute(pos: Position, s: String): Tree = { val ts = Utility.parseAttributeValue(s, text(pos, _), entityRef(pos, _)) ts match { - case Nil => TypedSplice(tpd.ref(defn.NilModule) withPos pos) + case Nil => TypedSplice(tpd.ref(defn.NilModule).withSpan(pos)) case t :: Nil => t case _ => makeXMLseq(pos, ts) } diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 7a351f800d20..33cc66569905 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -650,7 +650,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { val str: Text = nameString(tree.symbol) tree match { case tree: RefTree => withPos(str, tree.sourcePos) - case tree: MemberDef => withPos(str, tree.sourcePos.withRange(tree.namePos)) + case tree: MemberDef => withPos(str, tree.sourcePos.withSpan(tree.namePos)) case _ => str } } diff --git a/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala b/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala index ad5a81b89f69..a3e7db3bfd9e 100644 --- a/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala +++ b/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala @@ -78,7 +78,7 @@ class QuoteCompiler extends Compiler { val run = DefDef(meth, quoted) val classTree = ClassDef(cls, DefDef(cls.primaryConstructor.asTerm), run :: Nil) - PackageDef(ref(defn.RootPackage).asInstanceOf[Ident], classTree :: Nil).withPos(pos) + PackageDef(ref(defn.RootPackage).asInstanceOf[Ident], classTree :: Nil).withSpan(pos) } def run(implicit ctx: Context): Unit = unsupported("run") diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala index cb3861c31af2..a45ebd7af229 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala @@ -407,7 +407,7 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w // TODO only enums generate this kind of type bounds. Is this possible without enums? If not generate tpd.TypeBoundsTree for enums instead x.tpe match { case tpe: Types.TypeBounds => - Some(tpd.TypeBoundsTree(tpd.TypeTree(tpe.lo).withPos(x.pos), tpd.TypeTree(tpe.hi).withPos(x.pos))) + Some(tpd.TypeBoundsTree(tpd.TypeTree(tpe.lo).withPosOf(x), tpd.TypeTree(tpe.hi).withPosOf(x))) case _ => None } case _ => None diff --git a/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala b/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala index cfc03a0f31e6..57d5d65c2303 100644 --- a/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala +++ b/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala @@ -53,7 +53,7 @@ abstract class AccessProxies { accessRef.becomes(forwardedArgss.head.head) else accessRef.appliedToTypes(forwardedTypes).appliedToArgss(forwardedArgss) - rhs.withPos(accessed.pos) + rhs.withSpan(accessed.pos) }) /** Add all needed accessors to the `body` of class `cls` */ @@ -97,7 +97,7 @@ abstract class AccessProxies { case Select(qual, _) if qual.tpe.derivesFrom(accessor.owner) => qual.select(accessor) case _ => ref(accessor) } - }.withPos(reference.pos) + }.withPosOf(reference) /** Given a reference to a getter accessor, the corresponding setter reference */ def useSetter(getterRef: Tree)(implicit ctx: Context): Tree = getterRef match { diff --git a/compiler/src/dotty/tools/dotc/transform/Bridges.scala b/compiler/src/dotty/tools/dotc/transform/Bridges.scala index eba3b5f9a378..f9cc044fbbec 100644 --- a/compiler/src/dotty/tools/dotc/transform/Bridges.scala +++ b/compiler/src/dotty/tools/dotc/transform/Bridges.scala @@ -107,7 +107,7 @@ class Bridges(root: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont else ref.appliedToArgss(argss) } - bridges += DefDef(bridge, bridgeRhs(_).withPos(bridge.pos)) + bridges += DefDef(bridge, bridgeRhs(_).withSpan(bridge.pos)) } /** Add all necessary bridges to template statements `stats`, and remove at the same diff --git a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala index 9f03c39f92ac..75a730f55ccf 100644 --- a/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala +++ b/compiler/src/dotty/tools/dotc/transform/CapturedVars.scala @@ -107,7 +107,7 @@ class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisPhase = ref(vble.info.classSymbol.companionModule.info.member(name).symbol) cpy.ValDef(vdef)( rhs = boxMethod(nme.create).appliedTo(vdef.rhs), - tpt = TypeTree(vble.info).withPos(vdef.tpt.pos)) + tpt = TypeTree(vble.info).withPosOf(vdef.tpt)) } else vdef } diff --git a/compiler/src/dotty/tools/dotc/transform/ClassOf.scala b/compiler/src/dotty/tools/dotc/transform/ClassOf.scala index 4938d4a993d2..31f15cfedd1c 100644 --- a/compiler/src/dotty/tools/dotc/transform/ClassOf.scala +++ b/compiler/src/dotty/tools/dotc/transform/ClassOf.scala @@ -21,7 +21,7 @@ class ClassOf extends MiniPhase { override def transformTypeApply(tree: TypeApply)(implicit ctx: Context): Tree = if (tree.symbol eq defn.Predef_classOf) { val targ = tree.args.head.tpe - clsOf(targ).ensureConforms(tree.tpe).withPos(tree.pos) + clsOf(targ).ensureConforms(tree.tpe).withPosOf(tree) } else tree } diff --git a/compiler/src/dotty/tools/dotc/transform/Constructors.scala b/compiler/src/dotty/tools/dotc/transform/Constructors.scala index 778eb842ad5b..f4210963a3be 100644 --- a/compiler/src/dotty/tools/dotc/transform/Constructors.scala +++ b/compiler/src/dotty/tools/dotc/transform/Constructors.scala @@ -149,7 +149,7 @@ class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase = case Ident(_) | Select(This(_), _) => var sym = tree.symbol if (sym is (ParamAccessor, butNot = Mutable)) sym = sym.subst(accessors, paramSyms) - if (sym.owner.isConstructor) ref(sym).withPos(tree.pos) else tree + if (sym.owner.isConstructor) ref(sym).withPosOf(tree) else tree case Apply(fn, Nil) => val fn1 = transform(fn) if ((fn1 ne fn) && fn1.symbol.is(Param) && fn1.symbol.owner.isPrimaryConstructor) @@ -195,7 +195,7 @@ class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase = val sym = stat.symbol if (isRetained(sym)) { if (!stat.rhs.isEmpty && !isWildcardArg(stat.rhs)) - constrStats += Assign(ref(sym), intoConstr(stat.rhs, sym)).withPos(stat.pos) + constrStats += Assign(ref(sym), intoConstr(stat.rhs, sym)).withPosOf(stat) clsStats += cpy.ValDef(stat)(rhs = EmptyTree) } else if (!stat.rhs.isEmpty) { @@ -230,7 +230,7 @@ class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase = if (!target.exists) Nil // this case arises when the parameter accessor is an alias else { val param = acc.subst(accessors, paramSyms) - val assigns = Assign(ref(target), ref(param)).withPos(tree.pos) :: Nil + val assigns = Assign(ref(target), ref(param)).withPosOf(tree) :: Nil if (acc.name != nme.OUTER) assigns else { // insert test: if ($outer eq null) throw new NullPointerException diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 00da443666f3..0b854d605542 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -180,8 +180,7 @@ object Erasure { } def constant(tree: Tree, const: Tree)(implicit ctx: Context): Tree = - (if (isPureExpr(tree)) const else Block(tree :: Nil, const)) - .withPos(tree.pos) + (if (isPureExpr(tree)) const else Block(tree :: Nil, const)).withPosOf(tree) final def box(tree: Tree, target: => String = "")(implicit ctx: Context): Tree = trace(i"boxing ${tree.showSummary}: ${tree.tpe} into $target") { tree.tpe.widen match { @@ -559,7 +558,7 @@ object Erasure { if (sym.isEffectivelyErased) erasedDef(sym) else super.typedValDef(untpd.cpy.ValDef(vdef)( - tpt = untpd.TypedSplice(TypeTree(sym.info).withPos(vdef.tpt.pos))), sym) + tpt = untpd.TypedSplice(TypeTree(sym.info).withPosOf(vdef.tpt))), sym) /** Besides normal typing, this function also compacts anonymous functions * with more than `MaxImplementedFunctionArity` parameters to use a single @@ -592,7 +591,7 @@ object Erasure { val ddef1 = untpd.cpy.DefDef(ddef)( tparams = Nil, vparamss = vparamss1, - tpt = untpd.TypedSplice(TypeTree(restpe).withPos(ddef.tpt.pos)), + tpt = untpd.TypedSplice(TypeTree(restpe).withPosOf(ddef.tpt)), rhs = rhs1) super.typedDefDef(ddef1, sym) } diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index f64a8ed55f37..fb711151f489 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -105,7 +105,7 @@ class ExplicitOuter extends MiniPhase with InfoTransformer { thisPhase => parent } else parent match { // ensure class parent is a constructor - case parent: TypeTree => New(parent.tpe, Nil).withPos(impl.pos) + case parent: TypeTree => New(parent.tpe, Nil).withPosOf(impl) case _ => parent } } @@ -359,7 +359,7 @@ object ExplicitOuter { } if (hasOuterParam(cls)) methPart(fun) match { - case Select(receiver, _) => outerArg(receiver).withPos(fun.pos) :: Nil + case Select(receiver, _) => outerArg(receiver).withPosOf(fun) :: Nil } else Nil } else Nil diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala index 7ab625ce2a17..e3f205504cb5 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala @@ -29,7 +29,7 @@ class ExplicitSelf extends MiniPhase { override def transformIdent(tree: Ident)(implicit ctx: Context): Tree = tree.tpe match { case tp: ThisType => ctx.debuglog(s"owner = ${ctx.owner}, context = ${ctx}") - This(tp.cls) withPos tree.pos + This(tp.cls).withPosOf(tree) case _ => tree } diff --git a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala index 6717b3499f05..7ec6a6856c53 100644 --- a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala +++ b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala @@ -107,7 +107,7 @@ class FirstTransform extends MiniPhase with InfoTransformer { thisPhase => if (meth.hasAnnotation(defn.NativeAnnot)) { meth.resetFlag(Deferred) polyDefDef(meth, - _ => _ => ref(defn.Sys_errorR).withPos(ddef.pos) + _ => _ => ref(defn.Sys_errorR).withPosOf(ddef) .appliedTo(Literal(Constant(s"native method stub")))) } @@ -133,7 +133,7 @@ class FirstTransform extends MiniPhase with InfoTransformer { thisPhase => */ private def toTypeTree(tree: Tree)(implicit ctx: Context) = { val binders = collectBinders.apply(Nil, tree) - val result: Tree = TypeTree(tree.tpe).withPos(tree.pos) + val result: Tree = TypeTree(tree.tpe).withPosOf(tree) (result /: binders)(Annotated(_, _)) } diff --git a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala index bbad627150d4..1dbaf4485c6b 100644 --- a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala +++ b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala @@ -240,7 +240,7 @@ trait FullParameterization { ref(vparam.symbol).ensureConforms(paramType) })) }) - }).withPos(originalDef.rhs.pos) + }).withPosOf(originalDef.rhs) } } diff --git a/compiler/src/dotty/tools/dotc/transform/GetClass.scala b/compiler/src/dotty/tools/dotc/transform/GetClass.scala index 77ba6d1b618d..0c82431e5f70 100644 --- a/compiler/src/dotty/tools/dotc/transform/GetClass.scala +++ b/compiler/src/dotty/tools/dotc/transform/GetClass.scala @@ -26,7 +26,7 @@ class GetClass extends MiniPhase { import ast.Trees._ tree match { case Apply(Select(qual, nme.getClass_), Nil) if qual.tpe.widen.isPrimitiveValueType => - clsOf(qual.tpe.widen).withPos(tree.pos) + clsOf(qual.tpe.widen).withPosOf(tree) case _ => tree } } diff --git a/compiler/src/dotty/tools/dotc/transform/Getters.scala b/compiler/src/dotty/tools/dotc/transform/Getters.scala index 60658f9bc460..f8c484f57ec5 100644 --- a/compiler/src/dotty/tools/dotc/transform/Getters.scala +++ b/compiler/src/dotty/tools/dotc/transform/Getters.scala @@ -78,10 +78,10 @@ class Getters extends MiniPhase with SymTransformer { private val NoGetterNeeded = Method | Param | JavaDefined | JavaStatic override def transformValDef(tree: ValDef)(implicit ctx: Context): Tree = - if (tree.symbol is Method) DefDef(tree.symbol.asTerm, tree.rhs).withPos(tree.pos) else tree + if (tree.symbol is Method) DefDef(tree.symbol.asTerm, tree.rhs).withPosOf(tree) else tree override def transformAssign(tree: Assign)(implicit ctx: Context): Tree = - if (tree.lhs.symbol is Method) tree.lhs.becomes(tree.rhs).withPos(tree.pos) else tree + if (tree.lhs.symbol is Method) tree.lhs.becomes(tree.rhs).withPosOf(tree) else tree } object Getters { diff --git a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala index 1c90a14f5cf6..05648e69692c 100644 --- a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -424,7 +424,7 @@ object LambdaLift { case proxies => val sym = tree.symbol val freeParamDefs = proxies.map(proxy => - thisPhase.transformFollowingDeep(ValDef(proxy.asTerm).withPos(tree.pos)).asInstanceOf[ValDef]) + thisPhase.transformFollowingDeep(ValDef(proxy.asTerm).withPosOf(tree)).asInstanceOf[ValDef]) def proxyInit(field: Symbol, param: Symbol) = thisPhase.transformFollowingDeep(memberRef(field).becomes(ref(param))) @@ -523,9 +523,9 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisPhase => val lft = lifter if (prefix eq NoPrefix) if (sym.enclosure != lft.currentEnclosure && !sym.isStatic) - (if (sym is Method) lft.memberRef(sym) else lft.proxyRef(sym)).withPos(tree.pos) + (if (sym is Method) lft.memberRef(sym) else lft.proxyRef(sym)).withPosOf(tree) else if (sym.owner.isClass) // sym was lifted out - ref(sym).withPos(tree.pos) + ref(sym).withPosOf(tree) else tree else if (!prefixIsElidable(tpe)) ref(tpe) @@ -536,7 +536,7 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisPhase => } override def transformApply(tree: Apply)(implicit ctx: Context): Apply = - cpy.Apply(tree)(tree.fun, lifter.addFreeArgs(tree.symbol, tree.args)).withPos(tree.pos) + cpy.Apply(tree)(tree.fun, lifter.addFreeArgs(tree.symbol, tree.args)).withPosOf(tree) override def transformClosure(tree: Closure)(implicit ctx: Context): Closure = cpy.Closure(tree)(env = lifter.addFreeArgs(tree.meth.symbol, tree.env)) @@ -553,7 +553,7 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisPhase => override def transformReturn(tree: Return)(implicit ctx: Context): Tree = tree.expr match { case Block(stats, value) => - Block(stats, Return(value, tree.from)).withPos(tree.pos) + Block(stats, Return(value, tree.from)).withPosOf(tree) case _ => tree } diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala index 9cd22a639b7a..87bf048ddfc4 100644 --- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala @@ -153,7 +153,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { val holderTree = ValDef(holderSymbol, New(holderImpl.typeRef, Nil)) val holderRef = ref(holderSymbol) - val getValue = holderRef.select(lazyNme.value).ensureApplied.withPos(x.pos) + val getValue = holderRef.select(lazyNme.value).ensureApplied.withPosOf(x) val initialized = holderRef.select(lazyNme.initialized).ensureApplied // def x$lzycompute(): Int = x$lzy.synchronized { diff --git a/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala b/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala index d90aa421a52a..572c6c3e3d0e 100644 --- a/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala +++ b/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala @@ -74,7 +74,7 @@ class LinkScala2Impls extends MiniPhase with IdentityDenotTransformer { thisPhas case Apply(sel @ Select(Super(_, _), _), args) if sel.symbol.owner.is(Scala2xTrait) && currentClass.mixins.contains(sel.symbol.owner) => val impl = implMethod(sel.symbol) - if (impl.exists) Apply(ref(impl), This(currentClass) :: args).withPos(app.pos) + if (impl.exists) Apply(ref(impl), This(currentClass) :: args).withPosOf(app) else app // could have been an abstract method in a trait linked to from a super constructor case Apply(sel, args) if sel.symbol.maybeOwner.is(ImplClass) && sel.symbol.owner.traitOfImplClass.is(Scala_2_12_Trait) => diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala index 2da2f39d6bb0..3acbf1e7827f 100644 --- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala +++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala @@ -250,13 +250,13 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase => def setters(mixin: ClassSymbol): List[Tree] = for (setter <- mixin.info.decls.filter(setr => setr.isSetter && !was(setr, Deferred))) - yield transformFollowing(DefDef(implementation(setter.asTerm), unitLiteral.withPos(cls.pos))) + yield transformFollowing(DefDef(implementation(setter.asTerm), unitLiteral.withSpan(cls.pos))) cpy.Template(impl)( constr = if (cls.is(Trait)) cpy.DefDef(impl.constr)(vparamss = Nil :: Nil) else impl.constr, - parents = impl.parents.map(p => TypeTree(p.tpe).withPos(p.pos)), + parents = impl.parents.map(p => TypeTree(p.tpe).withPosOf(p)), body = if (cls is Trait) traitDefs(impl.body) else { diff --git a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala index 35a6aa1b30f5..ca9f1f7c3c09 100644 --- a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala +++ b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala @@ -34,7 +34,7 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont else Super(This(cls), target.owner.name.asTypeName, false, target.owner) //println(i"super ref $target on $sup") - ast.untpd.Select(sup.withPos(pos), target.name) + ast.untpd.Select(sup.withSpan(pos), target.name) .withType(NamedType(sup.tpe, target)) //sup.select(target) } diff --git a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala index 23c0fb222b6c..0ca776d2acc8 100644 --- a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala +++ b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala @@ -86,6 +86,6 @@ class NonLocalReturns extends MiniPhase { } override def transformReturn(tree: Return)(implicit ctx: Context): Tree = - if (isNonLocalReturn(tree)) nonLocalReturnThrow(tree.expr, tree.from.symbol).withPos(tree.pos) + if (isNonLocalReturn(tree)) nonLocalReturnThrow(tree.expr, tree.from.symbol).withPosOf(tree) else tree } diff --git a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala index 138fe95114af..264c987d4424 100644 --- a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala +++ b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala @@ -70,7 +70,7 @@ class ParamForwarding(thisPhase: DenotTransformer) { val superAcc = Super(This(currentClass), tpnme.EMPTY, inConstrCall = false).select(alias) typr.println(i"adding param forwarder $superAcc") - DefDef(sym, superAcc.ensureConforms(sym.info.widen)).withPos(stat.pos) + DefDef(sym, superAcc.ensureConforms(sym.info.widen)).withPosOf(stat) } return forwarder(ctx.withPhase(thisPhase.next)) } diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 60afd0a7b313..b83d0fb153c8 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -823,7 +823,7 @@ object PatternMatcher { case plan2: TestPlan => emitWithMashedConditions(plan2 :: plans) case _ => - def emitCondWithPos(plan: TestPlan) = emitCondition(plan).withPos(plan.pos) + def emitCondWithPos(plan: TestPlan) = emitCondition(plan).withSpan(plan.pos) val conditions = plans.foldRight[Tree](EmptyTree) { (otherPlan, acc) => if (acc.isEmpty) emitCondWithPos(otherPlan) diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index 0d2352372b29..be4aa899f9fe 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -154,7 +154,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase case tp: PolyType if args.exists(isNamedArg) => val (namedArgs, otherArgs) = args.partition(isNamedArg) val args1 = reorderArgs(tp.paramNames, namedArgs.asInstanceOf[List[NamedArg]], otherArgs) - TypeApply(tycon, args1).withPos(tree.pos).withType(tree.tpe) + TypeApply(tycon, args1).withPosOf(tree).withType(tree.tpe) case _ => tree } @@ -193,7 +193,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase case tree: Ident if !tree.isType => handleMeta(tree.symbol) tree.tpe match { - case tpe: ThisType => This(tpe.cls).withPos(tree.pos) + case tpe: ThisType => This(tpe.cls).withPosOf(tree) case _ => tree } case tree @ Select(qual, name) => diff --git a/compiler/src/dotty/tools/dotc/transform/Staging.scala b/compiler/src/dotty/tools/dotc/transform/Staging.scala index cc194fc3c903..c488eb19aeb5 100644 --- a/compiler/src/dotty/tools/dotc/transform/Staging.scala +++ b/compiler/src/dotty/tools/dotc/transform/Staging.scala @@ -387,7 +387,7 @@ class Staging extends MacroTransformWithImplicits { val body2 = if (body1.isType) body1 else Inlined(Inliner.inlineCallTrace(ctx.owner, quote.pos), Nil, body1) - pickledQuote(body2, splices, body.tpe, isType).withPos(quote.pos) + pickledQuote(body2, splices, body.tpe, isType).withPosOf(quote) } else { // In top-level splice in an inline def. Keep the tree as it is, it will be transformed at inline site. @@ -439,7 +439,7 @@ class Staging extends MacroTransformWithImplicits { else if (level == 1) { val (body1, quotes) = nested(isQuote = false).split(splice.qualifier) val tpe = outer.embedded.getHoleType(splice) - val hole = makeHole(body1, quotes, tpe).withPos(splice.pos) + val hole = makeHole(body1, quotes, tpe).withPosOf(splice) // We do not place add the inline marker for trees that where lifted as they come from the same file as their // enclosing quote. Any intemediate splice will add it's own Inlined node and cancel it before splicig the lifted tree. // Note that lifted trees are not necessarily expressions and that Inlined nodes are expected to be expressions. @@ -450,7 +450,7 @@ class Staging extends MacroTransformWithImplicits { else if (enclosingInlineds.nonEmpty) { // level 0 in an inlined call val spliceCtx = ctx.outer // drop the last `inlineContext` val pos: SourcePosition = spliceCtx.source.atPos(enclosingInlineds.head.pos) - val evaluatedSplice = Splicer.splice(splice.qualifier, pos, macroClassLoader)(spliceCtx).withPos(splice.pos) + val evaluatedSplice = Splicer.splice(splice.qualifier, pos, macroClassLoader)(spliceCtx).withPosOf(splice) if (ctx.reporter.hasErrors) splice else transform(evaluatedSplice) } else if (!ctx.owner.isInlineMethod) { // level 0 outside an inline method @@ -579,7 +579,7 @@ class Staging extends MacroTransformWithImplicits { quotation(quotedTree, tree) case tree: TypeTree if tree.tpe.typeSymbol.isSplice => val splicedType = tree.tpe.stripTypeVar.asInstanceOf[TypeRef].prefix.termSymbol - splice(ref(splicedType).select(tpnme.UNARY_~).withPos(tree.pos)) + splice(ref(splicedType).select(tpnme.UNARY_~).withPosOf(tree)) case tree: Select if tree.symbol.isSplice => splice(tree) case tree: RefTree if tree.symbol.is(Inline) && tree.symbol.is(Param) => diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index b9061df6ca83..8c0a9d78b4dc 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -70,7 +70,7 @@ class SuperAccessors(thisPhase: DenotTransformer) { if (clazz is Trait) superName = superName.expandedName(clazz) val superInfo = sel.tpe.widenSingleton.ensureMethodic - val accPos = sel.pos.focus + val accRange = sel.pos.focus val superAcc = clazz.info.decl(superName) .suchThat(_.signature == superInfo.signature).symbol .orElse { @@ -78,17 +78,17 @@ class SuperAccessors(thisPhase: DenotTransformer) { val maybeDeferred = if (clazz is Trait) Deferred else EmptyFlags val acc = ctx.newSymbol( clazz, superName, Artifact | Method | maybeDeferred, - superInfo, coord = accPos).enteredAfter(thisPhase) + superInfo, coord = accRange).enteredAfter(thisPhase) // Diagnostic for SI-7091 if (!accDefs.contains(clazz)) ctx.error( s"Internal error: unable to store accessor definition in ${clazz}. clazz.hasPackageFlag=${clazz is Package}. Accessor required for ${sel} (${sel.show})", sel.sourcePos) - else accDefs(clazz) += DefDef(acc, EmptyTree).withPos(accPos) + else accDefs(clazz) += DefDef(acc, EmptyTree).withSpan(accRange) acc } - This(clazz).select(superAcc).withPos(sel.pos) + This(clazz).select(superAcc).withPosOf(sel) } /** Check selection `super.f` for conforming to rules. If necessary, diff --git a/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala b/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala index 0b9dde117732..ba8f2ac4e839 100644 --- a/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala @@ -94,7 +94,7 @@ class SyntheticMethods(thisPhase: DenotTransformer) { case nme.productElement => vrefss => productElementBody(accessors.length, vrefss.head.head) } ctx.log(s"adding $synthetic to $clazz at ${ctx.phase}") - DefDef(synthetic, syntheticRHS(ctx.withOwner(synthetic))).withPos(ctx.owner.pos.focus) + DefDef(synthetic, syntheticRHS(ctx.withOwner(synthetic))).withSpan(ctx.owner.pos.focus) } /** The class diff --git a/compiler/src/dotty/tools/dotc/transform/TailRec.scala b/compiler/src/dotty/tools/dotc/transform/TailRec.scala index 2c4a70294ad2..88a24ac7225f 100644 --- a/compiler/src/dotty/tools/dotc/transform/TailRec.scala +++ b/compiler/src/dotty/tools/dotc/transform/TailRec.scala @@ -330,7 +330,7 @@ class TailRec extends MiniPhase { case _ :: _ => val (tempValDefs, assigns) = (for ((lhs, rhs) <- assignThisAndParamPairs) yield { val temp = ctx.newSymbol(method, TailTempName.fresh(lhs.name.toTermName), Synthetic, lhs.info) - (ValDef(temp, rhs), Assign(ref(lhs), ref(temp)).withPos(tree.pos)) + (ValDef(temp, rhs), Assign(ref(lhs), ref(temp)).withPosOf(tree)) }).unzip tempValDefs ::: assigns case nil => @@ -342,7 +342,7 @@ class TailRec extends MiniPhase { * which can cause Ycheck errors. */ val tpt = TypeTree(method.info.resultType) - seq(assignments, Typed(Return(unitLiteral.withPos(tree.pos), continueLabel), tpt)) + seq(assignments, Typed(Return(unitLiteral.withPosOf(tree), continueLabel), tpt)) } else fail("it is not in tail position") } diff --git a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala index 827b2bd6c57e..f717114330e1 100644 --- a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala +++ b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala @@ -88,10 +88,10 @@ class TryCatchPatterns extends MiniPhase { val exName = ExceptionBinderName.fresh() val fallbackSelector = ctx.newSymbol(ctx.owner, exName, Flags.Synthetic | Flags.Case, defn.ThrowableType, coord = pos) - val sel = Ident(fallbackSelector.termRef).withPos(pos) + val sel = Ident(fallbackSelector.termRef).withSpan(pos) val rethrow = CaseDef(EmptyTree, EmptyTree, Throw(ref(fallbackSelector))) Some(CaseDef( - Bind(fallbackSelector, Underscore(fallbackSelector.info).withPos(pos)), + Bind(fallbackSelector, Underscore(fallbackSelector.info).withSpan(pos)), EmptyTree, transformFollowing(Match(sel, patternMatchCases ::: rethrow :: Nil))) ) diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 22839f9d0ef9..8281cc3fc184 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -147,7 +147,7 @@ object TypeTestsCasts { def isPrimitive(tp: Type) = tp.classSymbol.isPrimitiveValueClass def derivedTree(expr1: Tree, sym: Symbol, tp: Type) = - cpy.TypeApply(tree)(expr1.select(sym).withPos(expr.pos), List(TypeTree(tp))) + cpy.TypeApply(tree)(expr1.select(sym).withPosOf(expr), List(TypeTree(tp))) def effectiveClass(tp: Type): Symbol = if (tp.isRef(defn.PairClass)) effectiveClass(erasure(tp)) @@ -248,7 +248,7 @@ object TypeTestsCasts { */ def transformTypeTest(expr: Tree, testType: Type, flagUnrelated: Boolean): Tree = testType.dealias match { case _: SingletonType => - expr.isInstance(testType).withPos(tree.pos) + expr.isInstance(testType).withPosOf(tree) case OrType(tp1, tp2) => evalOnce(expr) { e => transformTypeTest(e, tp1, flagUnrelated = false) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index b8def0006d3c..8defadf6a90a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -521,7 +521,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => if (getter.isEmpty) missingArg(n) else { val substParam = addTyped( - treeToArg(spliceMeth(getter withPos normalizedFun.pos, normalizedFun)), + treeToArg(spliceMeth(getter.withPosOf(normalizedFun), normalizedFun)), formal) matchArgs(args1, formals1.mapconserve(substParam), n + 1) } @@ -930,7 +930,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => def newGenericArrayCall = ref(defn.DottyArraysModule) - .select(defn.newGenericArrayMethod).withPos(tree.pos) + .select(defn.newGenericArrayMethod).withPosOf(tree) .appliedToTypeTrees(targs).appliedToArgs(args) if (TypeErasure.isGeneric(targ.tpe)) @@ -958,7 +958,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => ttree.tpe match { case alias: TypeRef if alias.info.isTypeAlias && !nestedCtx.reporter.hasErrors => companionRef(alias) match { - case companion: TermRef => return untpd.ref(companion) withPos tree.pos + case companion: TermRef => return untpd.ref(companion).withPosOf(tree) case _ => } case _ => @@ -1086,7 +1086,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => args.init :+ argSeq case _ => val (regularArgs, varArgs) = args.splitAt(argTypes.length - 1) - regularArgs :+ untpd.SeqLiteral(varArgs, untpd.TypeTree()).withPos(tree.pos) + regularArgs :+ untpd.SeqLiteral(varArgs, untpd.TypeTree()).withPosOf(tree) } else if (argTypes.lengthCompare(1) == 0 && args.lengthCompare(1) > 0 && ctx.canAutoTuple) untpd.Tuple(args) :: Nil diff --git a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala index ac452780ccc4..639c36229169 100644 --- a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala +++ b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala @@ -105,7 +105,7 @@ trait Dynamic { self: Typer with Applications => } private def coreDynamic(qual: untpd.Tree, dynName: Name, name: Name, selPos: Position, targs: List[untpd.Tree])(implicit ctx: Context): untpd.Apply = { - val select = untpd.Select(qual, dynName).withPos(selPos) + val select = untpd.Select(qual, dynName).withSpan(selPos) val selectWithTypes = if (targs.isEmpty) select else untpd.TypeApply(select, targs) @@ -144,7 +144,7 @@ trait Dynamic { self: Typer with Applications => // ($qual: Selectable).$selectorName("$name", ..$ctags) val base = untpd.Apply( - untpd.TypedSplice(selectable.select(selectorName)).withPos(fun.pos), + untpd.TypedSplice(selectable.select(selectorName)).withPosOf(fun), (Literal(Constant(name.toString)) :: ctags).map(untpd.TypedSplice(_))) val scall = diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala index b6d16782a0bd..fe7cf6c9ee89 100644 --- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -47,8 +47,8 @@ abstract class Lifter { var liftedType = expr.tpe.widen if (liftedFlags.is(Method)) liftedType = ExprType(liftedType) val lifted = ctx.newSymbol(ctx.owner, name, liftedFlags | Synthetic, liftedType, coord = positionCoord(expr.pos)) - defs += liftedDef(lifted, expr).withPos(expr.pos) - ref(lifted.termRef).withPos(expr.pos.focus) + defs += liftedDef(lifted, expr).withPosOf(expr) + ref(lifted.termRef).withSpan(expr.pos.focus) } /** Lift out common part of lhs tree taking part in an operator assignment such as @@ -208,8 +208,8 @@ object EtaExpansion extends LiftImpure { var paramFlag = Synthetic | Param if (mt.isImplicitMethod) paramFlag |= Implicit val params = (mt.paramNames, paramTypes).zipped.map((name, tpe) => - ValDef(name, tpe, EmptyTree).withFlags(paramFlag).withPos(tree.pos.startPos)) - var ids: List[Tree] = mt.paramNames map (name => Ident(name).withPos(tree.pos.startPos)) + ValDef(name, tpe, EmptyTree).withFlags(paramFlag).withSpan(tree.pos.startPos)) + var ids: List[Tree] = mt.paramNames map (name => Ident(name).withSpan(tree.pos.startPos)) if (mt.paramInfos.nonEmpty && mt.paramInfos.last.isRepeatedParam) ids = ids.init :+ repeated(ids.last) var body: Tree = Apply(lifted, ids) diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 949f142bb12c..6615f61771ab 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -624,14 +624,13 @@ trait Implicits { self: Typer => if (etag.tpe.isError) EmptyTree else etag.select(nme.wrap) case tp if hasStableErasure(tp) && !defn.isBottomClass(tp.typeSymbol) => val sym = tp.typeSymbol - if (sym == defn.UnitClass || sym == defn.AnyClass || sym == defn.AnyValClass) - ref(defn.ClassTagModule).select(sym.name.toTermName).withPos(pos) - else - ref(defn.ClassTagModule) - .select(nme.apply) - .appliedToType(tp) - .appliedTo(clsOf(erasure(tp))) - .withPos(pos) + val classTag = ref(defn.ClassTagModule) + val tag = + if (sym == defn.UnitClass || sym == defn.AnyClass || sym == defn.AnyValClass) + classTag.select(sym.name.toTermName) + else + classTag.select(nme.apply).appliedToType(tp).appliedTo(clsOf(erasure(tp))) + tag.withSpan(pos) case tp => EmptyTree } @@ -677,7 +676,7 @@ trait Implicits { self: Typer => case args @ (arg1 :: arg2 :: Nil) if !ctx.featureEnabled(defn.LanguageModuleClass, nme.strictEquality) && ctx.test(implicit ctx => validEqAnyArgs(arg1, arg2)) => - ref(defn.Eq_eqAny).appliedToTypes(args).withPos(pos) + ref(defn.Eq_eqAny).appliedToTypes(args).withSpan(pos) case _ => EmptyTree } @@ -955,7 +954,7 @@ trait Implicits { self: Typer => /** Try to typecheck an implicit reference */ def typedImplicit(cand: Candidate, contextual: Boolean)(implicit ctx: Context): SearchResult = track("typedImplicit") { trace(i"typed implicit ${cand.ref}, pt = $pt, implicitsEnabled == ${ctx.mode is ImplicitsEnabled}", implicits, show = true) { val ref = cand.ref - var generated: Tree = tpd.ref(ref).withPos(pos.startPos) + var generated: Tree = tpd.ref(ref).withSpan(pos.startPos) val locked = ctx.typerState.ownedVars val generated1 = if (argument.isEmpty) @@ -980,7 +979,7 @@ trait Implicits { self: Typer => else tryConversion } lazy val shadowing = - typedUnadapted(untpd.Ident(cand.implicitRef.implicitName) withPos pos.toSynthetic)( + typedUnadapted(untpd.Ident(cand.implicitRef.implicitName).withSpan(pos.toSynthetic))( nestedContext().addMode(Mode.ImplicitShadowing).setExploreTyperState()) /** Is candidate reference the same as the `shadowing` reference? (i.e. @@ -1211,7 +1210,7 @@ trait Implicits { self: Typer => // other candidates need to be considered. ctx.searchHistory.recursiveRef(pt) match { case ref: TermRef => - SearchSuccess(tpd.ref(ref).withPos(pos.startPos), ref, 0)(ctx.typerState, ctx.gadt) + SearchSuccess(tpd.ref(ref).withSpan(pos.startPos), ref, 0)(ctx.typerState, ctx.gadt) case _ => val eligible = if (contextual) ctx.implicits.eligible(wildProto) @@ -1451,7 +1450,7 @@ final class SearchRoot extends SearchHistory { implicitDictionary.get(tpe) match { case Some((ref, _)) => implicitDictionary.put(tpe, (ref, result.tree)) - SearchSuccess(tpd.ref(ref).withPos(result.tree.pos), result.ref, result.level)(result.tstate, result.gstate) + SearchSuccess(tpd.ref(ref).withPosOf(result.tree), result.ref, result.level)(result.tstate, result.gstate) case None => result } } diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 06debba4df04..a077125899bc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -348,13 +348,13 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { def integrate(tree: Tree, originalOwner: Symbol)(implicit ctx: Context): Tree = { val result = tree.changeOwner(originalOwner, ctx.owner) if (!originalOwner.isContainedIn(inlinedMethod)) - Inlined(EmptyTree, Nil, result)(ctx.withSource(tree.source)).withPos(tree.pos) + Inlined(EmptyTree, Nil, result).withPosOf(tree) else result } def tryConstValue: Tree = ctx.typeComparer.constValue(callTypeArgs.head.tpe) match { - case Some(c) => Literal(c)(ctx.withSource(call.source)).withPos(call.pos) + case Some(c) => Literal(c).withPosOf(call) case _ => EmptyTree } @@ -706,7 +706,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { */ def newBinding(sym: TermSymbol, rhs: Tree): Unit = { sym.info = rhs.tpe.widenTermRefExpr - bindingsBuf += ValDef(sym, constToLiteral(rhs)).withPos(sym.pos) + bindingsBuf += ValDef(sym, constToLiteral(rhs)).withSpan(sym.pos) } def searchImplicit(sym: TermSymbol, tpt: Tree) = { diff --git a/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala b/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala index d073e16c373d..2277fdf5a491 100644 --- a/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala +++ b/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala @@ -168,7 +168,7 @@ object PrepareInlineable { ref(accessor) .appliedToTypeTrees(localRefs.map(TypeTree(_)) ++ targs) .appliedToArgss((qual :: Nil) :: argss) - .withPos(tree.pos) + .withPosOf(tree) // TODO: Handle references to non-public types. // This is quite tricky, as such types can appear anywhere, including as parts @@ -178,7 +178,7 @@ object PrepareInlineable { // // val accessor = accessorSymbol(tree, TypeAlias(tree.tpe)).asType // myAccessors += TypeDef(accessor).withPos(tree.pos.focus) - // ref(accessor).withPos(tree.pos) + // ref(accessor).withPosOf(tree) // case _ => tree } diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index df165bfb0435..d2165cd31be3 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -471,7 +471,7 @@ object ProtoTypes { def newTypeVars(tl: TypeLambda): List[TypeTree] = for (paramRef <- tl.paramRefs) yield { - val tt = new TypeVarBinder().withPos(owningTree.pos) + val tt = new TypeVarBinder().withPosOf(owningTree) val tvar = new TypeVar(paramRef, state) state.ownedVars += tvar tt.withType(tvar) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 9c85baf48d7d..702c417a89cc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -398,7 +398,7 @@ class Typer extends Namer val tree1 = ownType match { case ownType: NamedType if !prefixIsElidable(ownType) => - ref(ownType).withPos(tree.pos) + ref(ownType).withPosOf(tree) case _ => tree.withType(ownType) } @@ -517,7 +517,7 @@ class Typer extends Namer case _ => } if (checkClassType(tpt1.tpe, tpt1.sourcePos, traitReq = false, stablePrefixReq = true) eq defn.ObjectType) - tpt1 = TypeTree(defn.ObjectType).withPos(tpt1.pos) + tpt1 = TypeTree(defn.ObjectType).withPosOf(tpt1) tpt1 match { case AppliedTypeTree(_, targs) => @@ -543,7 +543,7 @@ class Typer extends Namer if (id.name == nme.WILDCARD || id.name == nme.WILDCARD_STAR) ifPat else { import untpd._ - typed(Bind(id.name, Typed(Ident(wildName), tree.tpt)).withPos(tree.pos), pt) + typed(Bind(id.name, Typed(Ident(wildName), tree.tpt)).withPosOf(tree), pt) } case _ => ifExpr } @@ -729,7 +729,7 @@ class Typer extends Namer val cond1 = typed(tree.cond, defn.BooleanType) val thenp2 :: elsep2 :: Nil = harmonic(harmonize, pt) { val thenp1 = typed(tree.thenp, pt.notApplied) - val elsep1 = typed(tree.elsep orElse (untpd.unitLiteral withPos tree.pos), pt.notApplied) + val elsep1 = typed(tree.elsep.orElse(untpd.unitLiteral.withPosOf(tree)), pt.notApplied) thenp1 :: elsep1 :: Nil } assignType(cpy.If(tree)(cond1, thenp2, elsep2), thenp2, elsep2) @@ -798,14 +798,14 @@ class Typer extends Namer val mt = companion.fromSymbols(params1.map(_.symbol), resultTpt.tpe) if (mt.isParamDependent) ctx.error(i"$mt is an illegal function type because it has inter-parameter dependencies", tree.sourcePos) - val resTpt = TypeTree(mt.nonDependentResultApprox).withPos(body.pos) + val resTpt = TypeTree(mt.nonDependentResultApprox).withPosOf(body) val typeArgs = params1.map(_.tpt) :+ resTpt val tycon = TypeTree(funCls.typeRef) val core = assignType(cpy.AppliedTypeTree(tree)(tycon, typeArgs), tycon, typeArgs) val appMeth = ctx.newSymbol(ctx.owner, nme.apply, Synthetic | Method | Deferred, mt, coord = body.pos) val appDef = assignType( untpd.DefDef(appMeth.name, Nil, List(params1), resultTpt, EmptyTree), - appMeth).withPos(body.pos) + appMeth).withPosOf(body) RefinedTypeTree(core, List(appDef), ctx.owner.asClass) } @@ -1000,7 +1000,7 @@ class Typer extends Namer else { val (protoFormals, _) = decomposeProtoFunction(pt, 1) val unchecked = pt.isRef(defn.PartialFunctionClass) - typed(desugar.makeCaseLambda(tree.cases, protoFormals.length, unchecked) withPos tree.pos, pt) + typed(desugar.makeCaseLambda(tree.cases, protoFormals.length, unchecked).withPosOf(tree), pt) } case _ => if (tree.isInline) checkInInlineContext("inline match", tree.sourcePos) @@ -1154,7 +1154,7 @@ class Typer extends Namer // Hence no adaptation is possible, and we assume WildcardType as prototype. (from, proto) } - val expr1 = typedExpr(tree.expr orElse untpd.unitLiteral.withPos(tree.pos), proto) + val expr1 = typedExpr(tree.expr orElse untpd.unitLiteral.withPosOf(tree), proto) assignType(cpy.Return(tree)(expr1, from)) } @@ -1179,7 +1179,7 @@ class Typer extends Namer def typedThrow(tree: untpd.Throw)(implicit ctx: Context): Tree = track("typedThrow") { val expr1 = typed(tree.expr, defn.ThrowableType) - Throw(expr1).withPos(tree.pos) + Throw(expr1).withPosOf(tree) } def typedSeqLiteral(tree: untpd.SeqLiteral, pt: Type)(implicit ctx: Context): SeqLiteral = track("typedSeqLiteral") { @@ -1223,7 +1223,7 @@ class Typer extends Namer tree.ensureCompletions tree.getAttachment(untpd.OriginalSymbol) match { case Some(origSym) => - tree.derivedTree(origSym).withPos(tree.pos) + tree.derivedTree(origSym).withPosOf(tree) // btw, no need to remove the attachment. The typed // tree is different from the untyped one, so the // untyped tree is no longer accessed after all @@ -1260,7 +1260,7 @@ class Typer extends Namer def typedRefinedTypeTree(tree: untpd.RefinedTypeTree)(implicit ctx: Context): RefinedTypeTree = track("typedRefinedTypeTree") { val tpt1 = if (tree.tpt.isEmpty) TypeTree(defn.ObjectType) else typedAheadType(tree.tpt) - val refineClsDef = desugar.refinedTypeToClass(tpt1, tree.refinements).withPos(tree.pos) + val refineClsDef = desugar.refinedTypeToClass(tpt1, tree.refinements).withPosOf(tree) val refineCls = createSymbol(refineClsDef).asClass val TypeDef(_, impl: Template) = typed(refineClsDef) val refinements1 = impl.body @@ -1320,7 +1320,7 @@ class Typer extends Namer // type parameter in `C`. // The transform does not apply for patterns, where empty bounds translate to // wildcard identifiers `_` instead. - TypeTree(tparamBounds).withPos(arg.pos) + TypeTree(tparamBounds).withPosOf(arg) case _ => typed(desugaredArg, argPt) } @@ -1401,7 +1401,7 @@ class Typer extends Namer // was rewritten to `x @ ctag(e)` by `tryWithClassTag`. // Rewrite further to `ctag(x @ e)` tpd.cpy.UnApply(body1)(fn, Nil, - typed(untpd.Bind(tree.name, untpd.TypedSplice(arg)).withPos(tree.pos), arg.tpe) :: Nil) + typed(untpd.Bind(tree.name, untpd.TypedSplice(arg)).withPosOf(tree), arg.tpe) :: Nil) case _ => if (tree.name == nme.WILDCARD) body1 else { @@ -1641,7 +1641,7 @@ class Typer extends Namer val impl1 = cpy.Template(impl)(constr1, parents1, self1, body1) .withType(dummy.termRef) if (!cls.is(AbstractOrTrait) && !ctx.isAfterTyper) - checkRealizableBounds(cls, cdef.sourcePos.withRange(cdef.namePos)) + checkRealizableBounds(cls, cdef.sourcePos.withSpan(cdef.namePos)) if (cls.is(Case) && cls.derivesFrom(defn.EnumClass)) { val firstParent = parents1.head.tpe.dealias.typeSymbol checkEnum(cdef, cls, firstParent) @@ -1720,7 +1720,7 @@ class Typer extends Namer /** Ensure that first parent tree refers to a real class. */ def ensureFirstTreeIsClass(parents: List[Tree], pos: Position)(implicit ctx: Context): List[Tree] = parents match { case p :: ps if p.tpe.classSymbol.isRealClass => parents - case _ => TypeTree(ensureFirstIsClass(parents.tpes, pos).head).withPos(pos.focus) :: parents + case _ => TypeTree(ensureFirstIsClass(parents.tpes, pos).head).withSpan(pos.focus) :: parents } /** If this is a real class, make sure its first parent is a @@ -1850,7 +1850,7 @@ class Typer extends Namer def typedTuple(tree: untpd.Tuple, pt: Type)(implicit ctx: Context): Tree = { val arity = tree.trees.length if (arity <= Definitions.MaxTupleArity) - typed(desugar.smallTuple(tree).withPos(tree.pos), pt) + typed(desugar.smallTuple(tree).withPosOf(tree), pt) else { val pts = if (arity == pt.tupleArity) pt.tupleElementTypes @@ -1859,11 +1859,11 @@ class Typer extends Namer if (ctx.mode.is(Mode.Type)) (elems :\ (TypeTree(defn.UnitType): Tree))((elemTpt, elemTpts) => AppliedTypeTree(TypeTree(defn.PairType), List(elemTpt, elemTpts))) - .withPos(tree.pos) + .withPosOf(tree) else { val tupleXXLobj = untpd.ref(defn.TupleXXLModule.termRef) val app = untpd.cpy.Apply(tree)(tupleXXLobj, elems.map(untpd.TypedSplice(_))) - .withPos(tree.pos) + .withPosOf(tree) val app1 = typed(app, defn.TupleXXLType) if (ctx.mode.is(Mode.Pattern)) app1 else { @@ -1964,7 +1964,7 @@ class Typer extends Namer case tree: untpd.TypedSplice => typedTypedSplice(tree) case tree: untpd.UnApply => typedUnApply(tree, pt) case tree: untpd.Tuple => typedTuple(tree, pt) - case tree: untpd.DependentTypeTree => typed(untpd.TypeTree().withPos(tree.pos), pt) + case tree: untpd.DependentTypeTree => typed(untpd.TypeTree().withPosOf(tree), pt) case tree: untpd.InfixOp if ctx.mode.isExpr => typedInfixOp(tree, pt) case tree @ untpd.PostfixOp(qual, Ident(nme.WILDCARD)) => typedAsFunction(tree, pt) case untpd.EmptyTree => tpd.EmptyTree @@ -2585,7 +2585,7 @@ class Typer extends Namer /** Adapt an expression of constant type to a different constant type `tpe`. */ def adaptConstant(tree: Tree, tpe: ConstantType): Tree = { - def lit = Literal(tpe.value).withPos(tree.pos) + def lit = Literal(tpe.value).withPosOf(tree) tree match { case Literal(c) => lit case tree @ Block(stats, expr) => tpd.cpy.Block(tree)(stats, adaptConstant(expr, tpe)) @@ -2635,7 +2635,7 @@ class Typer extends Namer try { findRef(name, WildcardType, ExtensionMethod, tree) match { case ref: TermRef => - extMethodApply(untpd.ref(ref).withPos(tree.pos), tree, mbrType) + extMethodApply(untpd.ref(ref).withPosOf(tree), tree, mbrType) case _ => EmptyTree } } diff --git a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala index f536d1d16266..ecdeea9aec0e 100644 --- a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala +++ b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala @@ -55,12 +55,12 @@ extends interfaces.SourcePosition with Showable { def endColumn: Int = source.column(end) def withOuter(outer: SourcePosition): SourcePosition = SourcePosition(source, pos, outer) - def withRange(range: Position) = SourcePosition(source, range, outer) + def withSpan(range: Position) = SourcePosition(source, range, outer) - def startPos: SourcePosition = withRange(pos.startPos) - def endPos : SourcePosition = withRange(pos.endPos) - def focus : SourcePosition = withRange(pos.focus) - def toSynthetic: SourcePosition = withRange(pos.toSynthetic) + def startPos: SourcePosition = withSpan(pos.startPos) + def endPos : SourcePosition = withSpan(pos.endPos) + def focus : SourcePosition = withSpan(pos.focus) + def toSynthetic: SourcePosition = withSpan(pos.toSynthetic) override def toString: String = s"${if (source.exists) source.file.toString else "(no source)"}:$pos" diff --git a/compiler/src/dotty/tools/repl/ReplCompiler.scala b/compiler/src/dotty/tools/repl/ReplCompiler.scala index 819043fb458b..e61bc6b15deb 100644 --- a/compiler/src/dotty/tools/repl/ReplCompiler.scala +++ b/compiler/src/dotty/tools/repl/ReplCompiler.scala @@ -92,12 +92,12 @@ class ReplCompiler extends Compiler { // special case simple reassignment (e.g. x = 3) // in order to print the new value in the REPL val assignName = (id.name ++ str.REPL_ASSIGN_SUFFIX).toTermName - val assign = ValDef(assignName, TypeTree(), id).withPos(expr.pos) + val assign = ValDef(assignName, TypeTree(), id).withPosOf(expr) defs += expr += assign case expr if expr.isTerm => val resName = (str.REPL_RES_PREFIX + valIdx).toTermName valIdx += 1 - val vd = ValDef(resName, TypeTree(), expr).withPos(expr.pos) + val vd = ValDef(resName, TypeTree(), expr).withPosOf(expr) defs += vd case other => defs += other @@ -135,7 +135,7 @@ class ReplCompiler extends Compiler { val tmpl = Template(emptyConstructor, Nil, EmptyValDef, defs.stats) val module = ModuleDef(objectName(defs.state), tmpl) - .withPos(Position(0, defs.stats.last.pos.end)) + .withSpan(Position(0, defs.stats.last.pos.end)) PackageDef(Ident(nme.EMPTY_PACKAGE), List(module)) } @@ -231,7 +231,7 @@ class ReplCompiler extends Compiler { val tmpl = Template(emptyConstructor, Nil, EmptyValDef, List(valdef)) val wrapper = TypeDef("$wrapper".toTypeName, tmpl) .withMods(Modifiers(Final)) - .withPos(Position(0, expr.length)) + .withSpan(Position(0, expr.length)) PackageDef(Ident(nme.EMPTY_PACKAGE), List(wrapper)) } From 6f6d1ab50b4ba7682e5fe9810ca029513fa9bc4c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 3 Jan 2019 16:03:52 +0100 Subject: [PATCH 33/75] Fix position pickler - align conditions for generating sourdce changes with new scheme for assigning source files to trees - Also: avoid context capture in Thicket --- .../src/dotty/tools/dotc/ast/Positioned.scala | 45 ++++++++++++------- .../src/dotty/tools/dotc/ast/TreeIds.scala | 2 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 4 +- .../src/dotty/tools/dotc/core/Contexts.scala | 12 +++-- .../dotc/core/tasty/PositionPickler.scala | 15 ++++--- 5 files changed, 52 insertions(+), 26 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index 8539812a3767..237e6eec4966 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -33,7 +33,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod def sourcePos(implicit ctx: Context): SourcePosition = source.atPos(pos) setId(TreeIds.nextIdFor(initialFile(src))) - setPos(initialPos, srcfile) + setPos(initialSpan(), srcfile) protected def setId(id: Int): Unit = { myUniqueId = id @@ -156,7 +156,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod newpd } - def initialFile(src: SourceInfo): AbstractFile = { + def elemsFile: AbstractFile = { def firstFile(x: Any): AbstractFile = x match { case x: Positioned if x.pos.exists => x.srcfile @@ -167,7 +167,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod null } def firstElemFile(n: Int): AbstractFile = - if (n == productArity) src.source.file + if (n == productArity) null else { val f = firstFile(productElement(n)) if (f != null) f else firstElemFile(n + 1) @@ -175,30 +175,45 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod firstElemFile(0) } - /** The initial, synthetic position. This is usually the union of all positioned children's positions. + private def initialFile(src: SourceInfo): AbstractFile = { + val f = elemsFile + if (f != null) f else src.srcfile + } + + /** The initial, synthetic span. This is usually the union of all positioned children's positions. + * @param ignoreTypeTrees If true, TypeTree children are not counted for the span. + * This is important for predicting whether a position entry is + * needed for pickling, since TypeTrees are pickled as types, so + * their position is lost. */ - def initialPos: Position = { + def initialSpan(ignoreTypeTrees: Boolean = false): Position = { + + def include(p1: Position, p2: Positioned) = p2 match { + case _: Trees.TypeTree[_] if ignoreTypeTrees => p1 + case _ => p1.union(p2.pos) + } + + def includeAll(pos: Position, xs: List[_]): Position = xs match { + case (p: Positioned) :: xs1 if sameSource(p) => includeAll(include(pos, p), xs1) + case (xs0: List[_]) :: xs1 => includeAll(includeAll(pos, xs0), xs1) + case _ :: xs1 => includeAll(pos, xs1) + case _ => pos + } + var n = productArity var pos = NoPosition while (n > 0) { n -= 1 productElement(n) match { - case p: Positioned if sameSource(p) => pos = pos union p.pos - case m: untpd.Modifiers => pos = unionPos(unionPos(pos, m.mods), m.annotations) - case xs: List[_] => pos = unionPos(pos, xs) + case p: Positioned if sameSource(p) => pos = include(pos, p) + case m: untpd.Modifiers => pos = includeAll(includeAll(pos, m.mods), m.annotations) + case xs: List[_] => pos = includeAll(pos, xs) case _ => } } pos.toSynthetic } - private def unionPos(pos: Position, xs: List[_]): Position = xs match { - case (p: Positioned) :: xs1 if sameSource(p) => unionPos(pos union p.pos, xs1) - case (xs0: List[_]) :: xs1 => unionPos(unionPos(pos, xs0), xs1) - case _ :: xs1 => unionPos(pos, xs1) - case _ => pos - } - private def sameSource(that: Positioned) = srcfile == that.srcfile def contains(that: Positioned): Boolean = { diff --git a/compiler/src/dotty/tools/dotc/ast/TreeIds.scala b/compiler/src/dotty/tools/dotc/ast/TreeIds.scala index 091e074487fe..8f22431ba54c 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeIds.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeIds.scala @@ -16,7 +16,7 @@ object TreeIds { @sharable private[this] val counters = new ConcurrentHashMap[AbstractFile, AtomicInteger] @sharable private[this] val fileOfChunk = mutable.ArrayBuffer[AbstractFile]() - def nextId(implicit src: SourceInfo): Int = nextIdFor(src.source.file) + def nextId(implicit src: SourceInfo): Int = nextIdFor(src.srcfile) def nextIdFor(file: AbstractFile): Int = { var ctr = counters.get(file) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 537e696f0647..7ce665223536 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -598,7 +598,7 @@ object Trees { case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T])(implicit @transientParam src: SourceInfo) extends Tree[T] { type ThisTree[-T >: Untyped] = Inlined[T] - override def initialPos: Position = call.pos + override def initialSpan(ignoreTypeTrees: Boolean): Position = call.pos } /** A type tree that represents an existing or inferred type */ @@ -790,7 +790,7 @@ object Trees { if (trees eq newTrees) this else - Thicket[T](newTrees).asInstanceOf[this.type] + Thicket[T](newTrees)(SourceInfo(srcfile)).asInstanceOf[this.type] } override def foreachInThicket(op: Tree[T] => Unit): Unit = diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 9fdb44b0d5f3..684e5f30d486 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -20,7 +20,7 @@ import config.Settings._ import config.Config import reporting._ import reporting.diagnostic.Message -import io.{AbstractFile, PlainFile, Path} +import io.{AbstractFile, NoAbstractFile, PlainFile, Path} import scala.io.Codec import collection.mutable import printing._ @@ -38,8 +38,12 @@ import plugins._ object Contexts { trait SourceInfo { - def source: SourceFile - def withSource(file: AbstractFile): SourceInfo + def srcfile: AbstractFile + } + object SourceInfo { + def apply(src: AbstractFile) = new SourceInfo { + def srcfile = src + } } private val (compilerCallbackLoc, store1) = Store.empty.newLocation[CompilerCallback]() @@ -169,6 +173,8 @@ object Contexts { protected def source_=(source: SourceFile): Unit = _source = source def source: SourceFile = _source + def srcfile = source.file + /** A map in which more contextual properties can be stored * Typically used for attributes that are read and written only in special situations. */ diff --git a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala index f480e4ea2ee3..32ead5f91162 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala @@ -48,16 +48,16 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad buf.writeInt(pickler.nameBuffer.nameIndex(source.path.toTermName).index) } - /** True if x's position shouldn't be reconstructed automatically from its initialPos + /** True if x's position shouldn't be reconstructed automatically from its initial span */ def alwaysNeedsPos(x: Positioned) = x match { case - // initialPos is inaccurate for trees with lazy field + // initialSpan is inaccurate for trees with lazy field _: WithLazyField[_] // A symbol is created before the corresponding tree is unpickled, // and its position cannot be changed afterwards. - // so we cannot use the tree initialPos to set the symbol position. + // so we cannot use the tree initialSpan to set the symbol position. // Instead, we always pickle the position of definitions. | _: Trees.DefTree[_] @@ -70,8 +70,13 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad case x: untpd.Tree => var sourceFile = current val pos = if (x.isInstanceOf[untpd.MemberDef]) x.pos else x.pos.toSynthetic - val sourceChange = x.source.file != current - if (pos.exists && (pos != x.initialPos.toSynthetic || sourceChange || alwaysNeedsPos(x))) { + val sourceChange = + x.source.file != x.elemsFile || + x.elemsFile == null && x.source.file != current + if (pos.exists && ( + pos != x.initialSpan(ignoreTypeTrees = true).toSynthetic || + sourceChange || + alwaysNeedsPos(x))) { addrOfTree(x) match { case Some(addr) if !pickledIndices.contains(addr.index) || sourceChange => // we currently do not share trees when unpickling, so if one path to a tree contains From 3f09d9186799adcc21493e6dba3008013136b219 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 3 Jan 2019 18:32:50 +0100 Subject: [PATCH 34/75] Harden IDE: Survive duplicate package and object --- .../src/dotty/tools/dotc/core/SymbolLoaders.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 6f40661e4edb..5c262656d970 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -70,19 +70,19 @@ object SymbolLoaders { // offer a setting to resolve the conflict one way or the other. // This was motivated by the desire to use YourKit probes, which // require yjp.jar at runtime. See SI-2089. - if (ctx.settings.YtermConflict.isDefault) - throw new TypeError( - i"""$owner contains object and package with same name: $pname - |one of them needs to be removed from classpath""") - else if (ctx.settings.YtermConflict.value == "package") { + if (ctx.settings.YtermConflict.value == "package" || ctx.mode.is(Mode.Interactive)) { ctx.warning( s"Resolving package/object name conflict in favor of package ${preExisting.fullName}. The object will be inaccessible.") owner.asClass.delete(preExisting) - } else { + } else if (ctx.settings.YtermConflict.value == "object") { ctx.warning( s"Resolving package/object name conflict in favor of object ${preExisting.fullName}. The package will be inaccessible.") return NoSymbol } + else + throw new TypeError( + i"""$owner contains object and package with same name: $pname + |one of them needs to be removed from classpath""") } ctx.newModuleSymbol(owner, pname, PackageCreationFlags, PackageCreationFlags, completer).entered From 6c07a941b385ceddbbadeca56098784c69fd7e17 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 3 Jan 2019 19:26:19 +0100 Subject: [PATCH 35/75] Position -> Span --- .../dotty/tools/backend/sjs/JSPositions.scala | 8 +- .../tools/dotc/ast/CheckTrees.scala.disabled | 2 +- .../src/dotty/tools/dotc/ast/Desugar.scala | 10 +- .../dotty/tools/dotc/ast/DesugarEnums.scala | 8 +- .../dotty/tools/dotc/ast/NavigateAST.scala | 6 +- .../src/dotty/tools/dotc/ast/Positioned.scala | 28 ++--- compiler/src/dotty/tools/dotc/ast/Trees.scala | 20 ++-- compiler/src/dotty/tools/dotc/ast/tpd.scala | 4 +- .../src/dotty/tools/dotc/core/Comments.scala | 20 ++-- .../dotty/tools/dotc/core/Decorators.scala | 6 +- .../src/dotty/tools/dotc/core/Symbols.scala | 6 +- .../src/dotty/tools/dotc/core/TypeOps.scala | 2 +- .../dotc/core/classfile/ClassfileParser.scala | 2 +- .../dotc/core/tasty/CommentUnpickler.scala | 4 +- .../dotc/core/tasty/PositionPickler.scala | 6 +- .../dotc/core/tasty/PositionUnpickler.scala | 14 +-- .../dotc/core/tasty/TastyClassName.scala | 2 +- .../tools/dotc/core/tasty/TastyPrinter.scala | 2 +- .../tools/dotc/core/tasty/TreeUnpickler.scala | 8 +- .../core/unpickleScala2/Scala2Unpickler.scala | 4 +- .../tools/dotc/interactive/Interactive.scala | 4 +- .../tools/dotc/interactive/SourceTree.scala | 4 +- .../tools/dotc/parsing/JavaParsers.scala | 10 +- .../dotty/tools/dotc/parsing/Parsers.scala | 50 ++++---- .../dotty/tools/dotc/parsing/Scanners.scala | 18 +-- .../dotc/parsing/TreeBuilder.scala.unused | 2 +- .../dotc/parsing/xml/MarkupParsers.scala | 34 +++--- .../dotc/parsing/xml/SymbolicXMLBuilder.scala | 26 ++-- .../dotc/printing/SyntaxHighlighting.scala | 4 +- .../tools/dotc/quoted/QuoteCompiler.scala | 4 +- .../dotty/tools/dotc/rewrites/Rewrites.scala | 12 +- .../dotc/tastyreflect/ContextOpsImpl.scala | 4 +- .../tools/dotc/transform/AccessProxies.scala | 4 +- .../dotty/tools/dotc/transform/Bridges.scala | 2 +- .../tools/dotc/transform/ExpandSAMs.scala | 2 +- .../IsInstanceOfEvaluator.scala.disabled | 4 +- .../dotty/tools/dotc/transform/MixinOps.scala | 4 +- .../tools/dotc/transform/PatternMatcher.scala | 6 +- .../dotty/tools/dotc/transform/Staging.scala | 2 +- .../tools/dotc/transform/SuperAccessors.scala | 2 +- .../dotc/transform/TryCatchPatterns.scala | 4 +- .../tools/dotc/transform/TypeTestsCasts.scala | 4 +- .../dotty/tools/dotc/typer/Applications.scala | 2 +- .../src/dotty/tools/dotc/typer/Dynamic.scala | 8 +- .../tools/dotc/typer/ErrorReporting.scala | 2 +- .../dotty/tools/dotc/typer/EtaExpansion.scala | 2 +- .../dotty/tools/dotc/typer/Implicits.scala | 16 +-- .../dotty/tools/dotc/typer/Inferencing.scala | 6 +- .../src/dotty/tools/dotc/typer/Inliner.scala | 2 +- .../src/dotty/tools/dotc/typer/Namer.scala | 4 +- .../src/dotty/tools/dotc/typer/ReTyper.scala | 4 +- .../dotty/tools/dotc/typer/RefChecks.scala | 8 +- .../dotty/tools/dotc/typer/TypeAssigner.scala | 2 +- .../src/dotty/tools/dotc/typer/Typer.scala | 16 +-- .../tools/dotc/typer/VarianceChecker.scala | 4 +- .../dotty/tools/dotc/util/Signatures.scala | 4 +- .../dotty/tools/dotc/util/SourceFile.scala | 6 +- .../tools/dotc/util/SourcePosition.scala | 8 +- .../util/{Positions.scala => Spans.scala} | 112 +++++++++--------- .../src/dotty/tools/repl/ReplCompiler.scala | 10 +- .../src/dotty/tools/repl/ReplDriver.scala | 4 +- .../dottydoc/model/comment/Comment.scala | 8 +- .../model/comment/CommentParser.scala | 8 +- .../dottydoc/model/comment/HtmlParsers.scala | 4 +- .../dottydoc/model/comment/WikiParser.scala | 6 +- .../tools/dottydoc/staticsite/Template.scala | 4 +- .../dotty/tools/dottydoc/util/syntax.scala | 4 +- .../languageserver/DottyLanguageServer.scala | 2 +- .../languageserver/worksheet/Worksheet.scala | 4 +- 69 files changed, 316 insertions(+), 312 deletions(-) rename compiler/src/dotty/tools/dotc/util/{Positions.scala => Spans.scala} (52%) diff --git a/compiler/src/dotty/tools/backend/sjs/JSPositions.scala b/compiler/src/dotty/tools/backend/sjs/JSPositions.scala index 0e2bae540d97..c4faa9569ce4 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSPositions.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSPositions.scala @@ -2,8 +2,8 @@ package dotty.tools.backend.sjs import dotty.tools.dotc.core._ import Contexts._ -import dotty.tools.dotc.util.Positions -import Positions.Position +import dotty.tools.dotc.util.Spans +import Spans.Span import org.scalajs.ir @@ -11,7 +11,7 @@ import org.scalajs.ir class JSPositions()(implicit ctx: Context) { /** Implicit conversion from dotty Position to ir.Position. */ - implicit def pos2irPos(pos: Position): ir.Position = { + implicit def pos2irPos(pos: Span): ir.Position = { if (!pos.exists) ir.Position.NoPosition else { val source = pos2irPosCache.toIRSource(ctx.compilationUnit.source) @@ -23,7 +23,7 @@ class JSPositions()(implicit ctx: Context) { /** Implicitly materializes an ir.Position from an implicit dotty Position. */ implicit def implicitPos2irPos( - implicit pos: Position): ir.Position = { + implicit pos: Span): ir.Position = { pos2irPos(pos) } diff --git a/compiler/src/dotty/tools/dotc/ast/CheckTrees.scala.disabled b/compiler/src/dotty/tools/dotc/ast/CheckTrees.scala.disabled index 255619f35d18..ea8a8709b00f 100644 --- a/compiler/src/dotty/tools/dotc/ast/CheckTrees.scala.disabled +++ b/compiler/src/dotty/tools/dotc/ast/CheckTrees.scala.disabled @@ -3,7 +3,7 @@ package dotc package ast import core._ -import util.Positions._, Types._, Contexts._, Constants._, Names._, Flags._ +import util.Spans._, Types._, Contexts._, Constants._, Names._, Flags._ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._ // TODO: revise, integrate in a checking phase. diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index cca27179b354..c0a0ae7646e4 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -3,7 +3,7 @@ package dotc package ast import core._ -import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._ +import util.Spans._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._ import Symbols._, StdNames._, Trees._ import Decorators._, transform.SymUtils._ import NameKinds.{UniqueName, EvidenceParamName, DefaultGetterName} @@ -793,7 +793,7 @@ object desugar { pats map { case id: Ident => expandSimpleEnumCase(id.name.asTermName, mods, - Position(pdef.pos.start, id.pos.end, id.pos.start)) + Span(pdef.pos.start, id.pos.end, id.pos.start)) } else { val pats1 = if (tpt.isEmpty) pats else pats map (Typed(_, tpt)) @@ -894,7 +894,7 @@ object desugar { case Assign(Ident(name), rhs) => cpy.NamedArg(arg)(name, rhs) case _ => arg } - def makeOp(fn: Tree, arg: Tree, selectPos: Position) = { + def makeOp(fn: Tree, arg: Tree, selectPos: Span) = { val args: List[Tree] = arg match { case Parens(arg) => assignToNamedArg(arg) :: Nil case Tuple(args) => args.mapConserve(assignToNamedArg) @@ -904,9 +904,9 @@ object desugar { } if (isLeftAssoc(op.name)) - makeOp(left, right, Position(left.pos.start, op.pos.end, op.pos.start)) + makeOp(left, right, Span(left.pos.start, op.pos.end, op.pos.start)) else - makeOp(right, left, Position(op.pos.start, right.pos.end)) + makeOp(right, left, Span(op.pos.start, right.pos.end)) } /** Translate tuple expressions of arity <= 22 diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index 09f60855d3db..c7577715330f 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -3,7 +3,7 @@ package dotc package ast import core._ -import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._ +import util.Spans._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._ import Symbols._, StdNames._, Trees._ import Decorators._ import util.Property @@ -44,7 +44,7 @@ object DesugarEnums { * It is an error if a type parameter is non-variant, or if its approximation * refers to pther type parameters. */ - def interpolatedEnumParent(pos: Position)(implicit ctx: Context): Tree = { + def interpolatedEnumParent(pos: Span)(implicit ctx: Context): Tree = { val tparams = enumClass.typeParams def isGround(tp: Type) = tp.subst(tparams, tparams.map(_ => NoType)) eq tp val targs = tparams map { tparam => @@ -195,7 +195,7 @@ object DesugarEnums { } /** Expand a module definition representing a parameterless enum case */ - def expandEnumModule(name: TermName, impl: Template, mods: Modifiers, pos: Position)(implicit ctx: Context): Tree = { + def expandEnumModule(name: TermName, impl: Template, mods: Modifiers, pos: Span)(implicit ctx: Context): Tree = { assert(impl.body.isEmpty) if (!enumClass.exists) EmptyTree else if (impl.parents.isEmpty) @@ -212,7 +212,7 @@ object DesugarEnums { } /** Expand a simple enum case */ - def expandSimpleEnumCase(name: TermName, mods: Modifiers, pos: Position)(implicit ctx: Context): Tree = + def expandSimpleEnumCase(name: TermName, mods: Modifiers, pos: Span)(implicit ctx: Context): Tree = if (!enumClass.exists) EmptyTree else if (enumClass.typeParams.nonEmpty) { val parent = interpolatedEnumParent(pos) diff --git a/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala b/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala index d2b34d4b9122..62845801772a 100644 --- a/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala +++ b/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala @@ -3,7 +3,7 @@ package ast import core.Contexts.Context import core.Decorators._ -import util.Positions._ +import util.Spans._ import Trees.{MemberDef, DefTree, WithLazyField} /** Utility functions to go from typed to untyped ASTs */ @@ -54,7 +54,7 @@ object NavigateAST { /** The reverse part of the untyped root of the compilation unit of `ctx` to * position `pos`. */ - def untypedPath(pos: Position)(implicit ctx: Context): List[Positioned] = + def untypedPath(pos: Span)(implicit ctx: Context): List[Positioned] = pathTo(pos, ctx.compilationUnit.untpdTree) @@ -67,7 +67,7 @@ object NavigateAST { * end point are the same, so this is useful when trying to reconcile * nodes with source code. */ - def pathTo(pos: Position, from: Positioned, skipZeroExtent: Boolean = false)(implicit ctx: Context): List[Positioned] = { + def pathTo(pos: Span, from: Positioned, skipZeroExtent: Boolean = false)(implicit ctx: Context): List[Positioned] = { def childPath(it: Iterator[Any], path: List[Positioned]): List[Positioned] = { while (it.hasNext) { val path1 = it.next() match { diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index 237e6eec4966..ad68186ef7bb 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -2,7 +2,7 @@ package dotty.tools package dotc package ast -import util.Positions._ +import util.Spans._ import util.{SourceFile, SourcePosition} import core.Contexts.{Context, SourceInfo} import core.Decorators._ @@ -20,10 +20,10 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod * component of the position. */ private var myUniqueId: Int = _ - private[this] var curPos: Position = _ + private[this] var curPos: Span = _ /** The item's position */ - def pos: Position = curPos + def pos: Span = curPos /** item's id */ def uniqueId: Int = myUniqueId @@ -43,7 +43,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod /** Destructively update `curPos` to given position. Also, set any missing * positions in children. */ - protected def setPos(pos: Position, file: AbstractFile): Unit = { + protected def setPos(pos: Span, file: AbstractFile): Unit = { setPosUnchecked(pos, file) if (pos.exists) setChildPositions(pos.toSynthetic, file) } @@ -53,7 +53,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod * If the positioned item is synthetic, the position is updated * destructively and the item itself is returned. */ - def withSpan(pos: Position): this.type = { + def withSpan(pos: Span): this.type = { val ownPos = this.pos val newpd: this.type = if (pos == ownPos || ownPos.isSynthetic) this else cloneIn(srcfile) @@ -83,7 +83,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod * any checks of consistency with - or updates of - other positions. * Called from Unpickler when entering positions. */ - private[dotc] def setPosUnchecked(pos: Position, file: AbstractFile = this.srcfile): Unit = { + private[dotc] def setPosUnchecked(pos: Span, file: AbstractFile = this.srcfile): Unit = { if (file != this.srcfile) setId(TreeIds.nextIdFor(file)) curPos = pos } @@ -99,7 +99,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod * But since mutual tail recursion is not supported in Scala, we express it instead * as a while loop with a termination by return in the middle. */ - private def setChildPositions(pos: Position, file: AbstractFile): Unit = { + private def setChildPositions(pos: Span, file: AbstractFile): Unit = { var n = productArity // subnodes are analyzed right to left var elems: List[Any] = Nil // children in lists still to be considered, from right to left var end = pos.end // the last defined offset, fill in positions up to this offset @@ -111,10 +111,10 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod // synthetic. We can preserve this invariant by always setting a // zero-extent position for these trees here. if (!p.pos.exists || p.pos.isZeroExtent) { - p.setPos(Position(start, start), file) + p.setPos(Span(start, start), file) fillIn(ps1, start, end) } else { - p.setPos(Position(start, end), file) + p.setPos(Span(start, end), file) fillIn(ps1, end, end) } case nil => @@ -186,14 +186,14 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod * needed for pickling, since TypeTrees are pickled as types, so * their position is lost. */ - def initialSpan(ignoreTypeTrees: Boolean = false): Position = { + def initialSpan(ignoreTypeTrees: Boolean = false): Span = { - def include(p1: Position, p2: Positioned) = p2 match { + def include(p1: Span, p2: Positioned) = p2 match { case _: Trees.TypeTree[_] if ignoreTypeTrees => p1 case _ => p1.union(p2.pos) } - def includeAll(pos: Position, xs: List[_]): Position = xs match { + def includeAll(pos: Span, xs: List[_]): Span = xs match { case (p: Positioned) :: xs1 if sameSource(p) => includeAll(include(pos, p), xs1) case (xs0: List[_]) :: xs1 => includeAll(includeAll(pos, xs0), xs1) case _ :: xs1 => includeAll(pos, xs1) @@ -201,7 +201,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod } var n = productArity - var pos = NoPosition + var pos = NoSpan while (n > 0) { n -= 1 productElement(n) match { @@ -246,7 +246,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod def checkPos(nonOverlapping: Boolean)(implicit ctx: Context): Unit = try { import untpd._ var lastPositioned: Positioned = null - var lastPos = NoPosition + var lastPos = NoSpan def check(p: Any): Unit = p match { case p: Positioned => assert(pos contains p.pos, diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 7ce665223536..9295530ee62b 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -3,7 +3,7 @@ package dotc package ast import core._ -import Types._, Names._, NameOps._, Flags._, util.Positions._, Contexts._, Constants._ +import Types._, Names._, NameOps._, Flags._, util.Spans._, Contexts._, Constants._ import SymDenotations._, Symbols._, Denotations._, StdNames._, Comments._ import language.higherKinds import collection.mutable.ListBuffer @@ -339,13 +339,13 @@ object Trees { * 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. + * a calling chain from `viewExists`), in that case the return position is NoSpan. */ - def namePos: Position = + def namePos: Span = if (pos.exists) { val point = pos.point - if (rawMods.is(Synthetic) || name.toTermName == nme.ERROR) Position(point) - else Position(point, point + name.stripModuleClassSuffix.lastPart.length, point) + if (rawMods.is(Synthetic) || name.toTermName == nme.ERROR) Span(point) + else Span(point, point + name.stripModuleClassSuffix.lastPart.length, point) } else pos } @@ -598,7 +598,7 @@ object Trees { case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T])(implicit @transientParam src: SourceInfo) extends Tree[T] { type ThisTree[-T >: Untyped] = Inlined[T] - override def initialSpan(ignoreTypeTrees: Boolean): Position = call.pos + override def initialSpan(ignoreTypeTrees: Boolean): Span = call.pos } /** A type tree that represents an existing or inferred type */ @@ -771,8 +771,8 @@ object Trees { trait WithoutTypeOrPos[-T >: Untyped] extends Tree[T] { override def withTypeUnchecked(tpe: Type): ThisTree[Type] = this.asInstanceOf[ThisTree[Type]] - override def pos: Position = NoPosition - override def setPos(pos: Position, file: AbstractFile): Unit = {} + override def pos: Span = NoSpan + override def setPos(pos: Span, file: AbstractFile): Unit = {} } /** Temporary class that results from translation of ModuleDefs @@ -799,9 +799,9 @@ object Trees { override def isEmpty: Boolean = trees.isEmpty override def toList: List[Tree[T]] = flatten(trees) override def toString: String = if (isEmpty) "EmptyTree" else "Thicket(" + trees.mkString(", ") + ")" - override def pos: Position = (NoPosition /: trees) ((pos, t) => pos union t.pos) + override def pos: Span = (NoSpan /: trees) ((pos, t) => pos union t.pos) - override def withSpan(pos: Position): this.type = + override def withSpan(pos: Span): this.type = mapElems(_.withSpan(pos)).asInstanceOf[this.type] override def withPosOf(posd: Positioned): this.type = mapElems(_.withPosOf(posd)).asInstanceOf[this.type] diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index d50ea2e8eb54..1132151bceff 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -7,7 +7,7 @@ import dotty.tools.dotc.typer.ProtoTypes.FunProtoTyped import transform.SymUtils._ import transform.TypeUtils._ import core._ -import util.Positions._, Types._, Contexts._, Constants._, Names._, Flags._, NameOps._ +import util.Spans._, Types._, Contexts._, Constants._, Names._, Flags._, NameOps._ import Symbols._, StdNames._, Annotations._, Trees._, Symbols._ import Decorators._, DenotTransformers._ import collection.mutable @@ -401,7 +401,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { * kind for the given element type in `elemTpe`. No type arguments or * `length` arguments are given. */ - def newArray(elemTpe: Type, returnTpe: Type, pos: Position, dims: JavaSeqLiteral)(implicit ctx: Context): Tree = { + def newArray(elemTpe: Type, returnTpe: Type, pos: Span, dims: JavaSeqLiteral)(implicit ctx: Context): Tree = { val elemClass = elemTpe.classSymbol def newArr = ref(defn.DottyArraysModule).select(defn.newArrayMethod).withSpan(pos) diff --git a/compiler/src/dotty/tools/dotc/core/Comments.scala b/compiler/src/dotty/tools/dotc/core/Comments.scala index c90a47408fe9..dcca7813808c 100644 --- a/compiler/src/dotty/tools/dotc/core/Comments.scala +++ b/compiler/src/dotty/tools/dotc/core/Comments.scala @@ -5,7 +5,7 @@ package core import ast.{ untpd, tpd } import Decorators._, Symbols._, Contexts._ import util.SourceFile -import util.Positions._ +import util.Spans._ import util.CommentParsing._ import util.Property.Key import parsing.Parsers.Parser @@ -45,7 +45,7 @@ object Comments { * @param expanded If this comment has been expanded, it's expansion, otherwise `None`. * @param usecases The usecases for this comment. */ - final case class Comment(pos: Position, raw: String, expanded: Option[String], usecases: List[UseCase]) { + final case class Comment(pos: Span, raw: String, expanded: Option[String], usecases: List[UseCase]) { /** Has this comment been cooked or expanded? */ def isExpanded: Boolean = expanded.isDefined @@ -74,10 +74,10 @@ object Comments { def isDocComment(comment: String): Boolean = comment.startsWith("/**") - def apply(pos: Position, raw: String): Comment = + def apply(pos: Span, raw: String): Comment = Comment(pos, raw, None, Nil) - private def parseUsecases(expandedComment: String, pos: Position)(implicit ctx: Context): List[UseCase] = + private def parseUsecases(expandedComment: String, pos: Span)(implicit ctx: Context): List[UseCase] = if (!isDocComment(expandedComment)) { Nil } else { @@ -94,9 +94,9 @@ object Comments { * def foo: A = ??? * }}} */ - private[this] def decomposeUseCase(body: String, pos: Position, start: Int, end: Int)(implicit ctx: Context): UseCase = { + private[this] def decomposeUseCase(body: String, pos: Span, start: Int, end: Int)(implicit ctx: Context): UseCase = { def subPos(start: Int, end: Int) = - if (pos == NoPosition) NoPosition + if (pos == NoSpan) NoSpan else { val start1 = pos.start + start val end1 = pos.end + end @@ -112,12 +112,12 @@ object Comments { } } - final case class UseCase(code: String, codePos: Position, untpdCode: untpd.Tree, tpdCode: Option[tpd.DefDef]) { + final case class UseCase(code: String, codePos: Span, untpdCode: untpd.Tree, tpdCode: Option[tpd.DefDef]) { def typed(tpdCode: tpd.DefDef): UseCase = copy(tpdCode = Some(tpdCode)) } object UseCase { - def apply(code: String, codePos: Position)(implicit ctx: Context): UseCase = { + def apply(code: String, codePos: Span)(implicit ctx: Context): UseCase = { val tree = { val tree = new Parser(new SourceFile("", code)).localDef(codePos.start) tree match { @@ -441,8 +441,8 @@ object Comments { * If a symbol does not have a doc comment but some overridden version of it does, * the position of the doc comment of the overridden version is returned instead. */ - def docCommentPos(sym: Symbol)(implicit ctx: Context): Position = - ctx.docCtx.flatMap(_.docstring(sym).map(_.pos)).getOrElse(NoPosition) + def docCommentPos(sym: Symbol)(implicit ctx: Context): Span = + ctx.docCtx.flatMap(_.docstring(sym).map(_.pos)).getOrElse(NoSpan) /** A version which doesn't consider self types, as a temporary measure: * an infinite loop has broken out between superComment and cookedDocComment diff --git a/compiler/src/dotty/tools/dotc/core/Decorators.scala b/compiler/src/dotty/tools/dotc/core/Decorators.scala index 601665468bbe..e21cfeccc7fd 100644 --- a/compiler/src/dotty/tools/dotc/core/Decorators.scala +++ b/compiler/src/dotty/tools/dotc/core/Decorators.scala @@ -4,7 +4,7 @@ package core import annotation.tailrec import Symbols._ import Contexts._, Names._, Phases._, printing.Texts._, printing.Printer -import util.Positions.Position, util.SourcePosition +import util.Spans.Span, util.SourcePosition import collection.mutable.ListBuffer import dotty.tools.dotc.transform.MegaPhase import ast.tpd._ @@ -165,8 +165,8 @@ object Decorators { } } - implicit def sourcePos(pos: Position)(implicit ctx: Context): SourcePosition = { - def recur(inlinedCalls: List[Tree], pos: Position): SourcePosition = inlinedCalls match { + implicit def sourcePos(pos: Span)(implicit ctx: Context): SourcePosition = { + def recur(inlinedCalls: List[Tree], pos: Span): SourcePosition = inlinedCalls match { case inlinedCall :: rest => sourceFile(inlinedCall).atPos(pos).withOuter(recur(rest, inlinedCall.pos)) case empty => diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index cf1db9803f81..8da179b17c51 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -13,7 +13,7 @@ import SymDenotations._ import printing.Texts._ import printing.Printer import Types._ -import util.Positions._ +import util.Spans._ import DenotTransformers._ import StdNames._ import NameOps._ @@ -212,7 +212,7 @@ trait Symbols { this: Context => /** Define a new symbol associated with a Bind or pattern wildcard and * make it gadt narrowable. */ - def newPatternBoundSymbol(name: Name, info: Type, pos: Position): Symbol = { + def newPatternBoundSymbol(name: Name, info: Type, pos: Span): Symbol = { val sym = newSymbol(owner, name, Case, info, coord = pos) if (name.isTypeName) { val bounds = info.bounds @@ -670,7 +670,7 @@ object Symbols { * the implicit conversion `sourcePos` will return the wrong result, careful! * TODO: Consider changing this method return type to `SourcePosition`. */ - final def pos: Position = if (coord.isPosition) coord.toPosition else NoPosition + final def pos: Span = if (coord.isPosition) coord.toPosition else NoSpan final def sourcePos(implicit ctx: Context): SourcePosition = { val source = { diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 345f6d2035d8..5d04517fe618 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -4,7 +4,7 @@ package core import Contexts._, Types._, Symbols._, Names._, Flags._ import SymDenotations._ -import util.Positions._ +import util.Spans._ import util.SourcePosition import NameKinds.DepParamName import Decorators._ diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index 80377807dedc..3111ce846444 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -4,7 +4,7 @@ package core package classfile import Contexts._, Symbols._, Types._, Names._, StdNames._, NameOps._, Scopes._, Decorators._ -import SymDenotations._, unpickleScala2.Scala2Unpickler._, Constants._, Annotations._, util.Positions._ +import SymDenotations._, unpickleScala2.Scala2Unpickler._, Constants._, Annotations._, util.Spans._ import NameKinds.DefaultGetterName import dotty.tools.dotc.core.tasty.{TastyHeaderUnpickler, TastyReader} import ast.tpd._ diff --git a/compiler/src/dotty/tools/dotc/core/tasty/CommentUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/CommentUnpickler.scala index 0dfe01f6ea12..f3d016921a4a 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/CommentUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/CommentUnpickler.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc.core.tasty import dotty.tools.dotc.core.Comments.Comment import dotty.tools.dotc.core.tasty.TastyBuffer.Addr -import dotty.tools.dotc.util.Positions.Position +import dotty.tools.dotc.util.Spans.Span import scala.collection.mutable.HashMap @@ -18,7 +18,7 @@ class CommentUnpickler(reader: TastyReader) { val length = readNat() if (length > 0) { val bytes = readBytes(length) - val position = new Position(readLongInt()) + val position = new Span(readLongInt()) val rawComment = new String(bytes, Charset.forName("UTF-8")) comments(addr) = Comment(position, rawComment) } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala index 32ead5f91162..4801e4ae2efd 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala @@ -11,7 +11,7 @@ import core._ import Contexts._, Symbols._, Annotations._, Decorators._ import collection.mutable import TastyBuffer._ -import util.Positions._ +import util.Spans._ import TastyFormat.SOURCE class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Addr]) { @@ -28,8 +28,8 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad def picklePositions(roots: List[Tree])(implicit ctx: Context): Unit = { var lastIndex = 0 - var lastPos = Position(0, 0) - def pickleDeltas(index: Int, pos: Position) = { + var lastPos = Span(0, 0) + def pickleDeltas(index: Int, pos: Span) = { val addrDelta = index - lastIndex val startDelta = pos.start - lastPos.start val endDelta = pos.end - lastPos.end diff --git a/compiler/src/dotty/tools/dotc/core/tasty/PositionUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/PositionUnpickler.scala index 0013a9d4c872..7e956cc411d2 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/PositionUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/PositionUnpickler.scala @@ -3,7 +3,7 @@ package dotc package core package tasty -import util.Positions._ +import util.Spans._ import collection.{mutable, Map} import TastyBuffer.{Addr, NameRef} import TastyFormat.SOURCE @@ -13,13 +13,13 @@ import Names.TermName class PositionUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName) { import reader._ - private var myPositions: mutable.HashMap[Addr, Position] = _ + private var myPositions: mutable.HashMap[Addr, Span] = _ private var mySourcePaths: mutable.HashMap[Addr, String] = _ private var isDefined = false def ensureDefined(): Unit = if (!isDefined) { - myPositions = new mutable.HashMap[Addr, Position] + myPositions = new mutable.HashMap[Addr, Span] mySourcePaths = new mutable.HashMap[Addr, String] var curIndex = 0 var curStart = 0 @@ -40,14 +40,14 @@ class PositionUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName) { if (hasStart) curStart += readInt() if (hasEnd) curEnd += readInt() myPositions(Addr(curIndex)) = - if (hasPoint) Position(curStart, curEnd, curStart + readInt()) - else Position(curStart, curEnd) + if (hasPoint) Span(curStart, curEnd, curStart + readInt()) + else Span(curStart, curEnd) } } isDefined = true } - private[tasty] def positions: Map[Addr, Position] = { + private[tasty] def positions: Map[Addr, Span] = { ensureDefined() myPositions } @@ -57,7 +57,7 @@ class PositionUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName) { mySourcePaths } - def posAt(addr: Addr): Position = positions.getOrElse(addr, NoPosition) + def posAt(addr: Addr): Span = positions.getOrElse(addr, NoSpan) def sourcePathAt(addr: Addr): String = sourcePaths.getOrElse(addr, "") } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyClassName.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyClassName.scala index ab7ead709560..6ca530997717 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyClassName.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyClassName.scala @@ -7,7 +7,7 @@ import Names.{Name, TermName} import StdNames.nme import TastyUnpickler._ import TastyBuffer.NameRef -import util.Positions.offsetToInt +import util.Spans.offsetToInt import printing.Highlighting._ /** Reads the package and class name of the class contained in this TASTy */ diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala index 54dbccc63ab2..232fd1a28cd5 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala @@ -6,7 +6,7 @@ import Contexts._, Decorators._ import Names.Name import TastyUnpickler._ import TastyBuffer.{Addr, NameRef} -import util.Positions.offsetToInt +import util.Spans.offsetToInt import printing.Highlighting._ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) { diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 9e53f85c4922..f103b8c67748 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -18,7 +18,7 @@ import Annotations._ import NameKinds._ import typer.ConstFold import typer.Checking.checkNonCyclic -import util.Positions._ +import util.Spans._ import util.SourceFile import io.AbstractFile import ast.{TreeTypeMap, Trees, tpd, untpd} @@ -1290,15 +1290,15 @@ class TreeUnpickler(reader: TastyReader, // ------ Setting positions ------------------------------------------------ /** Pickled position for `addr`. */ - def posAt(addr: Addr)(implicit ctx: Context): Position = + def posAt(addr: Addr)(implicit ctx: Context): Span = if (ctx.mode.is(Mode.ReadPositions)) { posUnpicklerOpt match { case Some(posUnpickler) => posUnpickler.posAt(addr) case _ => - NoPosition + NoSpan } - } else NoPosition + } else NoSpan /** Pickled source path at `addr`. */ def sourcePathAt(addr: Addr)(implicit ctx: Context): String = diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index d1297623da83..d8e5caec1997 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -10,7 +10,7 @@ import java.lang.Double.longBitsToDouble import Contexts._, Symbols._, Types._, Scopes._, SymDenotations._, Names._, NameOps._ import StdNames._, Denotations._, NameOps._, Flags._, Constants._, Annotations._ import NameKinds.{Scala2MethodNameKinds, SuperAccessorName, ExpandedName} -import util.Positions._ +import util.Spans._ import dotty.tools.dotc.ast.{tpd, untpd}, ast.tpd._ import ast.untpd.Modifiers import printing.Texts._ @@ -984,7 +984,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas symbol = readSymbolRef() } - implicit val pos: Position = NoPosition + implicit val pos: Span = NoSpan tag match { case EMPTYtree => diff --git a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala index 3a0fecc27c9e..2daea8c9d97c 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala @@ -9,7 +9,7 @@ import ast.{NavigateAST, Trees, tpd, untpd} import core._, core.Decorators._ import Contexts._, Flags._, Names._, NameOps._, Symbols._, Trees._, Types._ import transform.SymUtils.decorateSymbol -import util.Positions._, util.SourceFile, util.SourcePosition +import util.Spans._, util.SourceFile, util.SourcePosition import core.Denotations.SingleDenotation import NameKinds.SimpleNameKind import config.Printers.interactiv @@ -256,7 +256,7 @@ object Interactive { case None => Nil } - def pathTo(tree: Tree, pos: Position)(implicit ctx: Context): List[Tree] = + def pathTo(tree: Tree, pos: Span)(implicit ctx: Context): List[Tree] = if (tree.pos.contains(pos)) NavigateAST.pathTo(pos, tree, skipZeroExtent = true) .collect { case t: untpd.Tree => t } diff --git a/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala b/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala index aabfa0e2456c..8e0b07c2bb2d 100644 --- a/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala +++ b/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala @@ -7,7 +7,7 @@ import scala.io.Codec import ast.tpd import core._ import Contexts._, NameOps._, Symbols._, StdNames._ -import util._, util.Positions._ +import util._, util.Spans._ /** * A `tree` coming from `source` @@ -41,7 +41,7 @@ case class SourceTree(tree: tpd.Tree /** really: tpd.Import | tpd.NameTree */, s else // If we don't have a point, we need to find it (treePos.end - nameLength, treePos.end) - Position(start, end, start) + Span(start, end, start) } source.atPos(position) } diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala index 1736d7b905ec..18b879c1ee48 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -21,7 +21,7 @@ import Decorators._ import StdNames._ import dotty.tools.dotc.reporting.diagnostic.messages.IdentifierExpected import dotty.tools.dotc.util.SourceFile -import util.Positions._ +import util.Spans._ import scala.collection.mutable.ListBuffer object JavaParsers { @@ -87,7 +87,7 @@ object JavaParsers { skip() } - def errorTypeTree: TypeTree = TypeTree().withType(UnspecifiedErrorType).withSpan(Position(in.offset)) + def errorTypeTree: TypeTree = TypeTree().withType(UnspecifiedErrorType).withSpan(Span(in.offset)) // --------- tree building ----------------------------- @@ -603,7 +603,7 @@ object JavaParsers { } def importCompanionObject(cdef: TypeDef): Tree = - Import(Ident(cdef.name.toTermName).withSpan(NoPosition), Ident(nme.WILDCARD) :: Nil) + Import(Ident(cdef.name.toTermName).withSpan(NoSpan), Ident(nme.WILDCARD) :: Nil) // Importing the companion object members cannot be done uncritically: see // ticket #2377 wherein a class contains two static inner classes, each of which @@ -660,9 +660,9 @@ object JavaParsers { } else { val qual = ((Ident(names.head): Tree) /: names.tail.init) (Select(_, _)) val lastname = names.last - val ident = Ident(lastname).withSpan(Position(lastnameOffset)) + val ident = Ident(lastname).withSpan(Span(lastnameOffset)) // val selector = lastname match { -// case nme.WILDCARD => Pair(ident, Ident(null) withPos Position(-1)) +// case nme.WILDCARD => Pair(ident, Ident(null) withPos Span(-1)) // case _ => Pair(ident, ident) // } val imp = atPos(start) { Import(qual, List(ident)) } diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 971752892886..dcb4c55ef8b9 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -17,7 +17,7 @@ import NameKinds.WildcardParamName import ast.{Positioned, Trees} import ast.Trees._ import StdNames._ -import util.Positions._ +import util.Spans._ import Constants._ import ScriptParsers._ import Decorators._ @@ -71,11 +71,11 @@ object Parsers { /** Positions tree. * If `t` does not have a position yet, set its position to the given one. */ - def atPos[T <: Positioned](pos: Position)(t: T): T = + def atPos[T <: Positioned](pos: Span)(t: T): T = if (t.pos.isSourceDerived) t else t.withSpan(pos) def atPos[T <: Positioned](start: Offset, point: Offset, end: Offset)(t: T): T = - atPos(Position(start, end, point))(t) + atPos(Span(start, end, point))(t) /** If the last read offset is strictly greater than `start`, position tree * to position spanning from `start` to last read offset, with given point. @@ -103,7 +103,7 @@ object Parsers { if (in.token == BACKQUOTED_IDENT) in.offset + 1 else in.offset def sourcePos(off: Int = in.offset): SourcePosition = - source.atPos(Position(off)) + source.atPos(Span(off)) /* ------------- ERROR HANDLING ------------------------------------------- */ /** The offset where the last syntax error was reported, or if a skip to a @@ -117,14 +117,14 @@ object Parsers { def syntaxError(msg: => Message, offset: Int = in.offset): Unit = if (offset > lastErrorOffset) { val length = if (in.name != null) in.name.show.length else 0 - syntaxError(msg, Position(offset, offset + length)) + syntaxError(msg, Span(offset, offset + length)) lastErrorOffset = in.offset } /** Unconditionally issue an error at given position, without * updating lastErrorOffset. */ - def syntaxError(msg: => Message, pos: Position): Unit = + def syntaxError(msg: => Message, pos: Span): Unit = ctx.error(msg, source atPos pos) } @@ -263,14 +263,14 @@ object Parsers { ctx.warning(msg, sourcePos) def warning(msg: => Message, offset: Int = in.offset): Unit = - ctx.warning(msg, source atPos Position(offset)) + ctx.warning(msg, source atPos Span(offset)) def deprecationWarning(msg: => Message, offset: Int = in.offset): Unit = - ctx.deprecationWarning(msg, source atPos Position(offset)) + ctx.deprecationWarning(msg, source atPos Span(offset)) /** Issue an error at current offset that input is incomplete */ def incompleteInputError(msg: => Message): Unit = - ctx.incompleteInputError(msg, source atPos Position(in.offset)) + ctx.incompleteInputError(msg, source atPos Span(in.offset)) /** If at end of file, issue an incompleteInputError. * Otherwise issue a syntax error and skip to next safe point. @@ -349,7 +349,7 @@ object Parsers { def migrationWarningOrError(msg: String, offset: Int = in.offset): Unit = if (in.isScala2Mode) - ctx.migrationWarning(msg, source atPos Position(offset)) + ctx.migrationWarning(msg, source atPos Span(offset)) else syntaxError(msg, offset) @@ -708,7 +708,7 @@ object Parsers { if (inPattern) Block(Nil, inBraces(pattern())) else expr() else { - ctx.error(InterpolatedStringError(), source atPos Position(in.offset)) + ctx.error(InterpolatedStringError(), source atPos Span(in.offset)) EmptyTree } }) @@ -832,8 +832,8 @@ object Parsers { } } - private def implicitKwPos(start: Int): Position = - Position(start, start + nme.IMPLICITkw.asSimpleName.length) + private def implicitKwPos(start: Int): Span = + Span(start, start + nme.IMPLICITkw.asSimpleName.length) /** TypedFunParam ::= id ':' Type */ def typedFunParam(start: Offset, name: TermName, mods: Modifiers = EmptyModifiers): Tree = atPos(start) { @@ -903,7 +903,7 @@ object Parsers { else if (isSimpleLiteral) { SingletonTypeTree(literal()) } else if (in.token == USCORE) { val start = in.skipToken() - typeBounds().withSpan(Position(start, in.lastOffset, start)) + typeBounds().withSpan(Span(start, in.lastOffset, start)) } else if (isIdent(nme.raw.TILDE) && in.lookaheadIn(BitSet(IDENTIFIER, BACKQUOTED_IDENT))) atPos(in.offset) { PrefixOp(typeIdent(), path(thisOK = true)) } @@ -1030,7 +1030,7 @@ object Parsers { def typedOpt(): Tree = if (in.token == COLON) { in.nextToken(); toplevelTyp() } - else TypeTree().withSpan(Position(in.lastOffset)) + else TypeTree().withSpan(Span(in.lastOffset)) def typeDependingOn(location: Location.Value): Tree = if (location == Location.InParens) typ() @@ -1194,7 +1194,7 @@ object Parsers { assert(handlerStart != -1) syntaxError( EmptyCatchBlock(body), - Position(handlerStart, endOffset(handler)) + Span(handlerStart, endOffset(handler)) ) case _ => } @@ -1204,7 +1204,7 @@ object Parsers { else { if (handler.isEmpty) warning( EmptyCatchAndFinallyBlock(body), - source atPos Position(tryOffset, endOffset(body)) + source atPos Span(tryOffset, endOffset(body)) ) EmptyTree } @@ -1347,8 +1347,8 @@ object Parsers { in.nextToken() val t = infixType() if (false && in.isScala2Mode) { - patch(source, Position(start), "(") - patch(source, Position(in.lastOffset), ")") + patch(source, Span(start), "(") + patch(source, Span(in.lastOffset), ")") } t } @@ -1425,7 +1425,7 @@ object Parsers { val start = in.skipToken() val pname = WildcardParamName.fresh() val param = ValDef(pname, TypeTree(), EmptyTree).withFlags(SyntheticTermParam) - .withSpan(Position(start)) + .withSpan(Span(start)) placeholderParams = param :: placeholderParams atPos(start) { Ident(pname) } case LPAREN => @@ -1449,9 +1449,9 @@ object Parsers { impl.parents match { case parent :: Nil if missingBody => if (parent.isType) ensureApplied(wrapNew(parent)) - else parent.withSpan(Position(start, in.lastOffset)) + else parent.withSpan(Span(start, in.lastOffset)) case _ => - New(impl.withSpan(Position(start, in.lastOffset))) + New(impl.withSpan(Span(start, in.lastOffset))) } case _ => if (isLiteral) literal() @@ -2021,7 +2021,7 @@ object Parsers { if (in.token == EQUALS) { in.nextToken(); expr() } else EmptyTree if (implicitOffset >= 0) { - //mods = mods.withPos(mods.pos.union(Position(implicitOffset, implicitOffset))) + //mods = mods.withPos(mods.pos.union(Span(implicitOffset, implicitOffset))) implicitOffset = -1 } ValDef(name, tpt, default).withMods(mods) @@ -2100,7 +2100,7 @@ object Parsers { // The first import should start at the position of the keyword. val firstPos = if (t.pos.exists) t.pos.withStart(offset) - else Position(offset, in.lastOffset) + else Span(offset, in.lastOffset) t.withSpan(firstPos) :: rest case nil => nil } @@ -2232,7 +2232,7 @@ object Parsers { if (in.token == LBRACE) s"$resultTypeStr =" else ": Unit " // trailing space ensures that `def f()def g()` works. in.testScala2Mode(s"Procedure syntax no longer supported; `$toInsert' should be inserted here") && { - patch(source, Position(in.lastOffset), toInsert) + patch(source, Span(in.lastOffset), toInsert) true } } diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index 193c4d74d977..30792942b5a2 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -2,7 +2,7 @@ package dotty.tools package dotc package parsing -import core.Names._, core.Contexts._, core.Decorators._, util.Positions._ +import core.Names._, core.Contexts._, core.Decorators._, util.Spans._ import core.StdNames._, core.Comments._ import util.SourceFile import java.lang.Character.isDigit @@ -66,14 +66,14 @@ object Scanners { /** Generate an error at the given offset */ def error(msg: String, off: Offset = offset): Unit = { - ctx.error(msg, source atPos Position(off)) + ctx.error(msg, source atPos Span(off)) token = ERROR errOffset = off } /** signal an error where the input ended in the middle of a token */ def incompleteInputError(msg: String): Unit = { - ctx.incompleteInputError(msg, source atPos Position(offset)) + ctx.incompleteInputError(msg, source atPos Span(offset)) token = EOF errOffset = offset } @@ -178,10 +178,10 @@ object Scanners { private[this] var docstringMap: SortedMap[Int, Comment] = SortedMap.empty /* A Buffer for comment positions */ - private[this] val commentPosBuf = new mutable.ListBuffer[Position] + private[this] val commentPosBuf = new mutable.ListBuffer[Span] /** Return a list of all the comment positions */ - def commentPositions: List[Position] = commentPosBuf.toList + def commentPositions: List[Span] = commentPosBuf.toList private[this] def addComment(comment: Comment): Unit = { val lookahead = lookaheadReader() @@ -211,8 +211,8 @@ object Scanners { private def treatAsIdent() = { testScala2Mode(i"$name is now a keyword, write `$name` instead of $name to keep it as an identifier") - patch(source, Position(offset), "`") - patch(source, Position(offset + name.length), "`") + patch(source, Span(offset), "`") + patch(source, Span(offset + name.length), "`") IDENTIFIER } @@ -245,7 +245,7 @@ object Scanners { val isScala2Mode: Boolean = ctx.scala2Setting /** Cannot use ctx.featureEnabled because accessing the context would force too much */ - def testScala2Mode(msg: String, pos: Position = Position(offset)): Boolean = { + def testScala2Mode(msg: String, pos: Span = Span(offset)): Boolean = { if (isScala2Mode) ctx.migrationWarning(msg, source atPos pos) isScala2Mode } @@ -617,7 +617,7 @@ object Scanners { val start = lastCharOffset def finishComment(): Boolean = { if (keepComments) { - val pos = Position(start, charOffset - 1, start) + val pos = Span(start, charOffset - 1, start) val comment = Comment(pos, flushBuf(commentBuf)) commentPosBuf += pos diff --git a/compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused b/compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused index 5293368402c9..0513967ccc3e 100644 --- a/compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused +++ b/compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused @@ -5,7 +5,7 @@ package parsing import core._ import Flags._, Trees._, TypedTrees._, UntypedTrees._, Names._, StdNames._, NameOps._, Contexts._ import scala.collection.mutable.ListBuffer -import util.Positions._, Symbols._, Decorators._, Flags._, Constants._ +import util.Spans._, Symbols._, Decorators._, Flags._, Constants._ import TreeInfo._ /** Methods for building trees, used in the parser. All the trees diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala index 8d11b31fccd2..e839cd8873ca 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala @@ -8,7 +8,7 @@ import mutable.{ Buffer, ArrayBuffer, ListBuffer } import scala.util.control.ControlThrowable import scala.tasty.util.Chars.SU import Parsers._ -import util.Positions._ +import util.Spans._ import core._ import Constants._ import Contexts.SourceInfo @@ -51,7 +51,7 @@ object MarkupParsers { import Tokens.{ LBRACE, RBRACE } - type PositionType = Position + type PositionType = Span type InputType = CharArrayReader type ElementType = Tree type AttributesType = mutable.Map[String, Tree] @@ -73,7 +73,7 @@ object MarkupParsers { import parser.{ symbXMLBuilder => handle } def curOffset : Int = input.charOffset - 1 - var tmppos : Position = NoPosition + var tmppos : Span = NoSpan def ch: Char = input.ch /** this method assign the next character to ch and advances in input */ def nextch(): Unit = { input.nextChar() } @@ -82,7 +82,7 @@ object MarkupParsers { val result = ch; input.nextChar(); result } - def mkProcInstr(position: Position, name: String, text: String): ElementType = + def mkProcInstr(position: Span, name: String, text: String): ElementType = parser.symbXMLBuilder.procInstr(position, name, text) var xEmbeddedBlock: Boolean = false @@ -128,7 +128,7 @@ object MarkupParsers { case '"' | '\'' => val tmp = xAttributeValue(ch_returning_nextch) - try handle.parseAttribute(Position(start, curOffset, mid), tmp) + try handle.parseAttribute(Span(start, curOffset, mid), tmp) catch { case e: RuntimeException => errorAndResult("error parsing attribute value", parser.errorTermTree) @@ -161,12 +161,12 @@ object MarkupParsers { val start = curOffset xToken("[CDATA[") val mid = curOffset - xTakeUntil(handle.charData, () => Position(start, curOffset, mid), "]]>") + xTakeUntil(handle.charData, () => Span(start, curOffset, mid), "]]>") } def xUnparsed: Tree = { val start = curOffset - xTakeUntil(handle.unparsed, () => Position(start, curOffset, start), "") + xTakeUntil(handle.unparsed, () => Span(start, curOffset, start), "") } /** Comment ::= '' @@ -176,10 +176,10 @@ object MarkupParsers { def xComment: Tree = { val start = curOffset - 2 // Rewinding to include " Position(start, curOffset, start), "-->") + xTakeUntil(handle.comment, () => Span(start, curOffset, start), "-->") } - def appendText(pos: Position, ts: Buffer[Tree], txt: String): Unit = { + def appendText(pos: Span, ts: Buffer[Tree], txt: String): Unit = { def append(t: String) = ts append handle.text(pos, t) if (preserveWS) append(txt) @@ -220,7 +220,7 @@ object MarkupParsers { * @precond ch == '{' * @postcond: xEmbeddedBlock == false! */ - def content_BRACE(p: Position, ts: ArrayBuffer[Tree]): Unit = + def content_BRACE(p: Span, ts: ArrayBuffer[Tree]): Unit = if (xCheckEmbeddedBlock) ts append xEmbeddedExpr else appendText(p, ts, xText) @@ -250,7 +250,7 @@ object MarkupParsers { if (xEmbeddedBlock) ts append xEmbeddedExpr else { - tmppos = Position(curOffset) + tmppos = Span(curOffset) ch match { // end tag, cdata, comment, pi or child node case '<' => nextch() ; if (content_LT(ts)) return ts @@ -275,7 +275,7 @@ object MarkupParsers { val (qname, attrMap) = xTag(()) if (ch == '/') { // empty element xToken("/>") - handle.element(Position(start, curOffset, start), qname, attrMap, true, new ListBuffer[Tree]) + handle.element(Span(start, curOffset, start), qname, attrMap, true, new ListBuffer[Tree]) } else { // handle content xToken('>') @@ -286,7 +286,7 @@ object MarkupParsers { val ts = content xEndTag(qname) debugLastStartElement = debugLastStartElement.tail - val pos = Position(start, curOffset, start) + val pos = Span(start, curOffset, start) qname match { case "xml:group" => handle.group(pos, ts) case _ => handle.element(pos, qname, attrMap, false, ts) @@ -356,7 +356,7 @@ object MarkupParsers { val ts = new ArrayBuffer[Tree] val start = curOffset - tmppos = Position(curOffset) // Iuli: added this line, as it seems content_LT uses tmppos when creating trees + tmppos = Span(curOffset) // Iuli: added this line, as it seems content_LT uses tmppos when creating trees content_LT(ts) // parse more XML ? @@ -367,7 +367,7 @@ object MarkupParsers { ts append element xSpaceOpt() } - handle.makeXMLseq(Position(start, curOffset, start), ts) + handle.makeXMLseq(Span(start, curOffset, start), ts) } else { assert(ts.length == 1) @@ -454,7 +454,7 @@ object MarkupParsers { throw TruncatedXMLControl case _ => // text - appendText(Position(start1, curOffset, start1), ts, xText) + appendText(Span(start1, curOffset, start1), ts, xText) // here xEmbeddedBlock might be true: // if (xEmbeddedBlock) throw new ApplicationError("after:" + text); // assert } @@ -466,7 +466,7 @@ object MarkupParsers { debugLastStartElement = debugLastStartElement.tail } - handle.makeXMLpat(Position(start, curOffset, start), qname, ts) + handle.makeXMLpat(Span(start, curOffset, start), qname, ts) } } /* class MarkupParser */ } diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala b/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala index 3c33450fab57..ede21b715f16 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala @@ -9,7 +9,7 @@ import Decorators._ import Flags.Mutable import Names._, StdNames._, ast.Trees._, ast.{tpd, untpd} import Symbols._, Contexts._ -import util.Positions._ +import util.Spans._ import Parsers.Parser /** This class builds instance of `Tree` that represent XML. @@ -89,7 +89,7 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont /** Wildly wrong documentation deleted in favor of "self-documenting code." */ protected def mkXML( - pos: Position, + pos: Span, isPattern: Boolean, pre: Tree, label: Tree, @@ -108,28 +108,28 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont atPos(pos) { if (isPattern) pat else nonpat } } - final def entityRef(pos: Position, n: String): Tree = + final def entityRef(pos: Span, n: String): Tree = atPos(pos)( New(_scala_xml_EntityRef, LL(const(n))) ) // create scala.xml.Text here <: scala.xml.Node - final def text(pos: Position, txt: String): Tree = atPos(pos) { + final def text(pos: Span, txt: String): Tree = atPos(pos) { if (isPattern) makeTextPat(const(txt)) else makeText1(const(txt)) } def makeTextPat(txt: Tree): Apply = Apply(_scala_xml__Text, List(txt)) def makeText1(txt: Tree): Tree = New(_scala_xml_Text, LL(txt)) - def comment(pos: Position, text: String): Tree = atPos(pos)( Comment(const(text)) ) - def charData(pos: Position, txt: String): Tree = atPos(pos)( makeText1(const(txt)) ) + def comment(pos: Span, text: String): Tree = atPos(pos)( Comment(const(text)) ) + def charData(pos: Span, txt: String): Tree = atPos(pos)( makeText1(const(txt)) ) - def procInstr(pos: Position, target: String, txt: String): Tree = + def procInstr(pos: Span, target: String, txt: String): Tree = atPos(pos)( ProcInstr(const(target), const(txt)) ) protected def Comment(txt: Tree): Tree = New(_scala_xml_Comment, LL(txt)) protected def ProcInstr(target: Tree, txt: Tree): Tree = New(_scala_xml_ProcInstr, LL(target, txt)) /** @todo: attributes */ - def makeXMLpat(pos: Position, n: String, args: Seq[Tree]): Tree = { + def makeXMLpat(pos: Span, n: String, args: Seq[Tree]): Tree = { val (prepat, labpat) = splitPrefix(n) match { case (Some(pre), rest) => (const(pre), const(rest)) case _ => (wild, const(n)) @@ -144,7 +144,7 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont protected def convertToTextPat(buf: Seq[Tree]): List[Tree] = (buf map convertToTextPat).toList - def parseAttribute(pos: Position, s: String): Tree = { + def parseAttribute(pos: Span, s: String): Tree = { val ts = Utility.parseAttributeValue(s, text(pos, _), entityRef(pos, _)) ts match { case Nil => TypedSplice(tpd.ref(defn.NilModule).withSpan(pos)) @@ -159,7 +159,7 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont } /** could optimize if args.length == 0, args.length == 1 AND args(0) is <: Node. */ - def makeXMLseq(pos: Position, args: Seq[Tree]): Block = { + def makeXMLseq(pos: Span, args: Seq[Tree]): Block = { val buffer = ValDef(_buf, TypeTree(), New(_scala_xml_NodeBuffer, ListOfNil)) val applies = args filterNot isEmptyText map (t => Apply(Select(Ident(_buf), _plus), List(t))) @@ -173,13 +173,13 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont } /** Various node constructions. */ - def group(pos: Position, args: Seq[Tree]): Tree = + def group(pos: Span, args: Seq[Tree]): Tree = atPos(pos)( New(_scala_xml_Group, LL(makeXMLseq(pos, args))) ) - def unparsed(pos: Position, str: String): Tree = + def unparsed(pos: Span, str: String): Tree = atPos(pos)( New(_scala_xml_Unparsed, LL(const(str))) ) - def element(pos: Position, qname: String, attrMap: mutable.Map[String, Tree], empty: Boolean, args: Seq[Tree]): Tree = { + def element(pos: Span, qname: String, attrMap: mutable.Map[String, Tree], empty: Boolean, args: Seq[Tree]): Tree = { def handleNamespaceBinding(pre: String, z: String): Tree = { def mkAssign(t: Tree): Tree = Assign( Ident(_tmpscope), diff --git a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala index 989a3804e23a..27bfef936524 100644 --- a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala +++ b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala @@ -7,7 +7,7 @@ import dotty.tools.dotc.parsing.Parsers.Parser import dotty.tools.dotc.parsing.Scanners.Scanner import dotty.tools.dotc.parsing.Tokens._ import dotty.tools.dotc.reporting.Reporter -import dotty.tools.dotc.util.Positions.Position +import dotty.tools.dotc.util.Spans.Span import dotty.tools.dotc.util.SourceFile import java.util.Arrays @@ -39,7 +39,7 @@ object SyntaxHighlighting { def highlightRange(from: Int, to: Int, color: String) = Arrays.fill(colorAt.asInstanceOf[Array[AnyRef]], from, to, color) - def highlightPosition(pos: Position, color: String) = if (pos.exists) { + def highlightPosition(pos: Span, color: String) = if (pos.exists) { if (pos.start < 0 || pos.end > in.length) { if (debug) println(s"Trying to highlight erroneous position $pos. Input size: ${in.length}") diff --git a/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala b/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala index a3e7db3bfd9e..529c18023687 100644 --- a/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala +++ b/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala @@ -15,7 +15,7 @@ import dotty.tools.dotc.core.Symbols.defn import dotty.tools.dotc.core.Types.ExprType import dotty.tools.dotc.core.quoted.PickledQuotes import dotty.tools.dotc.transform.Staging -import dotty.tools.dotc.util.Positions.Position +import dotty.tools.dotc.util.Spans.Span import dotty.tools.dotc.util.SourceFile import dotty.tools.io.{Path, VirtualFile} @@ -66,7 +66,7 @@ class QuoteCompiler extends Compiler { * `package __root__ { class ' { def apply: Any = } }` */ private def inClass(expr: Expr[_])(implicit ctx: Context): Tree = { - val pos = Position(0) + val pos = Span(0) val assocFile = new VirtualFile("") val cls = ctx.newCompleteClassSymbol(defn.RootClass, outputClassName, EmptyFlags, diff --git a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala index 34b29d7c54bf..e6ed703fac10 100644 --- a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala +++ b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala @@ -1,8 +1,8 @@ package dotty.tools.dotc package rewrites -import util.{SourceFile, Positions} -import Positions.Position +import util.{SourceFile, Spans} +import Spans.Span import core.Contexts.Context import collection.mutable import scala.annotation.tailrec @@ -12,14 +12,14 @@ import dotty.tools.dotc.reporting.Reporter object Rewrites { private class PatchedFiles extends mutable.HashMap[SourceFile, Patches] - private case class Patch(pos: Position, replacement: String) { + private case class Patch(pos: Span, replacement: String) { def delta = replacement.length - (pos.end - pos.start) } private class Patches(source: SourceFile) { private val pbuf = new mutable.ListBuffer[Patch]() - def addPatch(pos: Position, replacement: String): Unit = + def addPatch(pos: Span, replacement: String): Unit = pbuf += Patch(pos, replacement) def apply(cs: Array[Char]): Array[Char] = { @@ -63,7 +63,7 @@ object Rewrites { /** If -rewrite is set, record a patch that replaces the range * given by `pos` in `source` by `replacement` */ - def patch(source: SourceFile, pos: Position, replacement: String)(implicit ctx: Context): Unit = + def patch(source: SourceFile, pos: Span, replacement: String)(implicit ctx: Context): Unit = if (ctx.reporter != Reporter.NoReporter) // NoReporter is used for syntax highlighting for (rewrites <- ctx.settings.rewrite.value) rewrites.patched @@ -71,7 +71,7 @@ object Rewrites { .addPatch(pos, replacement) /** Patch position in `ctx.compilationUnit.source`. */ - def patch(pos: Position, replacement: String)(implicit ctx: Context): Unit = + def patch(pos: Span, replacement: String)(implicit ctx: Context): Unit = patch(ctx.compilationUnit.source, pos, replacement) /** If -rewrite is set, apply all patches and overwrite patched source files. diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ContextOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ContextOpsImpl.scala index ef65bb4d9671..acac5c915e68 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/ContextOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ContextOpsImpl.scala @@ -1,6 +1,6 @@ package dotty.tools.dotc.tastyreflect -import dotty.tools.dotc.util.{Positions, SourcePosition} +import dotty.tools.dotc.util.{Spans, SourcePosition} trait ContextOpsImpl extends scala.tasty.reflect.ContextOps with CoreImpl { @@ -12,6 +12,6 @@ trait ContextOpsImpl extends scala.tasty.reflect.ContextOps with CoreImpl { def source: java.nio.file.Path = ctx.compilationUnit.source.file.jpath } - def rootPosition: SourcePosition = SourcePosition(rootContext.source, Positions.NoPosition) + def rootPosition: SourcePosition = SourcePosition(rootContext.source, Spans.NoSpan) } diff --git a/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala b/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala index 57d5d65c2303..ad6200d1c3ec 100644 --- a/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala +++ b/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala @@ -12,7 +12,7 @@ import TypeUtils._ import Types._ import NameKinds.ClassifiedNameKind import ast.Trees._ -import util.Positions.Position +import util.Spans.Span import config.Printers.transforms /** A utility class for generating access proxies. Currently used for @@ -75,7 +75,7 @@ abstract class AccessProxies { } /** A fresh accessor symbol */ - private def newAccessorSymbol(owner: Symbol, name: TermName, info: Type, pos: Position)(implicit ctx: Context): TermSymbol = { + private def newAccessorSymbol(owner: Symbol, name: TermName, info: Type, pos: Span)(implicit ctx: Context): TermSymbol = { val sym = ctx.newSymbol(owner, name, Synthetic | Method, info, coord = pos).entered if (sym.allOverriddenSymbols.exists(!_.is(Deferred))) sym.setFlag(Override) sym diff --git a/compiler/src/dotty/tools/dotc/transform/Bridges.scala b/compiler/src/dotty/tools/dotc/transform/Bridges.scala index f9cc044fbbec..8bbe6c2b5aa3 100644 --- a/compiler/src/dotty/tools/dotc/transform/Bridges.scala +++ b/compiler/src/dotty/tools/dotc/transform/Bridges.scala @@ -8,7 +8,7 @@ import DenotTransformers._ import ast.untpd import collection.{mutable, immutable} import ShortcutImplicits._ -import util.Positions.Position +import util.Spans.Span import util.SourcePosition /** A helper class for generating bridge methods in class `root`. */ diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala index 27bd533b49f5..744550e1192f 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala @@ -7,7 +7,7 @@ import MegaPhase._ import SymUtils._ import ast.Trees._ import dotty.tools.dotc.reporting.diagnostic.messages.TypeMismatch -import dotty.tools.dotc.util.Positions.Position +import dotty.tools.dotc.util.Spans.Span /** Expand SAM closures that cannot be represented by the JVM as lambdas to anonymous classes. * These fall into five categories diff --git a/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala.disabled b/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala.disabled index 4f6f8d3db3e4..481d0e23cf8b 100644 --- a/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala.disabled +++ b/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala.disabled @@ -50,7 +50,7 @@ class IsInstanceOfEvaluator extends MiniPhase { if (!scrutineeSubSelector && inMatch) { ctx.error( s"this case is unreachable due to `${selector.show}` not being a subclass of `${scrutinee.show}`", - Position(pos.start - 5, pos.end - 5) + Span(pos.start - 5, pos.end - 5) ) rewrite(qualifier, to = false) } else if (!scrutineeSubSelector && !inMatch) { @@ -73,7 +73,7 @@ class IsInstanceOfEvaluator extends MiniPhase { if (inMatch) { ctx.error( s"will never match since `${selector.show}` is not a subclass of `${scrutinee.show}`", - Position(qualifier.pos.start - 5, qualifier.pos.end - 5) // WHY 5? + Span(qualifier.pos.start - 5, qualifier.pos.end - 5) // WHY 5? ) rewrite(qualifier, to = false) } else { diff --git a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala index ca9f1f7c3c09..a33c6e0f0438 100644 --- a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala +++ b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala @@ -3,7 +3,7 @@ package transform import core._ import Symbols._, Types._, Contexts._, DenotTransformers._, Flags._ -import util.Positions._ +import util.Spans._ import SymUtils._ import StdNames._, NameOps._ import Decorators._ @@ -28,7 +28,7 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont res } - def superRef(target: Symbol, pos: Position = cls.pos): Tree = { + def superRef(target: Symbol, pos: Span = cls.pos): Tree = { val sup = if (target.isConstructor && !target.owner.is(Trait)) Super(This(cls), tpnme.EMPTY, true) else diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index b83d0fb153c8..1bf0123fe156 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -7,7 +7,7 @@ import MegaPhase._ import collection.mutable import Symbols._, Contexts._, Types._, StdNames._, NameOps._ import ast.Trees._ -import util.Positions._ +import util.Spans._ import typer.Applications.{isProductMatch, isGetMatch, productSelectors} import SymUtils._ import Flags._, Constants._ @@ -131,7 +131,7 @@ object PatternMatcher { /** The different kinds of plans */ sealed abstract class Plan { val id: Int = nxId; nxId += 1 } - case class TestPlan(test: Test, var scrutinee: Tree, pos: Position, + case class TestPlan(test: Test, var scrutinee: Tree, pos: Span, var onSuccess: Plan) extends Plan { override def equals(that: Any): Boolean = that match { case that: TestPlan => this.scrutinee === that.scrutinee && this.test == that.test @@ -147,7 +147,7 @@ object PatternMatcher { case class ResultPlan(var tree: Tree) extends Plan object TestPlan { - def apply(test: Test, sym: Symbol, pos: Position, ons: Plan): TestPlan = + def apply(test: Test, sym: Symbol, pos: Span, ons: Plan): TestPlan = TestPlan(test, ref(sym), pos, ons) } diff --git a/compiler/src/dotty/tools/dotc/transform/Staging.scala b/compiler/src/dotty/tools/dotc/transform/Staging.scala index c488eb19aeb5..c1760c680647 100644 --- a/compiler/src/dotty/tools/dotc/transform/Staging.scala +++ b/compiler/src/dotty/tools/dotc/transform/Staging.scala @@ -5,7 +5,7 @@ import core._ import Decorators._, Flags._, Types._, Contexts._, Symbols._, Constants._ import ast.Trees._ import ast.{TreeTypeMap, untpd} -import util.Positions._ +import util.Spans._ import util.SourcePosition import tasty.TreePickler.Hole import SymUtils._ diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index 8c0a9d78b4dc..5bdcb30062fb 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -9,7 +9,7 @@ import Contexts._, Flags._, Symbols._, NameOps._, Trees._ import TypeUtils._, SymUtils._ import DenotTransformers.DenotTransformer import Symbols._ -import util.Positions._ +import util.Spans._ import Decorators._ import NameKinds.SuperAccessorName diff --git a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala index f717114330e1..6ddb4b043b5a 100644 --- a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala +++ b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala @@ -9,7 +9,7 @@ import core.NameKinds.ExceptionBinderName import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.transform.MegaPhase.MiniPhase -import dotty.tools.dotc.util.Positions.Position +import dotty.tools.dotc.util.Spans.Span /** Compiles the cases that can not be handled by primitive catch cases as a common pattern match. * @@ -81,7 +81,7 @@ class TryCatchPatterns extends MiniPhase { false } - private def mkFallbackPatterMatchCase(patternMatchCases: List[CaseDef], pos: Position)( + private def mkFallbackPatterMatchCase(patternMatchCases: List[CaseDef], pos: Span)( implicit ctx: Context): Option[CaseDef] = { if (patternMatchCases.isEmpty) None else { diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 8281cc3fc184..8ffd326bf350 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -10,7 +10,7 @@ import TypeErasure._ import ValueClasses._ import SymUtils._ import core.Flags._ -import util.Positions._ +import util.Spans._ import reporting.diagnostic.messages.TypeTestAlwaysSucceeds import reporting.trace import config.Printers.{ transforms => debug } @@ -53,7 +53,7 @@ object TypeTestsCasts { * 7. if `P` is a refinement type, FALSE * 8. otherwise, TRUE */ - def checkable(X: Type, P: Type, pos: Position)(implicit ctx: Context): Boolean = { + def checkable(X: Type, P: Type, pos: Span)(implicit ctx: Context): Boolean = { def isAbstract(P: Type) = !P.dealias.typeSymbol.isClass def isPatternTypeSymbol(sym: Symbol) = !sym.isClass && sym.is(Case) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 8defadf6a90a..7f5ee898b5f9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -4,7 +4,7 @@ package typer import core._ import ast.{Trees, tpd, untpd} -import util.Positions._ +import util.Spans._ import util.Stats.track import util.{SourcePosition, NoSourcePosition} import Trees.Untyped diff --git a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala index 639c36229169..5cfe4e88a6b5 100644 --- a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala +++ b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala @@ -11,7 +11,7 @@ import dotty.tools.dotc.core.Names.{Name, TermName} import dotty.tools.dotc.core.StdNames._ import dotty.tools.dotc.core.Types._ import dotty.tools.dotc.core.Decorators._ -import util.Positions._ +import util.Spans._ import core.Symbols._ import core.Definitions import ErrorReporting._ @@ -49,7 +49,7 @@ trait Dynamic { self: Typer with Applications => * foo.bar[T0, ...](x = bazX, y = bazY, baz, ...) ~~> foo.applyDynamicNamed[T0, ...]("bar")(("x", bazX), ("y", bazY), ("", baz), ...) */ def typedDynamicApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = { - def typedDynamicApply(qual: untpd.Tree, name: Name, selPos: Position, targs: List[untpd.Tree]): Tree = { + def typedDynamicApply(qual: untpd.Tree, name: Name, selPos: Span, targs: List[untpd.Tree]): Tree = { def isNamedArg(arg: untpd.Tree): Boolean = arg match { case NamedArg(_, _) => true; case _ => false } val args = tree.args val dynName = if (args.exists(isNamedArg)) nme.applyDynamicNamed else nme.applyDynamic @@ -92,7 +92,7 @@ trait Dynamic { self: Typer with Applications => * foo.bar = baz ~~> foo.updateDynamic(bar)(baz) */ def typedDynamicAssign(tree: untpd.Assign, pt: Type)(implicit ctx: Context): Tree = { - def typedDynamicAssign(qual: untpd.Tree, name: Name, selPos: Position, targs: List[untpd.Tree]): Tree = + def typedDynamicAssign(qual: untpd.Tree, name: Name, selPos: Span, targs: List[untpd.Tree]): Tree = typedApply(untpd.Apply(coreDynamic(qual, nme.updateDynamic, name, selPos, targs), tree.rhs), pt) tree.lhs match { case sel @ Select(qual, name) if !isDynamicMethod(name) => @@ -104,7 +104,7 @@ trait Dynamic { self: Typer with Applications => } } - private def coreDynamic(qual: untpd.Tree, dynName: Name, name: Name, selPos: Position, targs: List[untpd.Tree])(implicit ctx: Context): untpd.Apply = { + private def coreDynamic(qual: untpd.Tree, dynName: Name, name: Name, selPos: Span, targs: List[untpd.Tree])(implicit ctx: Context): untpd.Apply = { val select = untpd.Select(qual, dynName).withSpan(selPos) val selectWithTypes = if (targs.isEmpty) select diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index 819947f2c513..a582aac88060 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -6,7 +6,7 @@ import ast._ import core._ import Types._, ProtoTypes._, Contexts._, Decorators._, Denotations._, Symbols._ import Implicits._, Flags._ -import util.Positions._ +import util.Spans._ import util.SourcePosition import java.util.regex.Matcher.quoteReplacement import reporting.diagnostic.Message diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala index fe7cf6c9ee89..cb3616289ee7 100644 --- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -11,7 +11,7 @@ import Symbols._ import Names._ import StdNames._ import NameKinds.UniqueName -import util.Positions._ +import util.Spans._ import collection.mutable import Trees._ diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 6615f61771ab..07874bacddf5 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -4,7 +4,7 @@ package typer import core._ import ast.{Trees, TreeTypeMap, untpd, tpd} -import util.Positions._ +import util.Spans._ import util.Stats.{track, record, monitored} import printing.{Showable, Printer} import printing.Texts._ @@ -611,7 +611,7 @@ trait Implicits { self: Typer => /** Find an implicit argument for parameter `formal`. * Return a failure as a SearchFailureType in the type of the returned tree. */ - def inferImplicitArg(formal: Type, pos: Position)(implicit ctx: Context): Tree = { + def inferImplicitArg(formal: Type, pos: Span)(implicit ctx: Context): Tree = { /** If `formal` is of the form ClassTag[T], where `T` is a class type, * synthesize a class tag for `T`. @@ -735,7 +735,7 @@ trait Implicits { self: Typer => } /** Search an implicit argument and report error if not found */ - def implicitArgTree(formal: Type, pos: Position)(implicit ctx: Context): Tree = { + def implicitArgTree(formal: Type, pos: Span)(implicit ctx: Context): Tree = { val arg = inferImplicitArg(formal, pos) if (arg.tpe.isInstanceOf[SearchFailureType]) ctx.error(missingArgMsg(arg, formal, ""), ctx.source.atPos(pos)) @@ -867,7 +867,7 @@ trait Implicits { self: Typer => } /** Check that equality tests between types `ltp` and `rtp` make sense */ - def checkCanEqual(ltp: Type, rtp: Type, pos: Position)(implicit ctx: Context): Unit = + def checkCanEqual(ltp: Type, rtp: Type, pos: Span)(implicit ctx: Context): Unit = if (!ctx.isAfterTyper && !assumedCanEqual(ltp, rtp)) { val res = implicitArgTree(defn.EqType.appliedTo(ltp, rtp), pos) implicits.println(i"Eq witness found for $ltp / $rtp: $res: ${res.tpe}") @@ -879,7 +879,7 @@ trait Implicits { self: Typer => * it should be applied, EmptyTree otherwise. * @param pos The position where errors should be reported. */ - def inferImplicit(pt: Type, argument: Tree, pos: Position)(implicit ctx: Context): SearchResult = track("inferImplicit") { + def inferImplicit(pt: Type, argument: Tree, pos: Span)(implicit ctx: Context): SearchResult = track("inferImplicit") { assert(ctx.phase.allowsImplicitSearch, if (argument.isEmpty) i"missing implicit parameter of type $pt after typer" else i"type error: ${argument.tpe} does not conform to $pt${err.whyNoMatchStr(argument.tpe, pt)}") @@ -925,7 +925,7 @@ trait Implicits { self: Typer => } /** An implicit search; parameters as in `inferImplicit` */ - class ImplicitSearch(protected val pt: Type, protected val argument: Tree, pos: Position)(implicit ctx: Context) { + class ImplicitSearch(protected val pt: Type, protected val argument: Tree, pos: Span)(implicit ctx: Context) { assert(argument.isEmpty || argument.tpe.isValueType || argument.tpe.isInstanceOf[ExprType], em"found: $argument: ${argument.tpe}, expected: $pt") @@ -1380,7 +1380,7 @@ abstract class SearchHistory { outer => def defineBynameImplicit(tpe: Type, result: SearchSuccess)(implicit ctx: Context): SearchResult = root.defineBynameImplicit(tpe, result) // This is NOOP unless at the root of this search history. - def emitDictionary(pos: Position, result: SearchResult)(implicit ctx: Context): SearchResult = result + def emitDictionary(pos: Span, result: SearchResult)(implicit ctx: Context): SearchResult = result override def toString: String = s"SearchHistory(open = $open, byname = $byname)" } @@ -1463,7 +1463,7 @@ final class SearchRoot extends SearchHistory { * @result The elaborated result, comprising the implicit dictionary and a result tree * substituted with references into the dictionary. */ - override def emitDictionary(pos: Position, result: SearchResult)(implicit ctx: Context): SearchResult = { + override def emitDictionary(pos: Span, result: SearchResult)(implicit ctx: Context): SearchResult = { if (implicitDictionary == null || implicitDictionary.isEmpty) result else { result match { diff --git a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala index c49bf8ef0ad6..de175d17753f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala @@ -8,7 +8,7 @@ import Contexts._, Types._, Flags._, Symbols._ import Trees._ import ProtoTypes._ import NameKinds.UniqueName -import util.Positions._ +import util.Spans._ import util.{Stats, SimpleIdentityMap} import Decorators._ import config.Printers.{gadts, typr} @@ -38,7 +38,7 @@ object Inferencing { /** The fully defined type, where all type variables are forced. * Throws an error if type contains wildcards. */ - def fullyDefinedType(tp: Type, what: String, pos: Position)(implicit ctx: Context): Type = + def fullyDefinedType(tp: Type, what: String, pos: Span)(implicit ctx: Context): Type = if (isFullyDefined(tp, ForceDegree.all)) tp else throw new Error(i"internal error: type of $what $tp is not fully defined, pos = $pos") // !!! DEBUG @@ -288,7 +288,7 @@ object Inferencing { * @return The list of type symbols that were created * to instantiate undetermined type variables that occur non-variantly */ - def maximizeType(tp: Type, pos: Position, fromScala2x: Boolean)(implicit ctx: Context): List[Symbol] = Stats.track("maximizeType") { + def maximizeType(tp: Type, pos: Span, fromScala2x: Boolean)(implicit ctx: Context): List[Symbol] = Stats.track("maximizeType") { val vs = variances(tp) val patternBound = new mutable.ListBuffer[Symbol] vs foreachBinding { (tvar, v) => diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index a077125899bc..cd2cb91cb660 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -24,7 +24,7 @@ import dotty.tools.dotc.util.{SimpleIdentityMap, SimpleIdentitySet} import collection.mutable import reporting.trace -import util.Positions.Position +import util.Spans.Span import util.SourcePosition import ast.TreeInfo diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index fdc7dca7c457..153fd50f9247 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -9,7 +9,7 @@ import Contexts._, Symbols._, Types._, SymDenotations._, Names._, NameOps._, Fla import NameKinds.DefaultGetterName import ast.desugar, ast.desugar._ import ProtoTypes._ -import util.Positions._ +import util.Spans._ import util.Property import collection.mutable import tpd.ListOfTreeDecorator @@ -243,7 +243,7 @@ class Namer { typer: Typer => } /** The enclosing class with given name; error if none exists */ - def enclosingClassNamed(name: TypeName, pos: Position)(implicit ctx: Context): Symbol = { + def enclosingClassNamed(name: TypeName, pos: Span)(implicit ctx: Context): Symbol = { if (name.isEmpty) NoSymbol else { val cls = ctx.owner.enclosingClassNamed(name) diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala index e3d2f4232dd0..16bff5e03cc9 100644 --- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala +++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala @@ -10,7 +10,7 @@ import Decorators._ import typer.ProtoTypes._ import ast.{tpd, untpd} import scala.util.control.NonFatal -import util.Positions.Position +import util.Spans.Span /** A version of Typer that keeps all symbols defined and referenced in a * previously typed tree. @@ -120,7 +120,7 @@ class ReTyper extends Typer with ReChecking { override def checkVariance(tree: Tree)(implicit ctx: Context): Unit = () override def inferView(from: Tree, to: Type)(implicit ctx: Context): Implicits.SearchResult = Implicits.NoMatchingImplicitsFailure - override def checkCanEqual(ltp: Type, rtp: Type, pos: Position)(implicit ctx: Context): Unit = () + override def checkCanEqual(ltp: Type, rtp: Type, pos: Span)(implicit ctx: Context): Unit = () override protected def addAccessorDefs(cls: Symbol, body: List[Tree])(implicit ctx: Context): List[Tree] = body override protected def checkEqualityEvidence(tree: tpd.Tree, pt: Type)(implicit ctx: Context): Unit = () } diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 151fe8cfbe6d..a5925698626c 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -7,7 +7,7 @@ import Symbols._, Types._, Contexts._, Flags._, Names._, NameOps._ import StdNames._, Denotations._, SymUtils._ import NameKinds.DefaultGetterName import Annotations._ -import util.Positions._ +import util.Spans._ import util.{Store, SourcePosition} import scala.collection.{ mutable, immutable } import ast._ @@ -861,7 +861,7 @@ object RefChecks { class OptLevelInfo { def levelAndIndex: LevelAndIndex = Map() - def enterReference(sym: Symbol, pos: Position): Unit = () + def enterReference(sym: Symbol, pos: Span): Unit = () } /** A class to help in forward reference checking */ @@ -877,10 +877,10 @@ object RefChecks { (m1, idx + 1) }._1 var maxIndex: Int = Int.MinValue - var refPos: Position = _ + var refPos: Span = _ var refSym: Symbol = _ - override def enterReference(sym: Symbol, pos: Position): Unit = + override def enterReference(sym: Symbol, pos: Span): Unit = if (sym.exists && sym.owner.isTerm) levelAndIndex.get(sym) match { case Some((level, idx)) if (level.maxIndex < idx) => diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index d6a8e6bbe420..d66fe8eeb16d 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -6,7 +6,7 @@ import core._ import ast._ import Contexts._, Constants._, Types._, Symbols._, Names._, Flags._, Decorators._ import ErrorReporting._, Annotations._, Denotations._, SymDenotations._, StdNames._ -import util.Positions._ +import util.Spans._ import util.SourcePosition import config.Printers.typr import ast.Trees._ diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 702c417a89cc..aec2f081e13b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -24,7 +24,7 @@ import ErrorReporting._ import Checking._ import Inferencing._ import EtaExpansion.etaExpand -import util.Positions._ +import util.Spans._ import util.common._ import util.Property import Applications.{ExtMethodApply, wrapDefs, productSelectorTypes} @@ -1476,7 +1476,7 @@ class Typer extends Namer if (sym.is(Lazy, butNot = Deferred | Module | Synthetic) && !sym.isVolatile && ctx.scala2Mode && ctx.settings.rewrite.value.isDefined && !ctx.isAfterTyper) - patch(Position(toUntyped(vdef).pos.start), "@volatile ") + patch(Span(toUntyped(vdef).pos.start), "@volatile ") } /** Adds inline to final vals with idempotent rhs @@ -1695,7 +1695,7 @@ class Typer extends Namer * - has C as its class symbol, and * - for all parents P_i: If P_i derives from C then P_i <:< CT. */ - def ensureFirstIsClass(parents: List[Type], pos: Position)(implicit ctx: Context): List[Type] = { + def ensureFirstIsClass(parents: List[Type], pos: Span)(implicit ctx: Context): List[Type] = { def realClassParent(cls: Symbol): ClassSymbol = if (!cls.isClass) defn.ObjectClass else if (!(cls is Trait)) cls.asClass @@ -1718,7 +1718,7 @@ class Typer extends Namer } /** Ensure that first parent tree refers to a real class. */ - def ensureFirstTreeIsClass(parents: List[Tree], pos: Position)(implicit ctx: Context): List[Tree] = parents match { + def ensureFirstTreeIsClass(parents: List[Tree], pos: Span)(implicit ctx: Context): List[Tree] = parents match { case p :: ps if p.tpe.classSymbol.isRealClass => parents case _ => TypeTree(ensureFirstIsClass(parents.tpes, pos).head).withSpan(pos.focus) :: parents } @@ -1794,8 +1794,8 @@ class Typer extends Namer ctx.errorOrMigrationWarning(OnlyFunctionsCanBeFollowedByUnderscore(recovered.tpe.widen), tree.sourcePos) if (ctx.scala2Mode) { // Under -rewrite, patch `x _` to `(() => x)` - patch(Position(tree.pos.start), "(() => ") - patch(Position(qual.pos.end, tree.pos.end), ")") + patch(Span(tree.pos.start), "(() => ") + patch(Span(qual.pos.end, tree.pos.end), ")") return typed(untpd.Function(Nil, qual), pt) } } @@ -1814,8 +1814,8 @@ class Typer extends Namer ctx.errorOrMigrationWarning(i"""The syntax ` _` is no longer supported; |you can $remedy""", tree.sourcePos) if (ctx.scala2Mode) { - patch(Position(tree.pos.start), prefix) - patch(Position(qual.pos.end, tree.pos.end), suffix) + patch(Span(tree.pos.start), prefix) + patch(Span(qual.pos.end, tree.pos.end), suffix) } } res diff --git a/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala b/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala index 688a0cda3557..76be55f9cc9d 100644 --- a/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala +++ b/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala @@ -8,7 +8,7 @@ import Decorators._ import Variances._ import NameKinds._ import TypeApplications.varianceConforms -import util.Positions._ +import util.Spans._ import util.SourcePosition import config.Printers.variances import reporting.trace @@ -160,7 +160,7 @@ class VarianceChecker()(implicit ctx: Context) { ctx.migrationWarning( s"According to new variance rules, this is no longer accepted; need to annotate with @uncheckedVariance:\n$msg", pos) - // patch(Position(pos.end), " @scala.annotation.unchecked.uncheckedVariance") + // patch(Span(pos.end), " @scala.annotation.unchecked.uncheckedVariance") // Patch is disabled until two TODOs are solved: // TODO use an import or shorten if possible // TODO need to use a `:' if annotation is on term diff --git a/compiler/src/dotty/tools/dotc/util/Signatures.scala b/compiler/src/dotty/tools/dotc/util/Signatures.scala index 4c44d337cbf3..6ce32b596334 100644 --- a/compiler/src/dotty/tools/dotc/util/Signatures.scala +++ b/compiler/src/dotty/tools/dotc/util/Signatures.scala @@ -7,7 +7,7 @@ import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Denotations.SingleDenotation import dotty.tools.dotc.core.Flags.Implicit import dotty.tools.dotc.core.Names.TermName -import dotty.tools.dotc.util.Positions.Position +import dotty.tools.dotc.util.Spans.Span import dotty.tools.dotc.core.Types.{ErrorType, MethodType, PolyType} import dotty.tools.dotc.reporting.diagnostic.messages @@ -48,7 +48,7 @@ object Signatures { * @return A triple containing the index of the parameter being edited, the index of the function * being called, the list of overloads of this function). */ - def callInfo(path: List[tpd.Tree], pos: Position)(implicit ctx: Context): (Int, Int, List[SingleDenotation]) = { + def callInfo(path: List[tpd.Tree], pos: Span)(implicit ctx: Context): (Int, Int, List[SingleDenotation]) = { path match { case Apply(fun, params) :: _ => val alreadyAppliedCount = Signatures.countParams(fun) diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index 00258f7a5d29..9685f0278985 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -7,7 +7,7 @@ import dotty.tools.io._ import java.util.regex.Pattern import java.io.IOException import scala.tasty.util.Chars._ -import Positions._ +import Spans._ import scala.io.Codec import scala.annotation.internal.sharable @@ -67,7 +67,7 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends /** The start of this file in the underlying source file */ def start: Int = 0 - def atPos(pos: Position): SourcePosition = + def atPos(pos: Span): SourcePosition = if (pos.exists) SourcePosition(underlying, pos) else NoSourcePosition @@ -155,6 +155,6 @@ object SourceFile { @sharable object NoSource extends SourceFile(NoAbstractFile, Array[Char]()) { override def exists: Boolean = false - override def atPos(pos: Position): SourcePosition = NoSourcePosition + override def atPos(pos: Span): SourcePosition = NoSourcePosition } diff --git a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala index ecdeea9aec0e..01c812c49cf3 100644 --- a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala +++ b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala @@ -4,11 +4,11 @@ package util import printing.{Showable, Printer} import printing.Texts._ -import Positions.{Position, NoPosition} +import Spans.{Span, NoSpan} import scala.annotation.internal.sharable /** A source position is comprised of a position in a source file */ -case class SourcePosition(source: SourceFile, pos: Position, outer: SourcePosition = NoSourcePosition) +case class SourcePosition(source: SourceFile, pos: Span, outer: SourcePosition = NoSourcePosition) extends interfaces.SourcePosition with Showable { /** Is `that` a source position contained in this source position ? * `outer` is not taken into account. */ @@ -55,7 +55,7 @@ extends interfaces.SourcePosition with Showable { def endColumn: Int = source.column(end) def withOuter(outer: SourcePosition): SourcePosition = SourcePosition(source, pos, outer) - def withSpan(range: Position) = SourcePosition(source, range, outer) + def withSpan(range: Span) = SourcePosition(source, range, outer) def startPos: SourcePosition = withSpan(pos.startPos) def endPos : SourcePosition = withSpan(pos.endPos) @@ -69,7 +69,7 @@ extends interfaces.SourcePosition with Showable { } /** A sentinel for a non-existing source position */ -@sharable object NoSourcePosition extends SourcePosition(NoSource, NoPosition) { +@sharable object NoSourcePosition extends SourcePosition(NoSource, NoSpan) { override def toString: String = "?" override def withOuter(outer: SourcePosition): SourcePosition = outer } diff --git a/compiler/src/dotty/tools/dotc/util/Positions.scala b/compiler/src/dotty/tools/dotc/util/Spans.scala similarity index 52% rename from compiler/src/dotty/tools/dotc/util/Positions.scala rename to compiler/src/dotty/tools/dotc/util/Spans.scala index 1e6814d7caf4..561bd8b87cfe 100644 --- a/compiler/src/dotty/tools/dotc/util/Positions.scala +++ b/compiler/src/dotty/tools/dotc/util/Spans.scala @@ -2,20 +2,24 @@ package dotty.tools.dotc package util import language.implicitConversions -/** Position format in little endian: +/** The offsets part of a full position, consisting of 2 or 3 entries: + * - start: the start offset of the span, in characters from start of file + * - end : the end offset of the span + * - point: if given, the offset where a sing;le `^` would be logically placed + * + & Spans are encoded according to the following format in little endian: * Start: unsigned 26 Bits (works for source files up to 64M) * End: unsigned 26 Bits * Point: unsigned 12 Bits relative to start - * NoPosition encoded as -1L (this is a normally invalid position - * because point would lie beyond end. + * NoSpan encoded as -1L (this is a normally invalid span because point would lie beyond end). */ -object Positions { +object Spans { private final val StartEndBits = 26 private final val StartEndMask = (1L << StartEndBits) - 1 private final val SyntheticPointDelta = (1 << (64 - StartEndBits * 2)) - 1 - /** The maximal representable offset in a position */ + /** The maximal representable offset in a span */ private final val MaxOffset = StartEndMask /** Convert offset `x` to an integer by sign extending the original @@ -24,97 +28,97 @@ object Positions { def offsetToInt(x: Int): Int = x << (32 - StartEndBits) >> (32 - StartEndBits) - /** A position indicates a range between a start offset and an end offset. - * Positions can be synthetic or source-derived. A source-derived position + /** A span indicates a range between a start offset and an end offset. + * Spans can be synthetic or source-derived. A source-derived span * has in addition a point lies somewhere between start and end. The point * is roughly where the ^ would go if an error was diagnosed at that position. * All quantities are encoded opaquely in a Long. */ - class Position(val coords: Long) extends AnyVal { + class Span(val coords: Long) extends AnyVal { - /** Is this position different from NoPosition? */ - def exists: Boolean = this != NoPosition + /** Is this span different from NoSpan? */ + def exists: Boolean = this != NoSpan - /** The start of this position. */ + /** The start of this span. */ def start: Int = { assert(exists) (coords & StartEndMask).toInt } - /** The end of this position */ + /** The end of this span */ def end: Int = { assert(exists) ((coords >>> StartEndBits) & StartEndMask).toInt } - /** The point of this position, returns start for synthetic positions */ + /** The point of this span, returns start for synthetic spans */ def point: Int = { assert(exists) val poff = pointDelta if (poff == SyntheticPointDelta) start else start + poff } - /** The difference between point and start in this position */ + /** The difference between point and start in this span */ def pointDelta: Int = (coords >>> (StartEndBits * 2)).toInt - def orElse(that: Position): Position = + def orElse(that: Span): Span = if (this.exists) this else that - /** The union of two positions. This is the least range that encloses - * both positions. It is always a synthetic position. + /** The union of two spans. This is the least range that encloses + * both spans. It is always a synthetic span. */ - def union(that: Position): Position = + def union(that: Span): Span = if (!this.exists) that else if (!that.exists) this - else Position(this.start min that.start, this.end max that.end, this.point) + else Span(this.start min that.start, this.end max that.end, this.point) - /** Does the range of this position contain the one of that position? */ - def contains(that: Position): Boolean = + /** Does the range of this span contain the one of that span? */ + def contains(that: Span): Boolean = !that.exists || exists && (start <= that.start && end >= that.end) - /** Is this position synthetic? */ + /** Is this span synthetic? */ def isSynthetic: Boolean = pointDelta == SyntheticPointDelta - /** Is this position source-derived? */ + /** Is this span source-derived? */ def isSourceDerived: Boolean = !isSynthetic - /** Is this a zero-extent position? */ + /** Is this a zero-extent span? */ def isZeroExtent: Boolean = start == end - /** A position where all components are shifted by a given `offset` - * relative to this position. + /** A span where all components are shifted by a given `offset` + * relative to this span. */ - def shift(offset: Int): Position = + def shift(offset: Int): Span = if (exists) fromOffsets(start + offset, end + offset, pointDelta) else this - /** The zero-extent position with start and end at the point of this position */ - def focus: Position = if (exists) Position(point) else NoPosition + /** The zero-extent span with start and end at the point of this span */ + def focus: Span = if (exists) Span(point) else NoSpan - /** The zero-extent position with start and end at the start of this position */ - def startPos: Position = if (exists) Position(start) else NoPosition + /** The zero-extent span with start and end at the start of this span */ + def startPos: Span = if (exists) Span(start) else NoSpan - /** The zero-extent position with start and end at the end of this position */ - def endPos: Position = if (exists) Position(end) else NoPosition + /** The zero-extent span with start and end at the end of this span */ + def endPos: Span = if (exists) Span(end) else NoSpan - /** A copy of this position with a different start */ - def withStart(start: Int): Position = + /** A copy of this span with a different start */ + def withStart(start: Int): Span = if (exists) fromOffsets(start, this.end, if (isSynthetic) SyntheticPointDelta else this.point - start) else this - /** A copy of this position with a different end */ - def withEnd(end: Int): Position = + /** A copy of this span with a different end */ + def withEnd(end: Int): Span = if (exists) fromOffsets(this.start, end, pointDelta) else this - /** A copy of this position with a different point */ - def withPoint(point: Int): Position = + /** A copy of this span with a different point */ + def withPoint(point: Int): Span = if (exists) fromOffsets(this.start, this.end, point - this.start) else this - /** A synthetic copy of this position */ - def toSynthetic: Position = if (isSynthetic) this else Position(start, end) + /** A synthetic copy of this span */ + def toSynthetic: Span = if (isSynthetic) this else Span(start, end) override def toString: String = { val (left, right) = if (isSynthetic) ("<", ">") else ("[", "]") @@ -127,30 +131,30 @@ object Positions { private def fromOffsets(start: Int, end: Int, pointDelta: Int) = { //assert(start <= end || start == 1 && end == 0, s"$start..$end") - new Position( + new Span( (start & StartEndMask).toLong | ((end & StartEndMask).toLong << StartEndBits) | (pointDelta.toLong << (StartEndBits * 2))) } - /** A synthetic position with given start and end */ - def Position(start: Int, end: Int): Position = + /** A synthetic span with given start and end */ + def Span(start: Int, end: Int): Span = fromOffsets(start, end, SyntheticPointDelta) - /** A source-derived position with given start, end, and point delta */ - def Position(start: Int, end: Int, point: Int): Position = { + /** A source-derived span with given start, end, and point delta */ + def Span(start: Int, end: Int, point: Int): Span = { val pointDelta = (point - start) max 0 fromOffsets(start, end, if (pointDelta >= SyntheticPointDelta) 0 else pointDelta) } - /** A synthetic zero-extent position that starts and ends at given `start`. */ - def Position(start: Int): Position = Position(start, start) + /** A synthetic zero-extent span that starts and ends at given `start`. */ + def Span(start: Int): Span = Span(start, start) - /** A sentinel for a non-existing position */ - val NoPosition: Position = Position(1, 0) + /** A sentinel for a non-existing span */ + val NoSpan: Span = Span(1, 0) /** The coordinate of a symbol. This is either an index or - * a zero-range position. + * a zero-range span. */ class Coord(val encoding: Int) extends AnyVal { def isIndex: Boolean = encoding > 0 @@ -159,15 +163,15 @@ object Positions { assert(isIndex) encoding - 1 } - def toPosition: Position = { + def toPosition: Span = { assert(isPosition) - if (this == NoCoord) NoPosition else Position(-1 - encoding) + if (this == NoCoord) NoSpan else Span(-1 - encoding) } } /** An index coordinate */ implicit def indexCoord(n: Int): Coord = new Coord(n + 1) - implicit def positionCoord(pos: Position): Coord = + implicit def positionCoord(pos: Span): Coord = if (pos.exists) new Coord(-(pos.point + 1)) else NoCoord diff --git a/compiler/src/dotty/tools/repl/ReplCompiler.scala b/compiler/src/dotty/tools/repl/ReplCompiler.scala index e61bc6b15deb..a90aebe4eee7 100644 --- a/compiler/src/dotty/tools/repl/ReplCompiler.scala +++ b/compiler/src/dotty/tools/repl/ReplCompiler.scala @@ -14,7 +14,7 @@ import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.reporting.diagnostic.messages import dotty.tools.dotc.transform.PostTyper import dotty.tools.dotc.typer.ImportInfo -import dotty.tools.dotc.util.Positions._ +import dotty.tools.dotc.util.Spans._ import dotty.tools.dotc.util.{ParsedComment, SourceFile} import dotty.tools.dotc.{CompilationUnit, Compiler, Run} import dotty.tools.repl.results._ @@ -135,7 +135,7 @@ class ReplCompiler extends Compiler { val tmpl = Template(emptyConstructor, Nil, EmptyValDef, defs.stats) val module = ModuleDef(objectName(defs.state), tmpl) - .withSpan(Position(0, defs.stats.last.pos.end)) + .withSpan(Span(0, defs.stats.last.pos.end)) PackageDef(Ident(nme.EMPTY_PACKAGE), List(module)) } @@ -231,7 +231,7 @@ class ReplCompiler extends Compiler { val tmpl = Template(emptyConstructor, Nil, EmptyValDef, List(valdef)) val wrapper = TypeDef("$wrapper".toTypeName, tmpl) .withMods(Modifiers(Final)) - .withSpan(Position(0, expr.length)) + .withSpan(Span(0, expr.length)) PackageDef(Ident(nme.EMPTY_PACKAGE), List(wrapper)) } @@ -244,7 +244,7 @@ class ReplCompiler extends Compiler { case _ => List( new messages.Error( s"Couldn't parse '$expr' to valid scala", - sourceFile.atPos(Position(0, expr.length)) + sourceFile.atPos(Span(0, expr.length)) ) ).errors } @@ -253,7 +253,7 @@ class ReplCompiler extends Compiler { def unwrapped(tree: tpd.Tree, sourceFile: SourceFile)(implicit ctx: Context): Result[tpd.ValDef] = { def error: Result[tpd.ValDef] = List(new messages.Error(s"Invalid scala expression", - sourceFile.atPos(Position(0, sourceFile.content.length)))).errors + sourceFile.atPos(Span(0, sourceFile.content.length)))).errors import tpd._ tree match { diff --git a/compiler/src/dotty/tools/repl/ReplDriver.scala b/compiler/src/dotty/tools/repl/ReplDriver.scala index 38bbaffff0e4..fce239acc405 100644 --- a/compiler/src/dotty/tools/repl/ReplDriver.scala +++ b/compiler/src/dotty/tools/repl/ReplDriver.scala @@ -17,7 +17,7 @@ import dotty.tools.dotc.interactive.Completion import dotty.tools.dotc.printing.SyntaxHighlighting import dotty.tools.dotc.reporting.MessageRendering import dotty.tools.dotc.reporting.diagnostic.{Message, MessageContainer} -import dotty.tools.dotc.util.Positions.Position +import dotty.tools.dotc.util.Spans.Span import dotty.tools.dotc.util.{SourceFile, SourcePosition} import dotty.tools.dotc.{CompilationUnit, Driver} import dotty.tools.io._ @@ -169,7 +169,7 @@ class ReplDriver(settings: Array[String], val unit = new CompilationUnit(file) unit.tpdTree = tree implicit val ctx = state.context.fresh.setCompilationUnit(unit) - val srcPos = SourcePosition(file, Position(cursor)) + val srcPos = SourcePosition(file, Span(cursor)) val (_, completions) = Completion.completions(srcPos) completions.map(makeCandidate) } diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala index dbc76d2fd618..eab6cfc2f01c 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala @@ -5,7 +5,7 @@ package comment import dotty.tools.dottydoc.util.syntax._ import dotty.tools.dotc.core.Contexts.Context -import dotty.tools.dotc.util.Positions._ +import dotty.tools.dotc.util.Spans._ import com.vladsch.flexmark.ast.{ Node => MarkdownNode } import HtmlParsers._ import util.MemberLookup @@ -59,7 +59,7 @@ private[comment] case class ParsedComment ( trait MarkupConversion[T] extends MemberLookup { def ent: Entity - def pos: Position + def pos: Span def parsed: ParsedComment protected def linkedExceptions(m: Map[String, String])(implicit ctx: Context): Map[String, String] @@ -104,7 +104,7 @@ trait MarkupConversion[T] extends MemberLookup { ) } -case class MarkdownComment(ent: Entity, parsed: ParsedComment, pos: Position) +case class MarkdownComment(ent: Entity, parsed: ParsedComment, pos: Span) extends MarkupConversion[MarkdownNode] { def stringToMarkup(str: String)(implicit ctx: Context) = @@ -135,7 +135,7 @@ extends MarkupConversion[MarkdownNode] { .mapValues(stringToMarkup) } -case class WikiComment(ent: Entity, parsed: ParsedComment, pos: Position) +case class WikiComment(ent: Entity, parsed: ParsedComment, pos: Span) extends MarkupConversion[Body] { def filterEmpty(xs: Map[String,String])(implicit ctx: Context) = diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala index f5b1b35cc8ee..9dc6c2baf24f 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala @@ -3,7 +3,7 @@ package model package comment import dotty.tools.dottydoc.util.syntax._ -import dotty.tools.dotc.util.Positions._ +import dotty.tools.dotc.util.Spans._ import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Decorators._ @@ -28,7 +28,7 @@ trait CommentParser extends util.MemberLookup { packages: Map[String, Package], comment: List[String], src: String, - pos: Position, + pos: Span, site: Symbol = NoSymbol )(implicit ctx: Context): ParsedComment = { @@ -202,7 +202,7 @@ trait CommentParser extends util.MemberLookup { // with the point being at the very end. This ensures that the entire // comment will be visible in error reporting. A more fine-grained // reporting would be amazing here. - entity.symbol.sourcePosition(Position(pos.start, pos.end, pos.end)) + entity.symbol.sourcePosition(Span(pos.start, pos.end, pos.end)) ) cmt @@ -236,7 +236,7 @@ trait CommentParser extends util.MemberLookup { entity: Entity, packages: Map[String, Package], string: String, - pos: Position, + pos: Span, site: Symbol )(implicit ctx: Context): Body = new WikiParser(entity, packages, string, pos, site).document() } diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala index 1faa25f326c5..e0a370e69044 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala @@ -4,7 +4,7 @@ package model package comment import dotc.core.Contexts.Context -import dotc.util.Positions._ +import dotc.util.Spans._ import dotty.tools.dottydoc.util.syntax._ import util.MemberLookup @@ -70,7 +70,7 @@ object HtmlParsers { } implicit class StringToWiki(val text: String) extends AnyVal { - def toWiki(origin: Entity, packages: Map[String, Package], pos: Position): Body = + def toWiki(origin: Entity, packages: Map[String, Package], pos: Span): Body = new WikiParser(origin, packages, text, pos, origin.symbol).document() } diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/WikiParser.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/WikiParser.scala index 70f85a53e29c..38b1d5f60c5d 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/comment/WikiParser.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/WikiParser.scala @@ -3,7 +3,7 @@ package model package comment import dotty.tools.dotc.core.Contexts.Context -import dotty.tools.dotc.util.Positions._ +import dotty.tools.dotc.util.Spans._ import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.config.Printers.dottydoc import util.MemberLookup @@ -21,7 +21,7 @@ private[comment] final class WikiParser( entity: Entity, packages: Map[String, Package], val buffer: String, - pos: Position, + pos: Span, site: Symbol ) extends CharReader(buffer) with MemberLookup { wiki => var summaryParsed = false @@ -402,7 +402,7 @@ private[comment] final class WikiParser( } } - def reportError(pos: Position, message: String) = + def reportError(pos: Span, message: String) = dottydoc.println(s"$pos: $message") } diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/Template.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/Template.scala index efa011e0a8a8..8bfe7b084cfd 100644 --- a/doc-tool/src/dotty/tools/dottydoc/staticsite/Template.scala +++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/Template.scala @@ -6,7 +6,7 @@ import scala.util.control.NonFatal import dotc.util.SourceFile import dotc.core.Contexts.Context -import dotc.util.Positions.{ Position, NoPosition } +import dotc.util.Spans.Span import util.syntax._ trait Template { @@ -68,7 +68,7 @@ case class LiquidTemplate(path: String, content: SourceFile) extends Template wi s"unexpected end of file, expected: '$expected'" else s"unexpected token '$unexpected', expected: '$expected'", - content atPos Position(mm.index) + content atPos Span(mm.index) ) None diff --git a/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala b/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala index 4edb71b387dd..e0e2ae1f26e2 100644 --- a/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala +++ b/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala @@ -9,7 +9,7 @@ import core.ContextDottydoc import dotc.core.Symbols._ import dotc.util.{ SourcePosition, SourceFile } -import dotc.util.Positions.Position +import dotc.util.Spans.Span import scala.io.Codec object syntax { @@ -20,7 +20,7 @@ object syntax { } implicit class SymbolExtensions(val sym: Symbol) extends AnyVal { - def sourcePosition(pos: Position)(implicit ctx: Context): SourcePosition = + def sourcePosition(pos: Span)(implicit ctx: Context): SourcePosition = ctx.getSource(sym.sourceFile).atPos(pos) } } diff --git a/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala b/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala index 9703bb022f18..4aec9eb9f35d 100644 --- a/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala +++ b/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala @@ -646,7 +646,7 @@ object DottyLanguageServer { else pos val source = driver.openedFiles(uri) if (source.exists) { - val p = Positions.Position(source.lineToOffset(actualPosition.getLine) + actualPosition.getCharacter) + val p = Spans.Span(source.lineToOffset(actualPosition.getLine) + actualPosition.getCharacter) new SourcePosition(source, p) } else NoSourcePosition diff --git a/language-server/src/dotty/tools/languageserver/worksheet/Worksheet.scala b/language-server/src/dotty/tools/languageserver/worksheet/Worksheet.scala index 88cd82368044..58b30961c106 100644 --- a/language-server/src/dotty/tools/languageserver/worksheet/Worksheet.scala +++ b/language-server/src/dotty/tools/languageserver/worksheet/Worksheet.scala @@ -3,7 +3,7 @@ package dotty.tools.languageserver.worksheet import dotty.tools.dotc.ast.tpd.{DefTree, Template, Tree, TypeDef} import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.interactive.SourceTree -import dotty.tools.dotc.util.Positions.Position +import dotty.tools.dotc.util.Spans.Span import dotty.tools.dotc.util.SourceFile import dotty.tools.dotc.core.Flags.Synthetic @@ -71,7 +71,7 @@ object Worksheet { (line, source) } - private def bounds(pos: Position): (Int, Int) = (pos.start, pos.end) + private def bounds(pos: Span): (Int, Int) = (pos.start, pos.end) } From cf94fc4deb7b11a1e82122191c0e821646450b4e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 3 Jan 2019 19:31:05 +0100 Subject: [PATCH 36/75] Add missing check files --- tests/run/i3396.check | 1 + tests/run/tuple-cons-2.check | 1 + 2 files changed, 2 insertions(+) create mode 100644 tests/run/i3396.check create mode 100644 tests/run/tuple-cons-2.check diff --git a/tests/run/i3396.check b/tests/run/i3396.check new file mode 100644 index 000000000000..d00491fd7e5b --- /dev/null +++ b/tests/run/i3396.check @@ -0,0 +1 @@ +1 diff --git a/tests/run/tuple-cons-2.check b/tests/run/tuple-cons-2.check new file mode 100644 index 000000000000..2f42f3bc5bd3 --- /dev/null +++ b/tests/run/tuple-cons-2.check @@ -0,0 +1 @@ +(1,2,3,4,5,6) From 012c5e974ec89466d3064c8ceb772afd228ee727 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 3 Jan 2019 19:37:24 +0100 Subject: [PATCH 37/75] Fix rebase breakage --- compiler/src/dotty/tools/dotc/core/tasty/TastyHTMLPrinter.scala | 2 +- compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyHTMLPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyHTMLPrinter.scala index 4366ce29f76b..e6d2ea258760 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyHTMLPrinter.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyHTMLPrinter.scala @@ -6,7 +6,7 @@ import Contexts._, Decorators._ import Names.Name import TastyUnpickler._ import TastyBuffer.NameRef -import util.Positions.offsetToInt +import util.Spans.offsetToInt import printing.Highlighting._ class TastyHTMLPrinter(bytes: Array[Byte])(implicit ctx: Context) extends TastyPrinter(bytes) { diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala index 232fd1a28cd5..bc4cf6e4e405 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala @@ -129,7 +129,7 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) { def unpickle(reader: TastyReader, tastyName: NameTable): String = { sb.append(s" ${reader.endAddr.index - reader.currentAddr.index}") - val positions = new PositionUnpickler(reader).positions + val positions = new PositionUnpickler(reader, tastyName).positions sb.append(s" position bytes:\n") val sorted = positions.toSeq.sortBy(_._1.index) for ((addr, pos) <- sorted) { From ca4e463584e13dddec4ab754f6f8c8e2b31e6080 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 3 Jan 2019 19:45:54 +0100 Subject: [PATCH 38/75] atPos -> atSpan --- .../dotty/tools/backend/sjs/JSPositions.scala | 10 +++++----- .../src/dotty/tools/dotc/ast/DesugarEnums.scala | 2 +- .../src/dotty/tools/dotc/ast/Positioned.scala | 2 +- .../src/dotty/tools/dotc/core/Comments.scala | 2 +- .../src/dotty/tools/dotc/core/Decorators.scala | 4 ++-- compiler/src/dotty/tools/dotc/core/Symbols.scala | 2 +- .../tools/dotc/interactive/SourceTree.scala | 4 ++-- .../src/dotty/tools/dotc/parsing/Parsers.scala | 16 ++++++++-------- .../src/dotty/tools/dotc/parsing/Scanners.scala | 6 +++--- .../src/dotty/tools/dotc/transform/Staging.scala | 2 +- .../src/dotty/tools/dotc/typer/Docstrings.scala | 2 +- .../src/dotty/tools/dotc/typer/Implicits.scala | 6 +++--- compiler/src/dotty/tools/dotc/typer/Namer.scala | 2 +- .../src/dotty/tools/dotc/typer/RefChecks.scala | 4 ++-- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- .../src/dotty/tools/dotc/util/SourceFile.scala | 4 ++-- compiler/src/dotty/tools/repl/ReplCompiler.scala | 4 ++-- .../tools/dottydoc/staticsite/Template.scala | 2 +- .../src/dotty/tools/dottydoc/util/syntax.scala | 2 +- 19 files changed, 39 insertions(+), 39 deletions(-) diff --git a/compiler/src/dotty/tools/backend/sjs/JSPositions.scala b/compiler/src/dotty/tools/backend/sjs/JSPositions.scala index c4faa9569ce4..46c4509229b3 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSPositions.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSPositions.scala @@ -11,11 +11,11 @@ import org.scalajs.ir class JSPositions()(implicit ctx: Context) { /** Implicit conversion from dotty Position to ir.Position. */ - implicit def pos2irPos(pos: Span): ir.Position = { - if (!pos.exists) ir.Position.NoPosition + implicit def pos2irPos(span: Span): ir.Position = { + if (!span.exists) ir.Position.NoPosition else { val source = pos2irPosCache.toIRSource(ctx.compilationUnit.source) - val sourcePos = ctx.compilationUnit.source.atPos(pos) + val sourcePos = ctx.compilationUnit.source.atSpan(span) // dotty positions are 1-based but IR positions are 0-based ir.Position(source, sourcePos.line-1, sourcePos.column-1) } @@ -23,8 +23,8 @@ class JSPositions()(implicit ctx: Context) { /** Implicitly materializes an ir.Position from an implicit dotty Position. */ implicit def implicitPos2irPos( - implicit pos: Span): ir.Position = { - pos2irPos(pos) + implicit span: Span): ir.Position = { + pos2irPos(span) } private[this] object pos2irPosCache { // scalastyle:ignore diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index c7577715330f..9d18febd3c77 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -57,7 +57,7 @@ object DesugarEnums { if (tparam.variance == 0) "is non variant" else "has bounds that depend on a type parameter in the same parameter list" errorType(i"""cannot determine type argument for enum parent $enumClass, - |type parameter $tparam $problem""", ctx.source.atPos(pos)) + |type parameter $tparam $problem""", ctx.source.atSpan(pos)) } } TypeTree(enumClass.typeRef.appliedTo(targs)).withSpan(pos) diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index ad68186ef7bb..46af5212b041 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -30,7 +30,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod protected def srcfile: AbstractFile = TreeIds.fileOfId(uniqueId) def source(implicit ctx: Context): SourceFile = ctx.getSource(srcfile) - def sourcePos(implicit ctx: Context): SourcePosition = source.atPos(pos) + def sourcePos(implicit ctx: Context): SourcePosition = source.atSpan(pos) setId(TreeIds.nextIdFor(initialFile(src))) setPos(initialSpan(), srcfile) diff --git a/compiler/src/dotty/tools/dotc/core/Comments.scala b/compiler/src/dotty/tools/dotc/core/Comments.scala index dcca7813808c..355e9aac250c 100644 --- a/compiler/src/dotty/tools/dotc/core/Comments.scala +++ b/compiler/src/dotty/tools/dotc/core/Comments.scala @@ -125,7 +125,7 @@ object Comments { val newName = ctx.freshNames.newName(tree.name, NameKinds.DocArtifactName) tree.copy(name = newName) case _ => - ctx.error(ProperDefinitionNotFound(), ctx.source.atPos(codePos)) + ctx.error(ProperDefinitionNotFound(), ctx.source.atSpan(codePos)) tree } } diff --git a/compiler/src/dotty/tools/dotc/core/Decorators.scala b/compiler/src/dotty/tools/dotc/core/Decorators.scala index e21cfeccc7fd..0ba45d11ce92 100644 --- a/compiler/src/dotty/tools/dotc/core/Decorators.scala +++ b/compiler/src/dotty/tools/dotc/core/Decorators.scala @@ -168,9 +168,9 @@ object Decorators { implicit def sourcePos(pos: Span)(implicit ctx: Context): SourcePosition = { def recur(inlinedCalls: List[Tree], pos: Span): SourcePosition = inlinedCalls match { case inlinedCall :: rest => - sourceFile(inlinedCall).atPos(pos).withOuter(recur(rest, inlinedCall.pos)) + sourceFile(inlinedCall).atSpan(pos).withOuter(recur(rest, inlinedCall.pos)) case empty => - ctx.source.atPos(pos) + ctx.source.atSpan(pos) } recur(enclosingInlineds, pos) } diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 8da179b17c51..d791ab5765cf 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -680,7 +680,7 @@ object Symbols { ctx.source else ctx.getSource(f) } - source.atPos(pos) + source.atSpan(pos) } // ParamInfo types and methods diff --git a/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala b/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala index 8e0b07c2bb2d..99dd682d7ab8 100644 --- a/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala +++ b/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala @@ -17,7 +17,7 @@ import util._, util.Spans._ case class SourceTree(tree: tpd.Tree /** really: tpd.Import | tpd.NameTree */, source: SourceFile) { /** The position of `tree` */ - final def pos(implicit ctx: Context): SourcePosition = source.atPos(tree.pos) + final def pos(implicit ctx: Context): SourcePosition = source.atSpan(tree.pos) /** The position of the name in `tree` */ def namePos(implicit ctx: Context): SourcePosition = tree match { @@ -43,7 +43,7 @@ case class SourceTree(tree: tpd.Tree /** really: tpd.Import | tpd.NameTree */, s (treePos.end - nameLength, treePos.end) Span(start, end, start) } - source.atPos(position) + source.atSpan(position) } case _ => NoSourcePosition diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index dcb4c55ef8b9..cdba54f1731c 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -103,7 +103,7 @@ object Parsers { if (in.token == BACKQUOTED_IDENT) in.offset + 1 else in.offset def sourcePos(off: Int = in.offset): SourcePosition = - source.atPos(Span(off)) + source.atSpan(Span(off)) /* ------------- ERROR HANDLING ------------------------------------------- */ /** The offset where the last syntax error was reported, or if a skip to a @@ -125,7 +125,7 @@ object Parsers { * updating lastErrorOffset. */ def syntaxError(msg: => Message, pos: Span): Unit = - ctx.error(msg, source atPos pos) + ctx.error(msg, source.atSpan(pos)) } trait OutlineParserCommon extends ParserCommon { @@ -263,14 +263,14 @@ object Parsers { ctx.warning(msg, sourcePos) def warning(msg: => Message, offset: Int = in.offset): Unit = - ctx.warning(msg, source atPos Span(offset)) + ctx.warning(msg, source.atSpan(Span(offset))) def deprecationWarning(msg: => Message, offset: Int = in.offset): Unit = - ctx.deprecationWarning(msg, source atPos Span(offset)) + ctx.deprecationWarning(msg, source.atSpan(Span(offset))) /** Issue an error at current offset that input is incomplete */ def incompleteInputError(msg: => Message): Unit = - ctx.incompleteInputError(msg, source atPos Span(in.offset)) + ctx.incompleteInputError(msg, source.atSpan(Span(in.offset))) /** If at end of file, issue an incompleteInputError. * Otherwise issue a syntax error and skip to next safe point. @@ -349,7 +349,7 @@ object Parsers { def migrationWarningOrError(msg: String, offset: Int = in.offset): Unit = if (in.isScala2Mode) - ctx.migrationWarning(msg, source atPos Span(offset)) + ctx.migrationWarning(msg, source.atSpan(Span(offset))) else syntaxError(msg, offset) @@ -708,7 +708,7 @@ object Parsers { if (inPattern) Block(Nil, inBraces(pattern())) else expr() else { - ctx.error(InterpolatedStringError(), source atPos Span(in.offset)) + ctx.error(InterpolatedStringError(), source.atSpan(Span(in.offset))) EmptyTree } }) @@ -1204,7 +1204,7 @@ object Parsers { else { if (handler.isEmpty) warning( EmptyCatchAndFinallyBlock(body), - source atPos Span(tryOffset, endOffset(body)) + source.atSpan(Span(tryOffset, endOffset(body))) ) EmptyTree } diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index 30792942b5a2..2d27c2059602 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -66,14 +66,14 @@ object Scanners { /** Generate an error at the given offset */ def error(msg: String, off: Offset = offset): Unit = { - ctx.error(msg, source atPos Span(off)) + ctx.error(msg, source atSpan Span(off)) token = ERROR errOffset = off } /** signal an error where the input ended in the middle of a token */ def incompleteInputError(msg: String): Unit = { - ctx.incompleteInputError(msg, source atPos Span(offset)) + ctx.incompleteInputError(msg, source atSpan Span(offset)) token = EOF errOffset = offset } @@ -246,7 +246,7 @@ object Scanners { /** Cannot use ctx.featureEnabled because accessing the context would force too much */ def testScala2Mode(msg: String, pos: Span = Span(offset)): Boolean = { - if (isScala2Mode) ctx.migrationWarning(msg, source atPos pos) + if (isScala2Mode) ctx.migrationWarning(msg, source atSpan pos) isScala2Mode } diff --git a/compiler/src/dotty/tools/dotc/transform/Staging.scala b/compiler/src/dotty/tools/dotc/transform/Staging.scala index c1760c680647..0655a014c7f7 100644 --- a/compiler/src/dotty/tools/dotc/transform/Staging.scala +++ b/compiler/src/dotty/tools/dotc/transform/Staging.scala @@ -449,7 +449,7 @@ class Staging extends MacroTransformWithImplicits { } else if (enclosingInlineds.nonEmpty) { // level 0 in an inlined call val spliceCtx = ctx.outer // drop the last `inlineContext` - val pos: SourcePosition = spliceCtx.source.atPos(enclosingInlineds.head.pos) + val pos: SourcePosition = spliceCtx.source.atSpan(enclosingInlineds.head.pos) val evaluatedSplice = Splicer.splice(splice.qualifier, pos, macroClassLoader)(spliceCtx).withPosOf(splice) if (ctx.reporter.hasErrors) splice else transform(evaluatedSplice) } diff --git a/compiler/src/dotty/tools/dotc/typer/Docstrings.scala b/compiler/src/dotty/tools/dotc/typer/Docstrings.scala index 2d4232f5f888..ef61df2f8141 100644 --- a/compiler/src/dotty/tools/dotc/typer/Docstrings.scala +++ b/compiler/src/dotty/tools/dotc/typer/Docstrings.scala @@ -38,7 +38,7 @@ object Docstrings { case List(df: tpd.DefDef) => usecase.typed(df) case _ => - ctx.error("`@usecase` was not a valid definition", ctx.source.atPos(usecase.codePos)) + ctx.error("`@usecase` was not a valid definition", ctx.source.atSpan(usecase.codePos)) usecase } } diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 07874bacddf5..68f882dcb399 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -738,7 +738,7 @@ trait Implicits { self: Typer => def implicitArgTree(formal: Type, pos: Span)(implicit ctx: Context): Tree = { val arg = inferImplicitArg(formal, pos) if (arg.tpe.isInstanceOf[SearchFailureType]) - ctx.error(missingArgMsg(arg, formal, ""), ctx.source.atPos(pos)) + ctx.error(missingArgMsg(arg, formal, ""), ctx.source.atSpan(pos)) arg } @@ -909,7 +909,7 @@ trait Implicits { self: Typer => case altResult: SearchSuccess => ctx.migrationWarning( s"According to new implicit resolution rules, this will be ambiguous:\n${result.reason.explanation}", - ctx.source.atPos(pos)) + ctx.source.atSpan(pos)) altResult case _ => result @@ -1153,7 +1153,7 @@ trait Implicits { self: Typer => |the search will fail with a global ambiguity error instead. | |Consider using the scala.implicits.Not class to implement similar functionality.""", - ctx.source.atPos(pos)) + ctx.source.atSpan(pos)) /** A relation that imfluences the order in which implicits are tried. * We prefer (in order of importance) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 153fd50f9247..e9f642e5bfbb 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -248,7 +248,7 @@ class Namer { typer: Typer => else { val cls = ctx.owner.enclosingClassNamed(name) if (!cls.exists) - ctx.error(s"no enclosing class or object is named $name", ctx.source.atPos(pos)) + ctx.error(s"no enclosing class or object is named $name", ctx.source.atSpan(pos)) cls } } diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index a5925698626c..cf3a9ff98538 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -959,7 +959,7 @@ class RefChecks extends MiniPhase { thisPhase => currentLevel.levelAndIndex.get(sym) match { case Some((level, symIdx)) if symIdx <= level.maxIndex => ctx.error(ForwardReferenceExtendsOverDefinition(sym, level.refSym), - ctx.source.atPos(level.refPos)) + ctx.source.atSpan(level.refPos)) case _ => } } @@ -1005,7 +1005,7 @@ class RefChecks extends MiniPhase { thisPhase => // An implementation restriction to avoid VerifyErrors and lazyvals mishaps; see SI-4717 ctx.debuglog("refsym = " + level.refSym) ctx.error("forward reference not allowed from self constructor invocation", - ctx.source.atPos(level.refPos)) + ctx.source.atSpan(level.refPos)) } } tree diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index aec2f081e13b..47efd7a2e44c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1713,7 +1713,7 @@ class Typer extends Namer val pcls = (defn.ObjectClass /: parents)(improve) typr.println(i"ensure first is class $parents%, % --> ${parents map (_ baseType pcls)}%, %") val first = ctx.typeComparer.glb(defn.ObjectType :: parents.map(_.baseType(pcls))) - checkFeasibleParent(first, ctx.source.atPos(pos), em" in inferred superclass $first") :: parents + checkFeasibleParent(first, ctx.source.atSpan(pos), em" in inferred superclass $first") :: parents } } diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index 9685f0278985..9d2fb6fd35aa 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -67,7 +67,7 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends /** The start of this file in the underlying source file */ def start: Int = 0 - def atPos(pos: Span): SourcePosition = + def atSpan(pos: Span): SourcePosition = if (pos.exists) SourcePosition(underlying, pos) else NoSourcePosition @@ -155,6 +155,6 @@ object SourceFile { @sharable object NoSource extends SourceFile(NoAbstractFile, Array[Char]()) { override def exists: Boolean = false - override def atPos(pos: Span): SourcePosition = NoSourcePosition + override def atSpan(pos: Span): SourcePosition = NoSourcePosition } diff --git a/compiler/src/dotty/tools/repl/ReplCompiler.scala b/compiler/src/dotty/tools/repl/ReplCompiler.scala index a90aebe4eee7..0941ab468bfb 100644 --- a/compiler/src/dotty/tools/repl/ReplCompiler.scala +++ b/compiler/src/dotty/tools/repl/ReplCompiler.scala @@ -244,7 +244,7 @@ class ReplCompiler extends Compiler { case _ => List( new messages.Error( s"Couldn't parse '$expr' to valid scala", - sourceFile.atPos(Span(0, expr.length)) + sourceFile.atSpan(Span(0, expr.length)) ) ).errors } @@ -253,7 +253,7 @@ class ReplCompiler extends Compiler { def unwrapped(tree: tpd.Tree, sourceFile: SourceFile)(implicit ctx: Context): Result[tpd.ValDef] = { def error: Result[tpd.ValDef] = List(new messages.Error(s"Invalid scala expression", - sourceFile.atPos(Span(0, sourceFile.content.length)))).errors + sourceFile.atSpan(Span(0, sourceFile.content.length)))).errors import tpd._ tree match { diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/Template.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/Template.scala index 8bfe7b084cfd..ef1f68b6e1c4 100644 --- a/doc-tool/src/dotty/tools/dottydoc/staticsite/Template.scala +++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/Template.scala @@ -68,7 +68,7 @@ case class LiquidTemplate(path: String, content: SourceFile) extends Template wi s"unexpected end of file, expected: '$expected'" else s"unexpected token '$unexpected', expected: '$expected'", - content atPos Span(mm.index) + content atSpan Span(mm.index) ) None diff --git a/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala b/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala index e0e2ae1f26e2..9129d8c0f176 100644 --- a/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala +++ b/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala @@ -21,6 +21,6 @@ object syntax { implicit class SymbolExtensions(val sym: Symbol) extends AnyVal { def sourcePosition(pos: Span)(implicit ctx: Context): SourcePosition = - ctx.getSource(sym.sourceFile).atPos(pos) + ctx.getSource(sym.sourceFile).atSpan(pos) } } From dbc5251ce9f4a95de006fca9c03ebc219cb446a8 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 4 Jan 2019 10:51:25 +0100 Subject: [PATCH 39/75] Rename SourcePos#pos -> SourcePos#span Also: Better toText for source positions - only print file name instead of full path - enclose in <...> when printing in trees --- .../backend/jvm/DottyBackendInterface.scala | 2 +- .../src/dotty/tools/dotc/ast/Positioned.scala | 4 ++-- .../tools/dotc/interactive/Completion.scala | 10 ++++---- .../tools/dotc/interactive/Interactive.scala | 6 ++--- .../tools/dotc/printing/PlainPrinter.scala | 7 +++--- .../tools/dotc/printing/RefinedPrinter.scala | 7 +++--- .../dotty/tools/dotc/transform/Bridges.scala | 2 +- .../dotty/tools/dotc/transform/Staging.scala | 2 +- .../dotty/tools/dotc/util/SourceFile.scala | 2 +- .../tools/dotc/util/SourcePosition.scala | 24 +++++++++---------- 10 files changed, 34 insertions(+), 32 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index d334929d9bdf..b3f8ce07a3fc 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -800,7 +800,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def freshLocal(cunit: CompilationUnit, name: String, tpe: Type, pos: Position, flags: Flags): Symbol = { - ctx.newSymbol(sym, name.toTermName, termFlagSet(flags), tpe, NoSymbol, pos.pos) + ctx.newSymbol(sym, name.toTermName, termFlagSet(flags), tpe, NoSymbol, pos.span) } def getter(clz: Symbol): Symbol = decorateSymbol(sym).getter diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index 46af5212b041..1ae023799469 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -73,9 +73,9 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod def withSourcePos(sourcePos: SourcePosition): this.type = { val ownPos = this.pos val newpd: this.type = - if (sourcePos.source.file == srcfile && sourcePos.pos == ownPos || ownPos.isSynthetic) this + if (sourcePos.source.file == srcfile && sourcePos.span == ownPos || ownPos.isSynthetic) this else cloneIn(sourcePos.source.file) - newpd.setPos(sourcePos.pos, sourcePos.source.file) + newpd.setPos(sourcePos.span, sourcePos.source.file) newpd } diff --git a/compiler/src/dotty/tools/dotc/interactive/Completion.scala b/compiler/src/dotty/tools/dotc/interactive/Completion.scala index d740d4098e3e..576a3cf59d13 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Completion.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Completion.scala @@ -40,7 +40,7 @@ object Completion { * @return offset and list of symbols for possible completions */ def completions(pos: SourcePosition)(implicit ctx: Context): (Int, List[Completion]) = { - val path = Interactive.pathTo(ctx.compilationUnit.tpdTree, pos.pos) + val path = Interactive.pathTo(ctx.compilationUnit.tpdTree, pos.span) computeCompletions(pos, path)(Interactive.contextOfPath(path)) } @@ -62,7 +62,7 @@ object Completion { else Mode.None case Thicket(name :: _ :: Nil) :: (_: Import) :: _ => - if (name.pos.contains(pos.pos)) Mode.Import + if (name.pos.contains(pos.span)) Mode.Import else Mode.None // Can't help completing the renaming case Import(_, _) :: _ => @@ -83,13 +83,13 @@ object Completion { completionPrefix(name :: Nil, pos) case Import(expr, selectors) :: _ => - selectors.find(_.pos.contains(pos.pos)).map { selector => + selectors.find(_.pos.contains(pos.span)).map { selector => completionPrefix(selector.asInstanceOf[Tree] :: Nil, pos) }.getOrElse("") case (ref: RefTree) :: _ => if (ref.name == nme.ERROR) "" - else ref.name.toString.take(pos.pos.point - ref.pos.point) + else ref.name.toString.take(pos.span.point - ref.pos.point) case _ => "" @@ -309,7 +309,7 @@ object Completion { */ private def implicitConversionTargets(qual: Tree)(implicit ctx: Context): Set[Type] = { val typer = ctx.typer - val conversions = new typer.ImplicitSearch(defn.AnyType, qual, pos.pos).allImplicits + val conversions = new typer.ImplicitSearch(defn.AnyType, qual, pos.span).allImplicits val targets = conversions.map(_.widen.finalResultType) interactiv.println(i"implicit conversion targets considered: ${targets.toList}%, %") targets diff --git a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala index 2daea8c9d97c..0cb961820e80 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala @@ -121,10 +121,10 @@ object Interactive { List(select.symbol) case (_: Thicket) :: (imp: Import) :: _ => - importedSymbols(imp, _.pos.contains(pos.pos)) + importedSymbols(imp, _.pos.contains(pos.span)) case (imp: Import) :: _ => - importedSymbols(imp, _.pos.contains(pos.pos)) + importedSymbols(imp, _.pos.contains(pos.span)) case _ => List(enclosingTree(path).symbol) @@ -252,7 +252,7 @@ object Interactive { */ def pathTo(trees: List[SourceTree], pos: SourcePosition)(implicit ctx: Context): List[Tree] = trees.find(_.pos.contains(pos)) match { - case Some(tree) => pathTo(tree.tree, pos.pos) + case Some(tree) => pathTo(tree.tree, pos.span) case None => Nil } diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 2dc13277ed38..7bf7bcd3af92 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -505,10 +505,11 @@ class PlainPrinter(_ctx: Context) extends Printer { nodeName ~ "(" ~ elems ~ tpSuffix ~ ")" ~ (Str(tree.sourcePos.toString) provided ctx.settings.YprintPos.value) }.close // todo: override in refined printer - def toText(pos: SourcePosition): Text = + def toText(pos: SourcePosition): Text = { if (!pos.exists) "" - else if (pos.source.exists) s"${pos.source.file}:${pos.line + 1}" - else s"(no source file, offset = ${pos.pos.point})" + else if (pos.source.exists) s"${pos.source.file.name}:${pos.line + 1}" + else s"(no source file, offset = ${pos.span.point})" + } def toText(result: SearchResult): Text = result match { case result: SearchSuccess => diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 33cc66569905..9db27d935f1b 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -605,9 +605,10 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { if (printPos) { val posStr = if (homogenizedView) - if (tree.isInstanceOf[MemberDef]) s"${tree.source}${tree.pos}" - else s"${tree.source}${tree.pos.toSynthetic}" - else tree.sourcePos.toString + if (tree.isInstanceOf[MemberDef]) Str(s"${tree.source}${tree.pos}") + else Str(s"${tree.source}${tree.pos.toSynthetic}") + else + "<" ~ toText(tree.sourcePos) ~ ">" val clsStr = ""//if (tree.isType) tree.getClass.toString else "" txt = (txt ~ "@" ~ posStr ~ clsStr).close } diff --git a/compiler/src/dotty/tools/dotc/transform/Bridges.scala b/compiler/src/dotty/tools/dotc/transform/Bridges.scala index 8bbe6c2b5aa3..fb81a495e238 100644 --- a/compiler/src/dotty/tools/dotc/transform/Bridges.scala +++ b/compiler/src/dotty/tools/dotc/transform/Bridges.scala @@ -86,7 +86,7 @@ class Bridges(root: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont owner = root, flags = (member.flags | Method | Bridge | Artifact) &~ (Accessor | ParamAccessor | CaseAccessor | Deferred | Lazy | Module), - coord = bridgePosFor(member).pos).enteredAfter(thisPhase).asTerm + coord = bridgePosFor(member).span).enteredAfter(thisPhase).asTerm ctx.debuglog( i"""generating bridge from ${other.showLocated}: ${other.info} diff --git a/compiler/src/dotty/tools/dotc/transform/Staging.scala b/compiler/src/dotty/tools/dotc/transform/Staging.scala index 0655a014c7f7..a95b72c9b9df 100644 --- a/compiler/src/dotty/tools/dotc/transform/Staging.scala +++ b/compiler/src/dotty/tools/dotc/transform/Staging.scala @@ -265,7 +265,7 @@ class Staging extends MacroTransformWithImplicits { None } else { val reqType = defn.QuotedTypeType.appliedTo(tp) - val tag = ctx.typer.inferImplicitArg(reqType, pos.pos) + val tag = ctx.typer.inferImplicitArg(reqType, pos.span) tag.tpe match { case fail: SearchFailureType => Some(i""" diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index 9d2fb6fd35aa..31028c82ce0e 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -77,7 +77,7 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends * For regular source files, simply return the argument. */ def positionInUltimateSource(position: SourcePosition): SourcePosition = - SourcePosition(underlying, position.pos shift start) + SourcePosition(underlying, position.span shift start) private def isLineBreak(idx: Int) = if (idx >= length) false else { diff --git a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala index 01c812c49cf3..a9a00eb55fcf 100644 --- a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala +++ b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala @@ -8,18 +8,18 @@ import Spans.{Span, NoSpan} import scala.annotation.internal.sharable /** A source position is comprised of a position in a source file */ -case class SourcePosition(source: SourceFile, pos: Span, outer: SourcePosition = NoSourcePosition) +case class SourcePosition(source: SourceFile, span: Span, outer: SourcePosition = NoSourcePosition) extends interfaces.SourcePosition with Showable { /** Is `that` a source position contained in this source position ? * `outer` is not taken into account. */ def contains(that: SourcePosition): Boolean = - this.source == that.source && this.pos.contains(that.pos) + this.source == that.source && this.span.contains(that.span) - def exists: Boolean = pos.exists + def exists: Boolean = span.exists def lineContent: String = source.lineContent(point) - def point: Int = pos.point + def point: Int = span.point /** The line of the position, starting at 0 */ def line: Int = source.offsetToLine(point) @@ -45,25 +45,25 @@ extends interfaces.SourcePosition with Showable { /** The column of the position, starting at 0 */ def column: Int = source.column(point) - def start: Int = pos.start + def start: Int = span.start def startLine: Int = source.offsetToLine(start) def startColumn: Int = source.column(start) def startColumnPadding: String = source.startColumnPadding(start) - def end: Int = pos.end + def end: Int = span.end def endLine: Int = source.offsetToLine(end) def endColumn: Int = source.column(end) - def withOuter(outer: SourcePosition): SourcePosition = SourcePosition(source, pos, outer) + def withOuter(outer: SourcePosition): SourcePosition = SourcePosition(source, span, outer) def withSpan(range: Span) = SourcePosition(source, range, outer) - def startPos: SourcePosition = withSpan(pos.startPos) - def endPos : SourcePosition = withSpan(pos.endPos) - def focus : SourcePosition = withSpan(pos.focus) - def toSynthetic: SourcePosition = withSpan(pos.toSynthetic) + def startPos: SourcePosition = withSpan(span.startPos) + def endPos : SourcePosition = withSpan(span.endPos) + def focus : SourcePosition = withSpan(span.focus) + def toSynthetic: SourcePosition = withSpan(span.toSynthetic) override def toString: String = - s"${if (source.exists) source.file.toString else "(no source)"}:$pos" + s"${if (source.exists) source.file.toString else "(no source)"}:$span" def toText(printer: Printer): Text = printer.toText(this) } From 6c88c936371d3f3bd060867ef93a8293738da807 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 4 Jan 2019 12:17:50 +0100 Subject: [PATCH 40/75] Rename Span#pos -> Span#span Also, related uses of `pos` local variables are renamed to `span`. --- .../dotty/tools/backend/sjs/JSCodeGen.scala | 60 ++++---- .../src/dotty/tools/dotc/ast/Desugar.scala | 26 ++-- .../dotty/tools/dotc/ast/DesugarEnums.scala | 20 +-- .../dotty/tools/dotc/ast/NavigateAST.scala | 25 ++-- .../src/dotty/tools/dotc/ast/Positioned.scala | 139 +++++++++--------- .../src/dotty/tools/dotc/ast/TreeInfo.scala | 4 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 25 ++-- compiler/src/dotty/tools/dotc/ast/tpd.scala | 12 +- .../dotty/tools/dotc/core/Decorators.scala | 10 -- .../dotc/core/quoted/PickledQuotes.scala | 2 +- .../dotc/core/tasty/PositionPickler.scala | 26 ++-- .../tools/dotc/core/tasty/TreeUnpickler.scala | 2 +- .../tools/dotc/interactive/Completion.scala | 8 +- .../tools/dotc/interactive/Interactive.scala | 14 +- .../tools/dotc/interactive/SourceTree.scala | 12 +- .../tools/dotc/parsing/JavaParsers.scala | 22 +-- .../dotty/tools/dotc/parsing/Parsers.scala | 64 ++++---- .../dotty/tools/dotc/parsing/Scanners.scala | 2 +- .../tools/dotc/printing/RefinedPrinter.scala | 6 +- .../dotc/printing/SyntaxHighlighting.scala | 22 +-- .../dotc/transform/ArrayConstructors.scala | 2 +- .../tools/dotc/transform/ExpandSAMs.scala | 4 +- .../dotty/tools/dotc/transform/LazyVals.scala | 4 +- .../dotty/tools/dotc/transform/LiftTry.scala | 4 +- .../dotty/tools/dotc/transform/Memoize.scala | 2 +- .../dotty/tools/dotc/transform/Mixin.scala | 2 +- .../dotc/transform/NonLocalReturns.scala | 2 +- .../tools/dotc/transform/PatternMatcher.scala | 22 +-- .../dotty/tools/dotc/transform/Pickler.scala | 2 +- .../tools/dotc/transform/PostTyper.scala | 4 +- .../dotty/tools/dotc/transform/Staging.scala | 4 +- .../tools/dotc/transform/SuperAccessors.scala | 2 +- .../dotty/tools/dotc/transform/TailRec.scala | 8 +- .../dotc/transform/TryCatchPatterns.scala | 10 +- .../tools/dotc/transform/TypeTestsCasts.scala | 6 +- .../dotty/tools/dotc/typer/Applications.scala | 10 +- .../src/dotty/tools/dotc/typer/Checking.scala | 2 +- .../src/dotty/tools/dotc/typer/Dynamic.scala | 28 ++-- .../dotty/tools/dotc/typer/EtaExpansion.scala | 8 +- .../dotty/tools/dotc/typer/Implicits.scala | 68 ++++----- .../dotty/tools/dotc/typer/Inferencing.scala | 10 +- .../src/dotty/tools/dotc/typer/Inliner.scala | 6 +- .../src/dotty/tools/dotc/typer/Namer.scala | 18 +-- .../dotty/tools/dotc/typer/RefChecks.scala | 18 +-- .../src/dotty/tools/dotc/typer/Typer.scala | 68 ++++----- .../dotty/tools/dotc/util/Signatures.scala | 8 +- .../tools/dotc/util/SourcePosition.scala | 2 +- .../src/dotty/tools/repl/ReplCompiler.scala | 2 +- .../tools/dottydoc/core/DocASTPhase.scala | 2 +- 49 files changed, 415 insertions(+), 414 deletions(-) diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index ea248e766534..df01cfc6ddc5 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -484,7 +484,7 @@ class JSCodeGen()(implicit ctx: Context) { * Other (normal) methods are emitted with `genMethodBody()`. */ private def genMethodWithCurrentLocalNameScope(dd: DefDef): Option[js.MethodDef] = { - implicit val pos = dd.pos + implicit val pos = dd.span val sym = dd.symbol val vparamss = dd.vparamss val rhs = dd.rhs @@ -579,7 +579,7 @@ class JSCodeGen()(implicit ctx: Context) { private def genMethodDef(static: Boolean, methodName: js.PropertyName, paramsSyms: List[Symbol], resultIRType: jstpe.Type, tree: Tree, optimizerHints: OptimizerHints): js.MethodDef = { - implicit val pos = tree.pos + implicit val pos = tree.span ctx.debuglog("genMethod " + methodName.encodedName) ctx.debuglog("") @@ -598,7 +598,7 @@ class JSCodeGen()(implicit ctx: Context) { js.MethodDef(static, methodName, jsParams, resultIRType, Some(genBody()))( optimizerHints, None) /*} else { - assert(!static, tree.pos) + assert(!static, tree.span) withScopedVars( thisLocalVarIdent := Some(freshLocalIdent("this")) @@ -639,7 +639,7 @@ class JSCodeGen()(implicit ctx: Context) { private def genExpr(tree: Tree): js.Tree = { val result = genStatOrExpr(tree, isStat = false) assert(result.tpe != jstpe.NoType, - s"genExpr($tree) returned a tree with type NoType at pos ${tree.pos}") + s"genExpr($tree) returned a tree with type NoType at pos ${tree.span}") result } @@ -649,7 +649,7 @@ class JSCodeGen()(implicit ctx: Context) { * is transformed into an equivalent portion of the JS AST. */ private def genStatOrExpr(tree: Tree, isStat: Boolean): js.Tree = { - implicit val pos = tree.pos + implicit val pos = tree.span ctx.debuglog(" " + tree) ctx.debuglog("") @@ -660,7 +660,7 @@ class JSCodeGen()(implicit ctx: Context) { /* Must have been eliminated by the tail call transform performed * by genMethodBody(). */ assert(name != nme.THIS, - s"ValDef(_, nme.THIS, _, _) found at ${tree.pos}") + s"ValDef(_, nme.THIS, _, _) found at ${tree.span}") val sym = tree.symbol val rhs = tree.rhs @@ -719,7 +719,7 @@ class JSCodeGen()(implicit ctx: Context) { "Trying to access the this of another class: " + "tree.symbol = " + tree.symbol + ", class symbol = " + currentClassSym.get + - " pos:" + pos) + " span:" + pos) genLoadModule(tree.symbol) } @@ -856,7 +856,7 @@ class JSCodeGen()(implicit ctx: Context) { case _ => throw new FatalError("Unexpected tree in genExpr: " + - tree + "/" + tree.getClass + " at: " + (tree.pos: Position)) + tree + "/" + tree.getClass + " at: " + (tree.span: Position)) } } // end of genStatOrExpr() @@ -897,7 +897,7 @@ class JSCodeGen()(implicit ctx: Context) { * primitives, JS calls, etc. They are further dispatched in here. */ private def genApply(tree: Apply, isStat: Boolean): js.Tree = { - implicit val pos = tree.pos + implicit val pos = tree.span val args = tree.args val sym = tree.fun.symbol @@ -944,7 +944,7 @@ class JSCodeGen()(implicit ctx: Context) { * irrelevant. */ private def genSuperCall(tree: Apply, isStat: Boolean): js.Tree = { - implicit val pos = tree.pos + implicit val pos = tree.span val Apply(fun @ Select(sup @ Super(_, mix), _), args) = tree val sym = fun.symbol @@ -955,7 +955,7 @@ class JSCodeGen()(implicit ctx: Context) { genJSSuperCall(tree, isStat) } else*/ { val superCall = genApplyMethodStatically( - genThis()(sup.pos), sym, genActualArgs(sym, args)) + genThis()(sup.span), sym, genActualArgs(sym, args)) // Initialize the module instance just after the super constructor call. if (isStaticModule(currentClassSym) && !isModuleInitialized && @@ -980,7 +980,7 @@ class JSCodeGen()(implicit ctx: Context) { * * regular new */ private def genApplyNew(tree: Apply): js.Tree = { - implicit val pos = tree.pos + implicit val pos = tree.span val Apply(fun @ Select(New(tpt), nme.CONSTRUCTOR), args) = tree val ctor = fun.symbol @@ -1038,7 +1038,7 @@ class JSCodeGen()(implicit ctx: Context) { private def genPrimitiveOp(tree: Apply, isStat: Boolean): js.Tree = { import scala.tools.nsc.backend.ScalaPrimitivesOps._ - implicit val pos = tree.pos + implicit val pos = tree.span val Apply(fun, args) = tree val receiver = qualifierOf(fun) @@ -1078,7 +1078,7 @@ class JSCodeGen()(implicit ctx: Context) { private def genSimpleUnaryOp(tree: Apply, arg: Tree, code: Int): js.Tree = { import scala.tools.nsc.backend.ScalaPrimitivesOps._ - implicit val pos = tree.pos + implicit val pos = tree.span val resultIRType = toIRType(tree.tpe) val genArg = adaptPrimitive(genExpr(arg), resultIRType) @@ -1120,7 +1120,7 @@ class JSCodeGen()(implicit ctx: Context) { import scala.tools.nsc.backend.ScalaPrimitivesOps._ import js.UnaryOp._ - implicit val pos = tree.pos + implicit val pos = tree.span val lhsIRType = toIRType(lhs.tpe) val rhsIRType = toIRType(rhs.tpe) @@ -1423,7 +1423,7 @@ class JSCodeGen()(implicit ctx: Context) { */ private def genStringConcat(tree: Apply, receiver: Tree, args: List[Tree]): js.Tree = { - implicit val pos = tree.pos + implicit val pos = tree.span val arg = args.head @@ -1450,7 +1450,7 @@ class JSCodeGen()(implicit ctx: Context) { /** Gen JS code for a call to Any.## */ private def genScalaHash(tree: Apply, receiver: Tree): js.Tree = { - implicit val pos = tree.pos + implicit val pos = tree.span genModuleApplyMethod(defn.ScalaRuntimeModule.requiredMethod(nme.hash_), List(genExpr(receiver))) @@ -1460,7 +1460,7 @@ class JSCodeGen()(implicit ctx: Context) { private def genArrayOp(tree: Tree, code: Int): js.Tree = { import scala.tools.nsc.backend.ScalaPrimitivesOps._ - implicit val pos = tree.pos + implicit val pos = tree.span val Apply(fun, args) = tree val arrayObj = qualifierOf(fun) @@ -1512,7 +1512,7 @@ class JSCodeGen()(implicit ctx: Context) { // common case for which there is no side-effect nor NPE genArg case _ => - implicit val pos = tree.pos + implicit val pos = tree.span /* TODO Check for a null receiver? * In theory, it's UB, but that decision should be left for link time. */ @@ -1522,7 +1522,7 @@ class JSCodeGen()(implicit ctx: Context) { /** Gen JS code for a coercion */ private def genCoercion(tree: Apply, receiver: Tree, code: Int): js.Tree = { - implicit val pos = tree.pos + implicit val pos = tree.span val source = genExpr(receiver) val resultType = toIRType(tree.tpe) @@ -1531,7 +1531,7 @@ class JSCodeGen()(implicit ctx: Context) { /** Gen a call to the special `throw` method. */ private def genThrow(tree: Apply, args: List[Tree]): js.Tree = { - implicit val pos = tree.pos + implicit val pos = tree.span val exception = args.head val genException = genExpr(exception) js.Throw { @@ -1555,7 +1555,7 @@ class JSCodeGen()(implicit ctx: Context) { * * Regular method call */ private def genNormalApply(tree: Apply, isStat: Boolean): js.Tree = { - implicit val pos = tree.pos + implicit val pos = tree.span val fun = tree.fun match { case fun: Ident => desugarIdent(fun).get @@ -1601,7 +1601,7 @@ class JSCodeGen()(implicit ctx: Context) { jsSuperClassValue: Option[js.Tree] = None)( implicit pos: Position): js.Tree = { - implicit val pos = tree.pos + implicit val pos = tree.span def noSpread = !args.exists(_.isInstanceOf[js.JSSpread]) val argc = args.size // meaningful only for methods that don't have varargs @@ -1759,7 +1759,7 @@ class JSCodeGen()(implicit ctx: Context) { * primitive instead.) */ private def genTypeApply(tree: TypeApply): js.Tree = { - implicit val pos = tree.pos + implicit val pos = tree.span val TypeApply(fun, targs) = tree @@ -1787,7 +1787,7 @@ class JSCodeGen()(implicit ctx: Context) { /** Gen JS code for a Java Seq literal. */ private def genJavaSeqLiteral(tree: JavaSeqLiteral): js.Tree = { - implicit val pos = tree.pos + implicit val pos = tree.span val genElems = tree.elems.map(genExpr) val arrayTypeRef = toTypeRef(tree.tpe).asInstanceOf[jstpe.ArrayTypeRef] @@ -1836,7 +1836,7 @@ class JSCodeGen()(implicit ctx: Context) { * available in the `body`. */ private def genClosure(tree: Closure): js.Tree = { - implicit val pos = tree.pos + implicit val pos = tree.span val Closure(env, call, functionalInterface) = tree val envSize = env.size @@ -1852,7 +1852,7 @@ class JSCodeGen()(implicit ctx: Context) { val allCaptureValues = qualifier :: env val formalAndActualCaptures = allCaptureValues.map { value => - implicit val pos = value.pos + implicit val pos = value.span val formalIdent = value match { case Ident(name) => freshLocalIdent(name.toString) case This(_) => freshLocalIdent("this") @@ -1975,7 +1975,7 @@ class JSCodeGen()(implicit ctx: Context) { /** Gen JS code for an isInstanceOf test (for reference types only) */ private def genIsInstanceOf(tree: Tree, value: js.Tree, to: Type): js.Tree = { - implicit val pos = tree.pos + implicit val pos = tree.span val sym = to.widenDealias.typeSymbol if (sym == defn.ObjectClass) { @@ -2193,7 +2193,7 @@ class JSCodeGen()(implicit ctx: Context) { * to perform the conversion to js.Array, then wrap in a Spread * operator. */ - implicit val pos = arg.pos + implicit val pos = arg.span val jsArrayArg = genModuleApplyMethod( jsdefn.Runtime_toJSVarArgs, List(genExpr(arg))) @@ -2210,7 +2210,7 @@ class JSCodeGen()(implicit ctx: Context) { */ private def tryGenRepeatedParamAsJSArray(arg: Tree, handleNil: Boolean): Option[List[js.Tree]] = { - implicit val pos = arg.pos + implicit val pos = arg.span // Given a method `def foo(args: T*)` arg match { diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index c0a0ae7646e4..0227bf3faef5 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -351,10 +351,10 @@ object desugar { val constrVparamss = if (originalVparamss.isEmpty) { // ensure parameter list is non-empty if (isCaseClass && originalTparams.isEmpty) - ctx.error(CaseClassMissingParamList(cdef), cdef.sourcePos.withSpan(cdef.namePos)) + ctx.error(CaseClassMissingParamList(cdef), cdef.sourcePos.withSpan(cdef.nameSpan)) ListOfNil } else if (isCaseClass && originalVparamss.head.exists(_.mods.is(Implicit))) { - ctx.error("Case classes should have a non-implicit parameter list", cdef.sourcePos.withSpan(cdef.namePos)) + ctx.error("Case classes should have a non-implicit parameter list", cdef.sourcePos.withSpan(cdef.nameSpan)) ListOfNil } else originalVparamss.nestedMap(toDefParam) @@ -398,7 +398,7 @@ object desugar { def appliedTypeTree(tycon: Tree, args: List[Tree]) = (if (args.isEmpty) tycon else AppliedTypeTree(tycon, args)) - .withSpan(cdef.pos.startPos) + .withSpan(cdef.span.startPos) def isHK(tparam: Tree): Boolean = tparam match { case TypeDef(_, LambdaTypeTree(tparams, body)) => true @@ -704,19 +704,19 @@ object desugar { if (mods is Package) PackageDef(Ident(moduleName), cpy.ModuleDef(mdef)(nme.PACKAGE, impl).withMods(mods &~ Package) :: Nil) else if (isEnumCase) - expandEnumModule(moduleName, impl, mods, mdef.pos) + expandEnumModule(moduleName, impl, mods, mdef.span) else { val clsName = moduleName.moduleClassName val clsRef = Ident(clsName) val modul = ValDef(moduleName, clsRef, New(clsRef, Nil)) .withMods(mods.toTermFlags & RetainedModuleValFlags | ModuleValCreationFlags) - .withSpan(mdef.pos.startPos) + .withSpan(mdef.span.startPos) val ValDef(selfName, selfTpt, _) = impl.self val selfMods = impl.self.mods if (!selfTpt.isEmpty) ctx.error(ObjectMayNotHaveSelfType(mdef), impl.self.sourcePos) val clsSelf = ValDef(selfName, SingletonTypeTree(Ident(moduleName)), impl.self.rhs) .withMods(selfMods) - .withSpan(impl.self.pos.orElse(impl.pos.startPos)) + .withSpan(impl.self.span.orElse(impl.span.startPos)) val clsTmpl = cpy.Template(impl)(self = clsSelf, body = impl.body) val cls = TypeDef(clsName, clsTmpl) .withMods(mods.toTypeFlags & RetainedModuleClassFlags | ModuleClassCreationFlags) @@ -793,7 +793,7 @@ object desugar { pats map { case id: Ident => expandSimpleEnumCase(id.name.asTermName, mods, - Span(pdef.pos.start, id.pos.end, id.pos.start)) + Span(pdef.span.start, id.span.end, id.span.start)) } else { val pats1 = if (tpt.isEmpty) pats else pats map (Typed(_, tpt)) @@ -842,7 +842,7 @@ object desugar { mods & Lazy | Synthetic | (if (ctx.owner.isClass) PrivateLocal else EmptyFlags) val firstDef = ValDef(tmpName, TypeTree(), matchExpr) - .withSpan(pat.pos.union(rhs.pos)).withMods(patMods) + .withSpan(pat.span.union(rhs.span)).withMods(patMods) def selector(n: Int) = Select(Ident(tmpName), nme.selectorName(n)) val restDefs = for (((named, tpt), n) <- vars.zipWithIndex) @@ -879,7 +879,7 @@ object desugar { def block(tree: Block)(implicit ctx: Context): Block = tree.expr match { case EmptyTree => cpy.Block(tree)(tree.stats, - unitLiteral.withSpan(if (tree.stats.isEmpty) tree.pos else tree.pos.endPos)) + unitLiteral.withSpan(if (tree.stats.isEmpty) tree.span else tree.span.endPos)) case _ => tree } @@ -904,9 +904,9 @@ object desugar { } if (isLeftAssoc(op.name)) - makeOp(left, right, Span(left.pos.start, op.pos.end, op.pos.start)) + makeOp(left, right, Span(left.span.start, op.span.end, op.span.start)) else - makeOp(right, left, Span(op.pos.start, right.pos.end)) + makeOp(right, left, Span(op.span.start, right.span.end)) } /** Translate tuple expressions of arity <= 22 @@ -1021,7 +1021,7 @@ object desugar { private def derivedValDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit ctx: Context) = { val vdef = ValDef(named.name.asTermName, tpt, rhs) .withMods(mods) - .withSpan(original.pos.withPoint(named.pos.start)) + .withSpan(original.span.withPoint(named.span.start)) val mayNeedSetter = valDef(vdef) mayNeedSetter } @@ -1029,7 +1029,7 @@ object desugar { private def derivedDefDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit src: SourceInfo) = DefDef(named.name.asTermName, Nil, Nil, tpt, rhs) .withMods(mods) - .withSpan(original.pos.withPoint(named.pos.start)) + .withSpan(original.span.withPoint(named.span.start)) /** Main desugaring method */ def apply(tree: Tree)(implicit ctx: Context): Tree = { diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index 9d18febd3c77..fbde1ecf6f83 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -44,7 +44,7 @@ object DesugarEnums { * It is an error if a type parameter is non-variant, or if its approximation * refers to pther type parameters. */ - def interpolatedEnumParent(pos: Span)(implicit ctx: Context): Tree = { + def interpolatedEnumParent(span: Span)(implicit ctx: Context): Tree = { val tparams = enumClass.typeParams def isGround(tp: Type) = tp.subst(tparams, tparams.map(_ => NoType)) eq tp val targs = tparams map { tparam => @@ -57,10 +57,10 @@ object DesugarEnums { if (tparam.variance == 0) "is non variant" else "has bounds that depend on a type parameter in the same parameter list" errorType(i"""cannot determine type argument for enum parent $enumClass, - |type parameter $tparam $problem""", ctx.source.atSpan(pos)) + |type parameter $tparam $problem""", ctx.source.atSpan(span)) } } - TypeTree(enumClass.typeRef.appliedTo(targs)).withSpan(pos) + TypeTree(enumClass.typeRef.appliedTo(targs)).withSpan(span) } /** A type tree referring to `enumClass` */ @@ -195,11 +195,11 @@ object DesugarEnums { } /** Expand a module definition representing a parameterless enum case */ - def expandEnumModule(name: TermName, impl: Template, mods: Modifiers, pos: Span)(implicit ctx: Context): Tree = { + def expandEnumModule(name: TermName, impl: Template, mods: Modifiers, span: Span)(implicit ctx: Context): Tree = { assert(impl.body.isEmpty) if (!enumClass.exists) EmptyTree else if (impl.parents.isEmpty) - expandSimpleEnumCase(name, mods, pos) + expandSimpleEnumCase(name, mods, span) else { def toStringMeth = DefDef(nme.toString_, Nil, Nil, TypeTree(defn.StringType), Literal(Constant(name.toString))) @@ -207,22 +207,22 @@ object DesugarEnums { val (tagMeth, scaffolding) = enumTagMeth(CaseKind.Object) val impl1 = cpy.Template(impl)(body = List(tagMeth, toStringMeth) ++ registerCall) val vdef = ValDef(name, TypeTree(), New(impl1)).withMods(mods | Final) - flatTree(scaffolding ::: vdef :: Nil).withSpan(pos) + flatTree(scaffolding ::: vdef :: Nil).withSpan(span) } } /** Expand a simple enum case */ - def expandSimpleEnumCase(name: TermName, mods: Modifiers, pos: Span)(implicit ctx: Context): Tree = + def expandSimpleEnumCase(name: TermName, mods: Modifiers, span: Span)(implicit ctx: Context): Tree = if (!enumClass.exists) EmptyTree else if (enumClass.typeParams.nonEmpty) { - val parent = interpolatedEnumParent(pos) + val parent = interpolatedEnumParent(span) val impl = Template(emptyConstructor, parent :: Nil, EmptyValDef, Nil) - expandEnumModule(name, impl, mods, pos) + expandEnumModule(name, impl, mods, span) } else { val (tag, scaffolding) = nextEnumTag(CaseKind.Simple) val creator = Apply(Ident(nme.DOLLAR_NEW), List(Literal(Constant(tag)), Literal(Constant(name.toString)))) val vdef = ValDef(name, enumClassRef, creator).withMods(mods | Final) - flatTree(scaffolding ::: vdef :: Nil).withSpan(pos) + flatTree(scaffolding ::: vdef :: Nil).withSpan(span) } } diff --git a/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala b/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala index 62845801772a..9fa11c8bf80d 100644 --- a/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala +++ b/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala @@ -7,6 +7,7 @@ import util.Spans._ import Trees.{MemberDef, DefTree, WithLazyField} /** Utility functions to go from typed to untyped ASTs */ +// TODO: Handle trees with mixed source files object NavigateAST { /** The untyped tree corresponding to typed tree `tree` in the compilation @@ -19,9 +20,9 @@ object NavigateAST { case _ => val loosePath = untypedPath(tree, exactMatch = false) throw new - Error(i"""no untyped tree for $tree, pos = ${tree.pos} + Error(i"""no untyped tree for $tree, pos = ${tree.sourcePos} |best matching path =\n$loosePath%\n====\n% - |path positions = ${loosePath.map(_.pos)}""") + |path positions = ${loosePath.map(_.sourcePos)}""") } /** The reverse path of untyped trees starting with a tree that closest matches @@ -39,35 +40,35 @@ object NavigateAST { def untypedPath(tree: tpd.Tree, exactMatch: Boolean = false)(implicit ctx: Context): List[Positioned] = tree match { case tree: MemberDef[_] => - untypedPath(tree.pos) match { + untypedPath(tree.span) match { case path @ (last: DefTree[_]) :: _ => path case path if !exactMatch => path case _ => Nil } case _ => - untypedPath(tree.pos) match { - case (path @ last :: _) if last.pos == tree.pos || !exactMatch => path + untypedPath(tree.span) match { + case (path @ last :: _) if last.span == tree.span || !exactMatch => path case _ => Nil } } /** The reverse part of the untyped root of the compilation unit of `ctx` to - * position `pos`. + * the given `span`. */ - def untypedPath(pos: Span)(implicit ctx: Context): List[Positioned] = - pathTo(pos, ctx.compilationUnit.untpdTree) + def untypedPath(span: Span)(implicit ctx: Context): List[Positioned] = + pathTo(span, ctx.compilationUnit.untpdTree) - /** The reverse path from node `from` to the node that closest encloses position `pos`, + /** The reverse path from node `from` to the node that closest encloses `span`, * or `Nil` if no such path exists. If a non-empty path is returned it starts with - * the node closest enclosing `pos` and ends with `from`. + * the node closest enclosing `span` and ends with `from`. * * @param skipZeroExtent If true, skip over zero-extent nodes in the search. These nodes * do not correspond to code the user wrote since their start and * end point are the same, so this is useful when trying to reconcile * nodes with source code. */ - def pathTo(pos: Span, from: Positioned, skipZeroExtent: Boolean = false)(implicit ctx: Context): List[Positioned] = { + def pathTo(span: Span, from: Positioned, skipZeroExtent: Boolean = false)(implicit ctx: Context): List[Positioned] = { def childPath(it: Iterator[Any], path: List[Positioned]): List[Positioned] = { while (it.hasNext) { val path1 = it.next() match { @@ -81,7 +82,7 @@ object NavigateAST { path } def singlePath(p: Positioned, path: List[Positioned]): List[Positioned] = - if (p.pos.exists && !(skipZeroExtent && p.pos.isZeroExtent) && p.pos.contains(pos)) { + if (p.span.exists && !(skipZeroExtent && p.span.isZeroExtent) && p.span.contains(span)) { // FIXME: We shouldn't be manually forcing trees here, we should replace // our usage of `productIterator` by something in `Positioned` that takes // care of low-level details like this for us. diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index 1ae023799469..005f42200858 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -20,17 +20,17 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod * component of the position. */ private var myUniqueId: Int = _ - private[this] var curPos: Span = _ + private[this] var mySpan: Span = _ - /** The item's position */ - def pos: Span = curPos + /** The span part of the item's position */ + def span: Span = mySpan /** item's id */ def uniqueId: Int = myUniqueId protected def srcfile: AbstractFile = TreeIds.fileOfId(uniqueId) def source(implicit ctx: Context): SourceFile = ctx.getSource(srcfile) - def sourcePos(implicit ctx: Context): SourcePosition = source.atSpan(pos) + def sourcePos(implicit ctx: Context): SourcePosition = source.atSpan(span) setId(TreeIds.nextIdFor(initialFile(src))) setPos(initialSpan(), srcfile) @@ -40,77 +40,76 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod //assert(id != 2067, getClass) } - /** Destructively update `curPos` to given position. Also, set any missing - * positions in children. + /** Destructively update `mySpan` to given span. Also, set any missing + * spans in children. */ - protected def setPos(pos: Span, file: AbstractFile): Unit = { - setPosUnchecked(pos, file) - if (pos.exists) setChildPositions(pos.toSynthetic, file) + protected def setPos(span: Span, file: AbstractFile): Unit = { + setOneSpan(span, file) + if (span.exists) setChildSpans(span.toSynthetic, file) } - /** A positioned item like this one with the position set to `pos`. - * if the positioned item is source-derived, a clone is returned. + /** A positioned item like this one with given `span`. + * If the positioned item is source-derived, a clone is returned. * If the positioned item is synthetic, the position is updated * destructively and the item itself is returned. */ - def withSpan(pos: Span): this.type = { - val ownPos = this.pos + def withSpan(span: Span): this.type = { + val ownSpan = this.span val newpd: this.type = - if (pos == ownPos || ownPos.isSynthetic) this else cloneIn(srcfile) - newpd.setPos(pos, srcfile) + if (span == ownSpan || ownSpan.isSynthetic) this else cloneIn(srcfile) + newpd.setPos(span, srcfile) newpd } def withPosOf(posd: Positioned): this.type = { - val ownPos = this.pos + val ownSpan = this.span val newpd: this.type = - if (posd.srcfile == srcfile && posd.pos == ownPos || ownPos.isSynthetic) this + if (posd.srcfile == srcfile && posd.span == ownSpan || ownSpan.isSynthetic) this else cloneIn(posd.srcfile) - newpd.setPos(posd.pos, posd.srcfile) + newpd.setPos(posd.span, posd.srcfile) newpd } def withSourcePos(sourcePos: SourcePosition): this.type = { - val ownPos = this.pos + val ownSpan = this.span val newpd: this.type = - if (sourcePos.source.file == srcfile && sourcePos.span == ownPos || ownPos.isSynthetic) this + if (sourcePos.source.file == srcfile && sourcePos.span == ownSpan || ownSpan.isSynthetic) this else cloneIn(sourcePos.source.file) newpd.setPos(sourcePos.span, sourcePos.source.file) newpd } - /** Set position of this tree only, without performing - * any checks of consistency with - or updates of - other positions. + /** Set span of this tree only, without updating children spans. * Called from Unpickler when entering positions. */ - private[dotc] def setPosUnchecked(pos: Span, file: AbstractFile = this.srcfile): Unit = { + private[dotc] def setOneSpan(span: Span, file: AbstractFile = this.srcfile): Unit = { if (file != this.srcfile) setId(TreeIds.nextIdFor(file)) - curPos = pos + mySpan = span } - /** If any children of this node do not have positions, - * fit their positions between the positions of the known subtrees + /** If any children of this node do not have spans, + * fit their spans between the spans of the known subtrees * and transitively visit their children. * The method is likely time-critical because it is invoked on any node * we create, so we want to avoid object allocations in the common case. * The method is naturally expressed as two mutually (tail-)recursive * functions, one which computes the next element to consider or terminates if there - * is none and the other which propagates the position information to that element. + * is none and the other which propagates the span information to that element. * But since mutual tail recursion is not supported in Scala, we express it instead * as a while loop with a termination by return in the middle. */ - private def setChildPositions(pos: Span, file: AbstractFile): Unit = { + private def setChildSpans(span: Span, file: AbstractFile): Unit = { var n = productArity // subnodes are analyzed right to left var elems: List[Any] = Nil // children in lists still to be considered, from right to left - var end = pos.end // the last defined offset, fill in positions up to this offset - var outstanding: List[Positioned] = Nil // nodes that need their positions filled once a start position + var end = span.end // the last defined offset, fill in spans up to this offset + var outstanding: List[Positioned] = Nil // nodes that need their spans filled once a start offset // is known, from left to right. def fillIn(ps: List[Positioned], start: Int, end: Int): Unit = ps match { case p :: ps1 => - // If a tree has no position or a zero-extent position, it should be + // If a tree has no span or a zero-extent span, it should be // synthetic. We can preserve this invariant by always setting a - // zero-extent position for these trees here. - if (!p.pos.exists || p.pos.isZeroExtent) { + // zero-extent span for these trees here. + if (!p.span.exists || p.span.isZeroExtent) { p.setPos(Span(start, start), file) fillIn(ps1, start, end) } else { @@ -130,15 +129,15 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod nextChild = productElement(n) } else { - fillIn(outstanding, pos.start, end) + fillIn(outstanding, span.start, end) return } nextChild match { case p: Positioned => - if (p.pos.exists) { - fillIn(outstanding, p.pos.end, end) + if (p.span.exists) { + fillIn(outstanding, p.span.end, end) outstanding = Nil - end = p.pos.start + end = p.span.start } else outstanding = p :: outstanding case m: untpd.Modifiers => @@ -150,15 +149,17 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod } } + /** Clone this node but assign it a fresh id which marks it as a node in `file`. */ protected def cloneIn(file: AbstractFile): this.type = { val newpd: this.type = clone.asInstanceOf[this.type] newpd.setId(TreeIds.nextIdFor(file)) newpd } + /** The source of the first element of this node that has a position */ def elemsFile: AbstractFile = { def firstFile(x: Any): AbstractFile = x match { - case x: Positioned if x.pos.exists => + case x: Positioned if x.span.exists => x.srcfile case x1 :: xs1 => val f = firstFile(x1) @@ -175,12 +176,16 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod firstElemFile(0) } + /** The source file to use for the `id` of this node. This is + * `elemsFile` if it exists, or the source file indicated by + * `src` otherwise + */ private def initialFile(src: SourceInfo): AbstractFile = { val f = elemsFile if (f != null) f else src.srcfile } - /** The initial, synthetic span. This is usually the union of all positioned children's positions. + /** The initial, synthetic span. This is usually the union of all positioned children's spans. * @param ignoreTypeTrees If true, TypeTree children are not counted for the span. * This is important for predicting whether a position entry is * needed for pickling, since TypeTrees are pickled as types, so @@ -190,28 +195,28 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod def include(p1: Span, p2: Positioned) = p2 match { case _: Trees.TypeTree[_] if ignoreTypeTrees => p1 - case _ => p1.union(p2.pos) + case _ => p1.union(p2.span) } - def includeAll(pos: Span, xs: List[_]): Span = xs match { - case (p: Positioned) :: xs1 if sameSource(p) => includeAll(include(pos, p), xs1) - case (xs0: List[_]) :: xs1 => includeAll(includeAll(pos, xs0), xs1) - case _ :: xs1 => includeAll(pos, xs1) - case _ => pos + def includeAll(span: Span, xs: List[_]): Span = xs match { + case (p: Positioned) :: xs1 if sameSource(p) => includeAll(include(span, p), xs1) + case (xs0: List[_]) :: xs1 => includeAll(includeAll(span, xs0), xs1) + case _ :: xs1 => includeAll(span, xs1) + case _ => span } var n = productArity - var pos = NoSpan + var span = NoSpan while (n > 0) { n -= 1 productElement(n) match { - case p: Positioned if sameSource(p) => pos = include(pos, p) - case m: untpd.Modifiers => pos = includeAll(includeAll(pos, m.mods), m.annotations) - case xs: List[_] => pos = includeAll(pos, xs) + case p: Positioned if sameSource(p) => span = include(span, p) + case m: untpd.Modifiers => span = includeAll(includeAll(span, m.mods), m.annotations) + case xs: List[_] => span = includeAll(span, xs) case _ => } } - pos.toSynthetic + span.toSynthetic } private def sameSource(that: Positioned) = srcfile == that.srcfile @@ -228,7 +233,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod false } (this eq that) || - (this.pos contains that.pos) && { + (this.span contains that.span) && { var n = productArity var found = false while (!found && n > 0) { @@ -240,24 +245,24 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod } /** Check that all positioned items in this tree satisfy the following conditions: - * - Parent positions contain child positions + * - Parent spans contain child spans * - If item is a non-empty tree, it has a position */ def checkPos(nonOverlapping: Boolean)(implicit ctx: Context): Unit = try { import untpd._ var lastPositioned: Positioned = null - var lastPos = NoSpan + var lastSpan = NoSpan def check(p: Any): Unit = p match { case p: Positioned => - assert(pos contains p.pos, - s"""position error, parent position does not contain child position - |parent = $this, - |parent position = $pos, - |child = $p, - |child position = ${p.pos}""".stripMargin) + assert(span contains p.span, + s"""position error, parent span does not contain child span + |parent = $this, + |parent span = $span, + |child = $p, + |child span = ${p.span}""".stripMargin) p match { case tree: Tree if !tree.isEmpty => - assert(tree.pos.exists, + assert(tree.span.exists, s"position error: position not set for $tree # ${tree.uniqueId}") case _ => } @@ -269,16 +274,16 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod if lastPositioned.isInstanceOf[ValDef] && !p.isInstanceOf[ValDef] => // ignore transition from last wildcard parameter to body case _ => - assert(!lastPos.exists || !p.pos.exists || lastPos.end <= p.pos.start, + assert(!lastSpan.exists || !p.span.exists || lastSpan.end <= p.span.start, s"""position error, child positions overlap or in wrong order - |parent = $this - |1st child = $lastPositioned - |1st child position = $lastPos - |2nd child = $p - |2nd child position = ${p.pos}""".stripMargin) + |parent = $this + |1st child = $lastPositioned + |1st child span = $lastSpan + |2nd child = $p + |2nd child span = ${p.span}""".stripMargin) } lastPositioned = p - lastPos = p.pos + lastSpan = p.span } p.checkPos(nonOverlapping) case m: untpd.Modifiers => diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 903c7aa9897b..86f6714b76a1 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -553,7 +553,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => * apply of a function class? */ def isSyntheticApply(tree: Tree): Boolean = tree match { - case Select(qual, nme.apply) => tree.pos.end == qual.pos.end + case Select(qual, nme.apply) => tree.span.end == qual.span.end case _ => false } @@ -667,7 +667,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => require(sym.pos.exists) object accum extends TreeAccumulator[List[Tree]] { def apply(x: List[Tree], tree: Tree)(implicit ctx: Context): List[Tree] = { - if (tree.pos.contains(sym.pos)) + if (tree.span.contains(sym.pos)) if (definedSym(tree) == sym) tree :: x else { val x1 = foldOver(x, tree) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 9295530ee62b..230030ea27f9 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -60,6 +60,11 @@ object Trees { if (Stats.enabled) ntrees += 1 + /** This tree, widened to `Positioned`. Used to make clear we only need the + * position, typically for error reporting. + */ + final def posd: Positioned = this + /** The type constructor at the root of the tree */ type ThisTree[T >: Untyped] <: Tree[T] @@ -341,13 +346,13 @@ object Trees { * 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 NoSpan. */ - def namePos: Span = - if (pos.exists) { - val point = pos.point + def nameSpan: Span = + if (span.exists) { + val point = span.point if (rawMods.is(Synthetic) || name.toTermName == nme.ERROR) Span(point) else Span(point, point + name.stripModuleClassSuffix.lastPart.length, point) } - else pos + else span } /** A ValDef or DefDef tree */ @@ -598,7 +603,7 @@ object Trees { case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T])(implicit @transientParam src: SourceInfo) extends Tree[T] { type ThisTree[-T >: Untyped] = Inlined[T] - override def initialSpan(ignoreTypeTrees: Boolean): Span = call.pos + override def initialSpan(ignoreTypeTrees: Boolean): Span = call.span } /** A type tree that represents an existing or inferred type */ @@ -771,8 +776,8 @@ object Trees { trait WithoutTypeOrPos[-T >: Untyped] extends Tree[T] { override def withTypeUnchecked(tpe: Type): ThisTree[Type] = this.asInstanceOf[ThisTree[Type]] - override def pos: Span = NoSpan - override def setPos(pos: Span, file: AbstractFile): Unit = {} + override def span: Span = NoSpan + override def setPos(span: Span, file: AbstractFile): Unit = {} } /** Temporary class that results from translation of ModuleDefs @@ -799,10 +804,10 @@ object Trees { override def isEmpty: Boolean = trees.isEmpty override def toList: List[Tree[T]] = flatten(trees) override def toString: String = if (isEmpty) "EmptyTree" else "Thicket(" + trees.mkString(", ") + ")" - override def pos: Span = (NoSpan /: trees) ((pos, t) => pos union t.pos) + override def span: Span = (NoSpan /: trees) ((span, t) => span union t.span) - override def withSpan(pos: Span): this.type = - mapElems(_.withSpan(pos)).asInstanceOf[this.type] + override def withSpan(span: Span): this.type = + mapElems(_.withSpan(span)).asInstanceOf[this.type] override def withPosOf(posd: Positioned): this.type = mapElems(_.withPosOf(posd)).asInstanceOf[this.type] override def withSourcePos(sourcePos: SourcePosition): this.type = diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 1132151bceff..c6b62d4a073a 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -204,7 +204,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { ta.assignType(untpd.ValDef(sym.name, TypeTree(sym.info), rhs), sym) def SyntheticValDef(name: TermName, rhs: Tree)(implicit ctx: Context): ValDef = - ValDef(ctx.newSymbol(ctx.owner, name, Synthetic, rhs.tpe.widen, coord = rhs.pos), rhs) + ValDef(ctx.newSymbol(ctx.owner, name, Synthetic, rhs.tpe.widen, coord = rhs.span), rhs) def DefDef(sym: TermSymbol, tparams: List[TypeSymbol], vparamss: List[List[TermSymbol]], resultType: Type, rhs: Tree)(implicit ctx: Context): DefDef = @@ -401,16 +401,16 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { * kind for the given element type in `elemTpe`. No type arguments or * `length` arguments are given. */ - def newArray(elemTpe: Type, returnTpe: Type, pos: Span, dims: JavaSeqLiteral)(implicit ctx: Context): Tree = { + def newArray(elemTpe: Type, returnTpe: Type, span: Span, dims: JavaSeqLiteral)(implicit ctx: Context): Tree = { val elemClass = elemTpe.classSymbol def newArr = - ref(defn.DottyArraysModule).select(defn.newArrayMethod).withSpan(pos) + ref(defn.DottyArraysModule).select(defn.newArrayMethod).withSpan(span) if (!ctx.erasedTypes) { assert(!TypeErasure.isGeneric(elemTpe)) //needs to be done during typer. See Applications.convertNewGenericArray - newArr.appliedToTypeTrees(TypeTree(returnTpe) :: Nil).appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withSpan(pos) + newArr.appliedToTypeTrees(TypeTree(returnTpe) :: Nil).appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withSpan(span) } else // after erasure - newArr.appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withSpan(pos) + newArr.appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withSpan(span) } /** The wrapped array method name for an array of type elemtp */ @@ -1236,7 +1236,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { private def focusPositions(tree: Tree)(implicit ctx: Context): Tree = { val transformer = new tpd.TreeMap { override def transform(tree: Tree)(implicit ctx: Context): Tree = { - super.transform(tree).withSpan(tree.pos.focus) + super.transform(tree).withSpan(tree.span.focus) } } transformer.transform(tree) diff --git a/compiler/src/dotty/tools/dotc/core/Decorators.scala b/compiler/src/dotty/tools/dotc/core/Decorators.scala index 0ba45d11ce92..8d8bdffa7151 100644 --- a/compiler/src/dotty/tools/dotc/core/Decorators.scala +++ b/compiler/src/dotty/tools/dotc/core/Decorators.scala @@ -165,16 +165,6 @@ object Decorators { } } - implicit def sourcePos(pos: Span)(implicit ctx: Context): SourcePosition = { - def recur(inlinedCalls: List[Tree], pos: Span): SourcePosition = inlinedCalls match { - case inlinedCall :: rest => - sourceFile(inlinedCall).atSpan(pos).withOuter(recur(rest, inlinedCall.pos)) - case empty => - ctx.source.atSpan(pos) - } - recur(enclosingInlineds, pos) - } - implicit class genericDeco[T](val x: T) extends AnyVal { def reporting(op: T => String, printer: config.Printers.Printer = config.Printers.default): T = { printer.println(op(x)) diff --git a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala index 385ef8e7b55b..6f9db78cef17 100644 --- a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala +++ b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala @@ -80,7 +80,7 @@ object PickledQuotes { treePkl.compactify() pickler.addrOfTree = treePkl.buf.addrOfTree pickler.addrOfSym = treePkl.addrOfSym - if (tree.pos.exists) + if (tree.span.exists) new PositionPickler(pickler, treePkl.buf.addrOfTree).picklePositions(tree :: Nil) if (quotePickling ne noPrinter) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala index 4801e4ae2efd..8c8a75700e3b 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala @@ -28,17 +28,17 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad def picklePositions(roots: List[Tree])(implicit ctx: Context): Unit = { var lastIndex = 0 - var lastPos = Span(0, 0) - def pickleDeltas(index: Int, pos: Span) = { + var lastSpan = Span(0, 0) + def pickleDeltas(index: Int, span: Span) = { val addrDelta = index - lastIndex - val startDelta = pos.start - lastPos.start - val endDelta = pos.end - lastPos.end - buf.writeInt(header(addrDelta, startDelta != 0, endDelta != 0, !pos.isSynthetic)) + val startDelta = span.start - lastSpan.start + val endDelta = span.end - lastSpan.end + buf.writeInt(header(addrDelta, startDelta != 0, endDelta != 0, !span.isSynthetic)) if (startDelta != 0) buf.writeInt(startDelta) if (endDelta != 0) buf.writeInt(endDelta) - if (!pos.isSynthetic) buf.writeInt(pos.pointDelta) + if (!span.isSynthetic) buf.writeInt(span.pointDelta) lastIndex = index - lastPos = pos + lastSpan = span pickledIndices += index } @@ -69,12 +69,12 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad def traverse(x: Any, current: AbstractFile): Unit = x match { case x: untpd.Tree => var sourceFile = current - val pos = if (x.isInstanceOf[untpd.MemberDef]) x.pos else x.pos.toSynthetic + val span = if (x.isInstanceOf[untpd.MemberDef]) x.span else x.span.toSynthetic val sourceChange = x.source.file != x.elemsFile || x.elemsFile == null && x.source.file != current - if (pos.exists && ( - pos != x.initialSpan(ignoreTypeTrees = true).toSynthetic || + if (span.exists && ( + span != x.initialSpan(ignoreTypeTrees = true).toSynthetic || sourceChange || alwaysNeedsPos(x))) { addrOfTree(x) match { @@ -82,8 +82,8 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad // we currently do not share trees when unpickling, so if one path to a tree contains // a source change while another does not, we have to record the position of the tree twice // in order not to miss the source change. Test case is t3232a.scala. - //println(i"pickling $x with $pos at $addr") - pickleDeltas(addr.index, pos) + //println(i"pickling $x with $span at $addr") + pickleDeltas(addr.index, span) if (x.source.file != current) { pickleSource(x.source.file) sourceFile = x.source.file @@ -92,7 +92,7 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad //println(i"no address for $x") } } - //else if (x.pos.exists) println(i"skipping $x") + //else if (x.span.exists) println(i"skipping $x") x match { case x: untpd.MemberDef @unchecked => for (ann <- x.symbol.annotations) traverse(ann.tree, sourceFile) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index f103b8c67748..0a7952f656a4 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -1335,7 +1335,7 @@ class TreeUnpickler(reader: TastyReader, /** Set position of `tree` at given `addr`. */ def setPos[T <: untpd.Tree](addr: Addr, tree: T)(implicit ctx: Context): tree.type = { val pos = posAt(addr) - if (pos.exists) tree.setPosUnchecked(pos, ctx.source.file) + if (pos.exists) tree.setOneSpan(pos, ctx.source.file) tree } } diff --git a/compiler/src/dotty/tools/dotc/interactive/Completion.scala b/compiler/src/dotty/tools/dotc/interactive/Completion.scala index 576a3cf59d13..7f8c2fef4e95 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Completion.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Completion.scala @@ -62,7 +62,7 @@ object Completion { else Mode.None case Thicket(name :: _ :: Nil) :: (_: Import) :: _ => - if (name.pos.contains(pos.span)) Mode.Import + if (name.span.contains(pos.span)) Mode.Import else Mode.None // Can't help completing the renaming case Import(_, _) :: _ => @@ -83,13 +83,13 @@ object Completion { completionPrefix(name :: Nil, pos) case Import(expr, selectors) :: _ => - selectors.find(_.pos.contains(pos.span)).map { selector => + selectors.find(_.span.contains(pos.span)).map { selector => completionPrefix(selector.asInstanceOf[Tree] :: Nil, pos) }.getOrElse("") case (ref: RefTree) :: _ => if (ref.name == nme.ERROR) "" - else ref.name.toString.take(pos.span.point - ref.pos.point) + else ref.name.toString.take(pos.span.point - ref.span.point) case _ => "" @@ -99,7 +99,7 @@ object Completion { /** Inspect `path` to determine the offset where the completion result should be inserted. */ private def completionOffset(path: List[Tree]): Int = { path match { - case (ref: RefTree) :: _ => ref.pos.point + case (ref: RefTree) :: _ => ref.span.point case _ => 0 } } diff --git a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala index 0cb961820e80..6f9561f4d393 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala @@ -121,10 +121,10 @@ object Interactive { List(select.symbol) case (_: Thicket) :: (imp: Import) :: _ => - importedSymbols(imp, _.pos.contains(pos.span)) + importedSymbols(imp, _.span.contains(pos.span)) case (imp: Import) :: _ => - importedSymbols(imp, _.pos.contains(pos.span)) + importedSymbols(imp, _.span.contains(pos.span)) case _ => List(enclosingTree(path).symbol) @@ -186,8 +186,8 @@ object Interactive { if (tree.symbol.exists && !tree.symbol.is(Synthetic) && !tree.symbol.isPrimaryConstructor - && tree.pos.exists - && !tree.pos.isZeroExtent + && tree.span.exists + && !tree.span.isZeroExtent && (include.isReferences || isDefinition(tree)) && treePredicate(tree)) buf += SourceTree(tree, source) @@ -256,9 +256,9 @@ object Interactive { case None => Nil } - def pathTo(tree: Tree, pos: Span)(implicit ctx: Context): List[Tree] = - if (tree.pos.contains(pos)) - NavigateAST.pathTo(pos, tree, skipZeroExtent = true) + def pathTo(tree: Tree, span: Span)(implicit ctx: Context): List[Tree] = + if (tree.span.contains(span)) + NavigateAST.pathTo(span, tree, skipZeroExtent = true) .collect { case t: untpd.Tree => t } .dropWhile(!_.hasType).asInstanceOf[List[tpd.Tree]] else Nil diff --git a/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala b/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala index 99dd682d7ab8..6bd4b1d57fc1 100644 --- a/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala +++ b/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala @@ -17,14 +17,14 @@ import util._, util.Spans._ case class SourceTree(tree: tpd.Tree /** really: tpd.Import | tpd.NameTree */, source: SourceFile) { /** The position of `tree` */ - final def pos(implicit ctx: Context): SourcePosition = source.atSpan(tree.pos) + final def pos(implicit ctx: Context): SourcePosition = source.atSpan(tree.span) /** The position of the name in `tree` */ def namePos(implicit ctx: Context): SourcePosition = tree match { case tree: tpd.NameTree => // FIXME: Merge with NameTree#namePos ? - val treePos = tree.pos - if (treePos.isZeroExtent || tree.name.toTermName == nme.ERROR) + val treeSpan = tree.span + if (treeSpan.isZeroExtent || tree.name.toTermName == nme.ERROR) NoSourcePosition else { // Constructors are named `` in the trees, but `this` in the source. @@ -36,11 +36,11 @@ case class SourceTree(tree: tpd.Tree /** really: tpd.Import | tpd.NameTree */, s // FIXME: This is incorrect in some cases, like with backquoted identifiers, // see https://github.com/lampepfl/dotty/pull/1634#issuecomment-257079436 val (start, end) = - if (!treePos.isSynthetic) - (treePos.point, treePos.point + nameLength) + if (!treeSpan.isSynthetic) + (treeSpan.point, treeSpan.point + nameLength) else // If we don't have a point, we need to find it - (treePos.end - nameLength, treePos.end) + (treeSpan.end - nameLength, treeSpan.end) Span(start, end, start) } source.atSpan(position) diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala index 18b879c1ee48..4980cb43b191 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -77,9 +77,9 @@ object JavaParsers { syntaxError(in.offset, msg, skipIt) } - def syntaxError(pos: Int, msg: String, skipIt: Boolean): Unit = { - if (pos > lastErrorOffset) { - syntaxError(msg, pos) + def syntaxError(offset: Int, msg: String, skipIt: Boolean): Unit = { + if (offset > lastErrorOffset) { + syntaxError(msg, offset) // no more errors on this token. lastErrorOffset = in.offset } @@ -230,7 +230,7 @@ object JavaParsers { case AppliedTypeTree(_, _) | Select(_, _) => tree case _ => - syntaxError(IdentifierExpected(tree.show), tree.pos) + syntaxError(IdentifierExpected(tree.show), tree.span) errorTypeTree } } @@ -248,14 +248,14 @@ object JavaParsers { var t: RefTree = atPos(in.offset) { Ident(ident()) } while (in.token == DOT) { in.nextToken() - t = atPos(t.pos.start, in.offset) { Select(t, ident()) } + t = atPos(t.span.start, in.offset) { Select(t, ident()) } } t } def optArrayBrackets(tpt: Tree): Tree = if (in.token == LBRACKET) { - val tpt1 = atPos(tpt.pos.start, in.offset) { arrayOf(tpt) } + val tpt1 = atPos(tpt.span.start, in.offset) { arrayOf(tpt) } in.nextToken() accept(RBRACKET) optArrayBrackets(tpt1) @@ -289,7 +289,7 @@ object JavaParsers { } while (in.token == DOT) { in.nextToken() - t = typeArgs(atPos(t.pos.start, in.offset)(typeSelect(t, ident()))) + t = typeArgs(atPos(t.span.start, in.offset)(typeSelect(t, ident()))) } convertToTypeId(t) } else { @@ -323,7 +323,7 @@ object JavaParsers { val t1 = convertToTypeId(t) val args = repsep(() => typeArg(), COMMA) acceptClosingAngle() - atPos(t1.pos.start) { + atPos(t1.span.start) { AppliedTypeTree(t1, args) } } else t @@ -445,7 +445,7 @@ object JavaParsers { var t = typ() if (in.token == DOTDOTDOT) { in.nextToken() - t = atPos(t.pos.start) { + t = atPos(t.span.start) { PostfixOp(t, Ident(tpnme.raw.STAR)) } } @@ -596,8 +596,8 @@ object JavaParsers { } def makeCompanionObject(cdef: TypeDef, statics: List[Tree]): Tree = - atPos(cdef.pos) { - assert(cdef.pos.exists) + atPos(cdef.span) { + assert(cdef.span.exists) ModuleDef(cdef.name.toTermName, makeTemplate(List(), statics, List(), false)).withMods((cdef.mods & Flags.RetainedModuleClassFlags).toTermFlags) } diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index cdba54f1731c..43cea2085ddb 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -71,8 +71,8 @@ object Parsers { /** Positions tree. * If `t` does not have a position yet, set its position to the given one. */ - def atPos[T <: Positioned](pos: Span)(t: T): T = - if (t.pos.isSourceDerived) t else t.withSpan(pos) + def atPos[T <: Positioned](span: Span)(t: T): T = + if (t.span.isSourceDerived) t else t.withSpan(span) def atPos[T <: Positioned](start: Offset, point: Offset, end: Offset)(t: T): T = atPos(Span(start, end, point))(t) @@ -81,7 +81,7 @@ object Parsers { * to position spanning from `start` to last read offset, with given point. * If the last offset is less than or equal to start, the tree `t` did not * consume any source for its construction. In this case, don't position it yet, - * but wait for its position to be determined by `setChildPositions` when the + * but wait for its position to be determined by `setChildSpans` when the * parent node is positioned. */ def atPos[T <: Positioned](start: Offset, point: Offset)(t: T): T = @@ -91,13 +91,13 @@ object Parsers { atPos(start, start)(t) def startOffset(t: Positioned): Int = - if (t.pos.exists) t.pos.start else in.offset + if (t.span.exists) t.span.start else in.offset def pointOffset(t: Positioned): Int = - if (t.pos.exists) t.pos.point else in.offset + if (t.span.exists) t.span.point else in.offset def endOffset(t: Positioned): Int = - if (t.pos.exists) t.pos.end else in.lastOffset + if (t.span.exists) t.span.end else in.lastOffset def nameStart: Offset = if (in.token == BACKQUOTED_IDENT) in.offset + 1 else in.offset @@ -124,8 +124,8 @@ object Parsers { /** Unconditionally issue an error at given position, without * updating lastErrorOffset. */ - def syntaxError(msg: => Message, pos: Span): Unit = - ctx.error(msg, source.atSpan(pos)) + def syntaxError(msg: => Message, span: Span): Unit = + ctx.error(msg, source.atSpan(span)) } trait OutlineParserCommon extends ParserCommon { @@ -371,7 +371,7 @@ object Parsers { case Typed(Ident(name), tpt) => makeParameter(name.asTermName, tpt, mods).withPosOf(tree) case _ => - syntaxError(s"not a legal $expected", tree.pos) + syntaxError(s"not a legal $expected", tree.span) makeParameter(nme.ERROR, tree, mods) } @@ -383,7 +383,7 @@ object Parsers { case id @ Select(qual, name) => cpy.Select(id)(qual, name.toTypeName) case _ => - syntaxError(IdentifierExpected(tree.show), tree.pos) + syntaxError(IdentifierExpected(tree.show), tree.span) tree } @@ -401,7 +401,7 @@ object Parsers { try op finally { placeholderParams match { - case vd :: _ => syntaxError(UnboundPlaceholderParameter(), vd.pos) + case vd :: _ => syntaxError(UnboundPlaceholderParameter(), vd.span) case _ => } placeholderParams = savedPlaceholderParams @@ -480,7 +480,7 @@ object Parsers { if (prec < opPrec || leftAssoc && prec == opPrec) { opStack = opStack.tail recur { - atPos(opInfo.operator.pos union opInfo.operand.pos union top.pos) { + atPos(opInfo.operator.span union opInfo.operand.span union top.span) { val op = opInfo.operator val l = opInfo.operand val r = top @@ -602,7 +602,7 @@ object Parsers { def handleThis(qual: Ident) = { in.nextToken() val t = atPos(start) { This(qual) } - if (!thisOK && in.token != DOT) syntaxError(DanglingThisInPath(), t.pos) + if (!thisOK && in.token != DOT) syntaxError(DanglingThisInPath(), t.span) dotSelectors(t, finish) } def handleSuper(qual: Ident) = { @@ -797,7 +797,7 @@ object Parsers { for (t <- ts) yield { t match { case t@ByNameTypeTree(t1) => - syntaxError(ByNameParameterNotSupported(t), t.pos) + syntaxError(ByNameParameterNotSupported(t), t.span) t1 case _ => t @@ -1011,7 +1011,7 @@ object Parsers { val t = typeBounds() val cbs = contextBounds(pname) if (cbs.isEmpty) t - else atPos((t.pos union cbs.head.pos).start) { ContextBounds(t, cbs) } + else atPos((t.span union cbs.head.span).start) { ContextBounds(t, cbs) } } def contextBounds(pname: TypeName): List[Tree] = in.token match { @@ -1052,7 +1052,7 @@ object Parsers { def rejectWildcard(t: Tree, fallbackTree: Tree): Tree = findNonValueTypeTree(t, false) match { case Some(wildcardTree) => - syntaxError(UnboundWildcardType(), wildcardTree.pos) + syntaxError(UnboundWildcardType(), wildcardTree.span) fallbackTree case None => t } @@ -1069,9 +1069,9 @@ object Parsers { case Some(typTree) => typTree match { case typTree: TypeBoundsTree => - syntaxError(UnboundWildcardType(), typTree.pos) + syntaxError(UnboundWildcardType(), typTree.span) case typTree: ByNameTypeTree => - syntaxError(ByNameParameterNotSupported(typTree), typTree.pos) + syntaxError(ByNameParameterNotSupported(typTree), typTree.span) } scalaAny case None => t @@ -1184,9 +1184,9 @@ object Parsers { val body = expr() val (handler, handlerStart) = if (in.token == CATCH) { - val pos = in.offset + val span = in.offset in.nextToken() - (expr(), pos) + (expr(), span) } else (EmptyTree, -1) handler match { @@ -1270,7 +1270,7 @@ object Parsers { if (isWildcard(t) && location != Location.InPattern) { val vd :: rest = placeholderParams placeholderParams = - cpy.ValDef(vd)(tpt = tpt).withSpan(vd.pos.union(tpt.pos)) :: rest + cpy.ValDef(vd)(tpt = tpt).withSpan(vd.span.union(tpt.span)) :: rest } Typed(t, tpt) } @@ -1300,7 +1300,7 @@ object Parsers { */ def implicitMatch(start: Int, imods: Modifiers) = { def markFirstIllegal(mods: List[Mod]) = mods match { - case mod :: _ => syntaxError(em"illegal modifier for implicit match", mod.pos) + case mod :: _ => syntaxError(em"illegal modifier for implicit match", mod.span) case _ => } imods.mods match { @@ -1315,7 +1315,7 @@ object Parsers { case pat => isVarPattern(pat) } if (!isImplicitPattern(pat)) - syntaxError(em"not a legal pattern for an implicit match", pat.pos) + syntaxError(em"not a legal pattern for an implicit match", pat.span) } result } @@ -1323,7 +1323,7 @@ object Parsers { /** `match' { TypeCaseClauses } */ def matchType(bound: Tree, t: Tree): MatchTypeTree = - atPos((if (bound.isEmpty) t else bound).pos.start, accept(MATCH)) { + atPos((if (bound.isEmpty) t else bound).span.start, accept(MATCH)) { inBraces(MatchTypeTree(bound, t, caseClauses(typeCaseClause))) } @@ -1738,8 +1738,8 @@ object Parsers { // `x: _*' is parsed in `ascription' if (isIdent(nme.raw.STAR)) { in.nextToken() - if (in.token != RPAREN) syntaxError(SeqWildcardPatternPos(), wildIndent.pos) - atPos(wildIndent.pos) { Ident(tpnme.WILDCARD_STAR) } + if (in.token != RPAREN) syntaxError(SeqWildcardPatternPos(), wildIndent.span) + atPos(wildIndent.span) { Ident(tpnme.WILDCARD_STAR) } } else wildIndent case LPAREN => atPos(in.offset) { makeTupleOrParens(inParens(patternsOpt())) } @@ -1892,8 +1892,8 @@ object Parsers { case Select(qual, name) => cpy.Select(tree)(adjustStart(start)(qual), name) case _ => tree } - if (tree1.pos.exists && start < tree1.pos.start) - tree1.withSpan(tree1.pos.withStart(start)) + if (tree1.span.exists && start < tree1.span.start) + tree1.withSpan(tree1.span.withStart(start)) else tree1 } @@ -2021,7 +2021,7 @@ object Parsers { if (in.token == EQUALS) { in.nextToken(); expr() } else EmptyTree if (implicitOffset >= 0) { - //mods = mods.withPos(mods.pos.union(Span(implicitOffset, implicitOffset))) + //mods = mods.withPos(mods.span.union(Span(implicitOffset, implicitOffset))) implicitOffset = -1 } ValDef(name, tpt, default).withMods(mods) @@ -2034,7 +2034,7 @@ object Parsers { case vparam :: rest => vparam.tpt match { case PostfixOp(_, op) if op.name == tpnme.raw.STAR => - syntaxError(VarArgsParamMustComeLast(), vparam.tpt.pos) + syntaxError(VarArgsParamMustComeLast(), vparam.tpt.span) case _ => } checkVarArgsRules(rest) @@ -2099,7 +2099,7 @@ object Parsers { case t :: rest => // The first import should start at the position of the keyword. val firstPos = - if (t.pos.exists) t.pos.withStart(offset) + if (t.span.exists) t.span.withStart(offset) else Span(offset, in.lastOffset) t.withSpan(firstPos) :: rest case nil => nil @@ -2640,7 +2640,7 @@ object Parsers { } if (isLegal) tree :: Nil else { - syntaxError("illegal refinement", tree.pos) + syntaxError("illegal refinement", tree.span) Nil } } diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index 2d27c2059602..c967c915b7c3 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -181,7 +181,7 @@ object Scanners { private[this] val commentPosBuf = new mutable.ListBuffer[Span] /** Return a list of all the comment positions */ - def commentPositions: List[Span] = commentPosBuf.toList + def commentSpans: List[Span] = commentPosBuf.toList private[this] def addComment(comment: Comment): Unit = { val lookahead = lookaheadReader() diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 9db27d935f1b..21ddf850d6fb 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -605,8 +605,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { if (printPos) { val posStr = if (homogenizedView) - if (tree.isInstanceOf[MemberDef]) Str(s"${tree.source}${tree.pos}") - else Str(s"${tree.source}${tree.pos.toSynthetic}") + if (tree.isInstanceOf[MemberDef]) Str(s"${tree.source}${tree.span}") + else Str(s"${tree.source}${tree.span.toSynthetic}") else "<" ~ toText(tree.sourcePos) ~ ">" val clsStr = ""//if (tree.isType) tree.getClass.toString else "" @@ -651,7 +651,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { val str: Text = nameString(tree.symbol) tree match { case tree: RefTree => withPos(str, tree.sourcePos) - case tree: MemberDef => withPos(str, tree.sourcePos.withSpan(tree.namePos)) + case tree: MemberDef => withPos(str, tree.sourcePos.withSpan(tree.nameSpan)) case _ => str } } diff --git a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala index 27bfef936524..9c3b75a06b10 100644 --- a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala +++ b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala @@ -39,13 +39,13 @@ object SyntaxHighlighting { def highlightRange(from: Int, to: Int, color: String) = Arrays.fill(colorAt.asInstanceOf[Array[AnyRef]], from, to, color) - def highlightPosition(pos: Span, color: String) = if (pos.exists) { - if (pos.start < 0 || pos.end > in.length) { + def highlightPosition(span: Span, color: String) = if (span.exists) { + if (span.start < 0 || span.end > in.length) { if (debug) - println(s"Trying to highlight erroneous position $pos. Input size: ${in.length}") + println(s"Trying to highlight erroneous position $span. Input size: ${in.length}") } else - highlightRange(pos.start, pos.end, color) + highlightRange(span.start, span.end, color) } val scanner = new Scanner(source) @@ -78,8 +78,8 @@ object SyntaxHighlighting { } } - for (pos <- scanner.commentPositions) - highlightPosition(pos, CommentColor) + for (span <- scanner.commentSpans) + highlightPosition(span, CommentColor) object TreeHighlighter extends untpd.UntypedTreeTraverser { import untpd._ @@ -92,7 +92,7 @@ object SyntaxHighlighting { def highlightAnnotations(tree: MemberDef): Unit = for (annotation <- tree.rawMods.annotations) - highlightPosition(annotation.pos, AnnotationColor) + highlightPosition(annotation.span, AnnotationColor) def highlight(trees: List[Tree])(implicit ctx: Context): Unit = trees.foreach(traverse) @@ -103,14 +103,14 @@ object SyntaxHighlighting { () case tree: ValOrDefDef => highlightAnnotations(tree) - highlightPosition(tree.namePos, ValDefColor) + highlightPosition(tree.nameSpan, ValDefColor) case tree: MemberDef /* ModuleDef | TypeDef */ => highlightAnnotations(tree) - highlightPosition(tree.namePos, TypeColor) + highlightPosition(tree.nameSpan, TypeColor) case tree: Ident if tree.isType => - highlightPosition(tree.pos, TypeColor) + highlightPosition(tree.span, TypeColor) case _: TypTree => - highlightPosition(tree.pos, TypeColor) + highlightPosition(tree.span, TypeColor) case _ => } traverseChildren(tree) diff --git a/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala b/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala index b524d060d4a2..e234ab76213d 100644 --- a/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala +++ b/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala @@ -26,7 +26,7 @@ class ArrayConstructors extends MiniPhase { override def transformApply(tree: tpd.Apply)(implicit ctx: Context): tpd.Tree = { def expand(elemType: Type, dims: List[Tree]) = - tpd.newArray(elemType, tree.tpe, tree.pos, JavaSeqLiteral(dims, TypeTree(defn.IntClass.typeRef))) + tpd.newArray(elemType, tree.tpe, tree.span, JavaSeqLiteral(dims, TypeTree(defn.IntClass.typeRef))) if (tree.fun.symbol eq defn.ArrayConstructor) { val TypeApply(tycon, targ :: Nil) = tree.fun diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala index 744550e1192f..995c78c95cca 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala @@ -109,13 +109,13 @@ class ExpandSAMs extends MiniPhase { val anonSym = anon.symbol val parents = List(defn.AbstractPartialFunctionType.appliedTo(tpe.argInfos), defn.SerializableType) - val pfSym = ctx.newNormalizedClassSymbol(anonSym.owner, tpnme.ANON_CLASS, Synthetic | Final, parents, coord = tree.pos) + val pfSym = ctx.newNormalizedClassSymbol(anonSym.owner, tpnme.ANON_CLASS, Synthetic | Final, parents, coord = tree.span) def overrideSym(sym: Symbol) = sym.copy( owner = pfSym, flags = Synthetic | Method | Final | Override, info = tpe.memberInfo(sym), - coord = tree.pos).asTerm.entered + coord = tree.span).asTerm.entered val isDefinedAtFn = overrideSym(defn.PartialFunction_isDefinedAt) val applyOrElseFn = overrideSym(defn.PartialFunction_applyOrElse) diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala index 87bf048ddfc4..1f65f21da5e1 100644 --- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala @@ -149,7 +149,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { // val x$lzy = new scala.runtime.LazyInt() val holderName = LazyLocalName.fresh(xname) val holderImpl = defn.LazyHolder()(ctx)(tpe.typeSymbol) - val holderSymbol = ctx.newSymbol(x.symbol.owner, holderName, containerFlags, holderImpl.typeRef, coord = x.pos) + val holderSymbol = ctx.newSymbol(x.symbol.owner, holderName, containerFlags, holderImpl.typeRef, coord = x.span) val holderTree = ValDef(holderSymbol, New(holderImpl.typeRef, Nil)) val holderRef = ref(holderSymbol) @@ -161,7 +161,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { // else x$lzy.initialize() // } val initName = LazyLocalInitName.fresh(xname) - val initSymbol = ctx.newSymbol(x.symbol.owner, initName, initFlags, MethodType(Nil, tpe), coord = x.pos) + val initSymbol = ctx.newSymbol(x.symbol.owner, initName, initFlags, MethodType(Nil, tpe), coord = x.span) val rhs = x.rhs.changeOwnerAfter(x.symbol, initSymbol, this) val initialize = holderRef.select(lazyNme.initialize).appliedTo(rhs) val initBody = holderRef diff --git a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala index 5faf20ce7d00..a85676602c4d 100644 --- a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala +++ b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala @@ -64,10 +64,10 @@ class LiftTry extends MiniPhase with IdentityDenotTransformer { thisPhase => override def transformTry(tree: Try)(implicit ctx: Context): Tree = if (needLift && tree.cases.nonEmpty) { - ctx.debuglog(i"lifting tree at ${tree.pos}, current owner = ${ctx.owner}") + ctx.debuglog(i"lifting tree at ${tree.span}, current owner = ${ctx.owner}") val fn = ctx.newSymbol( ctx.owner, LiftedTreeName.fresh(), Synthetic | Method, - MethodType(Nil, tree.tpe.widenIfUnstable), coord = tree.pos) + MethodType(Nil, tree.tpe.widenIfUnstable), coord = tree.span) tree.changeOwnerAfter(ctx.owner, fn, thisPhase) Block(DefDef(fn, tree) :: Nil, ref(fn).appliedToNone) } diff --git a/compiler/src/dotty/tools/dotc/transform/Memoize.scala b/compiler/src/dotty/tools/dotc/transform/Memoize.scala index aa9414f4ffcf..7e058c8b131a 100644 --- a/compiler/src/dotty/tools/dotc/transform/Memoize.scala +++ b/compiler/src/dotty/tools/dotc/transform/Memoize.scala @@ -82,7 +82,7 @@ class Memoize extends MiniPhase with IdentityDenotTransformer { thisPhase => name = sym.name.asTermName.fieldName, flags = Private | (if (sym is Stable) EmptyFlags else Mutable), info = fieldType, - coord = tree.pos + coord = tree.span ).withAnnotationsCarrying(sym, defn.FieldMetaAnnot) .enteredAfter(thisPhase) } diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala index 3acbf1e7827f..6e1425e9f5ba 100644 --- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala +++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala @@ -172,7 +172,7 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase => case _ => val Apply(sel @ Select(New(_), nme.CONSTRUCTOR), args) = tree val (callArgs, initArgs) = if (tree.symbol.owner.is(Trait)) (Nil, args) else (args, Nil) - (superRef(tree.symbol, tree.pos).appliedToArgs(callArgs), initArgs) + (superRef(tree.symbol, tree.span).appliedToArgs(callArgs), initArgs) } val superCallsAndArgs = ( diff --git a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala index 0ca776d2acc8..d37c9e9d58ad 100644 --- a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala +++ b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala @@ -68,7 +68,7 @@ class NonLocalReturns extends MiniPhase { private def nonLocalReturnTry(body: Tree, key: TermSymbol, meth: Symbol)(implicit ctx: Context) = { val keyDef = ValDef(key, New(defn.ObjectType, Nil)) val nonLocalReturnControl = defn.NonLocalReturnControlType - val ex = ctx.newSymbol(meth, nme.ex, EmptyFlags, nonLocalReturnControl, coord = body.pos) + val ex = ctx.newSymbol(meth, nme.ex, EmptyFlags, nonLocalReturnControl, coord = body.span) val pat = BindTyped(ex, nonLocalReturnControl) val rhs = If( ref(ex).select(nme.key).appliedToNone.select(nme.eq).appliedTo(ref(key)), diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 1bf0123fe156..fb72451b6a78 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -87,7 +87,7 @@ object PatternMatcher { private def newVar(rhs: Tree, flags: FlagSet): TermSymbol = ctx.newSymbol(ctx.owner, PatMatStdBinderName.fresh(), Synthetic | Case | flags, - sanitize(rhs.tpe), coord = rhs.pos) + sanitize(rhs.tpe), coord = rhs.span) // TODO: Drop Case once we use everywhere else `isPatmatGenerated`. /** The plan `let x = rhs in body(x)` where `x` is a fresh variable */ @@ -131,7 +131,7 @@ object PatternMatcher { /** The different kinds of plans */ sealed abstract class Plan { val id: Int = nxId; nxId += 1 } - case class TestPlan(test: Test, var scrutinee: Tree, pos: Span, + case class TestPlan(test: Test, var scrutinee: Tree, span: Span, var onSuccess: Plan) extends Plan { override def equals(that: Any): Boolean = that match { case that: TestPlan => this.scrutinee === that.scrutinee && this.test == that.test @@ -147,8 +147,8 @@ object PatternMatcher { case class ResultPlan(var tree: Tree) extends Plan object TestPlan { - def apply(test: Test, sym: Symbol, pos: Span, ons: Plan): TestPlan = - TestPlan(test, ref(sym), pos, ons) + def apply(test: Test, sym: Symbol, span: Span, ons: Plan): TestPlan = + TestPlan(test, ref(sym), span, ons) } /** The different kinds of tests */ @@ -297,7 +297,7 @@ object PatternMatcher { if (isSyntheticScala2Unapply(unapp.symbol) && caseAccessors.length == args.length) matchArgsPlan(caseAccessors.map(ref(scrutinee).select(_)), args, onSuccess) else if (unapp.tpe.widenSingleton.isRef(defn.BooleanClass)) - TestPlan(GuardTest, unapp, unapp.pos, onSuccess) + TestPlan(GuardTest, unapp, unapp.span, onSuccess) else { letAbstract(unapp) { unappResult => val isUnapplySeq = unapp.symbol.name == nme.unapplySeq @@ -320,7 +320,7 @@ object PatternMatcher { matchArgsPlan(selectors, args, onSuccess) } } - TestPlan(NonEmptyTest, unappResult, unapp.pos, argsPlan) + TestPlan(NonEmptyTest, unappResult, unapp.span, argsPlan) } } } @@ -329,7 +329,7 @@ object PatternMatcher { // begin patternPlan swapBind(tree) match { case Typed(pat, tpt) => - TestPlan(TypeTest(tpt), scrutinee, tree.pos, + TestPlan(TypeTest(tpt), scrutinee, tree.span, letAbstract(ref(scrutinee).asInstance(tpt.tpe)) { casted => nonNull += casted patternPlan(casted, pat, onSuccess) @@ -340,7 +340,7 @@ object PatternMatcher { if (implicits.nonEmpty) unapp = unapp.appliedToArgs(implicits) val unappPlan = unapplyPlan(unapp, args) if (scrutinee.info.isNotNull || nonNull(scrutinee)) unappPlan - else TestPlan(NonNullTest, scrutinee, tree.pos, unappPlan) + else TestPlan(NonNullTest, scrutinee, tree.span, unappPlan) case Bind(name, body) => if (name == nme.WILDCARD) patternPlan(scrutinee, body, onSuccess) else { @@ -365,14 +365,14 @@ object PatternMatcher { case SeqLiteral(pats, _) => matchElemsPlan(scrutinee, pats, exact = true, onSuccess) case _ => - TestPlan(EqualTest(tree), scrutinee, tree.pos, onSuccess) + TestPlan(EqualTest(tree), scrutinee, tree.span, onSuccess) } } private def caseDefPlan(scrutinee: Symbol, cdef: CaseDef): Plan = { var onSuccess: Plan = ResultPlan(cdef.body) if (!cdef.guard.isEmpty) - onSuccess = TestPlan(GuardTest, cdef.guard, cdef.guard.pos, onSuccess) + onSuccess = TestPlan(GuardTest, cdef.guard, cdef.guard.span, onSuccess) patternPlan(scrutinee, cdef.pat, onSuccess) } @@ -823,7 +823,7 @@ object PatternMatcher { case plan2: TestPlan => emitWithMashedConditions(plan2 :: plans) case _ => - def emitCondWithPos(plan: TestPlan) = emitCondition(plan).withSpan(plan.pos) + def emitCondWithPos(plan: TestPlan) = emitCondition(plan).withSpan(plan.span) val conditions = plans.foldRight[Tree](EmptyTree) { (otherPlan, acc) => if (acc.isEmpty) emitCondWithPos(otherPlan) diff --git a/compiler/src/dotty/tools/dotc/transform/Pickler.scala b/compiler/src/dotty/tools/dotc/transform/Pickler.scala index 0abee9001ba9..a8252a6e74e0 100644 --- a/compiler/src/dotty/tools/dotc/transform/Pickler.scala +++ b/compiler/src/dotty/tools/dotc/transform/Pickler.scala @@ -61,7 +61,7 @@ class Pickler extends Phase { treePkl.compactify() pickler.addrOfTree = treePkl.buf.addrOfTree pickler.addrOfSym = treePkl.addrOfSym - if (tree.pos.exists) + if (tree.span.exists) new PositionPickler(pickler, treePkl.buf.addrOfTree).picklePositions(tree :: Nil) if (!ctx.settings.YdropComments.value) diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index be4aa899f9fe..9fa5d9dde086 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -211,7 +211,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase tpd.cpy.Apply(tree)( tree.fun, tree.args.mapConserve(arg => - if (methType.isImplicitMethod && arg.pos.isSynthetic) ref(defn.Predef_undefined) + if (methType.isImplicitMethod && arg.span.isSynthetic) ref(defn.Predef_undefined) else dropInlines.transform(arg))) else tree @@ -239,7 +239,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase super.transform(tree1) } case Inlined(call, bindings, expansion) if !call.isEmpty => - val callTrace = Inliner.inlineCallTrace(call.symbol, call.pos) + val callTrace = Inliner.inlineCallTrace(call.symbol, call.sourcePos) cpy.Inlined(tree)(callTrace, transformSub(bindings), transform(expansion)(inlineContext(call))) case tree: Template => withNoCheckNews(tree.parents.flatMap(newPart)) { diff --git a/compiler/src/dotty/tools/dotc/transform/Staging.scala b/compiler/src/dotty/tools/dotc/transform/Staging.scala index a95b72c9b9df..64af2b445c6e 100644 --- a/compiler/src/dotty/tools/dotc/transform/Staging.scala +++ b/compiler/src/dotty/tools/dotc/transform/Staging.scala @@ -386,7 +386,7 @@ class Staging extends MacroTransformWithImplicits { if (level == 0 && !ctx.inInlineMethod) { val body2 = if (body1.isType) body1 - else Inlined(Inliner.inlineCallTrace(ctx.owner, quote.pos), Nil, body1) + else Inlined(Inliner.inlineCallTrace(ctx.owner, quote.sourcePos), Nil, body1) pickledQuote(body2, splices, body.tpe, isType).withPosOf(quote) } else { @@ -449,7 +449,7 @@ class Staging extends MacroTransformWithImplicits { } else if (enclosingInlineds.nonEmpty) { // level 0 in an inlined call val spliceCtx = ctx.outer // drop the last `inlineContext` - val pos: SourcePosition = spliceCtx.source.atSpan(enclosingInlineds.head.pos) + val pos: SourcePosition = spliceCtx.source.atSpan(enclosingInlineds.head.span) val evaluatedSplice = Splicer.splice(splice.qualifier, pos, macroClassLoader)(spliceCtx).withPosOf(splice) if (ctx.reporter.hasErrors) splice else transform(evaluatedSplice) } diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index 5bdcb30062fb..86a08e89e0eb 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -70,7 +70,7 @@ class SuperAccessors(thisPhase: DenotTransformer) { if (clazz is Trait) superName = superName.expandedName(clazz) val superInfo = sel.tpe.widenSingleton.ensureMethodic - val accRange = sel.pos.focus + val accRange = sel.span.focus val superAcc = clazz.info.decl(superName) .suchThat(_.signature == superInfo.signature).symbol .orElse { diff --git a/compiler/src/dotty/tools/dotc/transform/TailRec.scala b/compiler/src/dotty/tools/dotc/transform/TailRec.scala index 88a24ac7225f..2588d3f85478 100644 --- a/compiler/src/dotty/tools/dotc/transform/TailRec.scala +++ b/compiler/src/dotty/tools/dotc/transform/TailRec.scala @@ -117,8 +117,8 @@ class TailRec extends MiniPhase { val method = tree.symbol val mandatory = method.hasAnnotation(defn.TailrecAnnot) def noTailTransform(failureReported: Boolean) = { - // FIXME: want to report this error on `tree.namePos`, but - // because of extension method getting a weird pos, it is + // FIXME: want to report this error on `tree.nameSpan`, but + // because of extension method getting a weird position, it is // better to report on method symbol so there's no overlap. // We don't report a new error if failures were reported // during the transformation. @@ -285,7 +285,7 @@ class TailRec extends MiniPhase { ctx.error(s"Cannot rewrite recursive call: $reason", tree.sourcePos) } else - tailrec.println("Cannot rewrite recursive call at: " + tree.pos + " because: " + reason) + tailrec.println("Cannot rewrite recursive call at: " + tree.span + " because: " + reason) continue } @@ -303,7 +303,7 @@ class TailRec extends MiniPhase { if (isRecursiveCall) { if (inTailPosition) { - tailrec.println("Rewriting tail recursive call: " + tree.pos) + tailrec.println("Rewriting tail recursive call: " + tree.span) rewrote = true val assignParamPairs = for { diff --git a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala index 6ddb4b043b5a..b4cf235168e0 100644 --- a/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala +++ b/compiler/src/dotty/tools/dotc/transform/TryCatchPatterns.scala @@ -59,7 +59,7 @@ class TryCatchPatterns extends MiniPhase { override def transformTry(tree: Try)(implicit ctx: Context): Tree = { val (tryCases, patternMatchCases) = tree.cases.span(isCatchCase) - val fallbackCase = mkFallbackPatterMatchCase(patternMatchCases, tree.pos) + val fallbackCase = mkFallbackPatterMatchCase(patternMatchCases, tree.span) cpy.Try(tree)(cases = tryCases ++ fallbackCase) } @@ -81,17 +81,17 @@ class TryCatchPatterns extends MiniPhase { false } - private def mkFallbackPatterMatchCase(patternMatchCases: List[CaseDef], pos: Span)( + private def mkFallbackPatterMatchCase(patternMatchCases: List[CaseDef], span: Span)( implicit ctx: Context): Option[CaseDef] = { if (patternMatchCases.isEmpty) None else { val exName = ExceptionBinderName.fresh() val fallbackSelector = - ctx.newSymbol(ctx.owner, exName, Flags.Synthetic | Flags.Case, defn.ThrowableType, coord = pos) - val sel = Ident(fallbackSelector.termRef).withSpan(pos) + ctx.newSymbol(ctx.owner, exName, Flags.Synthetic | Flags.Case, defn.ThrowableType, coord = span) + val sel = Ident(fallbackSelector.termRef).withSpan(span) val rethrow = CaseDef(EmptyTree, EmptyTree, Throw(ref(fallbackSelector))) Some(CaseDef( - Bind(fallbackSelector, Underscore(fallbackSelector.info).withSpan(pos)), + Bind(fallbackSelector, Underscore(fallbackSelector.info).withSpan(span)), EmptyTree, transformFollowing(Match(sel, patternMatchCases ::: rethrow :: Nil))) ) diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 8ffd326bf350..c378054e13c8 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -53,7 +53,7 @@ object TypeTestsCasts { * 7. if `P` is a refinement type, FALSE * 8. otherwise, TRUE */ - def checkable(X: Type, P: Type, pos: Span)(implicit ctx: Context): Boolean = { + def checkable(X: Type, P: Type, span: Span)(implicit ctx: Context): Boolean = { def isAbstract(P: Type) = !P.dealias.typeSymbol.isClass def isPatternTypeSymbol(sym: Symbol) = !sym.isClass && sym.is(Case) @@ -103,7 +103,7 @@ object TypeTestsCasts { P1 <:< X // constraint P1 // use fromScala2x to avoid generating pattern bound symbols - maximizeType(P1, pos, fromScala2x = true) + maximizeType(P1, span, fromScala2x = true) val res = P1 <:< P debug.println("P1 : " + P1) @@ -273,7 +273,7 @@ object TypeTestsCasts { if (sym.isTypeTest) { val argType = tree.args.head.tpe - if (!checkable(expr.tpe, argType, tree.pos)) + if (!checkable(expr.tpe, argType, tree.span)) ctx.warning(i"the type test for $argType cannot be checked at runtime", tree.sourcePos) transformTypeTest(expr, tree.args.head.tpe, flagUnrelated = true) } diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 7f5ee898b5f9..f21f56960935 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -170,7 +170,7 @@ object Applications { /** A wrapper indicating that its argument is an application of an extension method. */ class ExtMethodApply(val app: Tree)(implicit @transientParam src: SourceInfo) extends tpd.Tree { - override def pos = app.pos + override def span = app.span def canEqual(that: Any): Boolean = app.canEqual(that) def productArity: Int = app.productArity @@ -870,7 +870,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => case Apply(fn @ Select(left, _), right :: Nil) if fn.hasType => val op = fn.symbol if (op == defn.Any_== || op == defn.Any_!=) - checkCanEqual(left.tpe.widen, right.tpe.widen, app.pos) + checkCanEqual(left.tpe.widen, right.tpe.widen, app.span) case _ => } app @@ -926,7 +926,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => */ def convertNewGenericArray(tree: Tree)(implicit ctx: Context): Tree = tree match { case Apply(TypeApply(tycon, targs@(targ :: Nil)), args) if tycon.symbol == defn.ArrayConstructor => - fullyDefinedType(tree.tpe, "array", tree.pos) + fullyDefinedType(tree.tpe, "array", tree.span) def newGenericArrayCall = ref(defn.DottyArraysModule) @@ -1054,10 +1054,10 @@ trait Applications extends Compatibility { self: Typer with Dynamic => val ownType = if (selType <:< unapplyArgType) { unapp.println(i"case 1 $unapplyArgType ${ctx.typerState.constraint}") - fullyDefinedType(unapplyArgType, "pattern selector", tree.pos) + fullyDefinedType(unapplyArgType, "pattern selector", tree.span) selType } else if (isSubTypeOfParent(unapplyArgType, selType)(ctx.addMode(Mode.GADTflexible))) { - val patternBound = maximizeType(unapplyArgType, tree.pos, fromScala2x) + val patternBound = maximizeType(unapplyArgType, tree.span, fromScala2x) if (patternBound.nonEmpty) unapplyFn = addBinders(unapplyFn, patternBound) unapp.println(i"case 2 $unapplyArgType ${ctx.typerState.constraint}") unapplyArgType diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 6591339ab949..f2f1524dbc1e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -873,7 +873,7 @@ trait Checking { val checker = new TreeTraverser { def traverse(t: Tree)(implicit ctx: Context) = { def check(owner: Symbol, checkedSym: Symbol) = - if (t.pos.isSourceDerived && owner == badOwner) + if (t.span.isSourceDerived && owner == badOwner) t match { case t: RefTree if allowed(t.name, checkedSym) => case _ => ctx.error(i"illegal reference to $checkedSym from $where", t.sourcePos) diff --git a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala index 5cfe4e88a6b5..6abb764b4ffc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala +++ b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala @@ -49,7 +49,7 @@ trait Dynamic { self: Typer with Applications => * foo.bar[T0, ...](x = bazX, y = bazY, baz, ...) ~~> foo.applyDynamicNamed[T0, ...]("bar")(("x", bazX), ("y", bazY), ("", baz), ...) */ def typedDynamicApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = { - def typedDynamicApply(qual: untpd.Tree, name: Name, selPos: Span, targs: List[untpd.Tree]): Tree = { + def typedDynamicApply(qual: untpd.Tree, name: Name, selSpan: Span, targs: List[untpd.Tree]): Tree = { def isNamedArg(arg: untpd.Tree): Boolean = arg match { case NamedArg(_, _) => true; case _ => false } val args = tree.args val dynName = if (args.exists(isNamedArg)) nme.applyDynamicNamed else nme.applyDynamic @@ -62,19 +62,19 @@ trait Dynamic { self: Typer with Applications => case arg => namedArgTuple("", arg) } val args1 = if (dynName == nme.applyDynamic) args else namedArgs - typedApply(untpd.Apply(coreDynamic(qual, dynName, name, selPos, targs), args1), pt) + typedApply(untpd.Apply(coreDynamic(qual, dynName, name, selSpan, targs), args1), pt) } } tree.fun match { case sel @ Select(qual, name) if !isDynamicMethod(name) => - typedDynamicApply(qual, name, sel.pos, Nil) + typedDynamicApply(qual, name, sel.span, Nil) case TypeApply(sel @ Select(qual, name), targs) if !isDynamicMethod(name) => - typedDynamicApply(qual, name, sel.pos, targs) + typedDynamicApply(qual, name, sel.span, targs) case TypeApply(fun, targs) => - typedDynamicApply(fun, nme.apply, fun.pos, targs) + typedDynamicApply(fun, nme.apply, fun.span, targs) case fun => - typedDynamicApply(fun, nme.apply, fun.pos, Nil) + typedDynamicApply(fun, nme.apply, fun.span, Nil) } } @@ -86,26 +86,26 @@ trait Dynamic { self: Typer with Applications => * through an existing transformation of in typedAssign [foo.bar(baz) = quux ~~> foo.bar.update(baz, quux)]. */ def typedDynamicSelect(tree: untpd.Select, targs: List[Tree], pt: Type)(implicit ctx: Context): Tree = - typedApply(coreDynamic(tree.qualifier, nme.selectDynamic, tree.name, tree.pos, targs), pt) + typedApply(coreDynamic(tree.qualifier, nme.selectDynamic, tree.name, tree.span, targs), pt) /** Translate selection that does not typecheck according to the normal rules into a updateDynamic. * foo.bar = baz ~~> foo.updateDynamic(bar)(baz) */ def typedDynamicAssign(tree: untpd.Assign, pt: Type)(implicit ctx: Context): Tree = { - def typedDynamicAssign(qual: untpd.Tree, name: Name, selPos: Span, targs: List[untpd.Tree]): Tree = - typedApply(untpd.Apply(coreDynamic(qual, nme.updateDynamic, name, selPos, targs), tree.rhs), pt) + def typedDynamicAssign(qual: untpd.Tree, name: Name, selSpan: Span, targs: List[untpd.Tree]): Tree = + typedApply(untpd.Apply(coreDynamic(qual, nme.updateDynamic, name, selSpan, targs), tree.rhs), pt) tree.lhs match { case sel @ Select(qual, name) if !isDynamicMethod(name) => - typedDynamicAssign(qual, name, sel.pos, Nil) + typedDynamicAssign(qual, name, sel.span, Nil) case TypeApply(sel @ Select(qual, name), targs) if !isDynamicMethod(name) => - typedDynamicAssign(qual, name, sel.pos, targs) + typedDynamicAssign(qual, name, sel.span, targs) case _ => errorTree(tree, ReassignmentToVal(tree.lhs.symbol.name)) } } - private def coreDynamic(qual: untpd.Tree, dynName: Name, name: Name, selPos: Span, targs: List[untpd.Tree])(implicit ctx: Context): untpd.Apply = { - val select = untpd.Select(qual, dynName).withSpan(selPos) + private def coreDynamic(qual: untpd.Tree, dynName: Name, name: Name, selSpan: Span, targs: List[untpd.Tree])(implicit ctx: Context): untpd.Apply = { + val select = untpd.Select(qual, dynName).withSpan(selSpan) val selectWithTypes = if (targs.isEmpty) select else untpd.TypeApply(select, targs) @@ -175,7 +175,7 @@ trait Dynamic { self: Typer with Applications => fail(name, i"has a method type with inter-parameter dependencies") else { val ctags = tpe.paramInfoss.flatten.map(pt => - implicitArgTree(defn.ClassTagType.appliedTo(pt.widenDealias :: Nil), fun.pos.endPos)) + implicitArgTree(defn.ClassTagType.appliedTo(pt.widenDealias :: Nil), fun.span.endPos)) structuralCall(nme.applyDynamic, ctags).asInstance(tpe.finalResultType) } diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala index cb3616289ee7..a93875f065d5 100644 --- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -46,9 +46,9 @@ abstract class Lifter { // don't instantiate here, as the type params could be further constrained, see tests/pos/pickleinf.scala var liftedType = expr.tpe.widen if (liftedFlags.is(Method)) liftedType = ExprType(liftedType) - val lifted = ctx.newSymbol(ctx.owner, name, liftedFlags | Synthetic, liftedType, coord = positionCoord(expr.pos)) + val lifted = ctx.newSymbol(ctx.owner, name, liftedFlags | Synthetic, liftedType, coord = positionCoord(expr.span)) defs += liftedDef(lifted, expr).withPosOf(expr) - ref(lifted.termRef).withSpan(expr.pos.focus) + ref(lifted.termRef).withSpan(expr.span.focus) } /** Lift out common part of lhs tree taking part in an operator assignment such as @@ -208,8 +208,8 @@ object EtaExpansion extends LiftImpure { var paramFlag = Synthetic | Param if (mt.isImplicitMethod) paramFlag |= Implicit val params = (mt.paramNames, paramTypes).zipped.map((name, tpe) => - ValDef(name, tpe, EmptyTree).withFlags(paramFlag).withSpan(tree.pos.startPos)) - var ids: List[Tree] = mt.paramNames map (name => Ident(name).withSpan(tree.pos.startPos)) + ValDef(name, tpe, EmptyTree).withFlags(paramFlag).withSpan(tree.span.startPos)) + var ids: List[Tree] = mt.paramNames map (name => Ident(name).withSpan(tree.span.startPos)) if (mt.paramInfos.nonEmpty && mt.paramInfos.last.isRepeatedParam) ids = ids.init :+ repeated(ids.last) var body: Tree = Apply(lifted, ids) diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 68f882dcb399..5d73671da847 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -597,7 +597,7 @@ trait Implicits { self: Typer => SelectionProto(name, memberProto, compat, privateOK = false) case tp => tp } - try inferImplicit(adjust(to), from, from.pos) + try inferImplicit(adjust(to), from, from.span) catch { case ex: AssertionError => implicits.println(s"view $from ==> $to") @@ -611,16 +611,16 @@ trait Implicits { self: Typer => /** Find an implicit argument for parameter `formal`. * Return a failure as a SearchFailureType in the type of the returned tree. */ - def inferImplicitArg(formal: Type, pos: Span)(implicit ctx: Context): Tree = { + def inferImplicitArg(formal: Type, span: Span)(implicit ctx: Context): Tree = { /** If `formal` is of the form ClassTag[T], where `T` is a class type, * synthesize a class tag for `T`. */ def synthesizedClassTag(formal: Type): Tree = formal.argInfos match { case arg :: Nil => - fullyDefinedType(arg, "ClassTag argument", pos) match { + fullyDefinedType(arg, "ClassTag argument", span) match { case defn.ArrayOf(elemTp) => - val etag = inferImplicitArg(defn.ClassTagType.appliedTo(elemTp), pos) + val etag = inferImplicitArg(defn.ClassTagType.appliedTo(elemTp), span) if (etag.tpe.isError) EmptyTree else etag.select(nme.wrap) case tp if hasStableErasure(tp) && !defn.isBottomClass(tp.typeSymbol) => val sym = tp.typeSymbol @@ -630,7 +630,7 @@ trait Implicits { self: Typer => classTag.select(sym.name.toTermName) else classTag.select(nme.apply).appliedToType(tp).appliedTo(clsOf(erasure(tp))) - tag.withSpan(pos) + tag.withSpan(span) case tp => EmptyTree } @@ -644,7 +644,7 @@ trait Implicits { self: Typer => var ok = true def apply(t: Type) = t match { case t @ TypeRef(NoPrefix, _) => - inferImplicit(defn.QuotedTypeType.appliedTo(t), EmptyTree, pos) match { + inferImplicit(defn.QuotedTypeType.appliedTo(t), EmptyTree, span) match { case SearchSuccess(tag, _, _) if tag.tpe.isStable => tag.tpe.select(defn.QuotedType_~) case _ => @@ -676,7 +676,7 @@ trait Implicits { self: Typer => case args @ (arg1 :: arg2 :: Nil) if !ctx.featureEnabled(defn.LanguageModuleClass, nme.strictEquality) && ctx.test(implicit ctx => validEqAnyArgs(arg1, arg2)) => - ref(defn.Eq_eqAny).appliedToTypes(args).withSpan(pos) + ref(defn.Eq_eqAny).appliedToTypes(args).withSpan(span) case _ => EmptyTree } @@ -706,14 +706,14 @@ trait Implicits { self: Typer => } def hasEq(tp: Type): Boolean = - inferImplicit(defn.EqType.appliedTo(tp, tp), EmptyTree, pos).isSuccess + inferImplicit(defn.EqType.appliedTo(tp, tp), EmptyTree, span).isSuccess def validEqAnyArgs(tp1: Type, tp2: Type)(implicit ctx: Context) = { - List(tp1, tp2).foreach(fullyDefinedType(_, "eqAny argument", pos)) + List(tp1, tp2).foreach(fullyDefinedType(_, "eqAny argument", span)) assumedCanEqual(tp1, tp2) || !hasEq(tp1) && !hasEq(tp2) } - inferImplicit(formal, EmptyTree, pos)(ctx) match { + inferImplicit(formal, EmptyTree, span)(ctx) match { case SearchSuccess(arg, _, _) => arg case fail @ SearchFailure(failed) => def trySpecialCase(cls: ClassSymbol, handler: Type => Tree, ifNot: => Tree) = { @@ -735,10 +735,10 @@ trait Implicits { self: Typer => } /** Search an implicit argument and report error if not found */ - def implicitArgTree(formal: Type, pos: Span)(implicit ctx: Context): Tree = { - val arg = inferImplicitArg(formal, pos) + def implicitArgTree(formal: Type, span: Span)(implicit ctx: Context): Tree = { + val arg = inferImplicitArg(formal, span) if (arg.tpe.isInstanceOf[SearchFailureType]) - ctx.error(missingArgMsg(arg, formal, ""), ctx.source.atSpan(pos)) + ctx.error(missingArgMsg(arg, formal, ""), ctx.source.atSpan(span)) arg } @@ -787,7 +787,7 @@ trait Implicits { self: Typer => case _ => Nil } def resolveTypes(targs: List[Tree])(implicit ctx: Context) = - targs.map(a => fullyDefinedType(a.tpe, "type argument", a.pos)) + targs.map(a => fullyDefinedType(a.tpe, "type argument", a.span)) // We can extract type arguments from: // - a function call: @@ -867,9 +867,9 @@ trait Implicits { self: Typer => } /** Check that equality tests between types `ltp` and `rtp` make sense */ - def checkCanEqual(ltp: Type, rtp: Type, pos: Span)(implicit ctx: Context): Unit = + def checkCanEqual(ltp: Type, rtp: Type, span: Span)(implicit ctx: Context): Unit = if (!ctx.isAfterTyper && !assumedCanEqual(ltp, rtp)) { - val res = implicitArgTree(defn.EqType.appliedTo(ltp, rtp), pos) + val res = implicitArgTree(defn.EqType.appliedTo(ltp, rtp), span) implicits.println(i"Eq witness found for $ltp / $rtp: $res: ${res.tpe}") } @@ -877,16 +877,16 @@ trait Implicits { self: Typer => * @param pt The expected type of the parameter or conversion. * @param argument If an implicit conversion is searched, the argument to which * it should be applied, EmptyTree otherwise. - * @param pos The position where errors should be reported. + * @param span The position where errors should be reported. */ - def inferImplicit(pt: Type, argument: Tree, pos: Span)(implicit ctx: Context): SearchResult = track("inferImplicit") { + def inferImplicit(pt: Type, argument: Tree, span: Span)(implicit ctx: Context): SearchResult = track("inferImplicit") { assert(ctx.phase.allowsImplicitSearch, if (argument.isEmpty) i"missing implicit parameter of type $pt after typer" else i"type error: ${argument.tpe} does not conform to $pt${err.whyNoMatchStr(argument.tpe, pt)}") trace(s"search implicit ${pt.show}, arg = ${argument.show}: ${argument.tpe.show}", implicits, show = true) { val result0 = try { - new ImplicitSearch(pt, argument, pos).bestImplicit(contextual = true) + new ImplicitSearch(pt, argument, span).bestImplicit(contextual = true) } catch { case ce: CyclicReference => ce.inImplicitSearch = true @@ -903,13 +903,13 @@ trait Implicits { self: Typer => result case result: SearchFailure if result.isAmbiguous => val deepPt = pt.deepenProto - if (deepPt ne pt) inferImplicit(deepPt, argument, pos) + if (deepPt ne pt) inferImplicit(deepPt, argument, span) else if (ctx.scala2Mode && !ctx.mode.is(Mode.OldOverloadingResolution)) { - inferImplicit(pt, argument, pos)(ctx.addMode(Mode.OldOverloadingResolution)) match { + inferImplicit(pt, argument, span)(ctx.addMode(Mode.OldOverloadingResolution)) match { case altResult: SearchSuccess => ctx.migrationWarning( s"According to new implicit resolution rules, this will be ambiguous:\n${result.reason.explanation}", - ctx.source.atSpan(pos)) + ctx.source.atSpan(span)) altResult case _ => result @@ -920,12 +920,12 @@ trait Implicits { self: Typer => result0 } // If we are at the outermost implicit search then emit the implicit dictionary, if any. - ctx.searchHistory.emitDictionary(pos, result) + ctx.searchHistory.emitDictionary(span, result) } } /** An implicit search; parameters as in `inferImplicit` */ - class ImplicitSearch(protected val pt: Type, protected val argument: Tree, pos: Span)(implicit ctx: Context) { + class ImplicitSearch(protected val pt: Type, protected val argument: Tree, span: Span)(implicit ctx: Context) { assert(argument.isEmpty || argument.tpe.isValueType || argument.tpe.isInstanceOf[ExprType], em"found: $argument: ${argument.tpe}, expected: $pt") @@ -954,7 +954,7 @@ trait Implicits { self: Typer => /** Try to typecheck an implicit reference */ def typedImplicit(cand: Candidate, contextual: Boolean)(implicit ctx: Context): SearchResult = track("typedImplicit") { trace(i"typed implicit ${cand.ref}, pt = $pt, implicitsEnabled == ${ctx.mode is ImplicitsEnabled}", implicits, show = true) { val ref = cand.ref - var generated: Tree = tpd.ref(ref).withSpan(pos.startPos) + var generated: Tree = tpd.ref(ref).withSpan(span.startPos) val locked = ctx.typerState.ownedVars val generated1 = if (argument.isEmpty) @@ -979,7 +979,7 @@ trait Implicits { self: Typer => else tryConversion } lazy val shadowing = - typedUnadapted(untpd.Ident(cand.implicitRef.implicitName).withSpan(pos.toSynthetic))( + typedUnadapted(untpd.Ident(cand.implicitRef.implicitName).withSpan(span.toSynthetic))( nestedContext().addMode(Mode.ImplicitShadowing).setExploreTyperState()) /** Is candidate reference the same as the `shadowing` reference? (i.e. @@ -1153,7 +1153,7 @@ trait Implicits { self: Typer => |the search will fail with a global ambiguity error instead. | |Consider using the scala.implicits.Not class to implement similar functionality.""", - ctx.source.atSpan(pos)) + ctx.source.atSpan(span)) /** A relation that imfluences the order in which implicits are tried. * We prefer (in order of importance) @@ -1210,7 +1210,7 @@ trait Implicits { self: Typer => // other candidates need to be considered. ctx.searchHistory.recursiveRef(pt) match { case ref: TermRef => - SearchSuccess(tpd.ref(ref).withSpan(pos.startPos), ref, 0)(ctx.typerState, ctx.gadt) + SearchSuccess(tpd.ref(ref).withSpan(span.startPos), ref, 0)(ctx.typerState, ctx.gadt) case _ => val eligible = if (contextual) ctx.implicits.eligible(wildProto) @@ -1380,7 +1380,7 @@ abstract class SearchHistory { outer => def defineBynameImplicit(tpe: Type, result: SearchSuccess)(implicit ctx: Context): SearchResult = root.defineBynameImplicit(tpe, result) // This is NOOP unless at the root of this search history. - def emitDictionary(pos: Span, result: SearchResult)(implicit ctx: Context): SearchResult = result + def emitDictionary(span: Span, result: SearchResult)(implicit ctx: Context): SearchResult = result override def toString: String = s"SearchHistory(open = $open, byname = $byname)" } @@ -1458,12 +1458,12 @@ final class SearchRoot extends SearchHistory { /** * Emit the implicit dictionary at the completion of an implicit search. * - * @param pos The position at which the search is elaborated. + * @param span The position at which the search is elaborated. * @param result The result of the search prior to substitution of recursive references. * @result The elaborated result, comprising the implicit dictionary and a result tree * substituted with references into the dictionary. */ - override def emitDictionary(pos: Span, result: SearchResult)(implicit ctx: Context): SearchResult = { + override def emitDictionary(span: Span, result: SearchResult)(implicit ctx: Context): SearchResult = { if (implicitDictionary == null || implicitDictionary.isEmpty) result else { result match { @@ -1516,9 +1516,9 @@ final class SearchRoot extends SearchHistory { // } val parents = List(defn.ObjectType, defn.SerializableType) - val classSym = ctx.newNormalizedClassSymbol(ctx.owner, LazyImplicitName.fresh().toTypeName, Synthetic | Final, parents, coord = pos) + val classSym = ctx.newNormalizedClassSymbol(ctx.owner, LazyImplicitName.fresh().toTypeName, Synthetic | Final, parents, coord = span) val vsyms = pruned.map(_._1.symbol) - val nsyms = vsyms.map(vsym => ctx.newSymbol(classSym, vsym.name, EmptyFlags, vsym.info, coord = pos).entered) + val nsyms = vsyms.map(vsym => ctx.newSymbol(classSym, vsym.name, EmptyFlags, vsym.info, coord = span).entered) val vsymMap = (vsyms zip nsyms).toMap val rhss = pruned.map(_._2) @@ -1537,7 +1537,7 @@ final class SearchRoot extends SearchHistory { val constr = ctx.newConstructor(classSym, Synthetic, Nil, Nil).entered val classDef = ClassDef(classSym, DefDef(constr), vdefs) - val valSym = ctx.newLazyImplicit(classSym.typeRef, pos) + val valSym = ctx.newLazyImplicit(classSym.typeRef, span) val inst = ValDef(valSym, New(classSym.typeRef, Nil)) // Substitute dictionary references into outermost result term. diff --git a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala index de175d17753f..389fe82c2732 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala @@ -38,9 +38,9 @@ object Inferencing { /** The fully defined type, where all type variables are forced. * Throws an error if type contains wildcards. */ - def fullyDefinedType(tp: Type, what: String, pos: Span)(implicit ctx: Context): Type = + def fullyDefinedType(tp: Type, what: String, span: Span)(implicit ctx: Context): Type = if (isFullyDefined(tp, ForceDegree.all)) tp - else throw new Error(i"internal error: type of $what $tp is not fully defined, pos = $pos") // !!! DEBUG + else throw new Error(i"internal error: type of $what $tp is not fully defined, pos = $span") // !!! DEBUG /** Instantiate selected type variables `tvars` in type `tp` */ @@ -144,7 +144,7 @@ object Inferencing { val (tl1, tvars) = constrained(tl, tree) var tree1 = AppliedTypeTree(tree.withType(tl1), tvars) tree1.tpe <:< pt - fullyDefinedType(tree1.tpe, "template parent", tree.pos) + fullyDefinedType(tree1.tpe, "template parent", tree.span) tree1 case _ => tree @@ -288,7 +288,7 @@ object Inferencing { * @return The list of type symbols that were created * to instantiate undetermined type variables that occur non-variantly */ - def maximizeType(tp: Type, pos: Span, fromScala2x: Boolean)(implicit ctx: Context): List[Symbol] = Stats.track("maximizeType") { + def maximizeType(tp: Type, span: Span, fromScala2x: Boolean)(implicit ctx: Context): List[Symbol] = Stats.track("maximizeType") { val vs = variances(tp) val patternBound = new mutable.ListBuffer[Symbol] vs foreachBinding { (tvar, v) => @@ -299,7 +299,7 @@ object Inferencing { if (bounds.hi <:< bounds.lo || bounds.hi.classSymbol.is(Final) || fromScala2x) tvar.instantiate(fromBelow = false) else { - val wildCard = ctx.newPatternBoundSymbol(UniqueName.fresh(tvar.origin.paramName), bounds, pos) + val wildCard = ctx.newPatternBoundSymbol(UniqueName.fresh(tvar.origin.paramName), bounds, span) tvar.instantiateWith(wildCard.typeRef) patternBound += wildCard } diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index cd2cb91cb660..eb4c9461c95b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -177,7 +177,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { private val inlineCallPrefix = qualifier(methPart) // Make sure all type arguments to the call are fully determined - for (targ <- callTypeArgs) fullyDefinedType(targ.tpe, "inlined type argument", targ.pos) + for (targ <- callTypeArgs) fullyDefinedType(targ.tpe, "inlined type argument", targ.span) /** A map from parameter names of the inlineable method to references of the actual arguments. * For a type argument this is the full argument type. @@ -211,7 +211,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { private val bindingsBuf = new mutable.ListBuffer[MemberDef] private def newSym(name: Name, flags: FlagSet, info: Type): Symbol = - ctx.newSymbol(ctx.owner, name, flags, info, coord = call.pos) + ctx.newSymbol(ctx.owner, name, flags, info, coord = call.span) /** A binding for the parameter of an inline method. This is a `val` def for * by-value parameters and a `def` def for by-name parameters. `val` defs inherit @@ -711,7 +711,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { def searchImplicit(sym: TermSymbol, tpt: Tree) = { val evTyper = new Typer - val evidence = evTyper.inferImplicitArg(tpt.tpe, tpt.pos)(ctx.fresh.setTyper(evTyper)) + val evidence = evTyper.inferImplicitArg(tpt.tpe, tpt.span)(ctx.fresh.setTyper(evTyper)) evidence.tpe match { case fail: Implicits.AmbiguousImplicits => ctx.error(evTyper.missingArgMsg(evidence, tpt.tpe, ""), tpt.sourcePos) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index e9f642e5bfbb..3fa6abb1a42c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -243,12 +243,12 @@ class Namer { typer: Typer => } /** The enclosing class with given name; error if none exists */ - def enclosingClassNamed(name: TypeName, pos: Span)(implicit ctx: Context): Symbol = { + def enclosingClassNamed(name: TypeName, span: Span)(implicit ctx: Context): Symbol = { if (name.isEmpty) NoSymbol else { val cls = ctx.owner.enclosingClassNamed(name) if (!cls.exists) - ctx.error(s"no enclosing class or object is named $name", ctx.source.atSpan(pos)) + ctx.error(s"no enclosing class or object is named $name", ctx.source.atSpan(span)) cls } } @@ -266,7 +266,7 @@ class Namer { typer: Typer => def createSymbol(tree: Tree)(implicit ctx: Context): Symbol = { def privateWithinClass(mods: Modifiers) = - enclosingClassNamed(mods.privateWithin, tree.pos) + enclosingClassNamed(mods.privateWithin, tree.span) /** Check that flags are OK for symbol. This is done early to avoid * catastrophic failure when we create a TermSymbol with TypeFlags, or vice versa. @@ -332,7 +332,7 @@ class Namer { typer: Typer => val cls = createOrRefine[ClassSymbol](tree, name, flags, cls => adjustIfModule(new ClassCompleter(cls, tree)(ctx), tree), - ctx.newClassSymbol(ctx.owner, name, _, _, _, tree.namePos, ctx.source.file)) + ctx.newClassSymbol(ctx.owner, name, _, _, _, tree.nameSpan, ctx.source.file)) cls.completer.asInstanceOf[ClassCompleter].init() cls case tree: MemberDef => @@ -364,9 +364,9 @@ class Namer { typer: Typer => val info = adjustIfModule(completer, tree) createOrRefine[Symbol](tree, name, flags | deferred | method | higherKinded, _ => info, - (fs, _, pwithin) => ctx.newSymbol(ctx.owner, name, fs, info, pwithin, tree.namePos)) + (fs, _, pwithin) => ctx.newSymbol(ctx.owner, name, fs, info, pwithin, tree.nameSpan)) case tree: Import => - recordSym(ctx.newImportSymbol(ctx.owner, new Completer(tree), tree.pos), tree) + recordSym(ctx.newImportSymbol(ctx.owner, new Completer(tree), tree.span), tree) case _ => NoSymbol } @@ -870,7 +870,7 @@ class Namer { typer: Typer => else { if (denot.is(ModuleClass) && denot.sourceModule.is(Implicit)) missingType(denot.symbol, "parent ")(creationContext) - fullyDefinedType(typedAheadExpr(parent).tpe, "class parent", parent.pos) + fullyDefinedType(typedAheadExpr(parent).tpe, "class parent", parent.span) } case _ => UnspecifiedErrorType.assertingErrorsReported @@ -917,7 +917,7 @@ class Namer { typer: Typer => val moduleType = cls.owner.thisType select sourceModule if (self.name == nme.WILDCARD) moduleType else recordSym( - ctx.newSymbol(cls, self.name, self.mods.flags, moduleType, coord = self.pos), + ctx.newSymbol(cls, self.name, self.mods.flags, moduleType, coord = self.span), self) } else createSymbol(self) @@ -1130,7 +1130,7 @@ class Namer { typer: Typer => } def cookedRhsType = deskolemize(dealiasIfUnit(widenRhs(rhsType))) - def lhsType = fullyDefinedType(cookedRhsType, "right-hand side", mdef.pos) + def lhsType = fullyDefinedType(cookedRhsType, "right-hand side", mdef.span) //if (sym.name.toString == "y") println(i"rhs = $rhsType, cooked = $cookedRhsType") if (inherited.exists) { if (sym.is(Final, butNot = Method)) { diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index cf3a9ff98538..9944e2ce3b3a 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -861,7 +861,7 @@ object RefChecks { class OptLevelInfo { def levelAndIndex: LevelAndIndex = Map() - def enterReference(sym: Symbol, pos: Span): Unit = () + def enterReference(sym: Symbol, span: Span): Unit = () } /** A class to help in forward reference checking */ @@ -877,15 +877,15 @@ object RefChecks { (m1, idx + 1) }._1 var maxIndex: Int = Int.MinValue - var refPos: Span = _ + var refSpan: Span = _ var refSym: Symbol = _ - override def enterReference(sym: Symbol, pos: Span): Unit = + override def enterReference(sym: Symbol, span: Span): Unit = if (sym.exists && sym.owner.isTerm) levelAndIndex.get(sym) match { case Some((level, idx)) if (level.maxIndex < idx) => level.maxIndex = idx - level.refPos = pos + level.refSpan = span level.refSym = sym case _ => } @@ -959,7 +959,7 @@ class RefChecks extends MiniPhase { thisPhase => currentLevel.levelAndIndex.get(sym) match { case Some((level, symIdx)) if symIdx <= level.maxIndex => ctx.error(ForwardReferenceExtendsOverDefinition(sym, level.refSym), - ctx.source.atSpan(level.refPos)) + ctx.source.atSpan(level.refSpan)) case _ => } } @@ -988,7 +988,7 @@ class RefChecks extends MiniPhase { thisPhase => override def transformIdent(tree: Ident)(implicit ctx: Context): Ident = { checkUndesiredProperties(tree.symbol, tree.sourcePos) - currentLevel.enterReference(tree.symbol, tree.pos) + currentLevel.enterReference(tree.symbol, tree.span) tree } @@ -1005,7 +1005,7 @@ class RefChecks extends MiniPhase { thisPhase => // An implementation restriction to avoid VerifyErrors and lazyvals mishaps; see SI-4717 ctx.debuglog("refsym = " + level.refSym) ctx.error("forward reference not allowed from self constructor invocation", - ctx.source.atSpan(level.refPos)) + ctx.source.atSpan(level.refSpan)) } } tree @@ -1015,9 +1015,9 @@ class RefChecks extends MiniPhase { thisPhase => val tpe = tree.tpe val sym = tpe.typeSymbol checkUndesiredProperties(sym, tree.sourcePos) - currentLevel.enterReference(sym, tree.pos) + currentLevel.enterReference(sym, tree.span) tpe.dealias.foreachPart { - case TermRef(_, s: Symbol) => currentLevel.enterReference(s, tree.pos) + case TermRef(_, s: Symbol) => currentLevel.enterReference(s, tree.span) case _ => } tree diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 47efd7a2e44c..d7e715627516 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -58,7 +58,7 @@ object Typer { /** Assert tree has a position, unless it is empty or a typed splice */ def assertPositioned(tree: untpd.Tree)(implicit ctx: Context): Unit = if (!tree.isEmpty && !tree.isInstanceOf[untpd.TypedSplice] && ctx.typerState.isGlobalCommittable) - assert(tree.pos.exists, s"position not set for $tree # ${tree.uniqueId} in ${tree.source}") + assert(tree.span.exists, s"position not set for $tree # ${tree.uniqueId} in ${tree.source}") /** A context property that indicates the owner of any expressions to be typed in the context * if that owner is different from the context's owner. Typically, a context with a class @@ -112,9 +112,9 @@ class Typer extends Namer * @param name the name of the identifier * @param pt the expected type * @param required flags the result's symbol must have - * @param pos position to use for error reporting + * @param posd indicates position to use for error reporting */ - def findRef(name: Name, pt: Type, required: FlagConjunction, tree: untpd.Tree)(implicit ctx: Context): Type = { + def findRef(name: Name, pt: Type, required: FlagConjunction, posd: Positioned)(implicit ctx: Context): Type = { val refctx = ctx val noImports = ctx.mode.is(Mode.InPackageClauseName) @@ -164,14 +164,14 @@ class Typer extends Namer } else { if (!scala2pkg && !previous.isError && !found.isError) { - refctx.error(AmbiguousImport(name, newPrec, prevPrec, prevCtx), tree.sourcePos) + refctx.error(AmbiguousImport(name, newPrec, prevPrec, prevCtx), posd.sourcePos) } previous } def selection(imp: ImportInfo, name: Name) = if (imp.sym.isCompleting) { - ctx.warning(i"cyclic ${imp.sym}, ignored", tree.sourcePos) + ctx.warning(i"cyclic ${imp.sym}, ignored", posd.sourcePos) NoType } else if (unimported.nonEmpty && unimported.contains(imp.site.termSymbol)) NoType @@ -193,7 +193,7 @@ class Typer extends Namer def checkUnambiguous(found: Type) = { val other = recur(selectors.tail) if (other.exists && found.exists && (found != other)) - refctx.error(em"reference to `$name` is ambiguous; it is imported twice", tree.sourcePos) + refctx.error(em"reference to `$name` is ambiguous; it is imported twice", posd.sourcePos) found } @@ -362,7 +362,7 @@ class Typer extends Namer unimported = Set.empty foundUnderScala2 = NoType try { - var found = findRef(name, pt, EmptyFlagConjunction, tree) + var found = findRef(name, pt, EmptyFlagConjunction, tree.posd) if (foundUnderScala2.exists && !(foundUnderScala2 =:= found)) { ctx.migrationWarning( ex"""Name resolution will change. @@ -603,7 +603,7 @@ class Typer extends Namer case tref: TypeRef if !tref.symbol.isClass && !ctx.isAfterTyper => require(ctx.mode.is(Mode.Pattern)) inferImplicit(defn.ClassTagType.appliedTo(tref), - EmptyTree, tree.tpt.pos)(ctx.retractMode(Mode.Pattern)) match { + EmptyTree, tree.tpt.span)(ctx.retractMode(Mode.Pattern)) match { case SearchSuccess(clsTag, _, _) => typed(untpd.Apply(untpd.TypedSplice(clsTag), untpd.TypedSplice(tree.expr)), pt) case _ => @@ -712,7 +712,7 @@ class Typer extends Namer def noLeaks(t: Tree): Boolean = escapingRefs(t, localSyms).isEmpty if (noLeaks(tree)) tree else { - fullyDefinedType(tree.tpe, "block", tree.pos) + fullyDefinedType(tree.tpe, "block", tree.span) var avoidingType = avoid(tree.tpe, localSyms) val ptDefined = isFullyDefined(pt, ForceDegree.none) if (ptDefined && !(avoidingType <:< pt)) avoidingType = pt @@ -802,7 +802,7 @@ class Typer extends Namer val typeArgs = params1.map(_.tpt) :+ resTpt val tycon = TypeTree(funCls.typeRef) val core = assignType(cpy.AppliedTypeTree(tree)(tycon, typeArgs), tycon, typeArgs) - val appMeth = ctx.newSymbol(ctx.owner, nme.apply, Synthetic | Method | Deferred, mt, coord = body.pos) + val appMeth = ctx.newSymbol(ctx.owner, nme.apply, Synthetic | Method | Deferred, mt, coord = body.span) val appDef = assignType( untpd.DefDef(appMeth.name, Nil, List(params1), resultTpt, EmptyTree), appMeth).withPosOf(body) @@ -812,7 +812,7 @@ class Typer extends Namer args match { case ValDef(_, _, _) :: _ => typedDependent(args.asInstanceOf[List[ValDef]])( - ctx.fresh.setOwner(ctx.newRefinedClassSymbol(tree.pos)).setNewScope) + ctx.fresh.setOwner(ctx.newRefinedClassSymbol(tree.span)).setNewScope) case _ => typed(cpy.AppliedTypeTree(tree)(untpd.TypeTree(funCls.typeRef), args :+ body), pt) } @@ -968,7 +968,7 @@ class Typer extends Namer throw new java.lang.Error( i"""internal error: cannot turn method type $mt into closure |because it has internal parameter dependencies, - |position = ${tree.pos}, raw type = ${mt.toString}""") // !!! DEBUG. Eventually, convert to an error? + |position = ${tree.span}, raw type = ${mt.toString}""") // !!! DEBUG. Eventually, convert to an error? } else if ((tree.tpt `eq` untpd.ImplicitEmptyTree) && mt.paramNames.isEmpty) // Note implicitness of function in target type since there are no method parameters that indicate it. @@ -977,7 +977,7 @@ class Typer extends Namer EmptyTree } case tp => - throw new java.lang.Error(i"internal error: closing over non-method $tp, pos = ${tree.pos}") + throw new java.lang.Error(i"internal error: closing over non-method $tp, pos = ${tree.span}") } else typed(tree.tpt) //println(i"typing closure $tree : ${meth1.tpe.widen}") @@ -1005,7 +1005,7 @@ class Typer extends Namer case _ => if (tree.isInline) checkInInlineContext("inline match", tree.sourcePos) val sel1 = typedExpr(tree.selector) - val selType = fullyDefinedType(sel1.tpe, "pattern selector", tree.pos).widen + val selType = fullyDefinedType(sel1.tpe, "pattern selector", tree.span).widen typedMatchFinish(tree, sel1, selType, tree.cases, pt) } } @@ -1384,7 +1384,7 @@ class Typer extends Namer //val ptt = if (lo.isEmpty && hi.isEmpty) pt else if (ctx.isAfterTyper) tree1 else { - val wildcardSym = ctx.newPatternBoundSymbol(tpnme.WILDCARD, tree1.tpe & pt, tree.pos) + val wildcardSym = ctx.newPatternBoundSymbol(tpnme.WILDCARD, tree1.tpe & pt, tree.span) untpd.Bind(tpnme.WILDCARD, tree1).withType(wildcardSym.typeRef) } } @@ -1392,7 +1392,7 @@ class Typer extends Namer } def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Tree = track("typedBind") { - val pt1 = fullyDefinedType(pt, "pattern variable", tree.pos) + val pt1 = fullyDefinedType(pt, "pattern variable", tree.span) val body1 = typed(tree.body, pt1) body1 match { case UnApply(fn, Nil, arg :: Nil) @@ -1410,7 +1410,7 @@ class Typer extends Namer val symTp = if (body1.tpe.isInstanceOf[TermRef]) pt1 else body1.tpe.underlyingIfRepeated(isJava = false) - val sym = ctx.newPatternBoundSymbol(tree.name, symTp, tree.pos) + val sym = ctx.newPatternBoundSymbol(tree.name, symTp, tree.span) if (pt == defn.ImplicitScrutineeTypeRef) sym.setFlag(Implicit) if (ctx.mode.is(Mode.InPatternAlternative)) ctx.error(i"Illegal variable ${sym.name} in pattern alternative", tree.sourcePos) @@ -1476,7 +1476,7 @@ class Typer extends Namer if (sym.is(Lazy, butNot = Deferred | Module | Synthetic) && !sym.isVolatile && ctx.scala2Mode && ctx.settings.rewrite.value.isDefined && !ctx.isAfterTyper) - patch(Span(toUntyped(vdef).pos.start), "@volatile ") + patch(Span(toUntyped(vdef).span.start), "@volatile ") } /** Adds inline to final vals with idempotent rhs @@ -1622,7 +1622,7 @@ class Typer extends Namer completeAnnotations(cdef, cls) val constr1 = typed(constr).asInstanceOf[DefDef] - val parentsWithClass = ensureFirstTreeIsClass(parents mapconserve typedParent, cdef.namePos) + val parentsWithClass = ensureFirstTreeIsClass(parents mapconserve typedParent, cdef.nameSpan) val parents1 = ensureConstrCall(cls, parentsWithClass)(superCtx) var self1 = typed(self)(ctx.outer).asInstanceOf[ValDef] // outer context where class members are not visible if (cls.isOpaqueCompanion) { @@ -1641,7 +1641,7 @@ class Typer extends Namer val impl1 = cpy.Template(impl)(constr1, parents1, self1, body1) .withType(dummy.termRef) if (!cls.is(AbstractOrTrait) && !ctx.isAfterTyper) - checkRealizableBounds(cls, cdef.sourcePos.withSpan(cdef.namePos)) + checkRealizableBounds(cls, cdef.sourcePos.withSpan(cdef.nameSpan)) if (cls.is(Case) && cls.derivesFrom(defn.EnumClass)) { val firstParent = parents1.head.tpe.dealias.typeSymbol checkEnum(cdef, cls, firstParent) @@ -1695,7 +1695,7 @@ class Typer extends Namer * - has C as its class symbol, and * - for all parents P_i: If P_i derives from C then P_i <:< CT. */ - def ensureFirstIsClass(parents: List[Type], pos: Span)(implicit ctx: Context): List[Type] = { + def ensureFirstIsClass(parents: List[Type], span: Span)(implicit ctx: Context): List[Type] = { def realClassParent(cls: Symbol): ClassSymbol = if (!cls.isClass) defn.ObjectClass else if (!(cls is Trait)) cls.asClass @@ -1713,14 +1713,14 @@ class Typer extends Namer val pcls = (defn.ObjectClass /: parents)(improve) typr.println(i"ensure first is class $parents%, % --> ${parents map (_ baseType pcls)}%, %") val first = ctx.typeComparer.glb(defn.ObjectType :: parents.map(_.baseType(pcls))) - checkFeasibleParent(first, ctx.source.atSpan(pos), em" in inferred superclass $first") :: parents + checkFeasibleParent(first, ctx.source.atSpan(span), em" in inferred superclass $first") :: parents } } /** Ensure that first parent tree refers to a real class. */ - def ensureFirstTreeIsClass(parents: List[Tree], pos: Span)(implicit ctx: Context): List[Tree] = parents match { + def ensureFirstTreeIsClass(parents: List[Tree], span: Span)(implicit ctx: Context): List[Tree] = parents match { case p :: ps if p.tpe.classSymbol.isRealClass => parents - case _ => TypeTree(ensureFirstIsClass(parents.tpes, pos).head).withSpan(pos.focus) :: parents + case _ => TypeTree(ensureFirstIsClass(parents.tpes, span).head).withSpan(span.focus) :: parents } /** If this is a real class, make sure its first parent is a @@ -1737,7 +1737,7 @@ class Typer extends Namer def checkVariance(tree: Tree)(implicit ctx: Context): Unit = VarianceChecker.check(tree) def localDummy(cls: ClassSymbol, impl: untpd.Template)(implicit ctx: Context): Symbol = - ctx.newLocalDummy(cls, impl.pos) + ctx.newLocalDummy(cls, impl.span) def typedImport(imp: untpd.Import, sym: Symbol)(implicit ctx: Context): Import = track("typedImport") { val expr1 = typedExpr(imp.expr, AnySelectionProto) @@ -1794,8 +1794,8 @@ class Typer extends Namer ctx.errorOrMigrationWarning(OnlyFunctionsCanBeFollowedByUnderscore(recovered.tpe.widen), tree.sourcePos) if (ctx.scala2Mode) { // Under -rewrite, patch `x _` to `(() => x)` - patch(Span(tree.pos.start), "(() => ") - patch(Span(qual.pos.end, tree.pos.end), ")") + patch(Span(tree.span.start), "(() => ") + patch(Span(qual.span.end, tree.span.end), ")") return typed(untpd.Function(Nil, qual), pt) } } @@ -1814,8 +1814,8 @@ class Typer extends Namer ctx.errorOrMigrationWarning(i"""The syntax ` _` is no longer supported; |you can $remedy""", tree.sourcePos) if (ctx.scala2Mode) { - patch(Span(tree.pos.start), prefix) - patch(Span(qual.pos.end, tree.pos.end), suffix) + patch(Span(tree.span.start), prefix) + patch(Span(qual.span.end, tree.span.end), suffix) } } res @@ -2016,8 +2016,8 @@ class Typer extends Namer catch { case ex: TypeError => errorTree(tree, ex.toMessage, tree.sourcePos.focus) - // This uses tree.pos.focus instead of the default tree.pos, because: - // - since tree can be a top-level definition, tree.pos can point to the whole definition + // This uses tree.span.focus instead of the default tree.span, because: + // - since tree can be a top-level definition, tree.span can point to the whole definition // - that would in turn hide all other type errors inside tree. // TODO: might be even better to store positions inside TypeErrors. } @@ -2354,7 +2354,7 @@ class Typer extends Namer def implicitArgs(formals: List[Type], argIndex: Int): List[Tree] = formals match { case Nil => Nil case formal :: formals1 => - val arg = inferImplicitArg(formal, tree.pos.endPos) + val arg = inferImplicitArg(formal, tree.span.endPos) arg.tpe match { case failed: SearchFailureType if !failed.isInstanceOf[AmbiguousImplicits] && !tree.symbol.hasDefaultParams => @@ -2468,7 +2468,7 @@ class Typer extends Namer sym.isConstructor || sym.matchNullaryLoosely || ctx.testScala2Mode(MissingEmptyArgumentList(sym), tree.sourcePos, - patch(tree.pos.endPos, "()")) + patch(tree.span.endPos, "()")) } // Reasons NOT to eta expand: @@ -2633,7 +2633,7 @@ class Typer extends Namer case SelectionProto(name, mbrType, _, _) => def tryExtension(implicit ctx: Context): Tree = try { - findRef(name, WildcardType, ExtensionMethod, tree) match { + findRef(name, WildcardType, ExtensionMethod, tree.posd) match { case ref: TermRef => extMethodApply(untpd.ref(ref).withPosOf(tree), tree, mbrType) case _ => EmptyTree diff --git a/compiler/src/dotty/tools/dotc/util/Signatures.scala b/compiler/src/dotty/tools/dotc/util/Signatures.scala index 6ce32b596334..14dcddcb77dd 100644 --- a/compiler/src/dotty/tools/dotc/util/Signatures.scala +++ b/compiler/src/dotty/tools/dotc/util/Signatures.scala @@ -44,15 +44,15 @@ object Signatures { * Extract (current parameter index, function index, functions) out of a method call. * * @param path The path to the function application - * @param pos The position of the cursor + * @param span The position of the cursor * @return A triple containing the index of the parameter being edited, the index of the function * being called, the list of overloads of this function). */ - def callInfo(path: List[tpd.Tree], pos: Span)(implicit ctx: Context): (Int, Int, List[SingleDenotation]) = { + def callInfo(path: List[tpd.Tree], span: Span)(implicit ctx: Context): (Int, Int, List[SingleDenotation]) = { path match { case Apply(fun, params) :: _ => val alreadyAppliedCount = Signatures.countParams(fun) - val paramIndex = params.indexWhere(_.pos.contains(pos)) match { + val paramIndex = params.indexWhere(_.span.contains(span)) match { case -1 => (params.length - 1 max 0) + alreadyAppliedCount case n => n + alreadyAppliedCount } @@ -170,7 +170,7 @@ object Signatures { // `null` parameter: `foo(bar, null)`. This may influence what's the "best" // alternative, so we discard it. val userParams = params match { - case xs :+ (nul @ Literal(Constant(null))) if nul.pos.isZeroExtent => xs + case xs :+ (nul @ Literal(Constant(null))) if nul.span.isZeroExtent => xs case _ => params } val userParamsTypes = userParams.map(_.tpe) diff --git a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala index a9a00eb55fcf..a2ef9a81ce9b 100644 --- a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala +++ b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala @@ -7,7 +7,7 @@ import printing.Texts._ import Spans.{Span, NoSpan} import scala.annotation.internal.sharable -/** A source position is comprised of a position in a source file */ +/** A source position is comprised of a span and a source file */ case class SourcePosition(source: SourceFile, span: Span, outer: SourcePosition = NoSourcePosition) extends interfaces.SourcePosition with Showable { /** Is `that` a source position contained in this source position ? diff --git a/compiler/src/dotty/tools/repl/ReplCompiler.scala b/compiler/src/dotty/tools/repl/ReplCompiler.scala index 0941ab468bfb..7e20f4e28313 100644 --- a/compiler/src/dotty/tools/repl/ReplCompiler.scala +++ b/compiler/src/dotty/tools/repl/ReplCompiler.scala @@ -135,7 +135,7 @@ class ReplCompiler extends Compiler { val tmpl = Template(emptyConstructor, Nil, EmptyValDef, defs.stats) val module = ModuleDef(objectName(defs.state), tmpl) - .withSpan(Span(0, defs.stats.last.pos.end)) + .withSpan(Span(0, defs.stats.last.span.end)) PackageDef(Ident(nme.EMPTY_PACKAGE), List(module)) } diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala index b51e93ab49d6..8c2fade43898 100644 --- a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala +++ b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala @@ -129,7 +129,7 @@ class DocASTPhase extends Phase { ValImpl(v.symbol, annotations(v.symbol), v.name.decode.toString, flags(v), path(v.symbol), returnType(v.tpt.tpe), kind) :: Nil case x => { - ctx.docbase.debug(s"Found unwanted entity: $x (${x.pos},\n${x.show}") + ctx.docbase.debug(s"Found unwanted entity: $x (${x.span},\n${x.show}") Nil } } From a958ecea2e614e68d4bee3409d340983f20d5e83 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 4 Jan 2019 12:35:23 +0100 Subject: [PATCH 41/75] Rename Symbol#pos -> span, Comment#pos -> span --- .../dotty/tools/backend/sjs/JSCodeGen.scala | 14 ++++---- .../src/dotty/tools/dotc/ast/TreeInfo.scala | 8 ++--- compiler/src/dotty/tools/dotc/ast/tpd.scala | 2 +- .../src/dotty/tools/dotc/core/Comments.scala | 32 +++++++++---------- .../src/dotty/tools/dotc/core/Symbols.scala | 13 ++++---- .../dotc/core/tasty/CommentPickler.scala | 2 +- .../dotc/reporting/diagnostic/messages.scala | 2 +- .../tools/dotc/transform/AccessProxies.scala | 8 ++--- .../dotty/tools/dotc/transform/Bridges.scala | 6 ++-- .../dotty/tools/dotc/transform/Mixin.scala | 2 +- .../dotty/tools/dotc/transform/MixinOps.scala | 4 +-- .../dotc/transform/NonLocalReturns.scala | 2 +- .../tools/dotc/transform/PatternMatcher.scala | 2 +- .../dotc/transform/SyntheticMethods.scala | 6 ++-- .../dotty/tools/dotc/typer/Applications.scala | 2 +- .../src/dotty/tools/dotc/typer/Inliner.scala | 2 +- .../src/dotty/tools/dotc/typer/Namer.scala | 2 +- .../src/dotty/tools/dotc/util/Spans.scala | 6 ++-- .../tools/dottydoc/core/DocstringPhase.scala | 6 ++-- 19 files changed, 60 insertions(+), 61 deletions(-) diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index df01cfc6ddc5..18a7a88e0b24 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -129,7 +129,7 @@ class JSCodeGen()(implicit ctx: Context) { /* Finally, we emit true code for the remaining class defs. */ for (td <- allTypeDefs) { val sym = td.symbol - implicit val pos: Position = sym.pos + implicit val pos: Position = sym.span /* Do not actually emit code for primitive types nor scala.Array. */ val isPrimitive = @@ -197,7 +197,7 @@ class JSCodeGen()(implicit ctx: Context) { */ private def genScalaClass(td: TypeDef): js.ClassDef = { val sym = td.symbol.asClass - implicit val pos: Position = sym.pos + implicit val pos: Position = sym.span assert(!sym.is(Trait), "genScalaClass() must be called only for normal classes: "+sym) @@ -321,7 +321,7 @@ class JSCodeGen()(implicit ctx: Context) { */ private def genRawJSClassData(td: TypeDef): js.ClassDef = { val sym = td.symbol.asClass - implicit val pos: Position = sym.pos + implicit val pos: Position = sym.span val classIdent = encodeClassFullNameIdent(sym) val kind = { @@ -357,7 +357,7 @@ class JSCodeGen()(implicit ctx: Context) { */ private def genInterface(td: TypeDef): js.ClassDef = { val sym = td.symbol.asClass - implicit val pos: Position = sym.pos + implicit val pos: Position = sym.span val classIdent = encodeClassFullNameIdent(sym) @@ -413,7 +413,7 @@ class JSCodeGen()(implicit ctx: Context) { // Non-method term members are fields classSym.info.decls.filter(f => !f.is(Method) && f.isTerm).map({ f => - implicit val pos = f.pos + implicit val pos = f.span val name = /*if (isExposed(f)) js.StringLiteral(jsNameOf(f)) @@ -506,7 +506,7 @@ class JSCodeGen()(implicit ctx: Context) { val methodName: js.PropertyName = encodeMethodSym(sym) def jsParams = for (param <- params) yield { - implicit val pos = param.pos + implicit val pos = param.span js.ParamDef(encodeLocalSym(param), toIRType(param.info), mutable = false, rest = false) } @@ -585,7 +585,7 @@ class JSCodeGen()(implicit ctx: Context) { ctx.debuglog("") val jsParams = for (param <- paramsSyms) yield { - implicit val pos = param.pos + implicit val pos = param.span js.ParamDef(encodeLocalSym(param), toIRType(param.info), mutable = false, rest = false) } diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 86f6714b76a1..6789bd55e96a 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -663,11 +663,11 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => * if no such path exists. * Pre: `sym` must have a position. */ - def defPath(sym: Symbol, root: Tree)(implicit ctx: Context): List[Tree] = trace.onDebug(s"defpath($sym with position ${sym.pos}, ${root.show})") { - require(sym.pos.exists) + def defPath(sym: Symbol, root: Tree)(implicit ctx: Context): List[Tree] = trace.onDebug(s"defpath($sym with position ${sym.span}, ${root.show})") { + require(sym.span.exists) object accum extends TreeAccumulator[List[Tree]] { def apply(x: List[Tree], tree: Tree)(implicit ctx: Context): List[Tree] = { - if (tree.span.contains(sym.pos)) + if (tree.span.contains(sym.span)) if (definedSym(tree) == sym) tree :: x else { val x1 = foldOver(x, tree) @@ -716,7 +716,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => * tree must be reachable from come tree stored in an enclosing context. */ def definingStats(sym: Symbol)(implicit ctx: Context): List[Tree] = - if (!sym.pos.exists || (ctx eq NoContext) || ctx.compilationUnit == null) Nil + if (!sym.span.exists || (ctx eq NoContext) || ctx.compilationUnit == null) Nil else defPath(sym, ctx.compilationUnit.tpdTree) match { case defn :: encl :: _ => def verify(stats: List[Tree]) = diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index c6b62d4a073a..8e86119732f9 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -314,7 +314,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { if (parents.head.classSymbol.is(Trait)) parents.head.parents.head :: parents else parents val cls = ctx.newNormalizedClassSymbol(owner, tpnme.ANON_CLASS, Synthetic | Final, parents1, - coord = fns.map(_.pos).reduceLeft(_ union _)) + coord = fns.map(_.span).reduceLeft(_ union _)) val constr = ctx.newConstructor(cls, Synthetic, Nil, Nil).entered def forwarder(fn: TermSymbol, name: TermName) = { val fwdMeth = fn.copy(cls, name, Synthetic | Method | Final).entered.asTerm diff --git a/compiler/src/dotty/tools/dotc/core/Comments.scala b/compiler/src/dotty/tools/dotc/core/Comments.scala index 355e9aac250c..1a8149edb40f 100644 --- a/compiler/src/dotty/tools/dotc/core/Comments.scala +++ b/compiler/src/dotty/tools/dotc/core/Comments.scala @@ -40,12 +40,12 @@ object Comments { * A `Comment` contains the unformatted docstring, it's position and potentially more * information that is populated when the comment is "cooked". * - * @param pos The position of this `Comment`. + * @param span The position span of this `Comment`. * @param raw The raw comment, as seen in the source code, without any expansion. * @param expanded If this comment has been expanded, it's expansion, otherwise `None`. * @param usecases The usecases for this comment. */ - final case class Comment(pos: Span, raw: String, expanded: Option[String], usecases: List[UseCase]) { + final case class Comment(span: Span, raw: String, expanded: Option[String], usecases: List[UseCase]) { /** Has this comment been cooked or expanded? */ def isExpanded: Boolean = expanded.isDefined @@ -65,8 +65,8 @@ object Comments { */ def expand(f: String => String)(implicit ctx: Context): Comment = { val expandedComment = f(raw) - val useCases = Comment.parseUsecases(expandedComment, pos) - Comment(pos, raw, Some(expandedComment), useCases) + val useCases = Comment.parseUsecases(expandedComment, span) + Comment(span, raw, Some(expandedComment), useCases) } } @@ -74,16 +74,16 @@ object Comments { def isDocComment(comment: String): Boolean = comment.startsWith("/**") - def apply(pos: Span, raw: String): Comment = - Comment(pos, raw, None, Nil) + def apply(span: Span, raw: String): Comment = + Comment(span, raw, None, Nil) - private def parseUsecases(expandedComment: String, pos: Span)(implicit ctx: Context): List[UseCase] = + private def parseUsecases(expandedComment: String, span: Span)(implicit ctx: Context): List[UseCase] = if (!isDocComment(expandedComment)) { Nil } else { tagIndex(expandedComment) .filter { startsWithTag(expandedComment, _, "@usecase") } - .map { case (start, end) => decomposeUseCase(expandedComment, pos, start, end) } + .map { case (start, end) => decomposeUseCase(expandedComment, span, start, end) } } /** Turns a usecase section into a UseCase, with code changed to: @@ -94,13 +94,13 @@ object Comments { * def foo: A = ??? * }}} */ - private[this] def decomposeUseCase(body: String, pos: Span, start: Int, end: Int)(implicit ctx: Context): UseCase = { + private[this] def decomposeUseCase(body: String, span: Span, start: Int, end: Int)(implicit ctx: Context): UseCase = { def subPos(start: Int, end: Int) = - if (pos == NoSpan) NoSpan + if (span == NoSpan) NoSpan else { - val start1 = pos.start + start - val end1 = pos.end + end - pos withStart start1 withPoint start1 withEnd end1 + val start1 = span.start + start + val end1 = span.end + end + span withStart start1 withPoint start1 withEnd end1 } val codeStart = skipWhitespace(body, start + "@usecase".length) @@ -199,7 +199,7 @@ object Comments { case None => // SI-8210 - The warning would be false negative when this symbol is a setter if (ownComment.indexOf("@inheritdoc") != -1 && ! sym.isSetter) - dottydoc.println(s"${sym.pos}: the comment for ${sym} contains @inheritdoc, but no parent comment is available to inherit from.") + dottydoc.println(s"${sym.span}: the comment for ${sym} contains @inheritdoc, but no parent comment is available to inherit from.") ownComment.replaceAllLiterally("@inheritdoc", "") case Some(sc) => if (ownComment == "") sc @@ -314,7 +314,7 @@ object Comments { val sectionTextBounds = extractSectionText(parent, section) cleanupSectionText(parent.substring(sectionTextBounds._1, sectionTextBounds._2)) case None => - dottydoc.println(s"""${sym.pos}: the """" + getSectionHeader + "\" annotation of the " + sym + + dottydoc.println(s"""${sym.span}: the """" + getSectionHeader + "\" annotation of the " + sym + " comment contains @inheritdoc, but the corresponding section in the parent is not defined.") "" } @@ -442,7 +442,7 @@ object Comments { * the position of the doc comment of the overridden version is returned instead. */ def docCommentPos(sym: Symbol)(implicit ctx: Context): Span = - ctx.docCtx.flatMap(_.docstring(sym).map(_.pos)).getOrElse(NoSpan) + ctx.docCtx.flatMap(_.docstring(sym).map(_.span)).getOrElse(NoSpan) /** A version which doesn't consider self types, as a temporary measure: * an infinite loop has broken out between superComment and cookedDocComment diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index d791ab5765cf..2a2eb9d15523 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -212,8 +212,8 @@ trait Symbols { this: Context => /** Define a new symbol associated with a Bind or pattern wildcard and * make it gadt narrowable. */ - def newPatternBoundSymbol(name: Name, info: Type, pos: Span): Symbol = { - val sym = newSymbol(owner, name, Case, info, coord = pos) + def newPatternBoundSymbol(name: Name, info: Type, span: Span): Symbol = { + val sym = newSymbol(owner, name, Case, info, coord = span) if (name.isTypeName) { val bounds = info.bounds gadt.addBound(sym, bounds.lo, isUpper = false) @@ -498,7 +498,7 @@ object Symbols { /** Does this symbol come from a currently compiled source file? */ final def isDefinedInCurrentRun(implicit ctx: Context): Boolean = - pos.exists && defRunId == ctx.runId && { + span.exists && defRunId == ctx.runId && { val file = associatedFile file != null && ctx.run.files.contains(file) } @@ -663,14 +663,13 @@ object Symbols { denot.owner.sourceSymbol else this - /** The position of this symbol, or NoPosition if the symbol was not loaded + /** The position of this symbol, or NoSpan if the symbol was not loaded * from source or from TASTY. This is always a zero-extent position. * * NOTE: If the symbol was not loaded from the current compilation unit, * the implicit conversion `sourcePos` will return the wrong result, careful! - * TODO: Consider changing this method return type to `SourcePosition`. */ - final def pos: Span = if (coord.isPosition) coord.toPosition else NoSpan + final def span: Span = if (coord.isSpan) coord.toSpan else NoSpan final def sourcePos(implicit ctx: Context): SourcePosition = { val source = { @@ -680,7 +679,7 @@ object Symbols { ctx.source else ctx.getSource(f) } - source.atSpan(pos) + source.atSpan(span) } // ParamInfo types and methods diff --git a/compiler/src/dotty/tools/dotc/core/tasty/CommentPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/CommentPickler.scala index 5fa2272d39e7..426f0194ccad 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/CommentPickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/CommentPickler.scala @@ -23,7 +23,7 @@ class CommentPickler(pickler: TastyPickler, addrOfTree: tpd.Tree => Option[Addr] buf.writeAddr(addr) buf.writeNat(length) buf.writeBytes(bytes, length) - buf.writeLongInt(cmt.pos.coords) + buf.writeLongInt(cmt.span.coords) case other => () } diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 9714b1dc518a..664db63647f4 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -2103,7 +2103,7 @@ object messages { case _ /* Signature.FullMatch */ => "\nThe definitions have matching type signatures after erasure." } } else "" - hl"${decl.showLocated} is already defined as ${previousDecl.showDcl} ${if (previousDecl.pos.exists) s"at line ${previousDecl.sourcePos.line + 1}" else ""}." + details + hl"${decl.showLocated} is already defined as ${previousDecl.showDcl} ${if (previousDecl.span.exists) s"at line ${previousDecl.sourcePos.line + 1}" else ""}." + details } val explanation: String = "" } diff --git a/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala b/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala index ad6200d1c3ec..59c88d06ea5f 100644 --- a/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala +++ b/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala @@ -53,7 +53,7 @@ abstract class AccessProxies { accessRef.becomes(forwardedArgss.head.head) else accessRef.appliedToTypes(forwardedTypes).appliedToArgss(forwardedArgss) - rhs.withSpan(accessed.pos) + rhs.withSpan(accessed.span) }) /** Add all needed accessors to the `body` of class `cls` */ @@ -75,8 +75,8 @@ abstract class AccessProxies { } /** A fresh accessor symbol */ - private def newAccessorSymbol(owner: Symbol, name: TermName, info: Type, pos: Span)(implicit ctx: Context): TermSymbol = { - val sym = ctx.newSymbol(owner, name, Synthetic | Method, info, coord = pos).entered + private def newAccessorSymbol(owner: Symbol, name: TermName, info: Type, span: Span)(implicit ctx: Context): TermSymbol = { + val sym = ctx.newSymbol(owner, name, Synthetic | Method, info, coord = span).entered if (sym.allOverriddenSymbols.exists(!_.is(Deferred))) sym.setFlag(Override) sym } @@ -85,7 +85,7 @@ abstract class AccessProxies { protected def accessorSymbol(owner: Symbol, accessorName: TermName, accessorInfo: Type, accessed: Symbol)(implicit ctx: Context): Symbol = { def refersToAccessed(sym: Symbol) = accessedBy.get(sym).contains(accessed) owner.info.decl(accessorName).suchThat(refersToAccessed).symbol.orElse { - val acc = newAccessorSymbol(owner, accessorName, accessorInfo, accessed.pos) + val acc = newAccessorSymbol(owner, accessorName, accessorInfo, accessed.span) accessedBy(acc) = accessed acc } diff --git a/compiler/src/dotty/tools/dotc/transform/Bridges.scala b/compiler/src/dotty/tools/dotc/transform/Bridges.scala index fb81a495e238..884d5c71f2fd 100644 --- a/compiler/src/dotty/tools/dotc/transform/Bridges.scala +++ b/compiler/src/dotty/tools/dotc/transform/Bridges.scala @@ -42,7 +42,7 @@ class Bridges(root: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont private val bridgeTarget = newMutableSymbolMap[Symbol] def bridgePosFor(member: Symbol): SourcePosition = - (if (member.owner == root && member.pos.exists) member else root).sourcePos + (if (member.owner == root && member.span.exists) member else root).sourcePos /** Add a bridge between `member` and `other`, where `member` overrides `other` * before erasure, if the following conditions are satisfied. @@ -90,7 +90,7 @@ class Bridges(root: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont ctx.debuglog( i"""generating bridge from ${other.showLocated}: ${other.info} - |to ${member.showLocated}: ${member.info} @ ${member.pos} + |to ${member.showLocated}: ${member.info} @ ${member.span} |bridge: ${bridge.showLocated} with flags: ${bridge.flags}""") bridgeTarget(bridge) = member @@ -107,7 +107,7 @@ class Bridges(root: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont else ref.appliedToArgss(argss) } - bridges += DefDef(bridge, bridgeRhs(_).withSpan(bridge.pos)) + bridges += DefDef(bridge, bridgeRhs(_).withSpan(bridge.span)) } /** Add all necessary bridges to template statements `stats`, and remove at the same diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala index 6e1425e9f5ba..17aeb40ea6ee 100644 --- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala +++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala @@ -250,7 +250,7 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase => def setters(mixin: ClassSymbol): List[Tree] = for (setter <- mixin.info.decls.filter(setr => setr.isSetter && !was(setr, Deferred))) - yield transformFollowing(DefDef(implementation(setter.asTerm), unitLiteral.withSpan(cls.pos))) + yield transformFollowing(DefDef(implementation(setter.asTerm), unitLiteral.withSpan(cls.span))) cpy.Template(impl)( constr = diff --git a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala index a33c6e0f0438..a78ee88886da 100644 --- a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala +++ b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala @@ -28,13 +28,13 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont res } - def superRef(target: Symbol, pos: Span = cls.pos): Tree = { + def superRef(target: Symbol, span: Span = cls.span): Tree = { val sup = if (target.isConstructor && !target.owner.is(Trait)) Super(This(cls), tpnme.EMPTY, true) else Super(This(cls), target.owner.name.asTypeName, false, target.owner) //println(i"super ref $target on $sup") - ast.untpd.Select(sup.withSpan(pos), target.name) + ast.untpd.Select(sup.withSpan(span), target.name) .withType(NamedType(sup.tpe, target)) //sup.select(target) } diff --git a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala index d37c9e9d58ad..39a4d36fd10d 100644 --- a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala +++ b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala @@ -37,7 +37,7 @@ class NonLocalReturns extends MiniPhase { private def nonLocalReturnKey(meth: Symbol)(implicit ctx: Context) = nonLocalReturnKeys.getOrElseUpdate(meth, ctx.newSymbol( - meth, NonLocalReturnKeyName.fresh(), Synthetic, defn.ObjectType, coord = meth.pos)) + meth, NonLocalReturnKeyName.fresh(), Synthetic, defn.ObjectType, coord = meth.span)) /** Generate a non-local return throw with given return expression from given method. * I.e. for the method's non-local return key, generate: diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index fb72451b6a78..65aadb86ccb9 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -256,7 +256,7 @@ object PatternMatcher { def matchElemsPlan(seqSym: Symbol, args: List[Tree], exact: Boolean, onSuccess: Plan) = { val selectors = args.indices.toList.map(idx => ref(seqSym).select(defn.Seq_apply.matchingMember(seqSym.info)).appliedTo(Literal(Constant(idx)))) - TestPlan(LengthTest(args.length, exact), seqSym, seqSym.pos, + TestPlan(LengthTest(args.length, exact), seqSym, seqSym.span, matchArgsPlan(selectors, args, onSuccess)) } diff --git a/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala b/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala index ba8f2ac4e839..04b68a932ac0 100644 --- a/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala @@ -94,7 +94,7 @@ class SyntheticMethods(thisPhase: DenotTransformer) { case nme.productElement => vrefss => productElementBody(accessors.length, vrefss.head.head) } ctx.log(s"adding $synthetic to $clazz at ${ctx.phase}") - DefDef(synthetic, syntheticRHS(ctx.withOwner(synthetic))).withSpan(ctx.owner.pos.focus) + DefDef(synthetic, syntheticRHS(ctx.withOwner(synthetic))).withSpan(ctx.owner.span.focus) } /** The class @@ -158,7 +158,7 @@ class SyntheticMethods(thisPhase: DenotTransformer) { * */ def equalsBody(that: Tree)(implicit ctx: Context): Tree = { - val thatAsClazz = ctx.newSymbol(ctx.owner, nme.x_0, Synthetic, clazzType, coord = ctx.owner.pos) // x$0 + val thatAsClazz = ctx.newSymbol(ctx.owner, nme.x_0, Synthetic, 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 comparisons = accessors map { accessor => @@ -213,7 +213,7 @@ class SyntheticMethods(thisPhase: DenotTransformer) { def caseHashCodeBody(implicit ctx: Context): Tree = { val seed = clazz.fullName.toString.hashCode if (accessors.nonEmpty) { - val acc = ctx.newSymbol(ctx.owner, "acc".toTermName, Mutable | Synthetic, defn.IntType, coord = ctx.owner.pos) + val acc = ctx.newSymbol(ctx.owner, "acc".toTermName, Mutable | Synthetic, defn.IntType, coord = ctx.owner.span) val accDef = ValDef(acc, Literal(Constant(seed))) val mixes = for (accessor <- accessors) yield Assign(ref(acc), ref(defn.staticsMethod("mix")).appliedTo(ref(acc), hashImpl(accessor))) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index f21f56960935..dc6f3f88f5b0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1234,7 +1234,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => // `isSubType` as a TypeVar might get constrained by a TypeRef it's // part of. val tp1Params = tp1.newLikeThis(tp1.paramNames, tp1.paramInfos, defn.AnyType) - fullyDefinedType(tp1Params, "type parameters of alternative", alt1.symbol.pos) + fullyDefinedType(tp1Params, "type parameters of alternative", alt1.symbol.span) val tparams = ctx.newTypeParams(alt1.symbol, tp1.paramNames, EmptyFlags, tp1.instantiateParamInfos(_)) isAsSpecific(alt1, tp1.instantiate(tparams.map(_.typeRef)), alt2, tp2) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index eb4c9461c95b..e7686752d990 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -706,7 +706,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { */ def newBinding(sym: TermSymbol, rhs: Tree): Unit = { sym.info = rhs.tpe.widenTermRefExpr - bindingsBuf += ValDef(sym, constToLiteral(rhs)).withSpan(sym.pos) + bindingsBuf += ValDef(sym, constToLiteral(rhs)).withSpan(sym.span) } def searchImplicit(sym: TermSymbol, tpt: Tree) = { diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 3fa6abb1a42c..2835ed310d1d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -936,7 +936,7 @@ class Namer { typer: Typer => symbolOfTree(constr).ensureCompleted() val parentTypes = defn.adjustForTuple(cls, cls.typeParams, - ensureFirstIsClass(parents.map(checkedParentType(_)), cls.pos)) + ensureFirstIsClass(parents.map(checkedParentType(_)), cls.span)) typr.println(i"completing $denot, parents = $parents%, %, parentTypes = $parentTypes%, %") val finalSelfInfo: TypeOrSymbol = diff --git a/compiler/src/dotty/tools/dotc/util/Spans.scala b/compiler/src/dotty/tools/dotc/util/Spans.scala index 561bd8b87cfe..16bf0ff9e460 100644 --- a/compiler/src/dotty/tools/dotc/util/Spans.scala +++ b/compiler/src/dotty/tools/dotc/util/Spans.scala @@ -158,13 +158,13 @@ object Spans { */ class Coord(val encoding: Int) extends AnyVal { def isIndex: Boolean = encoding > 0 - def isPosition: Boolean = encoding <= 0 + def isSpan: Boolean = encoding <= 0 def toIndex: Int = { assert(isIndex) encoding - 1 } - def toPosition: Span = { - assert(isPosition) + def toSpan: Span = { + assert(isSpan) if (this == NoCoord) NoSpan else Span(-1 - encoding) } } diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala index fa6c06cd4759..025c56cfa91c 100644 --- a/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala +++ b/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala @@ -32,11 +32,11 @@ class DocstringPhase extends DocMiniPhase with CommentParser with CommentCleaner comment <- getComment(ent.symbol) text <- comment.expandedBody } yield { - val parsed = parse(ent, ctx.docbase.packages, clean(text), text, comment.pos) + val parsed = parse(ent, ctx.docbase.packages, clean(text), text, comment.span) if (ctx.settings.wikiSyntax.value) - WikiComment(ent, parsed, comment.pos).comment + WikiComment(ent, parsed, comment.span).comment else - MarkdownComment(ent, parsed, comment.pos).comment + MarkdownComment(ent, parsed, comment.span).comment } } From 1d16fabf97e3ecc1dcdf57c96cd633eb6343d78b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 4 Jan 2019 12:43:17 +0100 Subject: [PATCH 42/75] Apply renamings to language server --- .../dotty/tools/languageserver/DottyLanguageServer.scala | 8 ++++---- .../dotty/tools/languageserver/worksheet/Worksheet.scala | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala b/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala index 4aec9eb9f35d..76ae83ffc374 100644 --- a/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala +++ b/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala @@ -18,7 +18,7 @@ import scala.io.Codec import dotc._ import ast.{Trees, tpd} -import core._, core.Decorators.{sourcePos => _, _} +import core._, core.Decorators._ import Annotations.AnnotInfo import Comments._, Constants._, Contexts._, Flags._, Names._, NameOps._, Symbols._, SymDenotations._, Trees._, Types._ import classpath.ClassPathEntries @@ -388,7 +388,7 @@ class DottyLanguageServer extends LanguageServer val refs = path match { // Selected a renaming in an import node - case Thicket(_ :: (rename: Ident) :: Nil) :: (_: Import) :: rest if rename.pos.contains(pos.pos) => + case Thicket(_ :: (rename: Ident) :: Nil) :: (_: Import) :: rest if rename.span.contains(pos.span) => findRenamedReferences(uriTrees, syms, rename.name) // Selected a reference that has been renamed @@ -545,7 +545,7 @@ class DottyLanguageServer extends LanguageServer val trees = driver.openedTrees(uri) val path = Interactive.pathTo(trees, pos).dropWhile(!_.isInstanceOf[Apply]) - val (paramN, callableN, alternatives) = Signatures.callInfo(path, pos.pos) + val (paramN, callableN, alternatives) = Signatures.callInfo(path, pos.span) val signatureInfos = alternatives.flatMap(Signatures.toSignature) new SignatureHelp(signatureInfos.map(signatureToSignatureInformation).asJava, callableN, paramN) @@ -754,7 +754,7 @@ object DottyLanguageServer { * @return The position in the actual source file (before wrapping). */ private def toUnwrappedPosition(position: SourcePosition): SourcePosition = { - new SourcePosition(position.source, position.pos, position.outer) { + new SourcePosition(position.source, position.span, position.outer) { override def startLine: Int = position.startLine - 1 override def endLine: Int = position.endLine - 1 } diff --git a/language-server/src/dotty/tools/languageserver/worksheet/Worksheet.scala b/language-server/src/dotty/tools/languageserver/worksheet/Worksheet.scala index 58b30961c106..f51149ae0dea 100644 --- a/language-server/src/dotty/tools/languageserver/worksheet/Worksheet.scala +++ b/language-server/src/dotty/tools/languageserver/worksheet/Worksheet.scala @@ -40,7 +40,7 @@ object Worksheet { template.body.flatMap { case statement: DefTree if statement.symbol.is(Synthetic) => None - case statement if seen.add(bounds(statement.pos)) => + case statement if seen.add(bounds(statement.span)) => Some(query(statement, tree.source)) case _ => None @@ -66,12 +66,12 @@ object Worksheet { * @param sourcefile The sourcefile of the worksheet. */ private def query(tree: Tree, sourcefile: SourceFile): (Int, String) = { - val line = sourcefile.offsetToLine(tree.pos.end) - val source = sourcefile.content.slice(tree.pos.start, tree.pos.end).mkString + val line = sourcefile.offsetToLine(tree.span.end) + val source = sourcefile.content.slice(tree.span.start, tree.span.end).mkString (line, source) } - private def bounds(pos: Span): (Int, Int) = (pos.start, pos.end) + private def bounds(span: Span): (Int, Int) = (span.start, span.end) } From 70768faa1bf606d971a301da705415f4351dc282 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 4 Jan 2019 12:50:46 +0100 Subject: [PATCH 43/75] Rename other uses of `pos` to `span` --- .../tools/dotc/core/tasty/TreeUnpickler.scala | 2 +- .../core/unpickleScala2/Scala2Unpickler.scala | 2 +- .../dotty/tools/dotc/parsing/Scanners.scala | 4 +- .../dotc/parsing/xml/MarkupParsers.scala | 12 ++--- .../dotc/parsing/xml/SymbolicXMLBuilder.scala | 52 +++++++++---------- .../dotty/tools/dotc/rewrites/Rewrites.scala | 28 +++++----- .../dotty/tools/dotc/typer/EtaExpansion.scala | 2 +- .../src/dotty/tools/dotc/typer/ReTyper.scala | 2 +- .../dotty/tools/dotc/util/SourceFile.scala | 6 +-- .../src/dotty/tools/dotc/util/Spans.scala | 4 +- .../dottydoc/model/comment/Comment.scala | 16 +++--- .../model/comment/CommentParser.scala | 14 ++--- .../dottydoc/model/comment/HtmlParsers.scala | 4 +- .../dottydoc/model/comment/WikiParser.scala | 12 ++--- .../dotty/tools/dottydoc/util/syntax.scala | 4 +- 15 files changed, 82 insertions(+), 82 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 0a7952f656a4..79dbb4ad34a4 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -1327,7 +1327,7 @@ class TreeUnpickler(reader: TastyReader, def coordAt(addr: Addr)(implicit ctx: Context): Coord = { val pos = posAt(addr) if (pos.exists) - positionCoord(pos) + spanCoord(pos) else indexCoord(addr.index) } diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index d8e5caec1997..fd02618c3111 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -984,7 +984,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas symbol = readSymbolRef() } - implicit val pos: Span = NoSpan + implicit val span: Span = NoSpan tag match { case EMPTYtree => diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index c967c915b7c3..ec1c3c28106f 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -245,8 +245,8 @@ object Scanners { val isScala2Mode: Boolean = ctx.scala2Setting /** Cannot use ctx.featureEnabled because accessing the context would force too much */ - def testScala2Mode(msg: String, pos: Span = Span(offset)): Boolean = { - if (isScala2Mode) ctx.migrationWarning(msg, source atSpan pos) + def testScala2Mode(msg: String, span: Span = Span(offset)): Boolean = { + if (isScala2Mode) ctx.migrationWarning(msg, source.atSpan(span)) isScala2Mode } diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala index e839cd8873ca..8d64c9388ca4 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala @@ -179,8 +179,8 @@ object MarkupParsers { xTakeUntil(handle.comment, () => Span(start, curOffset, start), "-->") } - def appendText(pos: Span, ts: Buffer[Tree], txt: String): Unit = { - def append(t: String) = ts append handle.text(pos, t) + def appendText(span: Span, ts: Buffer[Tree], txt: String): Unit = { + def append(t: String) = ts append handle.text(span, t) if (preserveWS) append(txt) else { @@ -286,10 +286,10 @@ object MarkupParsers { val ts = content xEndTag(qname) debugLastStartElement = debugLastStartElement.tail - val pos = Span(start, curOffset, start) + val span = Span(start, curOffset, start) qname match { - case "xml:group" => handle.group(pos, ts) - case _ => handle.element(pos, qname, attrMap, false, ts) + case "xml:group" => handle.group(span, ts) + case _ => handle.element(span, qname, attrMap, false, ts) } } } @@ -411,7 +411,7 @@ object MarkupParsers { */ def xScalaPatterns: List[Tree] = escapeToScala(parser.patterns(), "pattern") - def reportSyntaxError(pos: Int, str: String): Unit = parser.syntaxError(str, pos) + def reportSyntaxError(offset: Int, str: String): Unit = parser.syntaxError(str, offset) def reportSyntaxError(str: String): Unit = { reportSyntaxError(curOffset, "in XML literal: " + str) nextch() diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala b/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala index ede21b715f16..4469d309a461 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala @@ -89,7 +89,7 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont /** Wildly wrong documentation deleted in favor of "self-documenting code." */ protected def mkXML( - pos: Span, + span: Span, isPattern: Boolean, pre: Tree, label: Tree, @@ -100,41 +100,41 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont { def starArgs = if (children.isEmpty) Nil - else List(Typed(makeXMLseq(pos, children), wildStar)) + else List(Typed(makeXMLseq(span, children), wildStar)) def pat = Apply(_scala_xml__Elem, List(pre, label, wild, wild) ::: convertToTextPat(children)) def nonpat = New(_scala_xml_Elem, List(List(pre, label, attrs, scope, if (empty) Literal(Constant(true)) else Literal(Constant(false))) ::: starArgs)) - atPos(pos) { if (isPattern) pat else nonpat } + atPos(span) { if (isPattern) pat else nonpat } } - final def entityRef(pos: Span, n: String): Tree = - atPos(pos)( New(_scala_xml_EntityRef, LL(const(n))) ) + final def entityRef(span: Span, n: String): Tree = + atPos(span)( New(_scala_xml_EntityRef, LL(const(n))) ) // create scala.xml.Text here <: scala.xml.Node - final def text(pos: Span, txt: String): Tree = atPos(pos) { + final def text(span: Span, txt: String): Tree = atPos(span) { if (isPattern) makeTextPat(const(txt)) else makeText1(const(txt)) } def makeTextPat(txt: Tree): Apply = Apply(_scala_xml__Text, List(txt)) def makeText1(txt: Tree): Tree = New(_scala_xml_Text, LL(txt)) - def comment(pos: Span, text: String): Tree = atPos(pos)( Comment(const(text)) ) - def charData(pos: Span, txt: String): Tree = atPos(pos)( makeText1(const(txt)) ) + def comment(span: Span, text: String): Tree = atPos(span)( Comment(const(text)) ) + def charData(span: Span, txt: String): Tree = atPos(span)( makeText1(const(txt)) ) - def procInstr(pos: Span, target: String, txt: String): Tree = - atPos(pos)( ProcInstr(const(target), const(txt)) ) + def procInstr(span: Span, target: String, txt: String): Tree = + atPos(span)( ProcInstr(const(target), const(txt)) ) protected def Comment(txt: Tree): Tree = New(_scala_xml_Comment, LL(txt)) protected def ProcInstr(target: Tree, txt: Tree): Tree = New(_scala_xml_ProcInstr, LL(target, txt)) /** @todo: attributes */ - def makeXMLpat(pos: Span, n: String, args: Seq[Tree]): Tree = { + def makeXMLpat(span: Span, n: String, args: Seq[Tree]): Tree = { val (prepat, labpat) = splitPrefix(n) match { case (Some(pre), rest) => (const(pre), const(rest)) case _ => (wild, const(n)) } - mkXML(pos, true, prepat, labpat, null, null, false, args) + mkXML(span, true, prepat, labpat, null, null, false, args) } protected def convertToTextPat(t: Tree): Tree = t match { @@ -144,12 +144,12 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont protected def convertToTextPat(buf: Seq[Tree]): List[Tree] = (buf map convertToTextPat).toList - def parseAttribute(pos: Span, s: String): Tree = { - val ts = Utility.parseAttributeValue(s, text(pos, _), entityRef(pos, _)) + def parseAttribute(span: Span, s: String): Tree = { + val ts = Utility.parseAttributeValue(s, text(span, _), entityRef(span, _)) ts match { - case Nil => TypedSplice(tpd.ref(defn.NilModule).withSpan(pos)) + case Nil => TypedSplice(tpd.ref(defn.NilModule).withSpan(span)) case t :: Nil => t - case _ => makeXMLseq(pos, ts) + case _ => makeXMLseq(span, ts) } } @@ -159,11 +159,11 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont } /** could optimize if args.length == 0, args.length == 1 AND args(0) is <: Node. */ - def makeXMLseq(pos: Span, args: Seq[Tree]): Block = { + def makeXMLseq(span: Span, args: Seq[Tree]): Block = { val buffer = ValDef(_buf, TypeTree(), New(_scala_xml_NodeBuffer, ListOfNil)) val applies = args filterNot isEmptyText map (t => Apply(Select(Ident(_buf), _plus), List(t))) - atPos(pos)( Block(buffer :: applies.toList, Ident(_buf)) ) + atPos(span)( Block(buffer :: applies.toList, Ident(_buf)) ) } /** Returns (Some(prefix) | None, rest) based on position of ':' */ @@ -173,13 +173,13 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont } /** Various node constructions. */ - def group(pos: Span, args: Seq[Tree]): Tree = - atPos(pos)( New(_scala_xml_Group, LL(makeXMLseq(pos, args))) ) + def group(span: Span, args: Seq[Tree]): Tree = + atPos(span)( New(_scala_xml_Group, LL(makeXMLseq(span, args))) ) - def unparsed(pos: Span, str: String): Tree = - atPos(pos)( New(_scala_xml_Unparsed, LL(const(str))) ) + def unparsed(span: Span, str: String): Tree = + atPos(span)( New(_scala_xml_Unparsed, LL(const(str))) ) - def element(pos: Span, qname: String, attrMap: mutable.Map[String, Tree], empty: Boolean, args: Seq[Tree]): Tree = { + def element(span: Span, qname: String, attrMap: mutable.Map[String, Tree], empty: Boolean, args: Seq[Tree]): Tree = { def handleNamespaceBinding(pre: String, z: String): Tree = { def mkAssign(t: Tree): Tree = Assign( Ident(_tmpscope), @@ -210,7 +210,7 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont case (None, x) => (null, x) } - def mkAttributeTree(pre: String, key: String, value: Tree) = atPos(pos.toSynthetic) { + def mkAttributeTree(pre: String, key: String, value: Tree) = atPos(span.toSynthetic) { // XXX this is where we'd like to put Select(value, nme.toString_) for #1787 // after we resolve the Some(foo) situation. val baseArgs = List(const(key), value, Ident(_md)) @@ -244,7 +244,7 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont } val body = mkXML( - pos.toSynthetic, + span.toSynthetic, false, const(pre), const(newlabel), @@ -254,6 +254,6 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont args ) - atPos(pos.toSynthetic)(new XMLBlock(nsResult, new XMLBlock(attrResult, body))) + atPos(span.toSynthetic)(new XMLBlock(nsResult, new XMLBlock(attrResult, body))) } } diff --git a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala index e6ed703fac10..d31168b7d06a 100644 --- a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala +++ b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala @@ -12,22 +12,22 @@ import dotty.tools.dotc.reporting.Reporter object Rewrites { private class PatchedFiles extends mutable.HashMap[SourceFile, Patches] - private case class Patch(pos: Span, replacement: String) { - def delta = replacement.length - (pos.end - pos.start) + private case class Patch(span: Span, replacement: String) { + def delta = replacement.length - (span.end - span.start) } private class Patches(source: SourceFile) { private val pbuf = new mutable.ListBuffer[Patch]() - def addPatch(pos: Span, replacement: String): Unit = - pbuf += Patch(pos, replacement) + def addPatch(span: Span, replacement: String): Unit = + pbuf += Patch(span, replacement) def apply(cs: Array[Char]): Array[Char] = { val delta = pbuf.map(_.delta).sum - val patches = pbuf.toList.sortBy(_.pos.start) + val patches = pbuf.toList.sortBy(_.span.start) if (patches.nonEmpty) patches reduceLeft {(p1, p2) => - assert(p1.pos.end <= p2.pos.start, s"overlapping patches: $p1 and $p2") + assert(p1.span.end <= p2.span.start, s"overlapping patches: $p1 and $p2") p2 } val ds = new Array[Char](cs.length + delta) @@ -38,10 +38,10 @@ object Rewrites { outIdx + untouched } ps match { - case patch @ Patch(pos, replacement) :: ps1 => - val outNew = copy(pos.start) + case patch @ Patch(span, replacement) :: ps1 => + val outNew = copy(span.start) replacement.copyToArray(ds, outNew) - loop(ps1, pos.end, outNew + replacement.length) + loop(ps1, span.end, outNew + replacement.length) case Nil => val outNew = copy(cs.length) assert(outNew == ds.length, s"$outNew != ${ds.length}") @@ -61,18 +61,18 @@ object Rewrites { } /** If -rewrite is set, record a patch that replaces the range - * given by `pos` in `source` by `replacement` + * given by `span` in `source` by `replacement` */ - def patch(source: SourceFile, pos: Span, replacement: String)(implicit ctx: Context): Unit = + def patch(source: SourceFile, span: Span, replacement: String)(implicit ctx: Context): Unit = if (ctx.reporter != Reporter.NoReporter) // NoReporter is used for syntax highlighting for (rewrites <- ctx.settings.rewrite.value) rewrites.patched .getOrElseUpdate(source, new Patches(source)) - .addPatch(pos, replacement) + .addPatch(span, replacement) /** Patch position in `ctx.compilationUnit.source`. */ - def patch(pos: Span, replacement: String)(implicit ctx: Context): Unit = - patch(ctx.compilationUnit.source, pos, replacement) + def patch(span: Span, replacement: String)(implicit ctx: Context): Unit = + patch(ctx.compilationUnit.source, span, replacement) /** If -rewrite is set, apply all patches and overwrite patched source files. */ diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala index a93875f065d5..4220679d7dc3 100644 --- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -46,7 +46,7 @@ abstract class Lifter { // don't instantiate here, as the type params could be further constrained, see tests/pos/pickleinf.scala var liftedType = expr.tpe.widen if (liftedFlags.is(Method)) liftedType = ExprType(liftedType) - val lifted = ctx.newSymbol(ctx.owner, name, liftedFlags | Synthetic, liftedType, coord = positionCoord(expr.span)) + val lifted = ctx.newSymbol(ctx.owner, name, liftedFlags | Synthetic, liftedType, coord = spanCoord(expr.span)) defs += liftedDef(lifted, expr).withPosOf(expr) ref(lifted.termRef).withSpan(expr.span.focus) } diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala index 16bff5e03cc9..0a84f1e92da0 100644 --- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala +++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala @@ -120,7 +120,7 @@ class ReTyper extends Typer with ReChecking { override def checkVariance(tree: Tree)(implicit ctx: Context): Unit = () override def inferView(from: Tree, to: Type)(implicit ctx: Context): Implicits.SearchResult = Implicits.NoMatchingImplicitsFailure - override def checkCanEqual(ltp: Type, rtp: Type, pos: Span)(implicit ctx: Context): Unit = () + override def checkCanEqual(ltp: Type, rtp: Type, span: Span)(implicit ctx: Context): Unit = () override protected def addAccessorDefs(cls: Symbol, body: List[Tree])(implicit ctx: Context): List[Tree] = body override protected def checkEqualityEvidence(tree: tpd.Tree, pt: Type)(implicit ctx: Context): Unit = () } diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index 31028c82ce0e..9b479d0adecb 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -67,8 +67,8 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends /** The start of this file in the underlying source file */ def start: Int = 0 - def atSpan(pos: Span): SourcePosition = - if (pos.exists) SourcePosition(underlying, pos) + def atSpan(span: Span): SourcePosition = + if (span.exists) SourcePosition(underlying, span) else NoSourcePosition def isSelfContained: Boolean = underlying eq this @@ -155,6 +155,6 @@ object SourceFile { @sharable object NoSource extends SourceFile(NoAbstractFile, Array[Char]()) { override def exists: Boolean = false - override def atSpan(pos: Span): SourcePosition = NoSourcePosition + override def atSpan(span: Span): SourcePosition = NoSourcePosition } diff --git a/compiler/src/dotty/tools/dotc/util/Spans.scala b/compiler/src/dotty/tools/dotc/util/Spans.scala index 16bf0ff9e460..5aba4366defa 100644 --- a/compiler/src/dotty/tools/dotc/util/Spans.scala +++ b/compiler/src/dotty/tools/dotc/util/Spans.scala @@ -171,8 +171,8 @@ object Spans { /** An index coordinate */ implicit def indexCoord(n: Int): Coord = new Coord(n + 1) - implicit def positionCoord(pos: Span): Coord = - if (pos.exists) new Coord(-(pos.point + 1)) + implicit def spanCoord(span: Span): Coord = + if (span.exists) new Coord(-(span.point + 1)) else NoCoord /** A sentinel for a missing coordinate */ diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala index eab6cfc2f01c..e6a0219e5ede 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala @@ -59,7 +59,7 @@ private[comment] case class ParsedComment ( trait MarkupConversion[T] extends MemberLookup { def ent: Entity - def pos: Span + def span: Span def parsed: ParsedComment protected def linkedExceptions(m: Map[String, String])(implicit ctx: Context): Map[String, String] @@ -74,7 +74,7 @@ trait MarkupConversion[T] extends MemberLookup { case x :: xs => if (xs.nonEmpty) ctx.docbase.warn( s"Only allowed to have a single annotation for $annot", - ent.symbol.sourcePosition(pos) + ent.symbol.sourcePosition(span) ) Some(x) case _ => None @@ -104,7 +104,7 @@ trait MarkupConversion[T] extends MemberLookup { ) } -case class MarkdownComment(ent: Entity, parsed: ParsedComment, pos: Span) +case class MarkdownComment(ent: Entity, parsed: ParsedComment, span: Span) extends MarkupConversion[MarkdownNode] { def stringToMarkup(str: String)(implicit ctx: Context) = @@ -135,21 +135,21 @@ extends MarkupConversion[MarkdownNode] { .mapValues(stringToMarkup) } -case class WikiComment(ent: Entity, parsed: ParsedComment, pos: Span) +case class WikiComment(ent: Entity, parsed: ParsedComment, span: Span) extends MarkupConversion[Body] { def filterEmpty(xs: Map[String,String])(implicit ctx: Context) = - xs.mapValues(_.toWiki(ent, ctx.docbase.packages, pos)) + xs.mapValues(_.toWiki(ent, ctx.docbase.packages, span)) .filterNot { case (_, v) => v.blocks.isEmpty } def filterEmpty(xs: List[String])(implicit ctx: Context) = - xs.map(_.toWiki(ent, ctx.docbase.packages, pos)) + xs.map(_.toWiki(ent, ctx.docbase.packages, span)) def markupToHtml(t: Body)(implicit ctx: Context) = t.show(ent) def stringToMarkup(str: String)(implicit ctx: Context) = - str.toWiki(ent, ctx.docbase.packages, pos) + str.toWiki(ent, ctx.docbase.packages, span) def stringToShortHtml(str: String)(implicit ctx: Context) = { val parsed = stringToMarkup(str) @@ -157,7 +157,7 @@ extends MarkupConversion[Body] { } def linkedExceptions(m: Map[String, String])(implicit ctx: Context) = { - m.mapValues(_.toWiki(ent, ctx.docbase.packages, pos)).map { case (targetStr, body) => + m.mapValues(_.toWiki(ent, ctx.docbase.packages, span)).map { case (targetStr, body) => val link = lookup(Some(ent), ctx.docbase.packages, targetStr) val newBody = body match { case Body(List(Paragraph(Chain(content)))) => diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala index 9dc6c2baf24f..72c86d5d8b1a 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala @@ -21,14 +21,14 @@ trait CommentParser extends util.MemberLookup { * @param packages all packages parsed by Scaladoc tool, used for lookup * @param cleanComment a cleaned comment to be parsed * @param src the raw comment source string. - * @param pos the position of the comment in source. + * @param span the position of the comment in source. */ def parse( entity: Entity, packages: Map[String, Package], comment: List[String], src: String, - pos: Span, + span: Span, site: Symbol = NoSymbol )(implicit ctx: Context): ParsedComment = { @@ -159,7 +159,7 @@ trait CommentParser extends util.MemberLookup { bodyTags.keys.toSeq flatMap { case stk: SymbolTagKey if (stk.name == key.name) => Some(stk) case stk: SimpleTagKey if (stk.name == key.name) => - dottydoc.println(s"$pos: tag '@${stk.name}' must be followed by a symbol name") + dottydoc.println(s"$span: tag '@${stk.name}' must be followed by a symbol name") None case _ => None } @@ -167,7 +167,7 @@ trait CommentParser extends util.MemberLookup { for (key <- keys) yield { val bs = (bodyTags remove key).get if (bs.length > 1) - dottydoc.println(s"$pos: only one '@${key.name}' tag for symbol ${key.symbol} is allowed") + dottydoc.println(s"$span: only one '@${key.name}' tag for symbol ${key.symbol} is allowed") (key.symbol, bs.head) } Map.empty[String, String] ++ pairs @@ -202,7 +202,7 @@ trait CommentParser extends util.MemberLookup { // with the point being at the very end. This ensures that the entire // comment will be visible in error reporting. A more fine-grained // reporting would be amazing here. - entity.symbol.sourcePosition(Span(pos.start, pos.end, pos.end)) + entity.symbol.sourcePosition(Span(span.start, span.end, span.end)) ) cmt @@ -236,7 +236,7 @@ trait CommentParser extends util.MemberLookup { entity: Entity, packages: Map[String, Package], string: String, - pos: Span, + span: Span, site: Symbol - )(implicit ctx: Context): Body = new WikiParser(entity, packages, string, pos, site).document() + )(implicit ctx: Context): Body = new WikiParser(entity, packages, string, span, site).document() } diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala index e0a370e69044..c27ac22f36b2 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala @@ -70,8 +70,8 @@ object HtmlParsers { } implicit class StringToWiki(val text: String) extends AnyVal { - def toWiki(origin: Entity, packages: Map[String, Package], pos: Span): Body = - new WikiParser(origin, packages, text, pos, origin.symbol).document() + def toWiki(origin: Entity, packages: Map[String, Package], span: Span): Body = + new WikiParser(origin, packages, text, span, origin.symbol).document() } implicit class BodyToHtml(val body: Body) extends AnyVal { diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/WikiParser.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/WikiParser.scala index 38b1d5f60c5d..1d3aae5499ae 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/comment/WikiParser.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/WikiParser.scala @@ -21,7 +21,7 @@ private[comment] final class WikiParser( entity: Entity, packages: Map[String, Package], val buffer: String, - pos: Span, + span: Span, site: Symbol ) extends CharReader(buffer) with MemberLookup { wiki => var summaryParsed = false @@ -110,7 +110,7 @@ private[comment] final class WikiParser( jump("{{{") val str = readUntil("}}}") if (char == endOfText) - reportError(pos, "unclosed code block") + reportError(span, "unclosed code block") else jump("}}}") blockEnded("code block") @@ -124,7 +124,7 @@ private[comment] final class WikiParser( val text = getInline(check("=" * inLevel)) val outLevel = repeatJump('=', inLevel) if (inLevel != outLevel) - reportError(pos, "unbalanced or unclosed heading") + reportError(span, "unbalanced or unclosed heading") blockEnded("heading") Title(text, inLevel) } @@ -344,7 +344,7 @@ private[comment] final class WikiParser( /** {{{ eol ::= { whitespace } '\n' }}} */ def blockEnded(blockType: String): Unit = { if (char != endOfLine && char != endOfText) { - reportError(pos, "no additional content on same line after " + blockType) + reportError(span, "no additional content on same line after " + blockType) jumpUntil(endOfLine) } while (char == endOfLine) @@ -402,8 +402,8 @@ private[comment] final class WikiParser( } } - def reportError(pos: Span, message: String) = - dottydoc.println(s"$pos: $message") + def reportError(span: Span, message: String) = + dottydoc.println(s"$span: $message") } sealed class CharReader(buffer: String) { reader => diff --git a/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala b/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala index 9129d8c0f176..15c7e440f22e 100644 --- a/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala +++ b/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala @@ -20,7 +20,7 @@ object syntax { } implicit class SymbolExtensions(val sym: Symbol) extends AnyVal { - def sourcePosition(pos: Span)(implicit ctx: Context): SourcePosition = - ctx.getSource(sym.sourceFile).atSpan(pos) + def sourcePosition(span: Span)(implicit ctx: Context): SourcePosition = + ctx.getSource(sym.sourceFile).atSpan(span) } } From 39c4ca515860a3c2a96a5795d337d68f59c980a1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 4 Jan 2019 12:59:22 +0100 Subject: [PATCH 44/75] Polishings --- compiler/src/dotty/tools/dotc/ast/Positioned.scala | 12 ++++++------ .../dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 2 +- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index 005f42200858..4c6f5bad5c2a 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -40,12 +40,12 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod //assert(id != 2067, getClass) } - /** Destructively update `mySpan` to given span. Also, set any missing - * spans in children. + /** Destructively update `mySpan` to given span and potentially update `id` so that + * it refers to `file`. Also, set any missing positions in children. */ protected def setPos(span: Span, file: AbstractFile): Unit = { - setOneSpan(span, file) - if (span.exists) setChildSpans(span.toSynthetic, file) + setOnePos(span, file) + if (span.exists) setChildPositions(span.toSynthetic, file) } /** A positioned item like this one with given `span`. @@ -82,7 +82,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod /** Set span of this tree only, without updating children spans. * Called from Unpickler when entering positions. */ - private[dotc] def setOneSpan(span: Span, file: AbstractFile = this.srcfile): Unit = { + private[dotc] def setOnePos(span: Span, file: AbstractFile = this.srcfile): Unit = { if (file != this.srcfile) setId(TreeIds.nextIdFor(file)) mySpan = span } @@ -98,7 +98,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod * But since mutual tail recursion is not supported in Scala, we express it instead * as a while loop with a termination by return in the middle. */ - private def setChildSpans(span: Span, file: AbstractFile): Unit = { + private def setChildPositions(span: Span, file: AbstractFile): Unit = { var n = productArity // subnodes are analyzed right to left var elems: List[Any] = Nil // children in lists still to be considered, from right to left var end = span.end // the last defined offset, fill in spans up to this offset diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 79dbb4ad34a4..e1803622decc 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -1335,7 +1335,7 @@ class TreeUnpickler(reader: TastyReader, /** Set position of `tree` at given `addr`. */ def setPos[T <: untpd.Tree](addr: Addr, tree: T)(implicit ctx: Context): tree.type = { val pos = posAt(addr) - if (pos.exists) tree.setOneSpan(pos, ctx.source.file) + if (pos.exists) tree.setOnePos(pos, ctx.source.file) tree } } diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 43cea2085ddb..6f4a97bab59c 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -81,7 +81,7 @@ object Parsers { * to position spanning from `start` to last read offset, with given point. * If the last offset is less than or equal to start, the tree `t` did not * consume any source for its construction. In this case, don't position it yet, - * but wait for its position to be determined by `setChildSpans` when the + * but wait for its position to be determined by `setChildPositions` when the * parent node is positioned. */ def atPos[T <: Positioned](start: Offset, point: Offset)(t: T): T = From 7dc693e06e4c70e901d02e7fef8968333c476b7a Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 4 Jan 2019 13:25:25 +0100 Subject: [PATCH 45/75] Convert some checking methods to take Positioned arguments instead of SourcePos. It's more efficient since it does not need allocations. --- .../tools/dotc/transform/PostTyper.scala | 12 ++--- .../dotty/tools/dotc/typer/Applications.scala | 2 +- .../src/dotty/tools/dotc/typer/Checking.scala | 54 +++++++++---------- .../src/dotty/tools/dotc/typer/Namer.scala | 2 +- .../src/dotty/tools/dotc/typer/Typer.scala | 20 +++---- tests/neg/ski.scala | 2 +- 6 files changed, 46 insertions(+), 46 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index 9fa5d9dde086..9aa4de955d81 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -199,7 +199,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase case tree @ Select(qual, name) => handleMeta(tree.symbol) if (name.isTypeName) { - Checking.checkRealizable(qual.tpe, qual.sourcePos.focus) + Checking.checkRealizable(qual.tpe, qual.posd) super.transform(tree)(ctx.addMode(Mode.Type)) } else @@ -219,7 +219,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase case Select(nu: New, nme.CONSTRUCTOR) if isCheckable(nu) => // need to check instantiability here, because the type of the New itself // might be a type constructor. - Checking.checkInstantiable(tree.tpe, nu.sourcePos) + Checking.checkInstantiable(tree.tpe, nu.posd) withNoCheckNews(nu :: Nil)(super.transform(app)) case _ => super.transform(app) @@ -266,10 +266,10 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase } processMemberDef(super.transform(tree)) case tree: New if isCheckable(tree) => - Checking.checkInstantiable(tree.tpe, tree.sourcePos) + Checking.checkInstantiable(tree.tpe, tree.posd) super.transform(tree) case tree: Closure if !tree.tpt.isEmpty => - Checking.checkRealizable(tree.tpt.tpe, tree.sourcePos, "SAM type") + Checking.checkRealizable(tree.tpt.tpe, tree.posd, "SAM type") super.transform(tree) case tree @ Annotated(annotated, annot) => cpy.Annotated(tree)(transform(annotated), transformAnnot(annot)) @@ -277,7 +277,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase Checking.checkAppliedType(tree, boundsCheck = !ctx.mode.is(Mode.Pattern)) super.transform(tree) case SingletonTypeTree(ref) => - Checking.checkRealizable(ref.tpe, ref.sourcePos.focus) + Checking.checkRealizable(ref.tpe, ref.posd) super.transform(tree) case tree: TypeTree => tree.withType( @@ -289,7 +289,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase case tree: AndTypeTree => // Ideally, this should be done by Typer, but we run into cyclic references // when trying to typecheck self types which are intersections. - Checking.checkNonCyclicInherited(tree.tpe, tree.left.tpe :: tree.right.tpe :: Nil, EmptyScope, tree.sourcePos) + Checking.checkNonCyclicInherited(tree.tpe, tree.left.tpe :: tree.right.tpe :: Nil, EmptyScope, tree.posd) super.transform(tree) case tree: LambdaTypeTree => VarianceChecker.checkLambda(tree) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index dc6f3f88f5b0..73aecc92236b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -907,7 +907,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => if (typedArgs.length <= pt.paramInfos.length && !isNamed) if (typedFn.symbol == defn.Predef_classOf && typedArgs.nonEmpty) { val arg = typedArgs.head - checkClassType(arg.tpe, arg.sourcePos, traitReq = false, stablePrefixReq = false) + checkClassType(arg.tpe, arg.posd, traitReq = false, stablePrefixReq = false) } case _ => } diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index f2f1524dbc1e..766ce1f7f5e0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -79,16 +79,16 @@ object Checking { HKTypeLambda.fromParams(tparams, bound).appliedTo(args) if (boundsCheck) checkBounds(orderedArgs, bounds, instantiate) - def checkWildcardApply(tp: Type, pos: SourcePosition): Unit = tp match { + def checkWildcardApply(tp: Type): Unit = tp match { case tp @ AppliedType(tycon, args) => if (tycon.isLambdaSub && args.exists(_.isInstanceOf[TypeBounds])) ctx.errorOrMigrationWarning( ex"unreducible application of higher-kinded type $tycon to wildcard arguments", - pos) + tree.sourcePos) case _ => } def checkValidIfApply(implicit ctx: Context): Unit = - checkWildcardApply(tycon.tpe.appliedTo(args.map(_.tpe)), tree.sourcePos) + checkWildcardApply(tycon.tpe.appliedTo(args.map(_.tpe))) checkValidIfApply(ctx.addMode(Mode.AllowLambdaWildcardApply)) } @@ -118,28 +118,28 @@ object Checking { /** Check that `tp` refers to a nonAbstract class * and that the instance conforms to the self type of the created class. */ - def checkInstantiable(tp: Type, pos: SourcePosition)(implicit ctx: Context): Unit = + def checkInstantiable(tp: Type, posd: Positioned)(implicit ctx: Context): Unit = tp.underlyingClassRef(refinementOK = false) match { case tref: TypeRef => val cls = tref.symbol if (cls.is(AbstractOrTrait)) - ctx.error(CantInstantiateAbstractClassOrTrait(cls, isTrait = cls.is(Trait)), pos) + ctx.error(CantInstantiateAbstractClassOrTrait(cls, isTrait = cls.is(Trait)), posd.sourcePos) if (!cls.is(Module)) { // Create a synthetic singleton type instance, and check whether // it conforms to the self type of the class as seen from that instance. val stp = SkolemType(tp) val selfType = cls.asClass.givenSelfType.asSeenFrom(stp, cls) if (selfType.exists && !(stp <:< selfType)) - ctx.error(DoesNotConformToSelfTypeCantBeInstantiated(tp, selfType), pos) + ctx.error(DoesNotConformToSelfTypeCantBeInstantiated(tp, selfType), posd.sourcePos) } case _ => } /** Check that type `tp` is realizable. */ - def checkRealizable(tp: Type, pos: SourcePosition, what: String = "path")(implicit ctx: Context): Unit = { + def checkRealizable(tp: Type, posd: Positioned, what: String = "path")(implicit ctx: Context): Unit = { val rstatus = realizability(tp) if (rstatus ne Realizable) - ctx.errorOrMigrationWarning(em"$tp is not a legal $what\nsince it${rstatus.msg}", pos) + ctx.errorOrMigrationWarning(em"$tp is not a legal $what\nsince it${rstatus.msg}", posd.sourcePos) } /** A type map which checks that the only cycles in a type are F-bounds @@ -332,7 +332,7 @@ object Checking { * unless a type with the same name aleadry appears in `decls`. * @return true iff no cycles were detected */ - def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, pos: SourcePosition)(implicit ctx: Context): Unit = { + def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, posd: Positioned)(implicit ctx: Context): Unit = { def qualifies(sym: Symbol) = sym.name.isTypeName && !sym.is(Private) val abstractTypeNames = for (parent <- parents; mbr <- parent.abstractTypeMembers if qualifies(mbr.symbol)) @@ -350,7 +350,7 @@ object Checking { } catch { case ex: RecursionOverflow => - ctx.error(em"cyclic reference involving type $name", pos) + ctx.error(em"cyclic reference involving type $name", posd.sourcePos) false } } @@ -562,8 +562,8 @@ trait Checking { def checkNonCyclic(sym: Symbol, info: TypeBounds, reportErrors: Boolean)(implicit ctx: Context): Type = Checking.checkNonCyclic(sym, info, reportErrors) - def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, pos: SourcePosition)(implicit ctx: Context): Unit = - Checking.checkNonCyclicInherited(joint, parents, decls, pos) + def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, posd: Positioned)(implicit ctx: Context): Unit = + Checking.checkNonCyclicInherited(joint, parents, decls, posd) /** Check that Java statics and packages can only be used in selections. */ @@ -578,8 +578,8 @@ trait Checking { } /** Check that type `tp` is stable. */ - def checkStable(tp: Type, pos: SourcePosition)(implicit ctx: Context): Unit = - if (!tp.isStable) ctx.error(ex"$tp is not stable", pos) + def checkStable(tp: Type, posd: Positioned)(implicit ctx: Context): Unit = + if (!tp.isStable) ctx.error(ex"$tp is not stable", posd.sourcePos) /** Check that all type members of `tp` have realizable bounds */ def checkRealizableBounds(cls: Symbol, pos: SourcePosition)(implicit ctx: Context): Unit = { @@ -594,14 +594,14 @@ trait Checking { * check that class prefix is stable. * @return `tp` itself if it is a class or trait ref, ObjectType if not. */ - def checkClassType(tp: Type, pos: SourcePosition, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type = + def checkClassType(tp: Type, posd: Positioned, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type = tp.underlyingClassRef(refinementOK = false) match { case tref: TypeRef => - if (traitReq && !(tref.symbol is Trait)) ctx.error(TraitIsExpected(tref.symbol), pos) - if (stablePrefixReq && ctx.phase <= ctx.refchecksPhase) checkStable(tref.prefix, pos) + if (traitReq && !(tref.symbol is Trait)) ctx.error(TraitIsExpected(tref.symbol), posd.sourcePos) + if (stablePrefixReq && ctx.phase <= ctx.refchecksPhase) checkStable(tref.prefix, posd) tp case _ => - ctx.error(ex"$tp is not a class type", pos) + ctx.error(ex"$tp is not a class type", posd.sourcePos) defn.ObjectType } @@ -634,7 +634,7 @@ trait Checking { * - it is defined in Predef * - it is the scala.reflect.Selectable.reflectiveSelectable conversion */ - def checkImplicitConversionUseOK(sym: Symbol, pos: SourcePosition)(implicit ctx: Context): Unit = { + def checkImplicitConversionUseOK(sym: Symbol, posd: Positioned)(implicit ctx: Context): Unit = { val conversionOK = !sym.exists || sym.is(Synthetic) || @@ -643,7 +643,7 @@ trait Checking { sym.name == nme.reflectiveSelectable && sym.maybeOwner.maybeOwner.maybeOwner == defn.ScalaPackageClass if (!conversionOK) checkFeature(defn.LanguageModuleClass, nme.implicitConversions, - i"Use of implicit conversion ${sym.showLocated}", NoSymbol, pos) + i"Use of implicit conversion ${sym.showLocated}", NoSymbol, posd.sourcePos) } /** Issue a feature warning if feature is not enabled */ @@ -890,14 +890,14 @@ trait Checking { } /** Check that we are in an inline context (inside an inline method or in inline code) */ - def checkInInlineContext(what: String, pos: SourcePosition)(implicit ctx: Context): Unit = + def checkInInlineContext(what: String, posd: Positioned)(implicit ctx: Context): Unit = if (!ctx.inInlineMethod && !ctx.isInlineContext) { val inInlineUnapply = ctx.owner.ownersIterator.exists(owner => owner.name == nme.unapply && owner.is(Inline) && owner.is(Method)) val msg = if (inInlineUnapply) "cannot be used in an inline unapply" else "can only be used in an inline method" - ctx.error(em"$what $msg", pos) + ctx.error(em"$what $msg", posd.sourcePos) } /** Check that all case classes that extend `scala.Enum` are `enum` cases */ @@ -994,12 +994,12 @@ trait ReChecking extends Checking { trait NoChecking extends ReChecking { import tpd._ override def checkNonCyclic(sym: Symbol, info: TypeBounds, reportErrors: Boolean)(implicit ctx: Context): Type = info - override def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, pos: SourcePosition)(implicit ctx: Context): Unit = () + override def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, posd: Positioned)(implicit ctx: Context): Unit = () override def checkValue(tree: Tree, proto: Type)(implicit ctx: Context): tree.type = tree - override def checkStable(tp: Type, pos: SourcePosition)(implicit ctx: Context): Unit = () - override def checkClassType(tp: Type, pos: SourcePosition, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type = tp + override def checkStable(tp: Type, posd: Positioned)(implicit ctx: Context): Unit = () + override def checkClassType(tp: Type, posd: Positioned, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type = tp override def checkImplicitConversionDefOK(sym: Symbol)(implicit ctx: Context): Unit = () - override def checkImplicitConversionUseOK(sym: Symbol, pos: SourcePosition)(implicit ctx: Context): Unit = () + override def checkImplicitConversionUseOK(sym: Symbol, posd: Positioned)(implicit ctx: Context): Unit = () override def checkFeasibleParent(tp: Type, pos: SourcePosition, where: => String = "")(implicit ctx: Context): Type = tp override def checkInlineConformant(tree: Tree, isFinal: Boolean, what: => String)(implicit ctx: Context): Unit = () override def checkNoDoubleDeclaration(cls: Symbol)(implicit ctx: Context): Unit = () @@ -1011,6 +1011,6 @@ trait NoChecking extends ReChecking { override def checkCaseInheritance(parentSym: Symbol, caseCls: ClassSymbol, pos: SourcePosition)(implicit ctx: Context): Unit = () override def checkNoForwardDependencies(vparams: List[ValDef])(implicit ctx: Context): Unit = () override def checkMembersOK(tp: Type, pos: SourcePosition)(implicit ctx: Context): Type = tp - override def checkInInlineContext(what: String, pos: SourcePosition)(implicit ctx: Context): Unit = () + override def checkInInlineContext(what: String, posd: Positioned)(implicit ctx: Context): Unit = () override def checkFeature(base: ClassSymbol, name: TermName, description: => String, featureUseSite: Symbol, pos: SourcePosition)(implicit ctx: Context): Unit = () } diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 2835ed310d1d..90611e820dda 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -887,7 +887,7 @@ class Namer { typer: Typer => val ptype = parentType(parent)(ctx.superCallContext).dealiasKeepAnnots if (cls.isRefinementClass) ptype else { - val pt = checkClassType(ptype, parent.sourcePos, + val pt = checkClassType(ptype, parent.posd, traitReq = parent ne parents.head, stablePrefixReq = true) if (pt.derivesFrom(cls)) { val addendum = parent match { diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index d7e715627516..60de458bcc69 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -433,7 +433,7 @@ class Typer extends Namer case _ => app } case qual1 => - if (tree.name.isTypeName) checkStable(qual1.tpe, qual1.sourcePos) + if (tree.name.isTypeName) checkStable(qual1.tpe, qual1.posd) val select = typedSelect(tree, pt, qual1) if (select.tpe ne TryDynamicCallType) ConstFold(checkStableIdentPattern(select, pt)) else if (pt.isInstanceOf[FunOrPolyProto] || pt == AssignProto) select @@ -516,7 +516,7 @@ class Typer extends Namer case TypeApplications.EtaExpansion(tycon) => tpt1 = tpt1.withType(tycon) case _ => } - if (checkClassType(tpt1.tpe, tpt1.sourcePos, traitReq = false, stablePrefixReq = true) eq defn.ObjectType) + if (checkClassType(tpt1.tpe, tpt1.posd, traitReq = false, stablePrefixReq = true) eq defn.ObjectType) tpt1 = TypeTree(defn.ObjectType).withPosOf(tpt1) tpt1 match { @@ -725,7 +725,7 @@ class Typer extends Namer } def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context): Tree = track("typedIf") { - if (tree.isInline) checkInInlineContext("inline if", tree.sourcePos) + if (tree.isInline) checkInInlineContext("inline if", tree.posd) val cond1 = typed(tree.cond, defn.BooleanType) val thenp2 :: elsep2 :: Nil = harmonic(harmonize, pt) { val thenp1 = typed(tree.thenp, pt.notApplied) @@ -988,7 +988,7 @@ class Typer extends Namer tree.selector match { case EmptyTree => if (tree.isInline) { - checkInInlineContext("implicit match", tree.sourcePos) + checkInInlineContext("implicit match", tree.posd) val cases1 = tree.cases.mapconserve { case cdef @ CaseDef(pat @ Typed(Ident(nme.WILDCARD), _), _, _) => // case _ : T --> case evidence$n : T @@ -1003,7 +1003,7 @@ class Typer extends Namer typed(desugar.makeCaseLambda(tree.cases, protoFormals.length, unchecked).withPosOf(tree), pt) } case _ => - if (tree.isInline) checkInInlineContext("inline match", tree.sourcePos) + if (tree.isInline) checkInInlineContext("inline match", tree.posd) val sel1 = typedExpr(tree.selector) val selType = fullyDefinedType(sel1.tpe, "pattern selector", tree.span).widen typedMatchFinish(tree, sel1, selType, tree.cases, pt) @@ -1241,7 +1241,7 @@ class Typer extends Namer def typedSingletonTypeTree(tree: untpd.SingletonTypeTree)(implicit ctx: Context): SingletonTypeTree = track("typedSingletonTypeTree") { val ref1 = typedExpr(tree.ref) - checkStable(ref1.tpe, tree.sourcePos) + checkStable(ref1.tpe, tree.posd) assignType(cpy.SingletonTypeTree(tree)(ref1), ref1) } @@ -1660,7 +1660,7 @@ class Typer extends Namer cls, isRequired, cdef.sourcePos) } - checkNonCyclicInherited(cls.thisType, cls.classParents, cls.info.decls, cdef.sourcePos) + checkNonCyclicInherited(cls.thisType, cls.classParents, cls.info.decls, cdef.posd) // check value class constraints checkDerivedValueClass(cls, body1) @@ -1741,8 +1741,8 @@ class Typer extends Namer def typedImport(imp: untpd.Import, sym: Symbol)(implicit ctx: Context): Import = track("typedImport") { val expr1 = typedExpr(imp.expr, AnySelectionProto) - checkStable(expr1.tpe, imp.expr.sourcePos) - if (!ctx.isAfterTyper) checkRealizable(expr1.tpe, imp.expr.sourcePos) + checkStable(expr1.tpe, imp.expr.posd) + if (!ctx.isAfterTyper) checkRealizable(expr1.tpe, imp.expr.posd) assignType(cpy.Import(imp)(expr1, imp.selectors), sym) } @@ -2663,7 +2663,7 @@ class Typer extends Namer case SearchSuccess(inferred: ExtMethodApply, _, _) => inferred // nothing to check or adapt for extension method applications case SearchSuccess(inferred, _, _) => - checkImplicitConversionUseOK(inferred.symbol, tree.sourcePos) + checkImplicitConversionUseOK(inferred.symbol, tree.posd) readapt(inferred)(ctx.retractMode(Mode.ImplicitsEnabled)) case failure: SearchFailure => if (pt.isInstanceOf[ProtoType] && !failure.isAmbiguous) diff --git a/tests/neg/ski.scala b/tests/neg/ski.scala index 90a43039aa73..2c68f336e98c 100644 --- a/tests/neg/ski.scala +++ b/tests/neg/ski.scala @@ -18,7 +18,7 @@ trait S2[x <: Term, y <: Term] extends Term { } trait S3[x <: Term, y <: Term, z <: Term] extends Term { type ap[v <: Term] = eval#ap[v] // error: not a legal path - type eval = x#ap[z]#ap[y#ap[z]]#eval // error: not a legal path // error: not a legal path + type eval = x#ap[z]#ap[y#ap[z]]#eval // error: not a legal path } // The K combinator From 0a00ed22e39f8714113cef798d49193b6ef80450 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 4 Jan 2019 17:03:34 +0100 Subject: [PATCH 46/75] Simplify Parser `implicitOffset` can now be dropped, replaced by manipulating `impliedMods` directly. --- .../dotty/tools/dotc/parsing/Parsers.scala | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 6f4a97bab59c..d0f72c345dab 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -81,7 +81,7 @@ object Parsers { * to position spanning from `start` to last read offset, with given point. * If the last offset is less than or equal to start, the tree `t` did not * consume any source for its construction. In this case, don't position it yet, - * but wait for its position to be determined by `setChildPositions` when the + * but wait for its position to be determined by `setChildSpans` when the * parent node is positioned. */ def atPos[T <: Positioned](start: Offset, point: Offset)(t: T): T = @@ -1983,9 +1983,9 @@ object Parsers { prefix: Boolean = false, // clause precedes name of an extension method firstClause: Boolean = false) // clause is the first in regular list of clauses : List[ValDef] = { - var implicitOffset = -1 // use once + var impliedMods: Modifiers = EmptyModifiers - def param(impliedMods: Modifiers): ValDef = { + def param(): ValDef = { val start = in.offset var mods = impliedMods.withAnnotations(annotations()) if (ofClass) { @@ -2020,9 +2020,8 @@ object Parsers { val default = if (in.token == EQUALS) { in.nextToken(); expr() } else EmptyTree - if (implicitOffset >= 0) { - //mods = mods.withPos(mods.span.union(Span(implicitOffset, implicitOffset))) - implicitOffset = -1 + if (impliedMods.mods.nonEmpty) { + impliedMods = impliedMods.withMods(Nil) // keep only flags, so that parameter positions don't overlap } ValDef(name, tpt, default).withMods(mods) } @@ -2045,18 +2044,16 @@ object Parsers { if (in.token == RPAREN && !prefix) Nil else { def funArgMods(mods: Modifiers): Modifiers = - if (in.token == IMPLICIT) { - implicitOffset = in.offset + if (in.token == IMPLICIT) funArgMods(addMod(mods, atPos(accept(IMPLICIT)) { Mod.Implicit() })) - } else if (in.token == ERASED) funArgMods(addMod(mods, atPos(accept(ERASED)) { Mod.Erased() })) else mods - val paramMods = funArgMods(EmptyModifiers) + impliedMods = funArgMods(EmptyModifiers) val clause = - if (prefix) param(paramMods) :: Nil - else commaSeparated(() => param(paramMods)) + if (prefix) param() :: Nil + else commaSeparated(() => param()) checkVarArgsRules(clause) clause } From 078a49117d51ee15ffeca354188604c1504cad7e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 6 Jan 2019 11:05:36 +0100 Subject: [PATCH 47/75] Fix rebase breakage --- compiler/src/dotty/tools/dotc/typer/Applications.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 73aecc92236b..17b49ec52b31 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -176,13 +176,13 @@ object Applications { def productArity: Int = app.productArity def productElement(n: Int): Any = app.productElement(n) } - + /** The unapply method of this extractor also recognizes ExtMethodApplys in closure blocks. * This is necessary to deal with closures as left arguments of extension method applications. * A test case is i5606.scala */ object ExtMethodApply { - def apply(app: Tree) = new ExtMethodApply(app) + def apply(app: Tree)(implicit ctx: Context) = new ExtMethodApply(app) def unapply(tree: Tree)(implicit ctx: Context): Option[Tree] = tree match { case tree: ExtMethodApply => Some(tree.app) case Block(stats, ExtMethodApply(app)) => Some(tpd.cpy.Block(tree)(stats, app)) From fc3020b37cc244fa2598197b0b2218565b1ff5d4 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sat, 5 Jan 2019 12:43:31 +0100 Subject: [PATCH 48/75] Add missing source to context --- compiler/src/dotty/tools/repl/ParseResult.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/repl/ParseResult.scala b/compiler/src/dotty/tools/repl/ParseResult.scala index 9d5c89980f53..55068c3e7b29 100644 --- a/compiler/src/dotty/tools/repl/ParseResult.scala +++ b/compiler/src/dotty/tools/repl/ParseResult.scala @@ -110,7 +110,8 @@ object ParseResult { private def parseStats(sourceCode: String)(implicit ctx: Context): List[untpd.Tree] = { val source = new SourceFile("", sourceCode) - val parser = new Parser(source) + val ctx1 = ctx.fresh.setSource(source) + val parser = new Parser(source)(ctx1) val stats = parser.blockStatSeq() parser.accept(Tokens.EOF) stats From 2150fdda3230b1eb2dab75fc56fd3432ffaec105 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sat, 5 Jan 2019 12:44:12 +0100 Subject: [PATCH 49/75] Add missing contents to vitual files --- compiler/src/dotty/tools/dotc/util/SourceFile.scala | 2 +- compiler/src/dotty/tools/io/VirtualFile.scala | 13 +++++++++++++ compiler/test-resources/repl/notFound | 4 ++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 compiler/test-resources/repl/notFound diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index 9b479d0adecb..d55e9998e830 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -39,7 +39,7 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends lazy val content = computeContent def this(file: AbstractFile, codec: Codec) = this(file, new String(file.toByteArray, codec.charSet).toCharArray) - def this(name: String, content: String) = this(new VirtualFile(name), content.toCharArray) + def this(name: String, content: String) = this(new VirtualFile(name, content.getBytes), scala.io.Codec.UTF8) /** Tab increment; can be overridden */ def tabInc: Int = 8 diff --git a/compiler/src/dotty/tools/io/VirtualFile.scala b/compiler/src/dotty/tools/io/VirtualFile.scala index a790fc02a3d3..705f084ac6c1 100644 --- a/compiler/src/dotty/tools/io/VirtualFile.scala +++ b/compiler/src/dotty/tools/io/VirtualFile.scala @@ -25,6 +25,19 @@ class VirtualFile(val name: String, override val path: String) extends AbstractF */ def this(name: String) = this(name, name) + /** + * Initializes this instance with the specified name and an + * identical path. + * + * @param name the name of the virtual file to be created + * @param content the initial contents of the virtual file + * @return the created virtual file + */ + def this(name: String, content: Array[Byte]) = { + this(name) + this.content = content + } + override def hashCode: Int = path.hashCode override def equals(that: Any): Boolean = that match { case x: VirtualFile => x.path == path diff --git a/compiler/test-resources/repl/notFound b/compiler/test-resources/repl/notFound new file mode 100644 index 000000000000..34d4ce630810 --- /dev/null +++ b/compiler/test-resources/repl/notFound @@ -0,0 +1,4 @@ +scala> Foo +1 | Foo + | ^^^ + | Not found: Foo From fa08b7e0e3194c322db41b85ef68468f45194ff4 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sat, 5 Jan 2019 13:43:04 +0100 Subject: [PATCH 50/75] Avoid memoization of virtual source files with same path --- compiler/src/dotty/tools/io/VirtualFile.scala | 6 ------ compiler/test-resources/repl/notFound | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/io/VirtualFile.scala b/compiler/src/dotty/tools/io/VirtualFile.scala index 705f084ac6c1..5cd1bde187fb 100644 --- a/compiler/src/dotty/tools/io/VirtualFile.scala +++ b/compiler/src/dotty/tools/io/VirtualFile.scala @@ -38,12 +38,6 @@ class VirtualFile(val name: String, override val path: String) extends AbstractF this.content = content } - override def hashCode: Int = path.hashCode - override def equals(that: Any): Boolean = that match { - case x: VirtualFile => x.path == path - case _ => false - } - private[this] var content = Array.emptyByteArray def absolute: AbstractFile = this diff --git a/compiler/test-resources/repl/notFound b/compiler/test-resources/repl/notFound index 34d4ce630810..99379a89660d 100644 --- a/compiler/test-resources/repl/notFound +++ b/compiler/test-resources/repl/notFound @@ -2,3 +2,7 @@ scala> Foo 1 | Foo | ^^^ | Not found: Foo +scala> Bar +1 | Bar + | ^^^ + | Not found: Bar From 57e893f9f2389c88e6087db8226ae659696c845d Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sun, 6 Jan 2019 18:27:07 +0100 Subject: [PATCH 51/75] Use non-virtual files in dottydoc tests To avoid the trying to load virtual files based on their pickled names. --- .../dotty/tools/dottydoc/ConstructorTest.scala | 18 ++++++------------ .../tools/dottydoc/PackageStructure.scala | 15 +++++---------- .../dotty/tools/dottydoc/SimpleComments.scala | 5 +++-- .../test/dotty/tools/dottydoc/SourceUtil.scala | 18 ++++++++++++++++++ .../dotty/tools/dottydoc/UsecaseTest.scala | 18 ++++++------------ 5 files changed, 38 insertions(+), 36 deletions(-) create mode 100644 doc-tool/test/dotty/tools/dottydoc/SourceUtil.scala diff --git a/doc-tool/test/dotty/tools/dottydoc/ConstructorTest.scala b/doc-tool/test/dotty/tools/dottydoc/ConstructorTest.scala index 086abd99c9fd..ce90fd020212 100644 --- a/doc-tool/test/dotty/tools/dottydoc/ConstructorTest.scala +++ b/doc-tool/test/dotty/tools/dottydoc/ConstructorTest.scala @@ -14,8 +14,7 @@ class ConstructorsFromTastyTest extends ConstructorsBase with CheckFromTasty abstract class ConstructorsBase extends DottyDocTest { @Test def singleClassConstructor = { - val source = new SourceFile ( - "Class.scala", + val source = SourceUtil.makeTemp( """ |package scala | @@ -38,8 +37,7 @@ abstract class ConstructorsBase extends DottyDocTest { } @Test def constructorPlusImplicitArgList = { - val source = new SourceFile ( - "Class.scala", + val source = SourceUtil.makeTemp( """ |package scala | @@ -65,8 +63,7 @@ abstract class ConstructorsBase extends DottyDocTest { } @Test def multipleArgumentListsForConstructor = { - val source = new SourceFile ( - "Class.scala", + val source = SourceUtil.makeTemp( """ |package scala | @@ -93,8 +90,7 @@ abstract class ConstructorsBase extends DottyDocTest { } @Test def multipleConstructors = { - val source = new SourceFile ( - "Class.scala", + val source = SourceUtil.makeTemp( """ |package scala | @@ -133,8 +129,7 @@ abstract class ConstructorsBase extends DottyDocTest { } @Test def multipleConstructorsCC = { - val source = new SourceFile ( - "Class.scala", + val source = SourceUtil.makeTemp( """ |package scala | @@ -174,8 +169,7 @@ abstract class ConstructorsBase extends DottyDocTest { } @Test def traitParameters = { - val source = new SourceFile ( - "Trait.scala", + val source = SourceUtil.makeTemp( """ |package scala | diff --git a/doc-tool/test/dotty/tools/dottydoc/PackageStructure.scala b/doc-tool/test/dotty/tools/dottydoc/PackageStructure.scala index 2ef1352f2d07..5d235a0a6821 100644 --- a/doc-tool/test/dotty/tools/dottydoc/PackageStructure.scala +++ b/doc-tool/test/dotty/tools/dottydoc/PackageStructure.scala @@ -13,8 +13,7 @@ class PackageStructureFromTastyTest extends PackageStructureBase with CheckFromT abstract class PackageStructureBase extends DottyDocTest { @Test def sourceFileAnnotIsStripped = { - val source = new SourceFile( - "A.scala", + val source = SourceUtil.makeTemp( """package scala | |/** Some doc */ @@ -33,8 +32,7 @@ abstract class PackageStructureBase extends DottyDocTest { } @Test def multipleCompilationUnits = { - val source1 = new SourceFile( - "TraitA.scala", + val source1 = SourceUtil.makeTemp( """ |package scala | @@ -42,8 +40,7 @@ abstract class PackageStructureBase extends DottyDocTest { """.stripMargin ) - val source2 = new SourceFile( - "TraitB.scala", + val source2 = SourceUtil.makeTemp( """ |package scala | @@ -67,8 +64,7 @@ abstract class PackageStructureBase extends DottyDocTest { @Test def multiplePackages = { - val source1 = new SourceFile( - "TraitA.scala", + val source1 = SourceUtil.makeTemp( """ |package scala |package collection @@ -76,8 +72,7 @@ abstract class PackageStructureBase extends DottyDocTest { |trait A """.stripMargin) - val source2 = new SourceFile( - "TraitB.scala", + val source2 = SourceUtil.makeTemp( """ |package scala |package collection diff --git a/doc-tool/test/dotty/tools/dottydoc/SimpleComments.scala b/doc-tool/test/dotty/tools/dottydoc/SimpleComments.scala index f9d8ae043ba9..cbfd57fb568e 100644 --- a/doc-tool/test/dotty/tools/dottydoc/SimpleComments.scala +++ b/doc-tool/test/dotty/tools/dottydoc/SimpleComments.scala @@ -3,6 +3,7 @@ package dottydoc import model.internal._ import dotc.util.SourceFile +import dotty.tools.io._ import org.junit.Test import org.junit.Assert._ @@ -35,8 +36,7 @@ abstract class SimpleCommentsBase extends DottyDocTest { } @Test def simpleComment = { - val source = new SourceFile( - "HelloWorld.scala", + val source = SourceUtil.makeTemp( """ |package scala | @@ -45,6 +45,7 @@ abstract class SimpleCommentsBase extends DottyDocTest { """.stripMargin ) + val className = "scala.HelloWorld" check(className :: Nil, source :: Nil) { (ctx, packages) => diff --git a/doc-tool/test/dotty/tools/dottydoc/SourceUtil.scala b/doc-tool/test/dotty/tools/dottydoc/SourceUtil.scala new file mode 100644 index 000000000000..eef86f5da9d2 --- /dev/null +++ b/doc-tool/test/dotty/tools/dottydoc/SourceUtil.scala @@ -0,0 +1,18 @@ +package dotty.tools.dottydoc + +import dotty.tools.dotc.util.SourceFile +import dotty.tools.io.{Path, PlainFile} + +object SourceUtil { + + /** Create a temporary `.scala` source file with the given content */ + def makeTemp(content: String): SourceFile = { + val tempFile = java.io.File.createTempFile("dottydoc-test-", ".scala") + tempFile.deleteOnExit() + val file = new PlainFile(Path(tempFile.toPath)) + val out = file.output + out.write(content.getBytes) + new SourceFile(file, scala.io.Codec.UTF8) + } + +} diff --git a/doc-tool/test/dotty/tools/dottydoc/UsecaseTest.scala b/doc-tool/test/dotty/tools/dottydoc/UsecaseTest.scala index f3772a882782..79f2c4c1d4e8 100644 --- a/doc-tool/test/dotty/tools/dottydoc/UsecaseTest.scala +++ b/doc-tool/test/dotty/tools/dottydoc/UsecaseTest.scala @@ -15,8 +15,7 @@ class UsecaseFromTastyTest extends UsecaseBase with CheckFromTasty abstract class UsecaseBase extends DottyDocTest { @Test def simpleUsecase = { - val source = new SourceFile( - "DefWithUseCase.scala", + val source = SourceUtil.makeTemp( """ |package scala | @@ -61,8 +60,7 @@ abstract class UsecaseBase extends DottyDocTest { } @Test def simpleUsecaseAddedArg = { - val source = new SourceFile( - "DefWithUseCase.scala", + val source = SourceUtil.makeTemp( """ |package scala | @@ -108,8 +106,7 @@ abstract class UsecaseBase extends DottyDocTest { } @Test def simpleTparamUsecase = { - val source = new SourceFile( - "DefWithUseCase.scala", + val source = SourceUtil.makeTemp( """ |package scala | @@ -154,8 +151,7 @@ abstract class UsecaseBase extends DottyDocTest { } @Test def expandColl = { - val source = new SourceFile( - "ExpandColl.scala", + val source = SourceUtil.makeTemp( """ |package scala | @@ -199,8 +195,7 @@ abstract class UsecaseBase extends DottyDocTest { } @Test def checkStripping = { - val source = new SourceFile( - "CheckStripping.scala", + val source = SourceUtil.makeTemp( """ |package scala | @@ -236,8 +231,7 @@ abstract class UsecaseBase extends DottyDocTest { } @Test def multipleUseCases: Unit = { - val source = new SourceFile( - name = "MultipleUseCases.scala", + val source = SourceUtil.makeTemp( """ |package scala | From 6188f375a6c245a5e00f050fa1ece2ec3824e0a6 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sun, 6 Jan 2019 18:43:48 +0100 Subject: [PATCH 52/75] Update test to use Spans --- tests/pos-with-compiler/tasty/definitions.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/pos-with-compiler/tasty/definitions.scala b/tests/pos-with-compiler/tasty/definitions.scala index d54edfbba574..40363f4e8eeb 100644 --- a/tests/pos-with-compiler/tasty/definitions.scala +++ b/tests/pos-with-compiler/tasty/definitions.scala @@ -348,7 +348,7 @@ object ReflectionImpl extends Tasty { import dotty.tools.dotc._ import ast.tpd import core.{Types, Symbols, Contexts} - import util.{Positions} + import util.Spans type Type = Types.Type implicit class TypeDeco(x: Type) extends TypeAPI {} @@ -361,7 +361,7 @@ object ReflectionImpl extends Tasty { val owner = c.owner } - type Position = Positions.Position + type Position = Spans.Span implicit class PositionDeco(p: Position) extends PositionAPI { val start = p.start val end = p.end @@ -369,19 +369,19 @@ object ReflectionImpl extends Tasty { type Pattern = tpd.Tree implicit class PatternDeco(p: Pattern) extends TypedPositioned { - val pos = p.pos + val pos = p.span val tpe = p.tpe } type Term = tpd.Tree implicit class TermDeco(t: Term) extends TypedPositioned { - val pos = t.pos + val pos = t.span val tpe = t.tpe } type CaseDef = tpd.CaseDef implicit class CaseDefDeco(c: CaseDef) extends TypedPositioned { - val pos = c.pos + val pos = c.span val tpe = c.tpe } From ba52c01d7cf58d2bc4292779bd59e66ef364a8b2 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sun, 6 Jan 2019 19:01:09 +0100 Subject: [PATCH 53/75] Update missing `pos` to `span` --- compiler/src/dotty/tools/dotc/typer/Implicits.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 5d73671da847..87b9fc05d28d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -686,11 +686,11 @@ trait Implicits { self: Typer => * An EmptyTree is returned if materialization fails. */ def synthesizedValueOf(formal: Type)(implicit ctx: Context): Tree = { - def success(t: Tree) = New(defn.ValueOfClass.typeRef.appliedTo(t.tpe), t :: Nil).withPos(pos) + def success(t: Tree) = New(defn.ValueOfClass.typeRef.appliedTo(t.tpe), t :: Nil).withSpan(span) formal.argTypes match { case arg :: Nil => - fullyDefinedType(arg.dealias, "ValueOf argument", pos) match { + fullyDefinedType(arg.dealias, "ValueOf argument", span) match { case ConstantType(c: Constant) => success(Literal(c)) case TypeRef(_, sym) if sym == defn.UnitClass => From ff7a87ed460c8d98f6b155b1a873b146669ac1d0 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 7 Jan 2019 11:20:30 +0100 Subject: [PATCH 54/75] Update implicit modifier test Now we keep only flags on the parameters (except the first one), so that parameter positions don't overlap. --- .../test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala b/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala index 862159505465..4dab85983368 100644 --- a/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala +++ b/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala @@ -137,7 +137,7 @@ class ModifiersParsingTest { source = parse("def f(implicit a: Int, b: Int) = ???") assert(source.defParam(0).modifiers == List(Mod.Implicit())) - assert(source.defParam(1).modifiers == List(Mod.Implicit())) + assert(source.defParam(1).modifiers == List()) source = parse("def f(x: Int, y: Int)(implicit a: Int, b: Int) = ???") assert(source.defParam(0, 0).modifiers == List()) From d0d6393362b65582cc6feab97df977b9c6d484f2 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 7 Jan 2019 13:49:36 +0100 Subject: [PATCH 55/75] Add missing spans in closures Previously they where infered from the mods. --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 7 +++++-- compiler/test/dotty/tools/repl/TabcompleteTests.scala | 6 ++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 0227bf3faef5..7abec3b13e9c 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -933,11 +933,14 @@ object desugar { * def $anonfun(params) = body * Closure($anonfun) */ - def makeClosure(params: List[ValDef], body: Tree, tpt: Tree = null, isImplicit: Boolean)(implicit ctx: Context): Block = + def makeClosure(params: List[ValDef], body: Tree, tpt: Tree = null, isImplicit: Boolean)(implicit ctx: Context): Block = { + val span = params.headOption.fold(body.span)(_.span.union(body.span)) Block( DefDef(nme.ANON_FUN, Nil, params :: Nil, if (tpt == null) TypeTree() else tpt, body) + .withSpan(span) .withMods(synthetic | Artifact), - Closure(Nil, Ident(nme.ANON_FUN), if (isImplicit) ImplicitEmptyTree else EmptyTree)) + Closure(Nil, Ident(nme.ANON_FUN), if (isImplicit) ImplicitEmptyTree else EmptyTree)).withSpan(span) + } /** If `nparams` == 1, expand partial function * diff --git a/compiler/test/dotty/tools/repl/TabcompleteTests.scala b/compiler/test/dotty/tools/repl/TabcompleteTests.scala index 20b3552cdaef..5cd7f317191b 100644 --- a/compiler/test/dotty/tools/repl/TabcompleteTests.scala +++ b/compiler/test/dotty/tools/repl/TabcompleteTests.scala @@ -90,4 +90,10 @@ class TabcompleteTests extends ReplTest { val expected = List("Renamed") assertEquals(expected, tabComplete("val foo: Rena")) } + + @Test def tabClosureComplete = fromInitialState { implicit s => + assertEquals(List("map", "mapConserve"), tabComplete("Nil.map")) + assertEquals(List("map", "mapConserve"), tabComplete("(x: Int => Int) => Nil.map")) + assertEquals(List("apply"), tabComplete("(x: Int => Int) => x.ap")) + } } From 5413f87d3271a7dab9027835d467e6919be31811 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 7 Jan 2019 14:08:35 +0100 Subject: [PATCH 56/75] Comment debug assertion --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 230030ea27f9..43b1fa8dc43e 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -815,7 +815,7 @@ object Trees { } class EmptyTree[T >: Untyped] extends Thicket(Nil)(NoContext) { - assert(uniqueId != 1492) + // assert(uniqueId != 1492) } class EmptyValDef[T >: Untyped] extends ValDef[T]( From 1f7ab4163408f6ab068bd38c2bfad2ccd1e7a343 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 7 Jan 2019 14:15:22 +0100 Subject: [PATCH 57/75] Remove unnecessary workaround for repl --- compiler/src/dotty/tools/dotc/core/Symbols.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 2a2eb9d15523..1f88cbe33524 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -674,9 +674,7 @@ object Symbols { final def sourcePos(implicit ctx: Context): SourcePosition = { val source = { val f = sourceFile - if (f == null || f.isVirtual) - // don't trust virtual files for tree creation - replTest fails otherwise - ctx.source + if (f == null) ctx.source else ctx.getSource(f) } source.atSpan(span) From 19cf827105912c80f221a1850252c5a2fc948411 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 9 Jan 2019 10:17:22 +0100 Subject: [PATCH 58/75] Fix rebase breakage --- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index e7686752d990..2269dfebca16 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -879,7 +879,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { if (from.isEmpty) Some((caseBindings, cdef.body)) else { val Block(stats, expr) = tpd.Block(caseBindings, cdef.body).subst(from, to) - val typeDefs = to.collect { case sym if sym.name != tpnme.WILDCARD => tpd.TypeDef(sym).withPos(sym.pos) } + val typeDefs = to.collect { case sym if sym.name != tpnme.WILDCARD => tpd.TypeDef(sym).withSpan(sym.span) } Some((typeDefs ::: stats.asInstanceOf[List[MemberDef]], expr)) } } @@ -963,7 +963,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { // drop type ascriptions/casts hiding pattern-bound types (which are now aliases after reducing the match) // note that any actually necessary casts will be reinserted by the typing pass below val rhs1 = rhs0 match { - case Block(stats, t) if t.pos.isSynthetic => + case Block(stats, t) if t.span.isSynthetic => t match { case Typed(expr, _) => Block(stats, expr) @@ -1099,7 +1099,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { treeMap = { case ident: Ident if ident.isType && typeBindingsSet.contains(ident.symbol) => val TypeAlias(r) = ident.symbol.info - TypeTree(r).withPos(ident.pos) + TypeTree(r).withSpan(ident.span) case tree => tree } ) From 64918725c7c713e04912b73d08a6643b38f2b462 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 7 Jan 2019 08:58:26 +0100 Subject: [PATCH 59/75] Avoid creating source positions in backend interface --- .../backend/jvm/DottyBackendInterface.scala | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index b3f8ce07a3fc..6fe8caa9af2b 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -21,7 +21,8 @@ import Types._ import Symbols._ import Phases._ -import dotty.tools.dotc.util.{SourcePosition, NoSourcePosition} +import dotty.tools.dotc.util +import dotty.tools.dotc.util.Spans import Decorators._ import tpd._ @@ -41,7 +42,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma type CompilationUnit = dotc.CompilationUnit type Constant = Constants.Constant type Literal = tpd.Literal - type Position = SourcePosition + type Position = Spans.Span type Name = Names.Name type ClassDef = tpd.TypeDef type TypeDef = tpd.TypeDef @@ -77,7 +78,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma type Closure = tpd.Closure val NoSymbol: Symbol = Symbols.NoSymbol - val NoPosition: Position = NoSourcePosition + val NoPosition: Position = Spans.NoSpan val EmptyTree: Tree = tpd.EmptyTree @@ -383,12 +384,14 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def debuglog(msg: => String): Unit = ctx.debuglog(msg) def informProgress(msg: String): Unit = ctx.informProgress(msg) def log(msg: => String): Unit = ctx.log(msg) - def error(pos: SourcePosition, msg: String): Unit = ctx.error(msg, pos) - def warning(pos: SourcePosition, msg: String): Unit = ctx.warning(msg, pos) + def error(pos: Position, msg: String): Unit = ctx.error(msg, sourcePos(pos)) + def warning(pos: Position, msg: String): Unit = ctx.warning(msg, sourcePos(pos)) def abort(msg: String): Nothing = { ctx.error(msg) throw new RuntimeException(msg) } + def sourcePos(pos: Position)(implicit ctx: Context): util.SourcePosition = + ctx.source.atSpan(pos) def emitAsmp: Option[String] = None @@ -562,7 +565,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma implicit def positionHelper(a: Position): PositionHelper = new PositionHelper { def isDefined: Boolean = a.exists - def line: Int = a.line + 1 + def line: Int = sourcePos(a).line + 1 def finalPosition: Position = a } @@ -586,7 +589,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma implicit def treeHelper(a: Tree): TreeHelper = new TreeHelper { def symbol: Symbol = a.symbol - def pos: Position = a.sourcePos + def pos: Position = a.span def isEmpty: Boolean = a.isEmpty @@ -800,7 +803,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def freshLocal(cunit: CompilationUnit, name: String, tpe: Type, pos: Position, flags: Flags): Symbol = { - ctx.newSymbol(sym, name.toTermName, termFlagSet(flags), tpe, NoSymbol, pos.span) + ctx.newSymbol(sym, name.toTermName, termFlagSet(flags), tpe, NoSymbol, pos) } def getter(clz: Symbol): Symbol = decorateSymbol(sym).getter @@ -808,7 +811,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def moduleSuffix: String = "" // todo: validate that names already have $ suffix def outputDirectory: AbstractFile = DottyBackendInterface.this.outputDirectory - def pos: Position = sym.sourcePos + def pos: Position = sym.span def throwsAnnotations: List[Symbol] = Nil @@ -1104,7 +1107,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def _1: Type = field.tpe match { case JavaArrayType(elem) => elem case _ => - error(field.sourcePos, s"JavaSeqArray with type ${field.tpe} reached backend: $field") + error(field.span, s"JavaSeqArray with type ${field.tpe} reached backend: $field") UnspecifiedErrorType } def _2: List[Tree] = field.elems From 512d7c38888ec87dfcdb314a3ace56510a33bfd1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 7 Jan 2019 17:36:27 +0100 Subject: [PATCH 60/75] Optimize computation of Sourcefile#content --- .../dotty/tools/dotc/util/SourceFile.scala | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index d55e9998e830..cf5d409ab861 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -36,7 +36,12 @@ object ScriptSourceFile { class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends interfaces.SourceFile { - lazy val content = computeContent + private var myContent: Array[Char] = null + + def content(): Array[Char] = { + if (myContent == null) myContent = computeContent + myContent + } def this(file: AbstractFile, codec: Codec) = this(file, new String(file.toByteArray, codec.charSet).toCharArray) def this(name: String, content: String) = this(new VirtualFile(name, content.getBytes), scala.io.Codec.UTF8) @@ -54,9 +59,9 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends } override def hashCode: Int = file.path.## + start.## - def apply(idx: Int): Char = content.apply(idx) + def apply(idx: Int): Char = content().apply(idx) - val length: Int = content.length + val length: Int = content().length /** true for all source files except `NoSource` */ def exists: Boolean = true @@ -81,9 +86,9 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends private def isLineBreak(idx: Int) = if (idx >= length) false else { - val ch = content(idx) + val ch = content()(idx) // don't identify the CR in CR LF as a line break, since LF will do. - if (ch == CR) (idx + 1 == length) || (content(idx + 1) != LF) + if (ch == CR) (idx + 1 == length) || (content()(idx + 1) != LF) else isLineBreakChar(ch) } @@ -94,7 +99,7 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends buf += cs.length // sentinel, so that findLine below works smoother buf.toArray } - private lazy val lineIndices: Array[Int] = calculateLineIndices(content) + private lazy val lineIndices: Array[Int] = calculateLineIndices(content()) /** Map line to offset of first character in line */ def lineToOffset(index: Int): Int = lineIndices(index) @@ -130,7 +135,7 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends var idx = startOfLine(offset) var col = 0 while (idx != offset) { - col += (if (idx < length && content(idx) == '\t') (tabInc - col) % tabInc else 1) + col += (if (idx < length && content()(idx) == '\t') (tabInc - col) % tabInc else 1) idx += 1 } col @@ -141,7 +146,7 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends var idx = startOfLine(offset) val pad = new StringBuilder while (idx != offset) { - pad.append(if (idx < length && content(idx) == '\t') '\t' else ' ') + pad.append(if (idx < length && content()(idx) == '\t') '\t' else ' ') idx += 1 } pad.result() From a2f437adec3999d6720b0c1b54fb536243377e85 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 9 Jan 2019 16:00:56 +0100 Subject: [PATCH 61/75] Make SourceFile equals depend on file Used to depend on file's path, but that does not work for VirtualFiles that might be different even though they have the same path. --- compiler/src/dotty/tools/dotc/util/SourceFile.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index cf5d409ab861..4b791824cd40 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -54,10 +54,10 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends override def jfile: Optional[JFile] = Optional.ofNullable(file.file) override def equals(that : Any): Boolean = that match { - case that : SourceFile => file.path == that.file.path && start == that.start + case that : SourceFile => file == that.file && start == that.start case _ => false } - override def hashCode: Int = file.path.## + start.## + override def hashCode: Int = file.hashCode * 41 + start.hashCode def apply(idx: Int): Char = content().apply(idx) From cb3515b7a6a9d14c0b6446f1df45c7fc6064512b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 9 Jan 2019 16:02:37 +0100 Subject: [PATCH 62/75] Optimize equals + hashCode on PlainFile Use interned strings for the comparison of their paths. --- compiler/src/dotty/tools/dotc/Run.scala | 2 +- compiler/src/dotty/tools/io/PlainFile.scala | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index 21a4a65c7251..f5d1522749bc 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -240,7 +240,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint } def compile(sourceCode: String): Unit = { - val virtualFile = new VirtualFile(sourceCode) // use source code as name as it's used for equals + val virtualFile = new VirtualFile(sourceCode) val writer = new BufferedWriter(new OutputStreamWriter(virtualFile.output, "UTF-8")) // buffering is still advised by javadoc writer.write(sourceCode) writer.close() diff --git a/compiler/src/dotty/tools/io/PlainFile.scala b/compiler/src/dotty/tools/io/PlainFile.scala index f5bde26722fc..f171a5da81b5 100644 --- a/compiler/src/dotty/tools/io/PlainFile.scala +++ b/compiler/src/dotty/tools/io/PlainFile.scala @@ -33,6 +33,9 @@ class PlainFile(val givenPath: Path) extends AbstractFile { /** Returns the path of this abstract file. */ def path: String = givenPath.path + /** Returns the absolute path of this abstract file as an interned string. */ + val absolutePath: String = givenPath.toAbsolute.toString.intern + /** The absolute file. */ def absolute: PlainFile = new PlainFile(givenPath.toAbsolute) @@ -41,9 +44,9 @@ class PlainFile(val givenPath: Path) extends AbstractFile { override def output: OutputStream = givenPath.toFile.outputStream() override def sizeOption: Option[Int] = Some(givenPath.length.toInt) - override def hashCode(): Int = fpath.hashCode() + override def hashCode(): Int = System.identityHashCode(absolutePath) override def equals(that: Any): Boolean = that match { - case x: PlainFile => fpath == x.fpath + case x: PlainFile => absolutePath == x.absolutePath case _ => false } From d1008fc1abde419c2bd4cab32c8885c9802348fd Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 9 Jan 2019 17:43:41 +0100 Subject: [PATCH 63/75] Reduce concurrent hashmap lookups Reduce concurrent hashmap lookups in TreeIds by caching the last result in SourceInfo. This reduces lookups for typer/*.scala from 500K+ to 7.6K. --- .../src/dotty/tools/dotc/ast/TreeIds.scala | 18 +++++++++++++----- .../src/dotty/tools/dotc/core/Contexts.scala | 14 ++++++++++++-- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/TreeIds.scala b/compiler/src/dotty/tools/dotc/ast/TreeIds.scala index 8f22431ba54c..3a949196bb9e 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeIds.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeIds.scala @@ -16,13 +16,21 @@ object TreeIds { @sharable private[this] val counters = new ConcurrentHashMap[AbstractFile, AtomicInteger] @sharable private[this] val fileOfChunk = mutable.ArrayBuffer[AbstractFile]() - def nextId(implicit src: SourceInfo): Int = nextIdFor(src.srcfile) - - def nextIdFor(file: AbstractFile): Int = { - var ctr = counters.get(file) + def nextIdFor(file: AbstractFile)(implicit src: SourceInfo): Int = { + def getCounter: AtomicInteger = + if (file `eq` src.srcfile) { + var cachedCtr = src.counter + if (cachedCtr == null) { + cachedCtr = counters.get(file) + src.counter = cachedCtr + } + cachedCtr + } + else counters.get(file) + var ctr = getCounter if (ctr == null) { counters.putIfAbsent(file, new AtomicInteger) - ctr = counters.get(file) + ctr = getCounter } def recur(): Int = { val id = ctr.get diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 684e5f30d486..111e7b1e7994 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -34,11 +34,16 @@ import util.Property.Key import util.Store import xsbti.AnalysisCallback import plugins._ +import java.util.concurrent.atomic.AtomicInteger object Contexts { trait SourceInfo { def srcfile: AbstractFile + + private[this] var _counter: AtomicInteger = null + def counter = _counter + def counter_=(c: AtomicInteger) = _counter = c } object SourceInfo { def apply(src: AbstractFile) = new SourceInfo { @@ -170,7 +175,10 @@ object Contexts { /** The current source file */ private[this] var _source: SourceFile = _ - protected def source_=(source: SourceFile): Unit = _source = source + protected def source_=(source: SourceFile): Unit = { + _source = source + counter = null + } def source: SourceFile = _source def srcfile = source.file @@ -247,8 +255,10 @@ object Contexts { getSource(TreeIds.fileOfId(id)) /** Sourcefile corresponding to given abstract file, memoized */ - def getSource(file: AbstractFile, codec: => Codec = Codec(settings.encoding.value)) = + def getSource(file: AbstractFile, codec: => Codec = Codec(settings.encoding.value)) = { + util.Stats.record("getSource") base.sources.getOrElseUpdate(file, new SourceFile(file, codec)) + } def getSource(fileName: String): SourceFile = { val f = new PlainFile(Path(fileName)) From 44210925a58d5a060f3cf3f8ef59190140ac23fa Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 9 Jan 2019 23:03:40 +0100 Subject: [PATCH 64/75] Refactor SourceFile operations Deemphasize AbstractFile, drop TreeIds. --- .../src/dotty/tools/dotc/ast/Positioned.scala | 70 +++++++++---------- .../src/dotty/tools/dotc/ast/TreeIds.scala | 53 -------------- compiler/src/dotty/tools/dotc/ast/Trees.scala | 9 ++- compiler/src/dotty/tools/dotc/ast/tpd.scala | 5 +- .../src/dotty/tools/dotc/core/Contexts.scala | 70 +++++++++---------- .../src/dotty/tools/dotc/core/Symbols.scala | 22 +++--- .../dotc/core/tasty/PositionPickler.scala | 20 +++--- .../tools/dotc/core/tasty/TreeUnpickler.scala | 3 +- .../tools/dotc/interactive/SourceTree.scala | 5 +- .../tools/dotc/transform/ExpandPrivate.scala | 9 +-- .../dotty/tools/dotc/transform/Pickler.scala | 2 +- .../src/dotty/tools/dotc/typer/Inliner.scala | 4 +- .../src/dotty/tools/dotc/typer/Typer.scala | 2 +- .../dotty/tools/dotc/util/SourceFile.scala | 33 +++++++++ .../tools/dotc/util/SourcePosition.scala | 1 + .../src/dotty/tools/io/AbstractFile.scala | 3 + compiler/src/dotty/tools/io/PlainFile.scala | 5 +- .../tools/dottydoc/staticsite/Page.scala | 1 - .../dotty/tools/dottydoc/util/syntax.scala | 2 +- 19 files changed, 142 insertions(+), 177 deletions(-) delete mode 100644 compiler/src/dotty/tools/dotc/ast/TreeIds.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index 4c6f5bad5c2a..fd467fe370b8 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -3,12 +3,11 @@ package dotc package ast import util.Spans._ -import util.{SourceFile, SourcePosition} +import util.{SourceFile, NoSource, SourcePosition} import core.Contexts.{Context, SourceInfo} import core.Decorators._ import core.Flags.{JavaDefined, Extension} import core.StdNames.nme -import io.AbstractFile import annotation.transientParam import annotation.internal.sharable @@ -28,12 +27,11 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod /** item's id */ def uniqueId: Int = myUniqueId - protected def srcfile: AbstractFile = TreeIds.fileOfId(uniqueId) - def source(implicit ctx: Context): SourceFile = ctx.getSource(srcfile) + def source: SourceFile = SourceFile.fromId(uniqueId) def sourcePos(implicit ctx: Context): SourcePosition = source.atSpan(span) - setId(TreeIds.nextIdFor(initialFile(src))) - setPos(initialSpan(), srcfile) + setId(initialSource(src).nextId) + setPos(initialSpan(), source) protected def setId(id: Int): Unit = { myUniqueId = id @@ -43,7 +41,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod /** Destructively update `mySpan` to given span and potentially update `id` so that * it refers to `file`. Also, set any missing positions in children. */ - protected def setPos(span: Span, file: AbstractFile): Unit = { + protected def setPos(span: Span, file: SourceFile): Unit = { setOnePos(span, file) if (span.exists) setChildPositions(span.toSynthetic, file) } @@ -56,34 +54,34 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod def withSpan(span: Span): this.type = { val ownSpan = this.span val newpd: this.type = - if (span == ownSpan || ownSpan.isSynthetic) this else cloneIn(srcfile) - newpd.setPos(span, srcfile) + if (span == ownSpan || ownSpan.isSynthetic) this else cloneIn(source) + newpd.setPos(span, source) newpd } def withPosOf(posd: Positioned): this.type = { val ownSpan = this.span val newpd: this.type = - if (posd.srcfile == srcfile && posd.span == ownSpan || ownSpan.isSynthetic) this - else cloneIn(posd.srcfile) - newpd.setPos(posd.span, posd.srcfile) + if ((posd.source `eq` source) && posd.span == ownSpan || ownSpan.isSynthetic) this + else cloneIn(posd.source) + newpd.setPos(posd.span, posd.source) newpd } def withSourcePos(sourcePos: SourcePosition): this.type = { val ownSpan = this.span val newpd: this.type = - if (sourcePos.source.file == srcfile && sourcePos.span == ownSpan || ownSpan.isSynthetic) this - else cloneIn(sourcePos.source.file) - newpd.setPos(sourcePos.span, sourcePos.source.file) + if ((sourcePos.source `eq` source) && sourcePos.span == ownSpan || ownSpan.isSynthetic) this + else cloneIn(sourcePos.source) + newpd.setPos(sourcePos.span, sourcePos.source) newpd } /** Set span of this tree only, without updating children spans. * Called from Unpickler when entering positions. */ - private[dotc] def setOnePos(span: Span, file: AbstractFile = this.srcfile): Unit = { - if (file != this.srcfile) setId(TreeIds.nextIdFor(file)) + private[dotc] def setOnePos(span: Span, file: SourceFile = this.source): Unit = { + if (file `ne` this.source) setId(file.nextId) mySpan = span } @@ -98,7 +96,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod * But since mutual tail recursion is not supported in Scala, we express it instead * as a while loop with a termination by return in the middle. */ - private def setChildPositions(span: Span, file: AbstractFile): Unit = { + private def setChildPositions(span: Span, file: SourceFile): Unit = { var n = productArity // subnodes are analyzed right to left var elems: List[Any] = Nil // children in lists still to be considered, from right to left var end = span.end // the last defined offset, fill in spans up to this offset @@ -150,39 +148,39 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod } /** Clone this node but assign it a fresh id which marks it as a node in `file`. */ - protected def cloneIn(file: AbstractFile): this.type = { + protected def cloneIn(file: SourceFile): this.type = { val newpd: this.type = clone.asInstanceOf[this.type] - newpd.setId(TreeIds.nextIdFor(file)) + newpd.setId(file.nextId) newpd } /** The source of the first element of this node that has a position */ - def elemsFile: AbstractFile = { - def firstFile(x: Any): AbstractFile = x match { + def elemsSource: SourceFile = { + def firstSource(x: Any): SourceFile = x match { case x: Positioned if x.span.exists => - x.srcfile + x.source case x1 :: xs1 => - val f = firstFile(x1) - if (f != null) f else firstFile(xs1) + val f = firstSource(x1) + if (f.exists) f else firstSource(xs1) case _ => - null + NoSource } - def firstElemFile(n: Int): AbstractFile = - if (n == productArity) null + def firstElemSource(n: Int): SourceFile = + if (n == productArity) NoSource else { - val f = firstFile(productElement(n)) - if (f != null) f else firstElemFile(n + 1) + val f = firstSource(productElement(n)) + if (f.exists) f else firstElemSource(n + 1) } - firstElemFile(0) + firstElemSource(0) } /** The source file to use for the `id` of this node. This is - * `elemsFile` if it exists, or the source file indicated by + * `elemsSource` if it exists, or the source file indicated by * `src` otherwise */ - private def initialFile(src: SourceInfo): AbstractFile = { - val f = elemsFile - if (f != null) f else src.srcfile + private def initialSource(src: SourceInfo): SourceFile = { + val f = elemsSource + if (f.exists) f else src.source } /** The initial, synthetic span. This is usually the union of all positioned children's spans. @@ -219,7 +217,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod span.toSynthetic } - private def sameSource(that: Positioned) = srcfile == that.srcfile + private def sameSource(that: Positioned) = source `eq` that.source def contains(that: Positioned): Boolean = { def isParent(x: Any): Boolean = x match { diff --git a/compiler/src/dotty/tools/dotc/ast/TreeIds.scala b/compiler/src/dotty/tools/dotc/ast/TreeIds.scala deleted file mode 100644 index 3a949196bb9e..000000000000 --- a/compiler/src/dotty/tools/dotc/ast/TreeIds.scala +++ /dev/null @@ -1,53 +0,0 @@ -package dotty.tools -package dotc -package ast - -import core.Contexts.SourceInfo -import io.AbstractFile -import scala.annotation.internal.sharable -import scala.collection.mutable -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.atomic.AtomicInteger - -object TreeIds { - - private final val ChunkSize = 1024 - - @sharable private[this] val counters = new ConcurrentHashMap[AbstractFile, AtomicInteger] - @sharable private[this] val fileOfChunk = mutable.ArrayBuffer[AbstractFile]() - - def nextIdFor(file: AbstractFile)(implicit src: SourceInfo): Int = { - def getCounter: AtomicInteger = - if (file `eq` src.srcfile) { - var cachedCtr = src.counter - if (cachedCtr == null) { - cachedCtr = counters.get(file) - src.counter = cachedCtr - } - cachedCtr - } - else counters.get(file) - var ctr = getCounter - if (ctr == null) { - counters.putIfAbsent(file, new AtomicInteger) - ctr = getCounter - } - def recur(): Int = { - val id = ctr.get - if (id % ChunkSize == 0) newChunk(file, ctr) - else if (ctr.compareAndSet(id, id + 1)) id - else recur() - } - recur() - } - - private def newChunk(file: AbstractFile, ctr: AtomicInteger): Int = synchronized { - val id = fileOfChunk.length * ChunkSize - fileOfChunk += file - ctr.set(id + 1) - id - } - - def fileOfId(id: Int): AbstractFile = - fileOfChunk(id / ChunkSize) -} \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 43b1fa8dc43e..b5d49ae6517e 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -11,7 +11,6 @@ import printing.Printer import printing.Texts.Text import util.{Stats, Attachment, Property, SourceFile, SourcePosition} import config.Config -import io.AbstractFile import annotation.internal.sharable import annotation.unchecked.uncheckedVariance import annotation.transientParam @@ -134,7 +133,7 @@ object Trees { val tree = (if (myTpe == null || (myTpe.asInstanceOf[AnyRef] eq tpe.asInstanceOf[AnyRef])) this - else cloneIn(srcfile)).asInstanceOf[Tree[Type]] + else cloneIn(source)).asInstanceOf[Tree[Type]] tree overwriteType tpe tree.asInstanceOf[ThisTree[Type]] } @@ -325,7 +324,7 @@ object Trees { def rawComment: Option[Comment] = getAttachment(DocComment) def withMods(mods: untpd.Modifiers): ThisTree[Untyped] = { - val tree = if (myMods == null || (myMods == mods)) this else cloneIn(srcfile) + val tree = if (myMods == null || (myMods == mods)) this else cloneIn(source) tree.setMods(mods) tree.asInstanceOf[ThisTree[Untyped]] } @@ -777,7 +776,7 @@ object Trees { trait WithoutTypeOrPos[-T >: Untyped] extends Tree[T] { override def withTypeUnchecked(tpe: Type): ThisTree[Type] = this.asInstanceOf[ThisTree[Type]] override def span: Span = NoSpan - override def setPos(span: Span, file: AbstractFile): Unit = {} + override def setPos(span: Span, src: SourceFile): Unit = {} } /** Temporary class that results from translation of ModuleDefs @@ -795,7 +794,7 @@ object Trees { if (trees eq newTrees) this else - Thicket[T](newTrees)(SourceInfo(srcfile)).asInstanceOf[this.type] + Thicket[T](newTrees)(SourceInfo(source)).asInstanceOf[this.type] } override def foreachInThicket(op: Tree[T] => Unit): Unit = diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 8e86119732f9..ec39ca1fc2d7 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -1134,10 +1134,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { /** The source file where the symbol of the `inline` method referred to by `call` * is defined */ - def sourceFile(call: Tree)(implicit ctx: Context): SourceFile = { - val file = call.symbol.sourceFile - if (file != null && file.exists) ctx.getSource(file) else NoSource - } + def sourceFile(call: Tree)(implicit ctx: Context): SourceFile = call.symbol.source /** Desugar identifier into a select node. Return the tree itself if not possible */ def desugarIdent(tree: Ident)(implicit ctx: Context): Tree = { diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 111e7b1e7994..561a3acf5b37 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -12,7 +12,7 @@ import Symbols._ import Scopes._ import Uniques._ import ast.Trees._ -import ast.{untpd, TreeIds} +import ast.untpd import util.{FreshNameCreator, NoSource, SimpleIdentityMap, SourceFile} import typer.{Implicits, ImportInfo, Inliner, NamerContextOps, SearchHistory, SearchRoot, TypeAssigner, Typer} import Implicits.ContextualImplicits @@ -39,15 +39,11 @@ import java.util.concurrent.atomic.AtomicInteger object Contexts { trait SourceInfo { - def srcfile: AbstractFile - - private[this] var _counter: AtomicInteger = null - def counter = _counter - def counter_=(c: AtomicInteger) = _counter = c + def source: SourceFile } object SourceInfo { - def apply(src: AbstractFile) = new SourceInfo { - def srcfile = src + def apply(src: SourceFile) = new SourceInfo { + def source = src } } @@ -175,14 +171,9 @@ object Contexts { /** The current source file */ private[this] var _source: SourceFile = _ - protected def source_=(source: SourceFile): Unit = { - _source = source - counter = null - } + protected def source_=(source: SourceFile): Unit = _source = source def source: SourceFile = _source - def srcfile = source.file - /** A map in which more contextual properties can be stored * Typically used for attributes that are read and written only in special situations. */ @@ -251,34 +242,36 @@ object Contexts { implicitsCache } - def sourceOfTreeId(id: Int): SourceFile = - getSource(TreeIds.fileOfId(id)) - /** Sourcefile corresponding to given abstract file, memoized */ def getSource(file: AbstractFile, codec: => Codec = Codec(settings.encoding.value)) = { util.Stats.record("getSource") base.sources.getOrElseUpdate(file, new SourceFile(file, codec)) } - def getSource(fileName: String): SourceFile = { - val f = new PlainFile(Path(fileName)) - base.sources.get(f) match { - case Some(source) => - source - case None => - if (f.isDirectory) { - error(s"expected file, received directory '$fileName'") - NoSource - } - else if (f.exists) - getSource(f) - else { - error(s"not found: $fileName") - NoSource - } - } + /** Sourcefile with given path name, memoized */ + def getSource(path: SourceFile.PathName): SourceFile = base.sourceNamed.get(path) match { + case Some(source) => + source + case None => + val f = new PlainFile(Path(path.toString)) + if (f.isDirectory) { + error(s"expected file, received directory '$path'") + NoSource + } + else if (f.exists) { + val src = getSource(f) + base.sourceNamed(path) = src + src + } + else { + error(s"not found: $path") + NoSource + } } + /** Sourcefile with given path, memoized */ + def getSource(path: String): SourceFile = getSource(path.toTermName) + /** Those fields are used to cache phases created in withPhase. * phasedCtx is first phase with altered phase ever requested. * phasedCtxs is array that uses phaseId's as indexes, @@ -468,7 +461,9 @@ object Contexts { final def withSource(source: SourceFile): Context = if (source `eq` this.source) this - else if ((source `eq` outer.source) && (outer.sourceCtx(this.source) `eq` this)) outer + else if ((source `eq` outer.source) && + outer.sourceCtx != null && + (outer.sourceCtx(this.source) `eq` this)) outer else { if (sourceCtx == null) sourceCtx = SimpleIdentityMap.Empty val prev = sourceCtx(source) @@ -480,9 +475,6 @@ object Contexts { } } - final def withSource(f: AbstractFile): Context = - if (f == null) this else withSource(getSource(f)) - final def withProperty[T](key: Key[T], value: Option[T]): Context = if (property(key) == value) this else value match { @@ -701,6 +693,7 @@ object Contexts { /** Sources that were loaded */ val sources: mutable.HashMap[AbstractFile, SourceFile] = new mutable.HashMap[AbstractFile, SourceFile] + val sourceNamed: mutable.HashMap[SourceFile.PathName, SourceFile] = new mutable.HashMap[SourceFile.PathName, SourceFile] // Types state /** A table for hash consing unique types */ @@ -775,6 +768,7 @@ object Contexts { for ((_, set) <- uniqueSets) set.clear() errorTypeMsg.clear() sources.clear() + sourceNamed.clear() } // Test that access is single threaded diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 1f88cbe33524..fe31e8e7b539 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -623,25 +623,23 @@ object Symbols { final def symbol(implicit ev: DontUseSymbolOnSymbol): Nothing = unsupported("symbol") type DontUseSymbolOnSymbol - /** The source file from which this class was generated, null if not applicable. */ - final def sourceFile(implicit ctx: Context): AbstractFile = - if (!defTree.isEmpty) defTree.source.file + def source(implicit ctx: Context): SourceFile = + if (!defTree.isEmpty) defTree.source else { val file = associatedFile - if (file != null && file.extension != "class") file + if (file != null && file.extension != "class") ctx.getSource(file) else { val topLevelCls = denot.topLevelClass(ctx.withPhaseNoLater(ctx.flattenPhase)) topLevelCls.unforcedAnnotation(defn.SourceFileAnnot) match { case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match { - case Some(Constant(path: String)) => AbstractFile.getFile(path) - case none => null + case Some(Constant(path: String)) => ctx.getSource(path) + case none => NoSource } - case none => null + case none => NoSource } } } - def source(implicit ctx: Context): SourceFile = ctx.getSource(sourceFile) /** A symbol related to `sym` that is defined in source code. * @@ -672,12 +670,8 @@ object Symbols { final def span: Span = if (coord.isSpan) coord.toSpan else NoSpan final def sourcePos(implicit ctx: Context): SourcePosition = { - val source = { - val f = sourceFile - if (f == null) ctx.source - else ctx.getSource(f) - } - source.atSpan(span) + val src = source + (if (src.exists) src else ctx.source).atSpan(span) } // ParamInfo types and methods diff --git a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala index 8c8a75700e3b..6a9cb2e90375 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala @@ -6,7 +6,7 @@ package tasty import ast._ import ast.Trees._ import ast.Trees.WithLazyField -import io.{AbstractFile, NoAbstractFile} +import util.{SourceFile, NoSource} import core._ import Contexts._, Symbols._, Annotations._, Decorators._ import collection.mutable @@ -43,9 +43,9 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad pickledIndices += index } - def pickleSource(source: AbstractFile): Unit = { + def pickleSource(source: SourceFile): Unit = { buf.writeInt(SOURCE) - buf.writeInt(pickler.nameBuffer.nameIndex(source.path.toTermName).index) + buf.writeInt(pickler.nameBuffer.nameIndex(source.pathName).index) } /** True if x's position shouldn't be reconstructed automatically from its initial span @@ -66,13 +66,13 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad case _ => false } - def traverse(x: Any, current: AbstractFile): Unit = x match { + def traverse(x: Any, current: SourceFile): Unit = x match { case x: untpd.Tree => var sourceFile = current val span = if (x.isInstanceOf[untpd.MemberDef]) x.span else x.span.toSynthetic val sourceChange = - x.source.file != x.elemsFile || - x.elemsFile == null && x.source.file != current + x.source != x.elemsSource || + !x.elemsSource.exists && x.source != current if (span.exists && ( span != x.initialSpan(ignoreTypeTrees = true).toSynthetic || sourceChange || @@ -84,9 +84,9 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad // in order not to miss the source change. Test case is t3232a.scala. //println(i"pickling $x with $span at $addr") pickleDeltas(addr.index, span) - if (x.source.file != current) { - pickleSource(x.source.file) - sourceFile = x.source.file + if (x.source != current) { + pickleSource(x.source) + sourceFile = x.source } case _ => //println(i"no address for $x") @@ -106,7 +106,7 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad case _ => } for (root <- roots) { - traverse(root, NoAbstractFile) + traverse(root, NoSource) } } } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index e1803622decc..278ee242d610 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -20,7 +20,6 @@ import typer.ConstFold import typer.Checking.checkNonCyclic import util.Spans._ import util.SourceFile -import io.AbstractFile import ast.{TreeTypeMap, Trees, tpd, untpd} import Trees._ import Decorators._ @@ -1335,7 +1334,7 @@ class TreeUnpickler(reader: TastyReader, /** Set position of `tree` at given `addr`. */ def setPos[T <: untpd.Tree](addr: Addr, tree: T)(implicit ctx: Context): tree.type = { val pos = posAt(addr) - if (pos.exists) tree.setOnePos(pos, ctx.source.file) + if (pos.exists) tree.setOnePos(pos, ctx.source) tree } } diff --git a/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala b/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala index 6bd4b1d57fc1..f7cfb0ec155e 100644 --- a/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala +++ b/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala @@ -53,7 +53,7 @@ case class SourceTree(tree: tpd.Tree /** really: tpd.Import | tpd.NameTree */, s object SourceTree { def fromSymbol(sym: ClassSymbol, id: String = "")(implicit ctx: Context): List[SourceTree] = { if (sym == defn.SourceFileAnnot || // FIXME: No SourceFile annotation on SourceFile itself - sym.sourceFile == null) // FIXME: We cannot deal with external projects yet + !sym.source.exists) // FIXME: We cannot deal with external projects yet Nil else { import ast.Trees._ @@ -61,8 +61,7 @@ object SourceTree { case PackageDef(_, stats) => stats.flatMap(sourceTreeOfClass).headOption case tree: tpd.TypeDef if tree.symbol == sym => - val sourceFile = ctx.getSource(sym.sourceFile, Codec.UTF8) - Some(SourceTree(tree, sourceFile)) + Some(SourceTree(tree, sym.source)) case _ => None } diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala index 6d945ef05f48..741d9aa92719 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala @@ -72,6 +72,7 @@ class ExpandPrivate extends MiniPhase with IdentityDenotTransformer { thisPhase // Paths `p1` and `p2` are similar if they have a common suffix that follows // possibly different directory paths. That is, their common suffix extends // in both cases either to the start of the path or to a file separator character. + // TODO: should we test absolute paths instead? def isSimilar(p1: String, p2: String): Boolean = { var i = p1.length - 1 var j = p2.length - 1 @@ -83,10 +84,10 @@ class ExpandPrivate extends MiniPhase with IdentityDenotTransformer { thisPhase (j < 0 || p1(j) == separatorChar) } - assert(d.symbol.sourceFile != null && - ctx.owner.sourceFile != null && - isSimilar(d.symbol.sourceFile.path, ctx.owner.sourceFile.path), - s"private ${d.symbol.showLocated} in ${d.symbol.sourceFile} accessed from ${ctx.owner.showLocated} in ${ctx.owner.sourceFile}") + assert(d.symbol.source.exists && + ctx.owner.source.exists && + isSimilar(d.symbol.source.path, ctx.owner.source.path), + s"private ${d.symbol.showLocated} in ${d.symbol.source} accessed from ${ctx.owner.showLocated} in ${ctx.owner.source}") d.ensureNotPrivate.installAfter(thisPhase) } diff --git a/compiler/src/dotty/tools/dotc/transform/Pickler.scala b/compiler/src/dotty/tools/dotc/transform/Pickler.scala index a8252a6e74e0..a265e52153e6 100644 --- a/compiler/src/dotty/tools/dotc/transform/Pickler.scala +++ b/compiler/src/dotty/tools/dotc/transform/Pickler.scala @@ -116,7 +116,7 @@ class Pickler extends Phase { if (previous != unpickled) { output("before-pickling.txt", previous) output("after-pickling.txt", unpickled) - ctx.error(s"""pickling difference for $cls in ${cls.sourceFile}, for details: + ctx.error(s"""pickling difference for $cls in ${cls.source}, for details: | | diff before-pickling.txt after-pickling.txt""".stripMargin) } diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 2269dfebca16..fac20240344f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -123,7 +123,7 @@ object Inliner { if (enclosingInlineds.nonEmpty) inlined // Remove in the outer most inlined call else { val inlinedAtPos = inlined.call.sourcePos - val curSourceFile = ctx.compilationUnit.source.file + val curSource = ctx.compilationUnit.source /** Removes all Inlined trees, replacing them with blocks. * Repositions all trees directly inside an inlined expansion of a non empty call to the position of the call. @@ -136,7 +136,7 @@ object Inliner { case _ => val transformed = super.transform(tree) enclosingInlineds match { - case call :: _ if call.symbol.sourceFile != curSourceFile => + case call :: _ if call.symbol.source != curSource => // Until we implement JSR-45, we cannot represent in output positions in other source files. // So, reposition inlined code from other files with the call position: transformed.withPosOf(inlined.call) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 60de458bcc69..a199f18a96d0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -228,7 +228,7 @@ class Typer extends Namer */ def isDefinedInCurrentUnit(denot: Denotation)(implicit ctx: Context): Boolean = denot match { case MultiDenotation(d1, d2) => isDefinedInCurrentUnit(d1) || isDefinedInCurrentUnit(d2) - case denot: SingleDenotation => denot.symbol.sourceFile == ctx.source.file + case denot: SingleDenotation => denot.symbol.source `eq` ctx.compilationUnit.source } /** Is `denot` the denotation of a self symbol? */ diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index 4b791824cd40..223c59d9c0e0 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -9,7 +9,11 @@ import java.io.IOException import scala.tasty.util.Chars._ import Spans._ import scala.io.Codec +import core.Names.TermName import scala.annotation.internal.sharable +import core.Decorators.PreNamedString +import java.util.concurrent.atomic.AtomicInteger +import scala.collection.mutable import java.util.Optional @@ -35,6 +39,7 @@ object ScriptSourceFile { } class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends interfaces.SourceFile { + import SourceFile._ private var myContent: Array[Char] = null @@ -53,6 +58,8 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends override def path: String = file.path override def jfile: Optional[JFile] = Optional.ofNullable(file.file) + def pathName: PathName = file.absolutePath.toTermName + override def equals(that : Any): Boolean = that match { case that : SourceFile => file == that.file && start == that.start case _ => false @@ -153,9 +160,35 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends } override def toString: String = file.toString + + // Positioned ids + + private[this] val ctr = new AtomicInteger + + def nextId: Int = { + val id = ctr.get + if (id % ChunkSize == 0) newChunk + else if (ctr.compareAndSet(id, id + 1)) id + else nextId + } + + private def newChunk: Int = sourceOfChunk.synchronized { + val id = sourceOfChunk.length * ChunkSize + sourceOfChunk += this + ctr.set(id + 1) + id + } } object SourceFile { implicit def eqSurce: Eq[SourceFile, SourceFile] = Eq + + type PathName = TermName + + def fromId(id: Int): SourceFile = + sourceOfChunk(id / ChunkSize) + + private val ChunkSize = 1024 + @sharable private val sourceOfChunk = mutable.ArrayBuffer[SourceFile]() } @sharable object NoSource extends SourceFile(NoAbstractFile, Array[Char]()) { diff --git a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala index a2ef9a81ce9b..257d3ca42553 100644 --- a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala +++ b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala @@ -10,6 +10,7 @@ import scala.annotation.internal.sharable /** A source position is comprised of a span and a source file */ case class SourcePosition(source: SourceFile, span: Span, outer: SourcePosition = NoSourcePosition) extends interfaces.SourcePosition with Showable { + /** Is `that` a source position contained in this source position ? * `outer` is not taken into account. */ def contains(that: SourcePosition): Boolean = diff --git a/compiler/src/dotty/tools/io/AbstractFile.scala b/compiler/src/dotty/tools/io/AbstractFile.scala index 6d893a275bbc..67bd964ecc3d 100644 --- a/compiler/src/dotty/tools/io/AbstractFile.scala +++ b/compiler/src/dotty/tools/io/AbstractFile.scala @@ -89,6 +89,9 @@ abstract class AbstractFile extends Iterable[AbstractFile] { /** Returns the path of this abstract file. */ def path: String + /** Returns the absolute path of this abstract file. */ + def absolutePath: String = path + /** Returns the path of this abstract file in a canonical form. */ def canonicalPath: String = if (jpath == null) path else jpath.normalize.toString diff --git a/compiler/src/dotty/tools/io/PlainFile.scala b/compiler/src/dotty/tools/io/PlainFile.scala index f171a5da81b5..37a3707d9a2c 100644 --- a/compiler/src/dotty/tools/io/PlainFile.scala +++ b/compiler/src/dotty/tools/io/PlainFile.scala @@ -22,10 +22,11 @@ class PlainDirectory(givenPath: Directory) extends PlainFile(givenPath) { class PlainFile(val givenPath: Path) extends AbstractFile { assert(path ne null) + dotc.util.Stats.record("new PlainFile") + def jpath: JPath = givenPath.jpath override def underlyingSource: Some[PlainFile] = Some(this) - private val fpath = givenPath.toAbsolute /** Returns the name of this abstract file. */ def name: String = givenPath.name @@ -34,7 +35,7 @@ class PlainFile(val givenPath: Path) extends AbstractFile { def path: String = givenPath.path /** Returns the absolute path of this abstract file as an interned string. */ - val absolutePath: String = givenPath.toAbsolute.toString.intern + override val absolutePath: String = givenPath.toAbsolute.toString.intern /** The absolute file. */ def absolute: PlainFile = new PlainFile(givenPath.toAbsolute) diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/Page.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/Page.scala index 7de72693aaea..76e401188dfd 100644 --- a/doc-tool/src/dotty/tools/dottydoc/staticsite/Page.scala +++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/Page.scala @@ -89,7 +89,6 @@ trait Page { new SourceFile(virtualFile, Codec.UTF8) } - protected[this] var _yaml: Map[String, AnyRef /* String | JList[String] */] = _ protected[this] var _html: Option[String] = _ protected[this] def initFields(implicit ctx: Context) = { diff --git a/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala b/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala index 15c7e440f22e..2c99783d7182 100644 --- a/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala +++ b/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala @@ -21,6 +21,6 @@ object syntax { implicit class SymbolExtensions(val sym: Symbol) extends AnyVal { def sourcePosition(span: Span)(implicit ctx: Context): SourcePosition = - ctx.getSource(sym.sourceFile).atSpan(span) + sym.source.atSpan(span) } } From c03e31bcbc73cf5ed9597f41784e480e59335d02 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 10 Jan 2019 08:35:40 +0100 Subject: [PATCH 65/75] Optimize PlainFile.equals --- compiler/src/dotty/tools/io/PlainFile.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/io/PlainFile.scala b/compiler/src/dotty/tools/io/PlainFile.scala index 37a3707d9a2c..7ee263729e5b 100644 --- a/compiler/src/dotty/tools/io/PlainFile.scala +++ b/compiler/src/dotty/tools/io/PlainFile.scala @@ -47,7 +47,7 @@ class PlainFile(val givenPath: Path) extends AbstractFile { override def hashCode(): Int = System.identityHashCode(absolutePath) override def equals(that: Any): Boolean = that match { - case x: PlainFile => absolutePath == x.absolutePath + case x: PlainFile => absolutePath `eq` x.absolutePath case _ => false } From 036546f6438aee304ea3dc3e8f2461dcfd16b84f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 10 Jan 2019 14:52:24 +0100 Subject: [PATCH 66/75] Implement -Ydebug-pos When set, prints full source positions, not just file + line. --- compiler/src/dotty/tools/dotc/config/ScalaSettings.scala | 1 + compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala | 1 + compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 15cd9ef325ac..2026488631ba 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -87,6 +87,7 @@ class ScalaSettings extends Settings.SettingGroup { val YdebugFlags: Setting[Boolean] = BooleanSetting("-Ydebug-flags", "Print all flags of definitions") val YdebugMissingRefs: Setting[Boolean] = BooleanSetting("-Ydebug-missing-refs", "Print a stacktrace when a required symbol is missing") val YdebugNames: Setting[Boolean] = BooleanSetting("-Ydebug-names", "Show internal representation of names") + val YdebugPos: Setting[Boolean] = BooleanSetting("-Ydebug-pos", "Show full source positions including spans") val YtermConflict: Setting[String] = ChoiceSetting("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error") val Ylog: Setting[List[String]] = PhasesSetting("-Ylog", "Log operations during") val YemitTastyInClass: Setting[Boolean] = BooleanSetting("-Yemit-tasty-in-class", "Generate tasty in the .class file and add an empty *.hasTasty file.") diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 7bf7bcd3af92..60d9d4545488 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -42,6 +42,7 @@ class PlainPrinter(_ctx: Context) extends Printer { /** If true, tweak output so it is the same before and after pickling */ protected def homogenizedView: Boolean = ctx.settings.YtestPickler.value + protected def debugPos: Boolean = ctx.settings.YdebugPos.value def homogenize(tp: Type): Type = if (homogenizedView) diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 21ddf850d6fb..5344e738e79c 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -604,7 +604,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { if (!suppressPositions) { if (printPos) { val posStr = - if (homogenizedView) + if (homogenizedView || debugPos) if (tree.isInstanceOf[MemberDef]) Str(s"${tree.source}${tree.span}") else Str(s"${tree.source}${tree.span.toSynthetic}") else From 794734996306023691a576be6c8a3de97ff66467 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 10 Jan 2019 14:55:06 +0100 Subject: [PATCH 67/75] Revise PositionPickler The decision when to pickle a position is a time sink. Try to optimize this by not going through Positioned#{initialSpan,elemSource} functionality. --- .../src/dotty/tools/dotc/ast/Positioned.scala | 8 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 2 +- .../dotc/core/tasty/PositionPickler.scala | 116 ++++++++++++++---- 3 files changed, 103 insertions(+), 23 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index fd467fe370b8..ceeff662282b 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -139,7 +139,8 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod } else outstanding = p :: outstanding case m: untpd.Modifiers => - elems = elems ::: m.mods.reverse ::: m.annotations.reverse + if (m.mods.nonEmpty || m.annotations.nonEmpty) + elems = elems ::: m.mods.reverse ::: m.annotations.reverse case xs: List[_] => elems = elems ::: xs.reverse case _ => @@ -217,6 +218,11 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod span.toSynthetic } + /** How many elements to consider when computing the span. + * Normally: all, overridden in Inlined. + */ + def relevantElemCount = productArity + private def sameSource(that: Positioned) = source `eq` that.source def contains(that: Positioned): Boolean = { diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index b5d49ae6517e..675f0d276780 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -602,7 +602,7 @@ object Trees { case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T])(implicit @transientParam src: SourceInfo) extends Tree[T] { type ThisTree[-T >: Untyped] = Inlined[T] - override def initialSpan(ignoreTypeTrees: Boolean): Span = call.span + override def relevantElemCount = 1 // only consider call when computing span } /** A type tree that represents an existing or inferred type */ diff --git a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala index 6a9cb2e90375..981aa5c3202a 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala @@ -26,6 +26,19 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad (addrDelta << 3) | (toInt(hasStartDelta) << 2) | (toInt(hasEndDelta) << 1) | toInt(hasPoint) } + /** The result type of `matchDegree`, which encodes the kind of match between + * the position of a Positioned item and the inferred position computed by Positioned#setInitialPos. + */ + private type MatchDegree = Int + private final val Unknown = 0 // Nothing known yet + private final val StartMatch = 1 // We know that at least one element matches `start` + private final val EndMatch = 2 // We know that at least one element matches `end` + private final val SourceMatch = 4 // We know that the first element matches `source` + private final val SpanMismatch = 8 // We know that the span is different from initialSpan + private final val SourceMismatch = 16 // We know the source is different from the first element + private final val SpanMatch = StartMatch | EndMatch + private final val AllMatch = SpanMatch | SourceMatch + def picklePositions(roots: List[Tree])(implicit ctx: Context): Unit = { var lastIndex = 0 var lastSpan = Span(0, 0) @@ -66,30 +79,91 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Ad case _ => false } + //val msgs = new mutable.ListBuffer[String] + + /** The degree to which the source position of `x` matches the initial position computed + * from its elements. + * @pre The span of `x` exists + */ + def matchDegree(x: Positioned): MatchDegree = { + val src = x.source + val start = x.span.start + val end = x.span.end + + def checkElem(acc: MatchDegree, elem: Any): MatchDegree = elem match { + case _: Trees.TypeTree[_] => + // TypeTrees contribute nothing since they are pickled as types + acc + case elem: Positioned => + val espan = elem.span + if (!espan.exists) acc // elements without position don't contribute + else { + val esrc = elem.source + if (!esrc.exists) acc // elements without source don't contribute + else if (esrc `ne` src) + if ((acc & SourceMatch) == 0) SourceMismatch // first element source is different -> no match + else acc // subsequent elements with different source don't contribute + else { + var matches = acc | SourceMatch + val estart = espan.start + val eend = espan.end + if (estart == start) matches |= StartMatch + if (eend == end) matches |= EndMatch + if (estart < start || eend > end) matches |= SpanMismatch + matches + } + } + case elem: List[_] => + checkElems(acc, elem) + case m: untpd.Modifiers => + checkElems(checkElems(acc, m.mods), m.annotations) + case _ => + acc + } + def checkElems(acc: MatchDegree, elems: List[Any]): MatchDegree = elems match { + case elem :: elems1 => checkElems(checkElem(acc, elem), elems1) + case nil => acc + } + + val limit = x.relevantElemCount + var n = 0 + var acc: MatchDegree = Unknown + while (n < limit) { + acc = checkElem(acc, x.productElement(n)) + n += 1 + } + acc + } + def traverse(x: Any, current: SourceFile): Unit = x match { case x: untpd.Tree => var sourceFile = current - val span = if (x.isInstanceOf[untpd.MemberDef]) x.span else x.span.toSynthetic - val sourceChange = - x.source != x.elemsSource || - !x.elemsSource.exists && x.source != current - if (span.exists && ( - span != x.initialSpan(ignoreTypeTrees = true).toSynthetic || - sourceChange || - alwaysNeedsPos(x))) { - addrOfTree(x) match { - case Some(addr) if !pickledIndices.contains(addr.index) || sourceChange => - // we currently do not share trees when unpickling, so if one path to a tree contains - // a source change while another does not, we have to record the position of the tree twice - // in order not to miss the source change. Test case is t3232a.scala. - //println(i"pickling $x with $span at $addr") - pickleDeltas(addr.index, span) - if (x.source != current) { - pickleSource(x.source) - sourceFile = x.source - } - case _ => - //println(i"no address for $x") + if (x.span.exists) { + val mdegree = matchDegree(x) + val sourceChange = + mdegree == SourceMismatch || // source different from initial source, or + (mdegree & SourceMatch) == 0 && // initial source unknown, and + (x.source `ne` current) // source different from context + val needPos = + (mdegree & SpanMismatch) != 0 || // initial span exceeds current in some direction, or + (mdegree & SpanMatch) != SpanMatch || // initial span smaller than current, or + sourceChange || // source needs to be specified, or + alwaysNeedsPos(x) // always needs position anyway + if (needPos) { + addrOfTree(x) match { + case Some(addr) if !pickledIndices.contains(addr.index) || sourceChange => + // we currently do not share trees when unpickling, so if one path to a tree contains + // a source change while another does not, we have to record the position of the tree twice + // in order not to miss the source change. Test case is t3232a.scala. + //println(i"pickling $x with $span at $addr") + pickleDeltas(addr.index, x.span) + if (x.source != current) { + pickleSource(x.source) + sourceFile = x.source + } + case _ => + //println(i"no address for $x") + } } } //else if (x.span.exists) println(i"skipping $x") From 29c8f45ad15c76e5e5d9000c4ac6c0c5f7c70a7e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 10 Jan 2019 18:22:06 +0100 Subject: [PATCH 68/75] Fix rebase breakage --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index d0f72c345dab..79bc2c8ad87b 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -663,8 +663,8 @@ object Parsers { migrationWarningOrError(em"""symbol literal '${in.name} is no longer supported, |use a string literal "${in.name}" or an application Symbol("${in.name}") instead.""") if (in.isScala2Mode) { - patch(source, Position(in.offset, in.offset + 1), "Symbol(\"") - patch(source, Position(in.charOffset - 1), "\")") + patch(source, Span(in.offset, in.offset + 1), "Symbol(\"") + patch(source, Span(in.charOffset - 1), "\")") } atPos(in.skipToken()) { SymbolLit(in.strVal) } } From a7a8203649f6f525d4126b5562dcc46d438ad711 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 10 Jan 2019 21:18:57 +0100 Subject: [PATCH 69/75] Optimize initialPos in Positioned Single traversal to set id and span. --- .../src/dotty/tools/dotc/ast/Positioned.scala | 83 +++++++------------ 1 file changed, 32 insertions(+), 51 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index ceeff662282b..84a336ce52dd 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -18,8 +18,8 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod /** A unique identifier. Among other things, used for determining the source file * component of the position. */ - private var myUniqueId: Int = _ - private[this] var mySpan: Span = _ + private var myUniqueId: Int = -1 + private[this] var mySpan: Span = NoSpan /** The span part of the item's position */ def span: Span = mySpan @@ -30,8 +30,8 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod def source: SourceFile = SourceFile.fromId(uniqueId) def sourcePos(implicit ctx: Context): SourcePosition = source.atSpan(span) - setId(initialSource(src).nextId) - setPos(initialSpan(), source) + //setId(initialSource(src).nextId) + setPos(initialSpan(src), source) protected def setId(id: Int): Unit = { myUniqueId = id @@ -155,66 +155,49 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod newpd } - /** The source of the first element of this node that has a position */ - def elemsSource: SourceFile = { - def firstSource(x: Any): SourceFile = x match { - case x: Positioned if x.span.exists => - x.source - case x1 :: xs1 => - val f = firstSource(x1) - if (f.exists) f else firstSource(xs1) - case _ => - NoSource - } - def firstElemSource(n: Int): SourceFile = - if (n == productArity) NoSource - else { - val f = firstSource(productElement(n)) - if (f.exists) f else firstElemSource(n + 1) - } - firstElemSource(0) - } - - /** The source file to use for the `id` of this node. This is - * `elemsSource` if it exists, or the source file indicated by - * `src` otherwise - */ - private def initialSource(src: SourceInfo): SourceFile = { - val f = elemsSource - if (f.exists) f else src.source - } - /** The initial, synthetic span. This is usually the union of all positioned children's spans. - * @param ignoreTypeTrees If true, TypeTree children are not counted for the span. - * This is important for predicting whether a position entry is - * needed for pickling, since TypeTrees are pickled as types, so - * their position is lost. */ - def initialSpan(ignoreTypeTrees: Boolean = false): Span = { + def initialSpan(si: SourceInfo): Span = { - def include(p1: Span, p2: Positioned) = p2 match { - case _: Trees.TypeTree[_] if ignoreTypeTrees => p1 - case _ => p1.union(p2.span) + def include(span1: Span, p2: Positioned): Span = { + val span2 = p2.span + if (span2.exists) { + var src = if (uniqueId == -1) NoSource else source + val src2 = p2.source + if (src `eq` src2) span1.union(span2) + else if (!src.exists) { + setId(src2.nextId) + if (span1.exists) initialSpan(si) // we might have some mis-classified children; re-run everything + else span2 + } + else span1 // sources differ: ignore child span + } + else span1 } def includeAll(span: Span, xs: List[_]): Span = xs match { - case (p: Positioned) :: xs1 if sameSource(p) => includeAll(include(span, p), xs1) + case Nil => span + case (p: Positioned) :: xs1 => includeAll(include(span, p), xs1) case (xs0: List[_]) :: xs1 => includeAll(includeAll(span, xs0), xs1) case _ :: xs1 => includeAll(span, xs1) - case _ => span } - var n = productArity + val limit = relevantElemCount + var n = 0 var span = NoSpan - while (n > 0) { - n -= 1 + while (n < limit) { productElement(n) match { - case p: Positioned if sameSource(p) => span = include(span, p) - case m: untpd.Modifiers => span = includeAll(includeAll(span, m.mods), m.annotations) - case xs: List[_] => span = includeAll(span, xs) + case p: Positioned => + span = include(span, p) + case m: untpd.Modifiers => + span = includeAll(includeAll(span, m.mods), m.annotations) + case xs: ::[_] => + span = includeAll(span, xs) case _ => } + n += 1 } + if (uniqueId == -1) setId(si.source.nextId) span.toSynthetic } @@ -223,8 +206,6 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod */ def relevantElemCount = productArity - private def sameSource(that: Positioned) = source `eq` that.source - def contains(that: Positioned): Boolean = { def isParent(x: Any): Boolean = x match { case x: Positioned => From a3ee7c017196c697b608bc39d57af7606d8488b1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 11 Jan 2019 11:16:22 +0100 Subject: [PATCH 70/75] Optimize SourceFile.fromId --- .../dotty/tools/dotc/util/SourceFile.scala | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index 223c59d9c0e0..590e9518f72c 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -173,8 +173,14 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends } private def newChunk: Int = sourceOfChunk.synchronized { - val id = sourceOfChunk.length * ChunkSize - sourceOfChunk += this + val id = chunks << ChunkSizeLog + if (chunks == sourceOfChunk.length) { + val a = new Array[SourceFile](chunks * 2) + Array.copy(sourceOfChunk, 0, a, 0, chunks) + sourceOfChunk = a + } + sourceOfChunk(chunks) = this + chunks += 1 ctr.set(id + 1) id } @@ -184,11 +190,12 @@ object SourceFile { type PathName = TermName - def fromId(id: Int): SourceFile = - sourceOfChunk(id / ChunkSize) + def fromId(id: Int): SourceFile = sourceOfChunk(id >> ChunkSizeLog) - private val ChunkSize = 1024 - @sharable private val sourceOfChunk = mutable.ArrayBuffer[SourceFile]() + private final val ChunkSizeLog = 10 + private final val ChunkSize = 1 << ChunkSizeLog + @sharable private var chunks: Int = 0 + @sharable private var sourceOfChunk: Array[SourceFile] = new Array[SourceFile](2000) } @sharable object NoSource extends SourceFile(NoAbstractFile, Array[Char]()) { From 66ebabd592790b48478ebb2ad72c47a1b753a9ae Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 11 Jan 2019 13:29:25 +0100 Subject: [PATCH 71/75] Optimize Symbol#source It's called more often now that we generation source positions. Time for some caching. --- .../src/dotty/tools/dotc/core/Symbols.scala | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index fe31e8e7b539..ab569aba3996 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -623,24 +623,16 @@ object Symbols { final def symbol(implicit ev: DontUseSymbolOnSymbol): Nothing = unsupported("symbol") type DontUseSymbolOnSymbol - def source(implicit ctx: Context): SourceFile = + final def source(implicit ctx: Context): SourceFile = if (!defTree.isEmpty) defTree.source - else { - val file = associatedFile - if (file != null && file.extension != "class") ctx.getSource(file) - else { - val topLevelCls = denot.topLevelClass(ctx.withPhaseNoLater(ctx.flattenPhase)) - topLevelCls.unforcedAnnotation(defn.SourceFileAnnot) match { - case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match { - case Some(Constant(path: String)) => ctx.getSource(path) - case none => NoSource - } - case none => NoSource - } - } + else this match { + case cls: ClassSymbol => cls.sourceOfClass + case _ => + if (denot.is(Module)) denot.moduleClass.source + else if (denot.exists) denot.owner.source + else NoSource } - /** A symbol related to `sym` that is defined in source code. * * @see enclosingSourceSymbols @@ -771,6 +763,30 @@ object Symbols { if (assocFile != null || (this.owner is PackageClass) || this.isEffectiveRoot) assocFile else super.associatedFile + private[this] var mySource: SourceFile = NoSource + + final def sourceOfClass(implicit ctx: Context): SourceFile = { + if (!mySource.exists && !denot.is(Package)) + // this allows sources to be added in annotations after `sourceOfClass` is first called + mySource = { + val file = associatedFile + if (file != null && file.extension != "class") ctx.getSource(file) + else { + def sourceFromTopLevel(implicit ctx: Context) = + denot.topLevelClass.unforcedAnnotation(defn.SourceFileAnnot) match { + case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match { + case Some(Constant(path: String)) => + ctx.getSource(path) + case none => NoSource + } + case none => NoSource + } + sourceFromTopLevel(ctx.withPhaseNoLater(ctx.flattenPhase)) + } + }//.reporting(res => i"source of $this # $id in ${denot.owner} = $res") + mySource + } + final def classDenot(implicit ctx: Context): ClassDenotation = denot.asInstanceOf[ClassDenotation] From 8ed8723fc24c3d3e4446c9aeb15b1d0bfe82f4b1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 11 Jan 2019 16:33:48 +0100 Subject: [PATCH 72/75] Use SourceFile implicits instead of SourceInfo No need to do the wrapping --- .../src/dotty/tools/dotc/ast/Desugar.scala | 14 +- .../dotty/tools/dotc/ast/DesugarEnums.scala | 4 +- .../src/dotty/tools/dotc/ast/Positioned.scala | 10 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 228 ++++++++--------- compiler/src/dotty/tools/dotc/ast/untpd.scala | 242 +++++++++--------- .../src/dotty/tools/dotc/core/Contexts.scala | 10 - .../tools/dotc/core/tasty/TreePickler.scala | 5 +- .../dotc/parsing/xml/MarkupParsers.scala | 4 +- .../tools/dotc/tastyreflect/package.scala | 5 +- .../dotty/tools/dotc/typer/Applications.scala | 4 +- .../dotty/tools/dotc/typer/Implicits.scala | 6 +- .../dotty/tools/dotc/typer/ProtoTypes.scala | 5 +- .../dotty/tools/dotc/util/SourceFile.scala | 3 + .../src/dotty/tools/repl/ParseResult.scala | 3 +- 14 files changed, 268 insertions(+), 275 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 7abec3b13e9c..953f4846126b 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -8,7 +8,7 @@ import Symbols._, StdNames._, Trees._ import Decorators._, transform.SymUtils._ import NameKinds.{UniqueName, EvidenceParamName, DefaultGetterName} import typer.FrontEnd -import util.Property +import util.{Property, SourceFile} import collection.mutable.ListBuffer import reporting.diagnostic.messages._ import reporting.trace @@ -43,15 +43,15 @@ object desugar { // ----- DerivedTypeTrees ----------------------------------- - class SetterParamTree(implicit @transientParam src: SourceInfo) extends DerivedTypeTree { + class SetterParamTree(implicit @transientParam src: SourceFile) extends DerivedTypeTree { def derivedTree(sym: Symbol)(implicit ctx: Context): tpd.TypeTree = tpd.TypeTree(sym.info.resultType) } - class TypeRefTree(implicit @transientParam src: SourceInfo) extends DerivedTypeTree { + class TypeRefTree(implicit @transientParam src: SourceFile) extends DerivedTypeTree { def derivedTree(sym: Symbol)(implicit ctx: Context): tpd.TypeTree = tpd.TypeTree(sym.typeRef) } - class TermRefTree(implicit @transientParam src: SourceInfo) extends DerivedTypeTree { + class TermRefTree(implicit @transientParam src: SourceFile) extends DerivedTypeTree { def derivedTree(sym: Symbol)(implicit ctx: Context): tpd.Tree = tpd.ref(sym) } @@ -59,7 +59,7 @@ object desugar { * @param suffix String difference between existing parameter (call it `P`) and parameter owning the * DerivedTypeTree (call it `O`). We have: `O.name == P.name + suffix`. */ - class DerivedFromParamTree(suffix: String)(implicit @transientParam src: SourceInfo) extends DerivedTypeTree { + class DerivedFromParamTree(suffix: String)(implicit @transientParam src: SourceFile) extends DerivedTypeTree { /** Make sure that for all enclosing module classes their companion classes * are completed. Reason: We need the constructor of such companion classes to @@ -1029,7 +1029,7 @@ object desugar { mayNeedSetter } - private def derivedDefDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit src: SourceInfo) = + private def derivedDefDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit src: SourceFile) = DefDef(named.name.asTermName, Nil, Nil, tpt, rhs) .withMods(mods) .withSpan(original.span.withPoint(named.span.start)) @@ -1393,6 +1393,6 @@ object desugar { buf.toList } - private class IrrefutableGenFrom(pat: Tree, expr: Tree)(implicit @transientParam src: SourceInfo) + private class IrrefutableGenFrom(pat: Tree, expr: Tree)(implicit @transientParam src: SourceFile) extends GenFrom(pat, expr) } diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index fbde1ecf6f83..6e280e892671 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -6,7 +6,7 @@ import core._ import util.Spans._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._ import Symbols._, StdNames._, Trees._ import Decorators._ -import util.Property +import util.{Property, SourceFile} import typer.ErrorReporting._ import scala.annotation.internal.sharable @@ -73,7 +73,7 @@ object DesugarEnums { else if (isEnumCase(cdef)) cdef.withMods(cdef.mods.withFlags(cdef.mods.flags | Final)) else cdef - private def valuesDot(name: String)(implicit src: SourceInfo) = + private def valuesDot(name: String)(implicit src: SourceFile) = Select(Ident(nme.DOLLAR_VALUES), name.toTermName) private def registerCall(implicit ctx: Context): List[Tree] = if (enumClass.typeParams.nonEmpty) Nil diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala index 84a336ce52dd..c68c5d8b80f1 100644 --- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala +++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala @@ -4,7 +4,7 @@ package ast import util.Spans._ import util.{SourceFile, NoSource, SourcePosition} -import core.Contexts.{Context, SourceInfo} +import core.Contexts.Context import core.Decorators._ import core.Flags.{JavaDefined, Extension} import core.StdNames.nme @@ -13,7 +13,7 @@ import annotation.internal.sharable /** A base class for things that have positions (currently: modifiers and trees) */ -abstract class Positioned(implicit @transientParam src: SourceInfo) extends Product with Cloneable { +abstract class Positioned(implicit @transientParam src: SourceFile) extends Product with Cloneable { /** A unique identifier. Among other things, used for determining the source file * component of the position. @@ -157,7 +157,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod /** The initial, synthetic span. This is usually the union of all positioned children's spans. */ - def initialSpan(si: SourceInfo): Span = { + def initialSpan(givenSource: SourceFile): Span = { def include(span1: Span, p2: Positioned): Span = { val span2 = p2.span @@ -167,7 +167,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod if (src `eq` src2) span1.union(span2) else if (!src.exists) { setId(src2.nextId) - if (span1.exists) initialSpan(si) // we might have some mis-classified children; re-run everything + if (span1.exists) initialSpan(givenSource) // we might have some mis-classified children; re-run everything else span2 } else span1 // sources differ: ignore child span @@ -197,7 +197,7 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod } n += 1 } - if (uniqueId == -1) setId(si.source.nextId) + if (uniqueId == -1) setId(givenSource.nextId) span.toSynthetic } diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 675f0d276780..451f1ebb6054 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -9,7 +9,7 @@ import language.higherKinds import collection.mutable.ListBuffer import printing.Printer import printing.Texts.Text -import util.{Stats, Attachment, Property, SourceFile, SourcePosition} +import util.{Stats, Attachment, Property, SourceFile, NoSource, SourcePosition} import config.Config import annotation.internal.sharable import annotation.unchecked.uncheckedVariance @@ -51,7 +51,7 @@ object Trees { * - Type checking an untyped tree should remove all embedded `TypedSplice` * nodes. */ - abstract class Tree[-T >: Untyped](implicit @transientParam src: SourceInfo) + abstract class Tree[-T >: Untyped](implicit @transientParam src: SourceFile) extends Positioned with Product with Attachment.Container @@ -262,7 +262,7 @@ object Trees { } /** Tree's denotation can be derived from its type */ - abstract class DenotingTree[-T >: Untyped](implicit @transientParam src: SourceInfo) extends Tree[T] { + abstract class DenotingTree[-T >: Untyped](implicit @transientParam src: SourceFile) extends Tree[T] { type ThisTree[-T >: Untyped] <: DenotingTree[T] override def denot(implicit ctx: Context): Denotation = typeOpt match { case tpe: NamedType => tpe.denot @@ -279,7 +279,7 @@ object Trees { /** Tree's denot/isType/isTerm properties come from a subtree * identified by `forwardTo`. */ - abstract class ProxyTree[-T >: Untyped](implicit @transientParam src: SourceInfo) extends Tree[T] { + abstract class ProxyTree[-T >: Untyped](implicit @transientParam src: SourceFile) extends Tree[T] { type ThisTree[-T >: Untyped] <: ProxyTree[T] def forwardTo: Tree[T] override def denot(implicit ctx: Context): Denotation = forwardTo.denot @@ -288,13 +288,13 @@ object Trees { } /** Tree has a name */ - abstract class NameTree[-T >: Untyped](implicit @transientParam src: SourceInfo) extends DenotingTree[T] { + abstract class NameTree[-T >: Untyped](implicit @transientParam src: SourceFile) extends DenotingTree[T] { type ThisTree[-T >: Untyped] <: NameTree[T] def name: Name } /** Tree refers by name to a denotation */ - abstract class RefTree[-T >: Untyped](implicit @transientParam src: SourceInfo) extends NameTree[T] { + abstract class RefTree[-T >: Untyped](implicit @transientParam src: SourceFile) extends NameTree[T] { type ThisTree[-T >: Untyped] <: RefTree[T] def qualifier: Tree[T] override def isType: Boolean = name.isTypeName @@ -313,7 +313,7 @@ object Trees { * The envelope of a MemberDef contains the whole definition and has its point * on the opening keyword (or the next token after that if keyword is missing). */ - abstract class MemberDef[-T >: Untyped](implicit @transientParam src: SourceInfo) extends NameTree[T] with DefTree[T] { + abstract class MemberDef[-T >: Untyped](implicit @transientParam src: SourceFile) extends NameTree[T] with DefTree[T] { type ThisTree[-T >: Untyped] <: MemberDef[T] private[this] var myMods: untpd.Modifiers = null @@ -355,7 +355,7 @@ object Trees { } /** A ValDef or DefDef tree */ - abstract class ValOrDefDef[-T >: Untyped](implicit @transientParam src: SourceInfo) extends MemberDef[T] with WithLazyField[Tree[T]] { + abstract class ValOrDefDef[-T >: Untyped](implicit @transientParam src: SourceFile) extends MemberDef[T] with WithLazyField[Tree[T]] { def name: TermName def tpt: Tree[T] def unforcedRhs: LazyTree = unforced @@ -365,7 +365,7 @@ object Trees { // ----------- Tree case classes ------------------------------------ /** name */ - case class Ident[-T >: Untyped] private[ast] (name: Name)(implicit @transientParam src: SourceInfo) + case class Ident[-T >: Untyped] private[ast] (name: Name)(implicit @transientParam src: SourceFile) extends RefTree[T] { type ThisTree[-T >: Untyped] = Ident[T] def qualifier: Tree[T] = genericEmptyTree @@ -374,31 +374,31 @@ object Trees { def isBackquoted: Boolean = false } - class BackquotedIdent[-T >: Untyped]private[ast] (name: Name)(implicit @transientParam src: SourceInfo) + class BackquotedIdent[-T >: Untyped]private[ast] (name: Name)(implicit @transientParam src: SourceFile) extends Ident[T](name) { override def isBackquoted: Boolean = true override def toString: String = s"BackquotedIdent($name)" } - class SearchFailureIdent[-T >: Untyped] private[ast] (name: Name)(implicit @transientParam src: SourceInfo) + class SearchFailureIdent[-T >: Untyped] private[ast] (name: Name)(implicit @transientParam src: SourceFile) extends Ident[T](name) { override def toString: String = s"SearchFailureIdent($name)" } /** qualifier.name, or qualifier#name, if qualifier is a type */ - case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name)(implicit @transientParam src: SourceInfo) + case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name)(implicit @transientParam src: SourceFile) extends RefTree[T] { type ThisTree[-T >: Untyped] = Select[T] } - class SelectWithSig[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name, val sig: Signature)(implicit @transientParam src: SourceInfo) + class SelectWithSig[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name, val sig: Signature)(implicit @transientParam src: SourceFile) extends Select[T](qualifier, name) { override def toString: String = s"SelectWithSig($qualifier, $name, $sig)" } /** qual.this */ - case class This[-T >: Untyped] private[ast] (qual: untpd.Ident)(implicit @transientParam src: SourceInfo) + case class This[-T >: Untyped] private[ast] (qual: untpd.Ident)(implicit @transientParam src: SourceFile) extends DenotingTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = This[T] // Denotation of a This tree is always the underlying class; needs correction for modules. @@ -413,13 +413,13 @@ object Trees { } /** C.super[mix], where qual = C.this */ - case class Super[-T >: Untyped] private[ast] (qual: Tree[T], mix: untpd.Ident)(implicit @transientParam src: SourceInfo) + case class Super[-T >: Untyped] private[ast] (qual: Tree[T], mix: untpd.Ident)(implicit @transientParam src: SourceFile) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Super[T] def forwardTo: Tree[T] = qual } - abstract class GenericApply[-T >: Untyped](implicit @transientParam src: SourceInfo) extends ProxyTree[T] with TermTree[T] { + abstract class GenericApply[-T >: Untyped](implicit @transientParam src: SourceFile) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] <: GenericApply[T] val fun: Tree[T] val args: List[Tree[T]] @@ -427,50 +427,50 @@ object Trees { } /** fun(args) */ - case class Apply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit @transientParam src: SourceInfo) + case class Apply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit @transientParam src: SourceFile) extends GenericApply[T] { type ThisTree[-T >: Untyped] = Apply[T] } /** fun[args] */ - case class TypeApply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit @transientParam src: SourceInfo) + case class TypeApply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])(implicit @transientParam src: SourceFile) extends GenericApply[T] { type ThisTree[-T >: Untyped] = TypeApply[T] } /** const */ - case class Literal[-T >: Untyped] private[ast] (const: Constant)(implicit @transientParam src: SourceInfo) + case class Literal[-T >: Untyped] private[ast] (const: Constant)(implicit @transientParam src: SourceFile) extends Tree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Literal[T] } /** new tpt, but no constructor call */ - case class New[-T >: Untyped] private[ast] (tpt: Tree[T])(implicit @transientParam src: SourceInfo) + case class New[-T >: Untyped] private[ast] (tpt: Tree[T])(implicit @transientParam src: SourceFile) extends Tree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = New[T] } /** expr : tpt */ - case class Typed[-T >: Untyped] private[ast] (expr: Tree[T], tpt: Tree[T])(implicit @transientParam src: SourceInfo) + case class Typed[-T >: Untyped] private[ast] (expr: Tree[T], tpt: Tree[T])(implicit @transientParam src: SourceFile) extends ProxyTree[T] with TermTree[T] { type ThisTree[-T >: Untyped] = Typed[T] def forwardTo: Tree[T] = expr } /** name = arg, in a parameter list */ - case class NamedArg[-T >: Untyped] private[ast] (name: Name, arg: Tree[T])(implicit @transientParam src: SourceInfo) + case class NamedArg[-T >: Untyped] private[ast] (name: Name, arg: Tree[T])(implicit @transientParam src: SourceFile) extends Tree[T] { type ThisTree[-T >: Untyped] = NamedArg[T] } /** name = arg, outside a parameter list */ - case class Assign[-T >: Untyped] private[ast] (lhs: Tree[T], rhs: Tree[T])(implicit @transientParam src: SourceInfo) + case class Assign[-T >: Untyped] private[ast] (lhs: Tree[T], rhs: Tree[T])(implicit @transientParam src: SourceFile) extends TermTree[T] { type ThisTree[-T >: Untyped] = Assign[T] } /** { stats; expr } */ - case class Block[-T >: Untyped] private[ast] (stats: List[Tree[T]], expr: Tree[T])(implicit @transientParam src: SourceInfo) + case class Block[-T >: Untyped] private[ast] (stats: List[Tree[T]], expr: Tree[T])(implicit @transientParam src: SourceFile) extends Tree[T] { type ThisTree[-T >: Untyped] = Block[T] override def isType: Boolean = expr.isType @@ -478,12 +478,12 @@ object Trees { } /** if cond then thenp else elsep */ - case class If[-T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit @transientParam src: SourceInfo) + case class If[-T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit @transientParam src: SourceFile) extends TermTree[T] { type ThisTree[-T >: Untyped] = If[T] def isInline = false } - class InlineIf[T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit @transientParam src: SourceInfo) + class InlineIf[T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit @transientParam src: SourceFile) extends If(cond, thenp, elsep) { override def isInline = true override def toString = s"InlineIf($cond, $thenp, $elsep)" @@ -498,32 +498,32 @@ object Trees { * of the closure is a function type, otherwise it is the type * given in `tpt`, which must be a SAM type. */ - case class Closure[-T >: Untyped] private[ast] (env: List[Tree[T]], meth: Tree[T], tpt: Tree[T])(implicit @transientParam src: SourceInfo) + case class Closure[-T >: Untyped] private[ast] (env: List[Tree[T]], meth: Tree[T], tpt: Tree[T])(implicit @transientParam src: SourceFile) extends TermTree[T] { type ThisTree[-T >: Untyped] = Closure[T] } /** selector match { cases } */ - case class Match[-T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam src: SourceInfo) + case class Match[-T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam src: SourceFile) extends TermTree[T] { assert(cases.nonEmpty) type ThisTree[-T >: Untyped] = Match[T] def isInline = false } - class InlineMatch[T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam src: SourceInfo) + class InlineMatch[T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam src: SourceFile) extends Match(selector, cases) { override def isInline = true override def toString = s"InlineMatch($selector, $cases)" } /** case pat if guard => body; only appears as child of a Match */ - case class CaseDef[-T >: Untyped] private[ast] (pat: Tree[T], guard: Tree[T], body: Tree[T])(implicit @transientParam src: SourceInfo) + case class CaseDef[-T >: Untyped] private[ast] (pat: Tree[T], guard: Tree[T], body: Tree[T])(implicit @transientParam src: SourceFile) extends Tree[T] { type ThisTree[-T >: Untyped] = CaseDef[T] } /** label[tpt]: { expr } */ - case class Labeled[-T >: Untyped] private[ast] (bind: Bind[T], expr: Tree[T])(implicit @transientParam src: SourceInfo) + case class Labeled[-T >: Untyped] private[ast] (bind: Bind[T], expr: Tree[T])(implicit @transientParam src: SourceFile) extends NameTree[T] { type ThisTree[-T >: Untyped] = Labeled[T] def name: Name = bind.name @@ -534,13 +534,13 @@ object Trees { * After program transformations this is not necessarily the enclosing method, because * closures can intervene. */ - case class Return[-T >: Untyped] private[ast] (expr: Tree[T], from: Tree[T] = genericEmptyTree)(implicit @transientParam src: SourceInfo) + case class Return[-T >: Untyped] private[ast] (expr: Tree[T], from: Tree[T] = genericEmptyTree)(implicit @transientParam src: SourceFile) extends TermTree[T] { type ThisTree[-T >: Untyped] = Return[T] } /** while (cond) { body } */ - case class WhileDo[-T >: Untyped] private[ast] (cond: Tree[T], body: Tree[T])(implicit @transientParam src: SourceInfo) + case class WhileDo[-T >: Untyped] private[ast] (cond: Tree[T], body: Tree[T])(implicit @transientParam src: SourceFile) extends TermTree[T] { type ThisTree[-T >: Untyped] = WhileDo[T] } @@ -564,7 +564,7 @@ object Trees { * * Match(EmptyTree, $anonfun(x)>) */ - case class Try[-T >: Untyped] private[ast] (expr: Tree[T], cases: List[CaseDef[T]], finalizer: Tree[T])(implicit @transientParam src: SourceInfo) + case class Try[-T >: Untyped] private[ast] (expr: Tree[T], cases: List[CaseDef[T]], finalizer: Tree[T])(implicit @transientParam src: SourceFile) extends TermTree[T] { type ThisTree[-T >: Untyped] = Try[T] } @@ -572,13 +572,13 @@ object Trees { /** Seq(elems) * @param tpt The element type of the sequence. */ - case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit @transientParam src: SourceInfo) + case class SeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit @transientParam src: SourceFile) extends Tree[T] { type ThisTree[-T >: Untyped] = SeqLiteral[T] } /** Array(elems) */ - class JavaSeqLiteral[T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit @transientParam src: SourceInfo) + class JavaSeqLiteral[T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit @transientParam src: SourceFile) extends SeqLiteral(elems, elemtpt) { override def toString: String = s"JavaSeqLiteral($elems, $elemtpt)" } @@ -599,14 +599,14 @@ object Trees { * different context: `bindings` represent the arguments to the inlined * call, whereas `expansion` represents the body of the inlined function. */ - case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T])(implicit @transientParam src: SourceInfo) + case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T])(implicit @transientParam src: SourceFile) extends Tree[T] { type ThisTree[-T >: Untyped] = Inlined[T] override def relevantElemCount = 1 // only consider call when computing span } /** A type tree that represents an existing or inferred type */ - case class TypeTree[-T >: Untyped]()(implicit @transientParam src: SourceInfo) + case class TypeTree[-T >: Untyped]()(implicit @transientParam src: SourceFile) extends DenotingTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = TypeTree[T] override def isEmpty: Boolean = !hasType @@ -617,66 +617,66 @@ object Trees { /** A type tree that defines a new type variable. Its type is always a TypeVar. * Every TypeVar is created as the type of one TypeVarBinder. */ - class TypeVarBinder[-T >: Untyped](implicit @transientParam src: SourceInfo) extends TypeTree[T] + class TypeVarBinder[-T >: Untyped](implicit @transientParam src: SourceFile) extends TypeTree[T] /** ref.type */ - case class SingletonTypeTree[-T >: Untyped] private[ast] (ref: Tree[T])(implicit @transientParam src: SourceInfo) + case class SingletonTypeTree[-T >: Untyped] private[ast] (ref: Tree[T])(implicit @transientParam src: SourceFile) extends DenotingTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = SingletonTypeTree[T] } /** left & right */ - case class AndTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])(implicit @transientParam src: SourceInfo) + case class AndTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])(implicit @transientParam src: SourceFile) extends TypTree[T] { type ThisTree[-T >: Untyped] = AndTypeTree[T] } /** left | right */ - case class OrTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])(implicit @transientParam src: SourceInfo) + case class OrTypeTree[-T >: Untyped] private[ast] (left: Tree[T], right: Tree[T])(implicit @transientParam src: SourceFile) extends TypTree[T] { type ThisTree[-T >: Untyped] = OrTypeTree[T] } /** tpt { refinements } */ - case class RefinedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], refinements: List[Tree[T]])(implicit @transientParam src: SourceInfo) + case class RefinedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], refinements: List[Tree[T]])(implicit @transientParam src: SourceFile) extends ProxyTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = RefinedTypeTree[T] def forwardTo: Tree[T] = tpt } /** tpt[args] */ - case class AppliedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], args: List[Tree[T]])(implicit @transientParam src: SourceInfo) + case class AppliedTypeTree[-T >: Untyped] private[ast] (tpt: Tree[T], args: List[Tree[T]])(implicit @transientParam src: SourceFile) extends ProxyTree[T] with TypTree[T] { type ThisTree[-T >: Untyped] = AppliedTypeTree[T] def forwardTo: Tree[T] = tpt } /** [typeparams] -> tpt */ - case class LambdaTypeTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T])(implicit @transientParam src: SourceInfo) + case class LambdaTypeTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T])(implicit @transientParam src: SourceFile) extends TypTree[T] { type ThisTree[-T >: Untyped] = LambdaTypeTree[T] } /** [bound] selector match { cases } */ - case class MatchTypeTree[-T >: Untyped] private[ast] (bound: Tree[T], selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam src: SourceInfo) + case class MatchTypeTree[-T >: Untyped] private[ast] (bound: Tree[T], selector: Tree[T], cases: List[CaseDef[T]])(implicit @transientParam src: SourceFile) extends TypTree[T] { type ThisTree[-T >: Untyped] = MatchTypeTree[T] } /** => T */ - case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T])(implicit @transientParam src: SourceInfo) + case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T])(implicit @transientParam src: SourceFile) extends TypTree[T] { type ThisTree[-T >: Untyped] = ByNameTypeTree[T] } /** >: lo <: hi */ - case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T])(implicit @transientParam src: SourceInfo) + case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T])(implicit @transientParam src: SourceFile) extends TypTree[T] { type ThisTree[-T >: Untyped] = TypeBoundsTree[T] } /** name @ body */ - case class Bind[-T >: Untyped] private[ast] (name: Name, body: Tree[T])(implicit @transientParam src: SourceInfo) + case class Bind[-T >: Untyped] private[ast] (name: Name, body: Tree[T])(implicit @transientParam src: SourceFile) extends NameTree[T] with DefTree[T] with PatternTree[T] { type ThisTree[-T >: Untyped] = Bind[T] override def isType: Boolean = name.isTypeName @@ -684,7 +684,7 @@ object Trees { } /** tree_1 | ... | tree_n */ - case class Alternative[-T >: Untyped] private[ast] (trees: List[Tree[T]])(implicit @transientParam src: SourceInfo) + case class Alternative[-T >: Untyped] private[ast] (trees: List[Tree[T]])(implicit @transientParam src: SourceFile) extends PatternTree[T] { type ThisTree[-T >: Untyped] = Alternative[T] } @@ -703,13 +703,13 @@ object Trees { * val result = fun(sel)(implicits) * if (result.isDefined) "match patterns against result" */ - case class UnApply[-T >: Untyped] private[ast] (fun: Tree[T], implicits: List[Tree[T]], patterns: List[Tree[T]])(implicit @transientParam src: SourceInfo) + case class UnApply[-T >: Untyped] private[ast] (fun: Tree[T], implicits: List[Tree[T]], patterns: List[Tree[T]])(implicit @transientParam src: SourceFile) extends PatternTree[T] { type ThisTree[-T >: Untyped] = UnApply[T] } /** mods val name: tpt = rhs */ - case class ValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], private var preRhs: LazyTree)(implicit @transientParam src: SourceInfo) + case class ValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], private var preRhs: LazyTree)(implicit @transientParam src: SourceFile) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = ValDef[T] assert(isEmpty || tpt != genericEmptyTree) @@ -719,7 +719,7 @@ object Trees { /** mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs */ case class DefDef[-T >: Untyped] private[ast] (name: TermName, tparams: List[TypeDef[T]], - vparamss: List[List[ValDef[T]]], tpt: Tree[T], private var preRhs: LazyTree)(implicit @transientParam src: SourceInfo) + vparamss: List[List[ValDef[T]]], tpt: Tree[T], private var preRhs: LazyTree)(implicit @transientParam src: SourceFile) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = DefDef[T] assert(tpt != genericEmptyTree) @@ -732,7 +732,7 @@ object Trees { * mods type name = rhs or * mods type name >: lo <: hi, if rhs = TypeBoundsTree(lo, hi) & (lo ne hi) */ - case class TypeDef[-T >: Untyped] private[ast] (name: TypeName, rhs: Tree[T])(implicit @transientParam src: SourceInfo) + case class TypeDef[-T >: Untyped] private[ast] (name: TypeName, rhs: Tree[T])(implicit @transientParam src: SourceFile) extends MemberDef[T] { type ThisTree[-T >: Untyped] = TypeDef[T] @@ -741,7 +741,7 @@ object Trees { } /** extends parents { self => body } */ - case class Template[-T >: Untyped] private[ast] (constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], private var preBody: LazyTreeList)(implicit @transientParam src: SourceInfo) + case class Template[-T >: Untyped] private[ast] (constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], private var preBody: LazyTreeList)(implicit @transientParam src: SourceFile) extends DefTree[T] with WithLazyField[List[Tree[T]]] { type ThisTree[-T >: Untyped] = Template[T] def unforcedBody: LazyTreeList = unforced @@ -754,20 +754,20 @@ object Trees { * where a selector is either an untyped `Ident`, `name` or * an untyped thicket consisting of `name` and `rename`. */ - case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]])(implicit @transientParam src: SourceInfo) + case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]])(implicit @transientParam src: SourceFile) extends DenotingTree[T] { type ThisTree[-T >: Untyped] = Import[T] } /** package pid { stats } */ - case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]])(implicit @transientParam src: SourceInfo) + case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]])(implicit @transientParam src: SourceFile) extends ProxyTree[T] { type ThisTree[-T >: Untyped] = PackageDef[T] def forwardTo: RefTree[T] = pid } /** arg @annot */ - case class Annotated[-T >: Untyped] private[ast] (arg: Tree[T], annot: Tree[T])(implicit @transientParam src: SourceInfo) + case class Annotated[-T >: Untyped] private[ast] (arg: Tree[T], annot: Tree[T])(implicit @transientParam src: SourceFile) extends ProxyTree[T] { type ThisTree[-T >: Untyped] = Annotated[T] def forwardTo: Tree[T] = arg @@ -784,7 +784,7 @@ object Trees { * The contained trees will be integrated when transformed with * a `transform(List[Tree])` call. */ - case class Thicket[-T >: Untyped](trees: List[Tree[T]])(implicit @transientParam src: SourceInfo) + case class Thicket[-T >: Untyped](trees: List[Tree[T]])(implicit @transientParam src: SourceFile) extends Tree[T] with WithoutTypeOrPos[T] { myTpe = NoType.asInstanceOf[T] type ThisTree[-T >: Untyped] = Thicket[T] @@ -794,7 +794,7 @@ object Trees { if (trees eq newTrees) this else - Thicket[T](newTrees)(SourceInfo(source)).asInstanceOf[this.type] + Thicket[T](newTrees)(source).asInstanceOf[this.type] } override def foreachInThicket(op: Tree[T] => Unit): Unit = @@ -813,12 +813,12 @@ object Trees { mapElems(_.withSourcePos(sourcePos)).asInstanceOf[this.type] } - class EmptyTree[T >: Untyped] extends Thicket(Nil)(NoContext) { + class EmptyTree[T >: Untyped] extends Thicket(Nil)(NoSource) { // assert(uniqueId != 1492) } class EmptyValDef[T >: Untyped] extends ValDef[T]( - nme.WILDCARD, genericEmptyTree[T], genericEmptyTree[T])(NoContext) with WithoutTypeOrPos[T] { + nme.WILDCARD, genericEmptyTree[T], genericEmptyTree[T])(NoSource) with WithoutTypeOrPos[T] { myTpe = NoType.asInstanceOf[T] override def isEmpty: Boolean = true setMods(untpd.Modifiers(PrivateLocal)) @@ -953,11 +953,11 @@ object Trees { // ----- Auxiliary creation methods ------------------ - def Thicket(trees: List[Tree])(implicit src: SourceInfo): Thicket = new Thicket(trees) + def Thicket(trees: List[Tree])(implicit src: SourceFile): Thicket = new Thicket(trees) def Thicket(): Thicket = EmptyTree - def Thicket(x1: Tree, x2: Tree)(implicit src: SourceInfo): Thicket = Thicket(x1 :: x2 :: Nil) - def Thicket(x1: Tree, x2: Tree, x3: Tree)(implicit src: SourceInfo): Thicket = Thicket(x1 :: x2 :: x3 :: Nil) - def flatTree(xs: List[Tree])(implicit src: SourceInfo): Tree = flatten(xs) match { + def Thicket(x1: Tree, x2: Tree)(implicit src: SourceFile): Thicket = Thicket(x1 :: x2 :: Nil) + def Thicket(x1: Tree, x2: Tree, x3: Tree)(implicit src: SourceFile): Thicket = Thicket(x1 :: x2 :: x3 :: Nil) + def flatTree(xs: List[Tree])(implicit src: SourceFile): Tree = flatten(xs) match { case x :: Nil => x case ys => Thicket(ys) } @@ -977,10 +977,10 @@ object Trees { protected def postProcess(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] protected def postProcess(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T] - protected def finalize(tree: Tree, copied: untpd.Tree)(implicit src: SourceInfo): copied.ThisTree[T] = + protected def finalize(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] = postProcess(tree, copied.withPosOf(tree).withAttachmentsFrom(tree)) - protected def finalize(tree: Tree, copied: untpd.MemberDef)(implicit src: SourceInfo): copied.ThisTree[T] = + protected def finalize(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T] = postProcess(tree, copied.withPosOf(tree).withAttachmentsFrom(tree)) protected def srcCtx(tree: Tree)(implicit ctx: Context) = ctx.withSource(tree.source) @@ -988,16 +988,16 @@ object Trees { def Ident(tree: Tree)(name: Name)(implicit ctx: Context): Ident = tree match { case tree: BackquotedIdent => if (name == tree.name) tree - else finalize(tree, new BackquotedIdent(name)(srcCtx(tree))) + else finalize(tree, new BackquotedIdent(name)(tree.source)) case tree: Ident if name == tree.name => tree - case _ => finalize(tree, untpd.Ident(name)(srcCtx(tree))) + case _ => finalize(tree, untpd.Ident(name)(tree.source)) } def Select(tree: Tree)(qualifier: Tree, name: Name)(implicit ctx: Context): Select = tree match { case tree: SelectWithSig => if ((qualifier eq tree.qualifier) && (name == tree.name)) tree - else finalize(tree, new SelectWithSig(qualifier, name, tree.sig)(srcCtx(tree))) + else finalize(tree, new SelectWithSig(qualifier, name, tree.sig)(tree.source)) case tree: Select if (qualifier eq tree.qualifier) && (name == tree.name) => tree - case _ => finalize(tree, untpd.Select(qualifier, name)(srcCtx(tree))) + case _ => finalize(tree, untpd.Select(qualifier, name)(tree.source)) } /** Copy Ident or Select trees */ def Ref(tree: RefTree)(name: Name)(implicit ctx: Context): RefTree = tree match { @@ -1006,169 +1006,169 @@ object Trees { } def This(tree: Tree)(qual: untpd.Ident)(implicit ctx: Context): This = tree match { case tree: This if qual eq tree.qual => tree - case _ => finalize(tree, untpd.This(qual)(srcCtx(tree))) + case _ => finalize(tree, untpd.This(qual)(tree.source)) } def Super(tree: Tree)(qual: Tree, mix: untpd.Ident)(implicit ctx: Context): Super = tree match { case tree: Super if (qual eq tree.qual) && (mix eq tree.mix) => tree - case _ => finalize(tree, untpd.Super(qual, mix)(srcCtx(tree))) + case _ => finalize(tree, untpd.Super(qual, mix)(tree.source)) } def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply = tree match { case tree: Apply if (fun eq tree.fun) && (args eq tree.args) => tree - case _ => finalize(tree, untpd.Apply(fun, args)(srcCtx(tree))) + case _ => finalize(tree, untpd.Apply(fun, args)(tree.source)) } def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = tree match { case tree: TypeApply if (fun eq tree.fun) && (args eq tree.args) => tree - case _ => finalize(tree, untpd.TypeApply(fun, args)(srcCtx(tree))) + case _ => finalize(tree, untpd.TypeApply(fun, args)(tree.source)) } def Literal(tree: Tree)(const: Constant)(implicit ctx: Context): Literal = tree match { case tree: Literal if const == tree.const => tree - case _ => finalize(tree, untpd.Literal(const)(srcCtx(tree))) + case _ => finalize(tree, untpd.Literal(const)(tree.source)) } def New(tree: Tree)(tpt: Tree)(implicit ctx: Context): New = tree match { case tree: New if tpt eq tree.tpt => tree - case _ => finalize(tree, untpd.New(tpt)(srcCtx(tree))) + case _ => finalize(tree, untpd.New(tpt)(tree.source)) } def Typed(tree: Tree)(expr: Tree, tpt: Tree)(implicit ctx: Context): Typed = tree match { case tree: Typed if (expr eq tree.expr) && (tpt eq tree.tpt) => tree - case tree => finalize(tree, untpd.Typed(expr, tpt)(srcCtx(tree))) + case tree => finalize(tree, untpd.Typed(expr, tpt)(tree.source)) //.ensuring(res => res.uniqueId != 1471, s"source = $tree, ${tree.uniqueId}") } def NamedArg(tree: Tree)(name: Name, arg: Tree)(implicit ctx: Context): NamedArg = tree match { case tree: NamedArg if (name == tree.name) && (arg eq tree.arg) => tree - case _ => finalize(tree, untpd.NamedArg(name, arg)(srcCtx(tree))) + case _ => finalize(tree, untpd.NamedArg(name, arg)(tree.source)) } def Assign(tree: Tree)(lhs: Tree, rhs: Tree)(implicit ctx: Context): Assign = tree match { case tree: Assign if (lhs eq tree.lhs) && (rhs eq tree.rhs) => tree - case _ => finalize(tree, untpd.Assign(lhs, rhs)(srcCtx(tree))) + case _ => finalize(tree, untpd.Assign(lhs, rhs)(tree.source)) } def Block(tree: Tree)(stats: List[Tree], expr: Tree)(implicit ctx: Context): Block = tree match { case tree: Block if (stats eq tree.stats) && (expr eq tree.expr) => tree - case _ => finalize(tree, untpd.Block(stats, expr)(srcCtx(tree))) + case _ => finalize(tree, untpd.Block(stats, expr)(tree.source)) } def If(tree: Tree)(cond: Tree, thenp: Tree, elsep: Tree)(implicit ctx: Context): If = tree match { case tree: If if (cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep) => tree - case tree: InlineIf => finalize(tree, untpd.InlineIf(cond, thenp, elsep)(srcCtx(tree))) - case _ => finalize(tree, untpd.If(cond, thenp, elsep)(srcCtx(tree))) + case tree: InlineIf => finalize(tree, untpd.InlineIf(cond, thenp, elsep)(tree.source)) + case _ => finalize(tree, untpd.If(cond, thenp, elsep)(tree.source)) } def Closure(tree: Tree)(env: List[Tree], meth: Tree, tpt: Tree)(implicit ctx: Context): Closure = tree match { case tree: Closure if (env eq tree.env) && (meth eq tree.meth) && (tpt eq tree.tpt) => tree - case _ => finalize(tree, untpd.Closure(env, meth, tpt)(srcCtx(tree))) + case _ => finalize(tree, untpd.Closure(env, meth, tpt)(tree.source)) } def Match(tree: Tree)(selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match = tree match { case tree: Match if (selector eq tree.selector) && (cases eq tree.cases) => tree - case tree: InlineMatch => finalize(tree, untpd.InlineMatch(selector, cases)(srcCtx(tree))) - case _ => finalize(tree, untpd.Match(selector, cases)(srcCtx(tree))) + case tree: InlineMatch => finalize(tree, untpd.InlineMatch(selector, cases)(tree.source)) + case _ => finalize(tree, untpd.Match(selector, cases)(tree.source)) } def CaseDef(tree: Tree)(pat: Tree, guard: Tree, body: Tree)(implicit ctx: Context): CaseDef = tree match { case tree: CaseDef if (pat eq tree.pat) && (guard eq tree.guard) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.CaseDef(pat, guard, body)(srcCtx(tree))) + case _ => finalize(tree, untpd.CaseDef(pat, guard, body)(tree.source)) } def Labeled(tree: Tree)(bind: Bind, expr: Tree)(implicit ctx: Context): Labeled = tree match { case tree: Labeled if (bind eq tree.bind) && (expr eq tree.expr) => tree - case _ => finalize(tree, untpd.Labeled(bind, expr)(srcCtx(tree))) + case _ => finalize(tree, untpd.Labeled(bind, expr)(tree.source)) } def Return(tree: Tree)(expr: Tree, from: Tree)(implicit ctx: Context): Return = tree match { case tree: Return if (expr eq tree.expr) && (from eq tree.from) => tree - case _ => finalize(tree, untpd.Return(expr, from)(srcCtx(tree))) + case _ => finalize(tree, untpd.Return(expr, from)(tree.source)) } def WhileDo(tree: Tree)(cond: Tree, body: Tree)(implicit ctx: Context): WhileDo = tree match { case tree: WhileDo if (cond eq tree.cond) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.WhileDo(cond, body)(srcCtx(tree))) + case _ => finalize(tree, untpd.WhileDo(cond, body)(tree.source)) } def Try(tree: Tree)(expr: Tree, cases: List[CaseDef], finalizer: Tree)(implicit ctx: Context): Try = tree match { case tree: Try if (expr eq tree.expr) && (cases eq tree.cases) && (finalizer eq tree.finalizer) => tree - case _ => finalize(tree, untpd.Try(expr, cases, finalizer)(srcCtx(tree))) + case _ => finalize(tree, untpd.Try(expr, cases, finalizer)(tree.source)) } def SeqLiteral(tree: Tree)(elems: List[Tree], elemtpt: Tree)(implicit ctx: Context): SeqLiteral = tree match { case tree: JavaSeqLiteral => if ((elems eq tree.elems) && (elemtpt eq tree.elemtpt)) tree else finalize(tree, new JavaSeqLiteral(elems, elemtpt)) case tree: SeqLiteral if (elems eq tree.elems) && (elemtpt eq tree.elemtpt) => tree - case _ => finalize(tree, untpd.SeqLiteral(elems, elemtpt)(srcCtx(tree))) + case _ => finalize(tree, untpd.SeqLiteral(elems, elemtpt)(tree.source)) } def Inlined(tree: Tree)(call: tpd.Tree, bindings: List[MemberDef], expansion: Tree)(implicit ctx: Context): Inlined = tree match { case tree: Inlined if (call eq tree.call) && (bindings eq tree.bindings) && (expansion eq tree.expansion) => tree - case _ => finalize(tree, untpd.Inlined(call, bindings, expansion)(srcCtx(tree))) + case _ => finalize(tree, untpd.Inlined(call, bindings, expansion)(tree.source)) } def SingletonTypeTree(tree: Tree)(ref: Tree)(implicit ctx: Context): SingletonTypeTree = tree match { case tree: SingletonTypeTree if ref eq tree.ref => tree - case _ => finalize(tree, untpd.SingletonTypeTree(ref)(srcCtx(tree))) + case _ => finalize(tree, untpd.SingletonTypeTree(ref)(tree.source)) } def AndTypeTree(tree: Tree)(left: Tree, right: Tree)(implicit ctx: Context): AndTypeTree = tree match { case tree: AndTypeTree if (left eq tree.left) && (right eq tree.right) => tree - case _ => finalize(tree, untpd.AndTypeTree(left, right)(srcCtx(tree))) + case _ => finalize(tree, untpd.AndTypeTree(left, right)(tree.source)) } def OrTypeTree(tree: Tree)(left: Tree, right: Tree)(implicit ctx: Context): OrTypeTree = tree match { case tree: OrTypeTree if (left eq tree.left) && (right eq tree.right) => tree - case _ => finalize(tree, untpd.OrTypeTree(left, right)(srcCtx(tree))) + case _ => finalize(tree, untpd.OrTypeTree(left, right)(tree.source)) } def RefinedTypeTree(tree: Tree)(tpt: Tree, refinements: List[Tree])(implicit ctx: Context): RefinedTypeTree = tree match { case tree: RefinedTypeTree if (tpt eq tree.tpt) && (refinements eq tree.refinements) => tree - case _ => finalize(tree, untpd.RefinedTypeTree(tpt, refinements)(srcCtx(tree))) + case _ => finalize(tree, untpd.RefinedTypeTree(tpt, refinements)(tree.source)) } def AppliedTypeTree(tree: Tree)(tpt: Tree, args: List[Tree])(implicit ctx: Context): AppliedTypeTree = tree match { case tree: AppliedTypeTree if (tpt eq tree.tpt) && (args eq tree.args) => tree - case _ => finalize(tree, untpd.AppliedTypeTree(tpt, args)(srcCtx(tree))) + case _ => finalize(tree, untpd.AppliedTypeTree(tpt, args)(tree.source)) } def LambdaTypeTree(tree: Tree)(tparams: List[TypeDef], body: Tree)(implicit ctx: Context): LambdaTypeTree = tree match { case tree: LambdaTypeTree if (tparams eq tree.tparams) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.LambdaTypeTree(tparams, body)(srcCtx(tree))) + case _ => finalize(tree, untpd.LambdaTypeTree(tparams, body)(tree.source)) } def MatchTypeTree(tree: Tree)(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit ctx: Context): MatchTypeTree = tree match { case tree: MatchTypeTree if (bound eq tree.bound) && (selector eq tree.selector) && (cases eq tree.cases) => tree - case _ => finalize(tree, untpd.MatchTypeTree(bound, selector, cases)(srcCtx(tree))) + case _ => finalize(tree, untpd.MatchTypeTree(bound, selector, cases)(tree.source)) } def ByNameTypeTree(tree: Tree)(result: Tree)(implicit ctx: Context): ByNameTypeTree = tree match { case tree: ByNameTypeTree if result eq tree.result => tree - case _ => finalize(tree, untpd.ByNameTypeTree(result)(srcCtx(tree))) + case _ => finalize(tree, untpd.ByNameTypeTree(result)(tree.source)) } def TypeBoundsTree(tree: Tree)(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree = tree match { case tree: TypeBoundsTree if (lo eq tree.lo) && (hi eq tree.hi) => tree - case _ => finalize(tree, untpd.TypeBoundsTree(lo, hi)(srcCtx(tree))) + case _ => finalize(tree, untpd.TypeBoundsTree(lo, hi)(tree.source)) } def Bind(tree: Tree)(name: Name, body: Tree)(implicit ctx: Context): Bind = tree match { case tree: Bind if (name eq tree.name) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.Bind(name, body)(srcCtx(tree))) + case _ => finalize(tree, untpd.Bind(name, body)(tree.source)) } def Alternative(tree: Tree)(trees: List[Tree])(implicit ctx: Context): Alternative = tree match { case tree: Alternative if trees eq tree.trees => tree - case _ => finalize(tree, untpd.Alternative(trees)(srcCtx(tree))) + case _ => finalize(tree, untpd.Alternative(trees)(tree.source)) } def UnApply(tree: Tree)(fun: Tree, implicits: List[Tree], patterns: List[Tree])(implicit ctx: Context): UnApply = tree match { case tree: UnApply if (fun eq tree.fun) && (implicits eq tree.implicits) && (patterns eq tree.patterns) => tree - case _ => finalize(tree, untpd.UnApply(fun, implicits, patterns)(srcCtx(tree))) + case _ => finalize(tree, untpd.UnApply(fun, implicits, patterns)(tree.source)) } def ValDef(tree: Tree)(name: TermName, tpt: Tree, rhs: LazyTree)(implicit ctx: Context): ValDef = tree match { case tree: ValDef if (name == tree.name) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) => tree - case _ => finalize(tree, untpd.ValDef(name, tpt, rhs)(srcCtx(tree))) + case _ => finalize(tree, untpd.ValDef(name, tpt, rhs)(tree.source)) } def DefDef(tree: Tree)(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree)(implicit ctx: Context): DefDef = tree match { case tree: DefDef if (name == tree.name) && (tparams eq tree.tparams) && (vparamss eq tree.vparamss) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) => tree - case _ => finalize(tree, untpd.DefDef(name, tparams, vparamss, tpt, rhs)(srcCtx(tree))) + case _ => finalize(tree, untpd.DefDef(name, tparams, vparamss, tpt, rhs)(tree.source)) } def TypeDef(tree: Tree)(name: TypeName, rhs: Tree)(implicit ctx: Context): TypeDef = tree match { case tree: TypeDef if (name == tree.name) && (rhs eq tree.rhs) => tree - case _ => finalize(tree, untpd.TypeDef(name, rhs)(srcCtx(tree))) + case _ => finalize(tree, untpd.TypeDef(name, rhs)(tree.source)) } def Template(tree: Tree)(constr: DefDef, parents: List[Tree], self: ValDef, body: LazyTreeList)(implicit ctx: Context): Template = tree match { case tree: Template if (constr eq tree.constr) && (parents eq tree.parents) && (self eq tree.self) && (body eq tree.unforcedBody) => tree - case _ => finalize(tree, untpd.Template(constr, parents, self, body)(srcCtx(tree))) + case _ => finalize(tree, untpd.Template(constr, parents, self, body)(tree.source)) } def Import(tree: Tree)(expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = tree match { case tree: Import if (expr eq tree.expr) && (selectors eq tree.selectors) => tree - case _ => finalize(tree, untpd.Import(expr, selectors)(srcCtx(tree))) + case _ => finalize(tree, untpd.Import(expr, selectors)(tree.source)) } def PackageDef(tree: Tree)(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef = tree match { case tree: PackageDef if (pid eq tree.pid) && (stats eq tree.stats) => tree - case _ => finalize(tree, untpd.PackageDef(pid, stats)(srcCtx(tree))) + case _ => finalize(tree, untpd.PackageDef(pid, stats)(tree.source)) } def Annotated(tree: Tree)(arg: Tree, annot: Tree)(implicit ctx: Context): Annotated = tree match { case tree: Annotated if (arg eq tree.arg) && (annot eq tree.annot) => tree - case _ => finalize(tree, untpd.Annotated(arg, annot)(srcCtx(tree))) + case _ => finalize(tree, untpd.Annotated(arg, annot)(tree.source)) } def Thicket(tree: Tree)(trees: List[Tree])(implicit ctx: Context): Thicket = tree match { case tree: Thicket if trees eq tree.trees => tree - case _ => finalize(tree, untpd.Thicket(trees)(srcCtx(tree))) + case _ => finalize(tree, untpd.Thicket(trees)(tree.source)) } // Copier methods with default arguments; these demand that the original tree diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index d18c8f8f7045..796c01e6ae5a 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -5,7 +5,7 @@ package ast import core._ import Types._, Contexts._, Constants._, Names._, Flags._ import Symbols._, StdNames._, Trees._ -import util.Property +import util.{Property, SourceFile, NoSource} import language.higherKinds import annotation.transientParam import annotation.internal.sharable @@ -14,7 +14,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { // ----- Tree cases that exist in untyped form only ------------------ - abstract class OpTree(implicit @transientParam src: SourceInfo) extends Tree { + abstract class OpTree(implicit @transientParam src: SourceFile) extends Tree { def op: Ident override def isTerm: Boolean = op.name.isTermName override def isType: Boolean = op.name.isTypeName @@ -23,7 +23,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { /** A typed subtree of an untyped tree needs to be wrapped in a TypedSplice * @param owner The current owner at the time the tree was defined */ - abstract case class TypedSplice(splice: tpd.Tree)(val owner: Symbol)(implicit @transientParam src: SourceInfo) extends ProxyTree { + abstract case class TypedSplice(splice: tpd.Tree)(val owner: Symbol)(implicit @transientParam src: SourceFile) extends ProxyTree { def forwardTo: tpd.Tree = splice } @@ -33,31 +33,31 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { } /** mods object name impl */ - case class ModuleDef(name: TermName, impl: Template)(implicit @transientParam src: SourceInfo) + case class ModuleDef(name: TermName, impl: Template)(implicit @transientParam src: SourceFile) extends MemberDef { type ThisTree[-T >: Untyped] <: Trees.NameTree[T] with Trees.MemberDef[T] with ModuleDef def withName(name: Name)(implicit ctx: Context): ModuleDef = cpy.ModuleDef(this)(name.toTermName, impl) } - case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree)(implicit @transientParam src: SourceInfo) extends Tree with TermTree + case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree)(implicit @transientParam src: SourceFile) extends Tree with TermTree - case class SymbolLit(str: String)(implicit @transientParam src: SourceInfo) extends TermTree + case class SymbolLit(str: String)(implicit @transientParam src: SourceFile) extends TermTree /** An interpolated string * @param segments a list of two element tickets consisting of string literal and argument tree, * possibly with a simple string literal as last element of the list */ - case class InterpolatedString(id: TermName, segments: List[Tree])(implicit @transientParam src: SourceInfo) + case class InterpolatedString(id: TermName, segments: List[Tree])(implicit @transientParam src: SourceFile) extends TermTree /** A function type */ - case class Function(args: List[Tree], body: Tree)(implicit @transientParam src: SourceInfo) extends Tree { + case class Function(args: List[Tree], body: Tree)(implicit @transientParam src: SourceFile) extends Tree { override def isTerm: Boolean = body.isTerm override def isType: Boolean = body.isType } /** A function type with `implicit` or `erased` modifiers */ - class FunctionWithMods(args: List[Tree], body: Tree, val mods: Modifiers)(implicit @transientParam src: SourceInfo) + class FunctionWithMods(args: List[Tree], body: Tree, val mods: Modifiers)(implicit @transientParam src: SourceFile) extends Function(args, body) /** A function created from a wildcard expression @@ -67,40 +67,40 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * This is equivalent to Function, except that forms a special case for the overlapping * positions tests. */ - class WildcardFunction(placeholderParams: List[ValDef], body: Tree)(implicit @transientParam src: SourceInfo) + class WildcardFunction(placeholderParams: List[ValDef], body: Tree)(implicit @transientParam src: SourceFile) extends Function(placeholderParams, body) - case class InfixOp(left: Tree, op: Ident, right: Tree)(implicit @transientParam src: SourceInfo) extends OpTree - case class PostfixOp(od: Tree, op: Ident)(implicit @transientParam src: SourceInfo) extends OpTree - case class PrefixOp(op: Ident, od: Tree)(implicit @transientParam src: SourceInfo) extends OpTree { + case class InfixOp(left: Tree, op: Ident, right: Tree)(implicit @transientParam src: SourceFile) extends OpTree + case class PostfixOp(od: Tree, op: Ident)(implicit @transientParam src: SourceFile) extends OpTree + case class PrefixOp(op: Ident, od: Tree)(implicit @transientParam src: SourceFile) extends OpTree { override def isType: Boolean = op.isType override def isTerm: Boolean = op.isTerm } - case class Parens(t: Tree)(implicit @transientParam src: SourceInfo) extends ProxyTree { + case class Parens(t: Tree)(implicit @transientParam src: SourceFile) extends ProxyTree { def forwardTo: Tree = t } - case class Tuple(trees: List[Tree])(implicit @transientParam src: SourceInfo) extends Tree { + case class Tuple(trees: List[Tree])(implicit @transientParam src: SourceFile) extends Tree { override def isTerm: Boolean = trees.isEmpty || trees.head.isTerm override def isType: Boolean = !isTerm } - case class Throw(expr: Tree)(implicit @transientParam src: SourceInfo) extends TermTree - case class Quote(expr: Tree)(implicit @transientParam src: SourceInfo) extends TermTree - case class DoWhile(body: Tree, cond: Tree)(implicit @transientParam src: SourceInfo) extends TermTree - case class ForYield(enums: List[Tree], expr: Tree)(implicit @transientParam src: SourceInfo) extends TermTree - case class ForDo(enums: List[Tree], body: Tree)(implicit @transientParam src: SourceInfo) extends TermTree - case class GenFrom(pat: Tree, expr: Tree)(implicit @transientParam src: SourceInfo) extends Tree - case class GenAlias(pat: Tree, expr: Tree)(implicit @transientParam src: SourceInfo) extends Tree - case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit @transientParam src: SourceInfo) extends TypTree - case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit @transientParam src: SourceInfo) extends DefTree - case class DependentTypeTree(tp: List[Symbol] => Type)(implicit @transientParam src: SourceInfo) extends Tree - - @sharable object EmptyTypeIdent extends Ident(tpnme.EMPTY)(NoContext) with WithoutTypeOrPos[Untyped] { + case class Throw(expr: Tree)(implicit @transientParam src: SourceFile) extends TermTree + case class Quote(expr: Tree)(implicit @transientParam src: SourceFile) extends TermTree + case class DoWhile(body: Tree, cond: Tree)(implicit @transientParam src: SourceFile) extends TermTree + case class ForYield(enums: List[Tree], expr: Tree)(implicit @transientParam src: SourceFile) extends TermTree + case class ForDo(enums: List[Tree], body: Tree)(implicit @transientParam src: SourceFile) extends TermTree + case class GenFrom(pat: Tree, expr: Tree)(implicit @transientParam src: SourceFile) extends Tree + case class GenAlias(pat: Tree, expr: Tree)(implicit @transientParam src: SourceFile) extends Tree + case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit @transientParam src: SourceFile) extends TypTree + case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit @transientParam src: SourceFile) extends DefTree + case class DependentTypeTree(tp: List[Symbol] => Type)(implicit @transientParam src: SourceFile) extends Tree + + @sharable object EmptyTypeIdent extends Ident(tpnme.EMPTY)(NoSource) with WithoutTypeOrPos[Untyped] { override def isEmpty: Boolean = true } /** A block generated by the XML parser, only treated specially by * `Positioned#checkPos` */ - class XMLBlock(stats: List[Tree], expr: Tree)(implicit @transientParam src: SourceInfo) extends Block(stats, expr) + class XMLBlock(stats: List[Tree], expr: Tree)(implicit @transientParam src: SourceFile) extends Block(stats, expr) // ----- Modifiers ----------------------------------------------------- /** Mod is intended to record syntactic information about modifiers, it's @@ -108,35 +108,35 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * * For any query about semantic information, check `flags` instead. */ - sealed abstract class Mod(val flags: FlagSet)(implicit @transientParam src: SourceInfo) + sealed abstract class Mod(val flags: FlagSet)(implicit @transientParam src: SourceFile) extends Positioned object Mod { - case class Private()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Private) + case class Private()(implicit @transientParam src: SourceFile) extends Mod(Flags.Private) - case class Protected()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Protected) + case class Protected()(implicit @transientParam src: SourceFile) extends Mod(Flags.Protected) - case class Var()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Mutable) + case class Var()(implicit @transientParam src: SourceFile) extends Mod(Flags.Mutable) - case class Implicit()(implicit @transientParam src: SourceInfo) extends Mod(Flags.ImplicitCommon) + case class Implicit()(implicit @transientParam src: SourceFile) extends Mod(Flags.ImplicitCommon) - case class Erased()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Erased) + case class Erased()(implicit @transientParam src: SourceFile) extends Mod(Flags.Erased) - case class Final()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Final) + case class Final()(implicit @transientParam src: SourceFile) extends Mod(Flags.Final) - case class Sealed()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Sealed) + case class Sealed()(implicit @transientParam src: SourceFile) extends Mod(Flags.Sealed) - case class Opaque()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Opaque) + case class Opaque()(implicit @transientParam src: SourceFile) extends Mod(Flags.Opaque) - case class Override()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Override) + case class Override()(implicit @transientParam src: SourceFile) extends Mod(Flags.Override) - case class Abstract()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Abstract) + case class Abstract()(implicit @transientParam src: SourceFile) extends Mod(Flags.Abstract) - case class Lazy()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Lazy) + case class Lazy()(implicit @transientParam src: SourceFile) extends Mod(Flags.Lazy) - case class Inline()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Inline) + case class Inline()(implicit @transientParam src: SourceFile) extends Mod(Flags.Inline) - case class Enum()(implicit @transientParam src: SourceInfo) extends Mod(Flags.Enum) + case class Enum()(implicit @transientParam src: SourceFile) extends Mod(Flags.Enum) } /** Modifiers and annotations for definitions @@ -215,7 +215,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { /** A type tree that gets its type from some other tree's symbol. Enters the * type tree in the References attachment of the `from` tree as a side effect. */ - abstract class DerivedTypeTree(implicit @transientParam src: SourceInfo) extends TypeTree { + abstract class DerivedTypeTree(implicit @transientParam src: SourceFile) extends TypeTree { private[this] var myWatched: Tree = EmptyTree @@ -259,54 +259,54 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { // ------ Creation methods for untyped only ----------------- - def Ident(name: Name)(implicit src: SourceInfo): Ident = new Ident(name) - def BackquotedIdent(name: Name)(implicit src: SourceInfo): BackquotedIdent = new BackquotedIdent(name) - def SearchFailureIdent(name: Name)(implicit src: SourceInfo): SearchFailureIdent = new SearchFailureIdent(name) - def Select(qualifier: Tree, name: Name)(implicit src: SourceInfo): Select = new Select(qualifier, name) - def SelectWithSig(qualifier: Tree, name: Name, sig: Signature)(implicit src: SourceInfo): Select = new SelectWithSig(qualifier, name, sig) - def This(qual: Ident)(implicit src: SourceInfo): This = new This(qual) - def Super(qual: Tree, mix: Ident)(implicit src: SourceInfo): Super = new Super(qual, mix) - def Apply(fun: Tree, args: List[Tree])(implicit src: SourceInfo): Apply = new Apply(fun, args) - def TypeApply(fun: Tree, args: List[Tree])(implicit src: SourceInfo): TypeApply = new TypeApply(fun, args) - def Literal(const: Constant)(implicit src: SourceInfo): Literal = new Literal(const) - def New(tpt: Tree)(implicit src: SourceInfo): New = new New(tpt) - def Typed(expr: Tree, tpt: Tree)(implicit src: SourceInfo): Typed = new Typed(expr, tpt) - def NamedArg(name: Name, arg: Tree)(implicit src: SourceInfo): NamedArg = new NamedArg(name, arg) - def Assign(lhs: Tree, rhs: Tree)(implicit src: SourceInfo): Assign = new Assign(lhs, rhs) - def Block(stats: List[Tree], expr: Tree)(implicit src: SourceInfo): Block = new Block(stats, expr) - def If(cond: Tree, thenp: Tree, elsep: Tree)(implicit src: SourceInfo): If = new If(cond, thenp, elsep) - def InlineIf(cond: Tree, thenp: Tree, elsep: Tree)(implicit src: SourceInfo): If = new InlineIf(cond, thenp, elsep) - def Closure(env: List[Tree], meth: Tree, tpt: Tree)(implicit src: SourceInfo): Closure = new Closure(env, meth, tpt) - def Match(selector: Tree, cases: List[CaseDef])(implicit src: SourceInfo): Match = new Match(selector, cases) - def InlineMatch(selector: Tree, cases: List[CaseDef])(implicit src: SourceInfo): Match = new InlineMatch(selector, cases) - def CaseDef(pat: Tree, guard: Tree, body: Tree)(implicit src: SourceInfo): CaseDef = new CaseDef(pat, guard, body) - def Labeled(bind: Bind, expr: Tree)(implicit src: SourceInfo): Labeled = new Labeled(bind, expr) - def Return(expr: Tree, from: Tree)(implicit src: SourceInfo): Return = new Return(expr, from) - def WhileDo(cond: Tree, body: Tree)(implicit src: SourceInfo): WhileDo = new WhileDo(cond, body) - def Try(expr: Tree, cases: List[CaseDef], finalizer: Tree)(implicit src: SourceInfo): Try = new Try(expr, cases, finalizer) - def SeqLiteral(elems: List[Tree], elemtpt: Tree)(implicit src: SourceInfo): SeqLiteral = new SeqLiteral(elems, elemtpt) - def JavaSeqLiteral(elems: List[Tree], elemtpt: Tree)(implicit src: SourceInfo): JavaSeqLiteral = new JavaSeqLiteral(elems, elemtpt) - def Inlined(call: tpd.Tree, bindings: List[MemberDef], expansion: Tree)(implicit src: SourceInfo): Inlined = new Inlined(call, bindings, expansion) - def TypeTree()(implicit src: SourceInfo): TypeTree = new TypeTree() - def SingletonTypeTree(ref: Tree)(implicit src: SourceInfo): SingletonTypeTree = new SingletonTypeTree(ref) - def AndTypeTree(left: Tree, right: Tree)(implicit src: SourceInfo): AndTypeTree = new AndTypeTree(left, right) - def OrTypeTree(left: Tree, right: Tree)(implicit src: SourceInfo): OrTypeTree = new OrTypeTree(left, right) - def RefinedTypeTree(tpt: Tree, refinements: List[Tree])(implicit src: SourceInfo): RefinedTypeTree = new RefinedTypeTree(tpt, refinements) - def AppliedTypeTree(tpt: Tree, args: List[Tree])(implicit src: SourceInfo): AppliedTypeTree = new AppliedTypeTree(tpt, args) - def LambdaTypeTree(tparams: List[TypeDef], body: Tree)(implicit src: SourceInfo): LambdaTypeTree = new LambdaTypeTree(tparams, body) - def MatchTypeTree(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit src: SourceInfo): MatchTypeTree = new MatchTypeTree(bound, selector, cases) - def ByNameTypeTree(result: Tree)(implicit src: SourceInfo): ByNameTypeTree = new ByNameTypeTree(result) - def TypeBoundsTree(lo: Tree, hi: Tree)(implicit src: SourceInfo): TypeBoundsTree = new TypeBoundsTree(lo, hi) - def Bind(name: Name, body: Tree)(implicit src: SourceInfo): Bind = new Bind(name, body) - def Alternative(trees: List[Tree])(implicit src: SourceInfo): Alternative = new Alternative(trees) - def UnApply(fun: Tree, implicits: List[Tree], patterns: List[Tree])(implicit src: SourceInfo): UnApply = new UnApply(fun, implicits, patterns) - def ValDef(name: TermName, tpt: Tree, rhs: LazyTree)(implicit src: SourceInfo): ValDef = new ValDef(name, tpt, rhs) - def DefDef(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree)(implicit src: SourceInfo): DefDef = new DefDef(name, tparams, vparamss, tpt, rhs) - def TypeDef(name: TypeName, rhs: Tree)(implicit src: SourceInfo): TypeDef = new TypeDef(name, rhs) - def Template(constr: DefDef, parents: List[Tree], self: ValDef, body: LazyTreeList)(implicit src: SourceInfo): Template = new Template(constr, parents, self, body) - def Import(expr: Tree, selectors: List[Tree])(implicit src: SourceInfo): Import = new Import(expr, selectors) - def PackageDef(pid: RefTree, stats: List[Tree])(implicit src: SourceInfo): PackageDef = new PackageDef(pid, stats) - def Annotated(arg: Tree, annot: Tree)(implicit src: SourceInfo): Annotated = new Annotated(arg, annot) + def Ident(name: Name)(implicit src: SourceFile): Ident = new Ident(name) + def BackquotedIdent(name: Name)(implicit src: SourceFile): BackquotedIdent = new BackquotedIdent(name) + def SearchFailureIdent(name: Name)(implicit src: SourceFile): SearchFailureIdent = new SearchFailureIdent(name) + def Select(qualifier: Tree, name: Name)(implicit src: SourceFile): Select = new Select(qualifier, name) + def SelectWithSig(qualifier: Tree, name: Name, sig: Signature)(implicit src: SourceFile): Select = new SelectWithSig(qualifier, name, sig) + def This(qual: Ident)(implicit src: SourceFile): This = new This(qual) + def Super(qual: Tree, mix: Ident)(implicit src: SourceFile): Super = new Super(qual, mix) + def Apply(fun: Tree, args: List[Tree])(implicit src: SourceFile): Apply = new Apply(fun, args) + def TypeApply(fun: Tree, args: List[Tree])(implicit src: SourceFile): TypeApply = new TypeApply(fun, args) + def Literal(const: Constant)(implicit src: SourceFile): Literal = new Literal(const) + def New(tpt: Tree)(implicit src: SourceFile): New = new New(tpt) + def Typed(expr: Tree, tpt: Tree)(implicit src: SourceFile): Typed = new Typed(expr, tpt) + def NamedArg(name: Name, arg: Tree)(implicit src: SourceFile): NamedArg = new NamedArg(name, arg) + def Assign(lhs: Tree, rhs: Tree)(implicit src: SourceFile): Assign = new Assign(lhs, rhs) + def Block(stats: List[Tree], expr: Tree)(implicit src: SourceFile): Block = new Block(stats, expr) + def If(cond: Tree, thenp: Tree, elsep: Tree)(implicit src: SourceFile): If = new If(cond, thenp, elsep) + def InlineIf(cond: Tree, thenp: Tree, elsep: Tree)(implicit src: SourceFile): If = new InlineIf(cond, thenp, elsep) + def Closure(env: List[Tree], meth: Tree, tpt: Tree)(implicit src: SourceFile): Closure = new Closure(env, meth, tpt) + def Match(selector: Tree, cases: List[CaseDef])(implicit src: SourceFile): Match = new Match(selector, cases) + def InlineMatch(selector: Tree, cases: List[CaseDef])(implicit src: SourceFile): Match = new InlineMatch(selector, cases) + def CaseDef(pat: Tree, guard: Tree, body: Tree)(implicit src: SourceFile): CaseDef = new CaseDef(pat, guard, body) + def Labeled(bind: Bind, expr: Tree)(implicit src: SourceFile): Labeled = new Labeled(bind, expr) + def Return(expr: Tree, from: Tree)(implicit src: SourceFile): Return = new Return(expr, from) + def WhileDo(cond: Tree, body: Tree)(implicit src: SourceFile): WhileDo = new WhileDo(cond, body) + def Try(expr: Tree, cases: List[CaseDef], finalizer: Tree)(implicit src: SourceFile): Try = new Try(expr, cases, finalizer) + def SeqLiteral(elems: List[Tree], elemtpt: Tree)(implicit src: SourceFile): SeqLiteral = new SeqLiteral(elems, elemtpt) + def JavaSeqLiteral(elems: List[Tree], elemtpt: Tree)(implicit src: SourceFile): JavaSeqLiteral = new JavaSeqLiteral(elems, elemtpt) + def Inlined(call: tpd.Tree, bindings: List[MemberDef], expansion: Tree)(implicit src: SourceFile): Inlined = new Inlined(call, bindings, expansion) + def TypeTree()(implicit src: SourceFile): TypeTree = new TypeTree() + def SingletonTypeTree(ref: Tree)(implicit src: SourceFile): SingletonTypeTree = new SingletonTypeTree(ref) + def AndTypeTree(left: Tree, right: Tree)(implicit src: SourceFile): AndTypeTree = new AndTypeTree(left, right) + def OrTypeTree(left: Tree, right: Tree)(implicit src: SourceFile): OrTypeTree = new OrTypeTree(left, right) + def RefinedTypeTree(tpt: Tree, refinements: List[Tree])(implicit src: SourceFile): RefinedTypeTree = new RefinedTypeTree(tpt, refinements) + def AppliedTypeTree(tpt: Tree, args: List[Tree])(implicit src: SourceFile): AppliedTypeTree = new AppliedTypeTree(tpt, args) + def LambdaTypeTree(tparams: List[TypeDef], body: Tree)(implicit src: SourceFile): LambdaTypeTree = new LambdaTypeTree(tparams, body) + def MatchTypeTree(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit src: SourceFile): MatchTypeTree = new MatchTypeTree(bound, selector, cases) + def ByNameTypeTree(result: Tree)(implicit src: SourceFile): ByNameTypeTree = new ByNameTypeTree(result) + def TypeBoundsTree(lo: Tree, hi: Tree)(implicit src: SourceFile): TypeBoundsTree = new TypeBoundsTree(lo, hi) + def Bind(name: Name, body: Tree)(implicit src: SourceFile): Bind = new Bind(name, body) + def Alternative(trees: List[Tree])(implicit src: SourceFile): Alternative = new Alternative(trees) + def UnApply(fun: Tree, implicits: List[Tree], patterns: List[Tree])(implicit src: SourceFile): UnApply = new UnApply(fun, implicits, patterns) + def ValDef(name: TermName, tpt: Tree, rhs: LazyTree)(implicit src: SourceFile): ValDef = new ValDef(name, tpt, rhs) + def DefDef(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree)(implicit src: SourceFile): DefDef = new DefDef(name, tparams, vparamss, tpt, rhs) + def TypeDef(name: TypeName, rhs: Tree)(implicit src: SourceFile): TypeDef = new TypeDef(name, rhs) + def Template(constr: DefDef, parents: List[Tree], self: ValDef, body: LazyTreeList)(implicit src: SourceFile): Template = new Template(constr, parents, self, body) + def Import(expr: Tree, selectors: List[Tree])(implicit src: SourceFile): Import = new Import(expr, selectors) + def PackageDef(pid: RefTree, stats: List[Tree])(implicit src: SourceFile): PackageDef = new PackageDef(pid, stats) + def Annotated(arg: Tree, annot: Tree)(implicit src: SourceFile): Annotated = new Annotated(arg, annot) // ------ Additional creation methods for untyped only ----------------- @@ -335,32 +335,32 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { ensureApplied((prefix /: argss)(Apply(_, _))) } - def Block(stat: Tree, expr: Tree)(implicit src: SourceInfo): Block = + def Block(stat: Tree, expr: Tree)(implicit src: SourceFile): Block = Block(stat :: Nil, expr) - def Apply(fn: Tree, arg: Tree)(implicit src: SourceInfo): Apply = + def Apply(fn: Tree, arg: Tree)(implicit src: SourceFile): Apply = Apply(fn, arg :: Nil) - def ensureApplied(tpt: Tree)(implicit src: SourceInfo): Tree = tpt match { + def ensureApplied(tpt: Tree)(implicit src: SourceFile): Tree = tpt match { case _: Apply => tpt case _ => Apply(tpt, Nil) } - def AppliedTypeTree(tpt: Tree, arg: Tree)(implicit src: SourceInfo): AppliedTypeTree = + def AppliedTypeTree(tpt: Tree, arg: Tree)(implicit src: SourceFile): AppliedTypeTree = AppliedTypeTree(tpt, arg :: Nil) def TypeTree(tpe: Type)(implicit ctx: Context): TypedSplice = TypedSplice(TypeTree().withTypeUnchecked(tpe)) - def unitLiteral(implicit src: SourceInfo): Literal = Literal(Constant(())) + def unitLiteral(implicit src: SourceFile): Literal = Literal(Constant(())) def ref(tp: NamedType)(implicit ctx: Context): Tree = TypedSplice(tpd.ref(tp)) - def rootDot(name: Name)(implicit src: SourceInfo): Select = Select(Ident(nme.ROOTPKG), name) - def scalaDot(name: Name)(implicit src: SourceInfo): Select = Select(rootDot(nme.scala_), name) - def scalaUnit(implicit src: SourceInfo): Select = scalaDot(tpnme.Unit) - def scalaAny(implicit src: SourceInfo): Select = scalaDot(tpnme.Any) - def javaDotLangDot(name: Name)(implicit src: SourceInfo): Select = Select(Select(Ident(nme.java), nme.lang), name) + def rootDot(name: Name)(implicit src: SourceFile): Select = Select(Ident(nme.ROOTPKG), name) + def scalaDot(name: Name)(implicit src: SourceFile): Select = Select(rootDot(nme.scala_), name) + def scalaUnit(implicit src: SourceFile): Select = scalaDot(tpnme.Unit) + def scalaAny(implicit src: SourceFile): Select = scalaDot(tpnme.Any) + def javaDotLangDot(name: Name)(implicit src: SourceFile): Select = Select(Select(Ident(nme.java), nme.lang), name) def makeConstructor(tparams: List[TypeDef], vparamss: List[List[ValDef]], rhs: Tree = EmptyTree)(implicit ctx: Context): DefDef = DefDef(nme.CONSTRUCTOR, tparams, vparamss, TypeTree(), rhs) @@ -428,84 +428,84 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def ModuleDef(tree: Tree)(name: TermName, impl: Template)(implicit ctx: Context): ModuleDef = tree match { case tree: ModuleDef if (name eq tree.name) && (impl eq tree.impl) => tree - case _ => finalize(tree, untpd.ModuleDef(name, impl)(srcCtx(tree))) + case _ => finalize(tree, untpd.ModuleDef(name, impl)(tree.source)) } def ParsedTry(tree: Tree)(expr: Tree, handler: Tree, finalizer: Tree)(implicit ctx: Context): TermTree = tree match { case tree: ParsedTry if (expr eq tree.expr) && (handler eq tree.handler) && (finalizer eq tree.finalizer) => tree - case _ => finalize(tree, untpd.ParsedTry(expr, handler, finalizer)(srcCtx(tree))) + case _ => finalize(tree, untpd.ParsedTry(expr, handler, finalizer)(tree.source)) } def SymbolLit(tree: Tree)(str: String)(implicit ctx: Context): TermTree = tree match { case tree: SymbolLit if str == tree.str => tree - case _ => finalize(tree, untpd.SymbolLit(str)(srcCtx(tree))) + case _ => finalize(tree, untpd.SymbolLit(str)(tree.source)) } def InterpolatedString(tree: Tree)(id: TermName, segments: List[Tree])(implicit ctx: Context): TermTree = tree match { case tree: InterpolatedString if (id eq tree.id) && (segments eq tree.segments) => tree - case _ => finalize(tree, untpd.InterpolatedString(id, segments)(srcCtx(tree))) + case _ => finalize(tree, untpd.InterpolatedString(id, segments)(tree.source)) } def Function(tree: Tree)(args: List[Tree], body: Tree)(implicit ctx: Context): Tree = tree match { case tree: Function if (args eq tree.args) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.Function(args, body)(srcCtx(tree))) + case _ => finalize(tree, untpd.Function(args, body)(tree.source)) } def InfixOp(tree: Tree)(left: Tree, op: Ident, right: Tree)(implicit ctx: Context): Tree = tree match { case tree: InfixOp if (left eq tree.left) && (op eq tree.op) && (right eq tree.right) => tree - case _ => finalize(tree, untpd.InfixOp(left, op, right)(srcCtx(tree))) + case _ => finalize(tree, untpd.InfixOp(left, op, right)(tree.source)) } def PostfixOp(tree: Tree)(od: Tree, op: Ident)(implicit ctx: Context): Tree = tree match { case tree: PostfixOp if (od eq tree.od) && (op eq tree.op) => tree - case _ => finalize(tree, untpd.PostfixOp(od, op)(srcCtx(tree))) + case _ => finalize(tree, untpd.PostfixOp(od, op)(tree.source)) } def PrefixOp(tree: Tree)(op: Ident, od: Tree)(implicit ctx: Context): Tree = tree match { case tree: PrefixOp if (op eq tree.op) && (od eq tree.od) => tree - case _ => finalize(tree, untpd.PrefixOp(op, od)(srcCtx(tree))) + case _ => finalize(tree, untpd.PrefixOp(op, od)(tree.source)) } def Parens(tree: Tree)(t: Tree)(implicit ctx: Context): ProxyTree = tree match { case tree: Parens if t eq tree.t => tree - case _ => finalize(tree, untpd.Parens(t)(srcCtx(tree))) + case _ => finalize(tree, untpd.Parens(t)(tree.source)) } def Tuple(tree: Tree)(trees: List[Tree])(implicit ctx: Context): Tree = tree match { case tree: Tuple if trees eq tree.trees => tree - case _ => finalize(tree, untpd.Tuple(trees)(srcCtx(tree))) + case _ => finalize(tree, untpd.Tuple(trees)(tree.source)) } def Throw(tree: Tree)(expr: Tree)(implicit ctx: Context): TermTree = tree match { case tree: Throw if expr eq tree.expr => tree - case _ => finalize(tree, untpd.Throw(expr)(srcCtx(tree))) + case _ => finalize(tree, untpd.Throw(expr)(tree.source)) } def Quote(tree: Tree)(expr: Tree)(implicit ctx: Context): TermTree = tree match { case tree: Quote if expr eq tree.expr => tree - case _ => finalize(tree, untpd.Quote(expr)(srcCtx(tree))) + case _ => finalize(tree, untpd.Quote(expr)(tree.source)) } def DoWhile(tree: Tree)(body: Tree, cond: Tree)(implicit ctx: Context): TermTree = tree match { case tree: DoWhile if (body eq tree.body) && (cond eq tree.cond) => tree - case _ => finalize(tree, untpd.DoWhile(body, cond)(srcCtx(tree))) + case _ => finalize(tree, untpd.DoWhile(body, cond)(tree.source)) } def ForYield(tree: Tree)(enums: List[Tree], expr: Tree)(implicit ctx: Context): TermTree = tree match { case tree: ForYield if (enums eq tree.enums) && (expr eq tree.expr) => tree - case _ => finalize(tree, untpd.ForYield(enums, expr)(srcCtx(tree))) + case _ => finalize(tree, untpd.ForYield(enums, expr)(tree.source)) } def ForDo(tree: Tree)(enums: List[Tree], body: Tree)(implicit ctx: Context): TermTree = tree match { case tree: ForDo if (enums eq tree.enums) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.ForDo(enums, body)(srcCtx(tree))) + case _ => finalize(tree, untpd.ForDo(enums, body)(tree.source)) } def GenFrom(tree: Tree)(pat: Tree, expr: Tree)(implicit ctx: Context): Tree = tree match { case tree: GenFrom if (pat eq tree.pat) && (expr eq tree.expr) => tree - case _ => finalize(tree, untpd.GenFrom(pat, expr)(srcCtx(tree))) + case _ => finalize(tree, untpd.GenFrom(pat, expr)(tree.source)) } def GenAlias(tree: Tree)(pat: Tree, expr: Tree)(implicit ctx: Context): Tree = tree match { case tree: GenAlias if (pat eq tree.pat) && (expr eq tree.expr) => tree - case _ => finalize(tree, untpd.GenAlias(pat, expr)(srcCtx(tree))) + case _ => finalize(tree, untpd.GenAlias(pat, expr)(tree.source)) } def ContextBounds(tree: Tree)(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit ctx: Context): TypTree = tree match { case tree: ContextBounds if (bounds eq tree.bounds) && (cxBounds eq tree.cxBounds) => tree - case _ => finalize(tree, untpd.ContextBounds(bounds, cxBounds)(srcCtx(tree))) + case _ => finalize(tree, untpd.ContextBounds(bounds, cxBounds)(tree.source)) } def PatDef(tree: Tree)(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit ctx: Context): Tree = tree match { case tree: PatDef if (mods eq tree.mods) && (pats eq tree.pats) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree - case _ => finalize(tree, untpd.PatDef(mods, pats, tpt, rhs)(srcCtx(tree))) + case _ => finalize(tree, untpd.PatDef(mods, pats, tpt, rhs)(tree.source)) } def TypedSplice(tree: Tree)(splice: tpd.Tree)(implicit ctx: Context): ProxyTree = tree match { case tree: TypedSplice if splice `eq` tree.splice => tree - case _ => finalize(tree, untpd.TypedSplice(splice)(srcCtx(tree))) + case _ => finalize(tree, untpd.TypedSplice(splice)(ctx)) } } diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 561a3acf5b37..48fd7ebeaceb 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -38,15 +38,6 @@ import java.util.concurrent.atomic.AtomicInteger object Contexts { - trait SourceInfo { - def source: SourceFile - } - object SourceInfo { - def apply(src: SourceFile) = new SourceInfo { - def source = src - } - } - private val (compilerCallbackLoc, store1) = Store.empty.newLocation[CompilerCallback]() private val (sbtCallbackLoc, store2) = store1.newLocation[AnalysisCallback]() private val (printerFnLoc, store3) = store2.newLocation[Context => Printer](new RefinedPrinter(_)) @@ -86,7 +77,6 @@ object Contexts { with Reporting with NamerContextOps with Plugins - with SourceInfo with Cloneable { thiscontext => implicit def ctx: Context = this diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 38a440ae38dd..6dfa4f91e3a8 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -14,13 +14,14 @@ import TastyBuffer._ import transform.SymUtils._ import printing.Printer import printing.Texts._ +import util.SourceFile import annotation.transientParam object TreePickler { val sectionName = "ASTs" - case class Hole(idx: Int, args: List[tpd.Tree])(implicit @transientParam src: SourceInfo) extends tpd.Tree { + case class Hole(idx: Int, args: List[tpd.Tree])(implicit @transientParam src: SourceFile) extends tpd.Tree { override def fallbackToText(printer: Printer): Text = s"[[$idx|" ~~ printer.toTextGlobal(args, ", ") ~~ "]]" } @@ -332,8 +333,6 @@ class TreePickler(pickler: TastyPickler) { writeByte(SHAREDterm) writeRef(addr) } - //else if (tree.source `ne` ctx.source) - // pickleTree(tree)(ctx.withSource(tree.source)) else try tree match { case Ident(name) => diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala index 8d64c9388ca4..a56df8e14906 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala @@ -11,7 +11,7 @@ import Parsers._ import util.Spans._ import core._ import Constants._ -import Contexts.SourceInfo +import util.SourceFile import Utility._ @@ -47,7 +47,7 @@ object MarkupParsers { override def getMessage: String = "input ended while parsing XML" } - class MarkupParser(parser: Parser, final val preserveWS: Boolean)(implicit src: SourceInfo) extends MarkupParserCommon { + class MarkupParser(parser: Parser, final val preserveWS: Boolean)(implicit src: SourceFile) extends MarkupParserCommon { import Tokens.{ LBRACE, RBRACE } diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/package.scala b/compiler/src/dotty/tools/dotc/tastyreflect/package.scala index 3fef58f370bc..cb621a059cf2 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/package.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/package.scala @@ -1,18 +1,19 @@ package dotty.tools.dotc import dotty.tools.dotc.ast.Trees.{Tree, Untyped} -import dotty.tools.dotc.core.Contexts.{Context, SourceInfo} +import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Symbols.Symbol import dotty.tools.dotc.core.Types.Type import dotty.tools.dotc.core.SymDenotations.SymDenotation import scala.annotation.transientParam +import util.SourceFile package object tastyreflect { type PackageDefinition = PackageDefinitionImpl[Type] /** Represents the symbol of a definition in tree form */ - case class PackageDefinitionImpl[-T >: Untyped] private[tastyreflect] (sym: Symbol)(implicit @transientParam src: SourceInfo) extends Tree[T] { + case class PackageDefinitionImpl[-T >: Untyped] private[tastyreflect] (sym: Symbol)(implicit @transientParam src: SourceFile) extends Tree[T] { type ThisTree[-T >: Untyped] = PackageDefinitionImpl[T] override def denot(implicit ctx: Context): SymDenotation = sym.denot diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 17b49ec52b31..4d67cc1a19c5 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -6,7 +6,7 @@ import core._ import ast.{Trees, tpd, untpd} import util.Spans._ import util.Stats.track -import util.{SourcePosition, NoSourcePosition} +import util.{SourcePosition, NoSourcePosition, SourceFile} import Trees.Untyped import Contexts._ import Flags._ @@ -169,7 +169,7 @@ object Applications { /** A wrapper indicating that its argument is an application of an extension method. */ - class ExtMethodApply(val app: Tree)(implicit @transientParam src: SourceInfo) extends tpd.Tree { + class ExtMethodApply(val app: Tree)(implicit @transientParam src: SourceFile) extends tpd.Tree { override def span = app.span def canEqual(that: Any): Boolean = app.canEqual(that) diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 87b9fc05d28d..77bdc1a110cd 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -28,7 +28,7 @@ import reporting.diagnostic.Message import Inferencing.fullyDefinedType import Trees._ import Hashable._ -import util.Property +import util.{Property, SourceFile, NoSource} import config.Config import config.Printers.{implicits, implicitsDetailed} import collection.mutable @@ -348,7 +348,7 @@ object Implicits { } object SearchFailure { - def apply(tpe: SearchFailureType)(implicit src: SourceInfo): SearchFailure = { + def apply(tpe: SearchFailureType)(implicit src: SourceFile): SearchFailure = { val id = if (tpe.isInstanceOf[AmbiguousImplicits]) "/* ambiguous */" else "/* missing */" @@ -387,7 +387,7 @@ object Implicits { @sharable object NoMatchingImplicits extends NoMatchingImplicits(NoType, EmptyTree) @sharable val NoMatchingImplicitsFailure: SearchFailure = - SearchFailure(NoMatchingImplicits)(NoContext) + SearchFailure(NoMatchingImplicits)(NoSource) /** An ambiguous implicits failure */ class AmbiguousImplicits(val alt1: SearchSuccess, val alt2: SearchSuccess, val expectedType: Type, val argument: Tree) extends SearchFailureType { diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index d2165cd31be3..c031a22a9796 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -12,6 +12,7 @@ import util.{Stats, SimpleIdentityMap} import Decorators._ import Uniques._ import config.Printers.typr +import util.SourceFile import scala.annotation.internal.sharable @@ -410,7 +411,7 @@ object ProtoTypes { } class UnapplyFunProto(argType: Type, typer: Typer)(implicit ctx: Context) extends FunProto( - untpd.TypedSplice(dummyTreeOfType(argType)(ctx))(ctx) :: Nil, WildcardType)(typer) + untpd.TypedSplice(dummyTreeOfType(argType)(ctx.source))(ctx) :: Nil, WildcardType)(typer) /** A prototype for expressions [] that are type-parameterized: * @@ -652,7 +653,7 @@ object ProtoTypes { /** Dummy tree to be used as an argument of a FunProto or ViewProto type */ object dummyTreeOfType { - def apply(tp: Type)(implicit src: SourceInfo): Tree = untpd.Literal(Constant(null)) withTypeUnchecked tp + def apply(tp: Type)(implicit src: SourceFile): Tree = untpd.Literal(Constant(null)) withTypeUnchecked tp def unapply(tree: untpd.Tree): Option[Type] = tree match { case Literal(Constant(null)) => Some(tree.typeOpt) case _ => None diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index 590e9518f72c..de726bd02fd0 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -10,6 +10,7 @@ import scala.tasty.util.Chars._ import Spans._ import scala.io.Codec import core.Names.TermName +import core.Contexts.Context import scala.annotation.internal.sharable import core.Decorators.PreNamedString import java.util.concurrent.atomic.AtomicInteger @@ -188,6 +189,8 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends object SourceFile { implicit def eqSurce: Eq[SourceFile, SourceFile] = Eq + implicit def fromContext(implicit ctx: Context): SourceFile = ctx.source + type PathName = TermName def fromId(id: Int): SourceFile = sourceOfChunk(id >> ChunkSizeLog) diff --git a/compiler/src/dotty/tools/repl/ParseResult.scala b/compiler/src/dotty/tools/repl/ParseResult.scala index 55068c3e7b29..956ddf7e2dcd 100644 --- a/compiler/src/dotty/tools/repl/ParseResult.scala +++ b/compiler/src/dotty/tools/repl/ParseResult.scala @@ -110,8 +110,7 @@ object ParseResult { private def parseStats(sourceCode: String)(implicit ctx: Context): List[untpd.Tree] = { val source = new SourceFile("", sourceCode) - val ctx1 = ctx.fresh.setSource(source) - val parser = new Parser(source)(ctx1) + val parser = new Parser(source)(ctx.withSource(source)) val stats = parser.blockStatSeq() parser.accept(Tokens.EOF) stats From 5a6b1ee3214bcac47ba849dfc41fec6362da73d1 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 14 Jan 2019 10:57:18 +0100 Subject: [PATCH 73/75] Make virtual source files explicit --- compiler/src/dotty/tools/dotc/core/Comments.scala | 2 +- .../src/dotty/tools/dotc/printing/SyntaxHighlighting.scala | 2 +- compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala | 4 ++-- compiler/src/dotty/tools/dotc/util/SourceFile.scala | 3 ++- compiler/src/dotty/tools/repl/JLineTerminal.scala | 2 +- compiler/src/dotty/tools/repl/ParseResult.scala | 2 +- compiler/src/dotty/tools/repl/ReplCompiler.scala | 4 ++-- compiler/src/dotty/tools/repl/ReplDriver.scala | 2 +- compiler/test/dotty/tools/dotc/ast/UntypedTreeMapTest.scala | 2 +- .../test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala | 2 +- doc-tool/test/dotty/tools/dottydoc/TypeRendering.scala | 2 +- 11 files changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Comments.scala b/compiler/src/dotty/tools/dotc/core/Comments.scala index 1a8149edb40f..06079a6e4c48 100644 --- a/compiler/src/dotty/tools/dotc/core/Comments.scala +++ b/compiler/src/dotty/tools/dotc/core/Comments.scala @@ -119,7 +119,7 @@ object Comments { object UseCase { def apply(code: String, codePos: Span)(implicit ctx: Context): UseCase = { val tree = { - val tree = new Parser(new SourceFile("", code)).localDef(codePos.start) + val tree = new Parser(SourceFile.virtual("", code)).localDef(codePos.start) tree match { case tree: untpd.DefDef => val newName = ctx.freshNames.newName(tree.name, NameKinds.DocArtifactName) diff --git a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala index 9c3b75a06b10..96f091c392b3 100644 --- a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala +++ b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala @@ -33,7 +33,7 @@ object SyntaxHighlighting { if (in.isEmpty || ctx.settings.color.value == "never") in else { implicit val ctx = freshCtx - val source = new SourceFile("", in) + val source = SourceFile.virtual("", in) val colorAt = Array.fill(in.length)(NoColor) def highlightRange(from: Int, to: Int, color: String) = diff --git a/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala b/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala index 529c18023687..fd259f55a505 100644 --- a/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala +++ b/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala @@ -51,12 +51,12 @@ class QuoteCompiler extends Compiler { val tree = if (putInClass) inClass(exprUnit.expr) else PickledQuotes.quotedExprToTree(exprUnit.expr) - val source = new SourceFile("", "") + val source = SourceFile.virtual("", "") CompilationUnit.mkCompilationUnit(source, tree, forceTrees = true) case typeUnit: TypeCompilationUnit => assert(!putInClass) val tree = PickledQuotes.quotedTypeToTree(typeUnit.tpe) - val source = new SourceFile("", "") + val source = SourceFile.virtual("", "") CompilationUnit.mkCompilationUnit(source, tree, forceTrees = true) } } diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index de726bd02fd0..e1f3c9578f77 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -50,7 +50,6 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends } def this(file: AbstractFile, codec: Codec) = this(file, new String(file.toByteArray, codec.charSet).toCharArray) - def this(name: String, content: String) = this(new VirtualFile(name, content.getBytes), scala.io.Codec.UTF8) /** Tab increment; can be overridden */ def tabInc: Int = 8 @@ -195,6 +194,8 @@ object SourceFile { def fromId(id: Int): SourceFile = sourceOfChunk(id >> ChunkSizeLog) + def virtual(name: String, content: String) = new SourceFile(new VirtualFile(name, content.getBytes), scala.io.Codec.UTF8) + private final val ChunkSizeLog = 10 private final val ChunkSize = 1 << ChunkSizeLog @sharable private var chunks: Int = 0 diff --git a/compiler/src/dotty/tools/repl/JLineTerminal.scala b/compiler/src/dotty/tools/repl/JLineTerminal.scala index 7868eacf4831..3376714e5bee 100644 --- a/compiler/src/dotty/tools/repl/JLineTerminal.scala +++ b/compiler/src/dotty/tools/repl/JLineTerminal.scala @@ -110,7 +110,7 @@ final class JLineTerminal extends java.io.Closeable { case class TokenData(token: Token, start: Int, end: Int) def currentToken: TokenData /* | Null */ = { - val source = new SourceFile("", input) + val source = SourceFile.virtual("", input) val scanner = new Scanner(source)(ctx.fresh.setReporter(Reporter.NoReporter)) while (scanner.token != EOF) { val start = scanner.offset diff --git a/compiler/src/dotty/tools/repl/ParseResult.scala b/compiler/src/dotty/tools/repl/ParseResult.scala index 956ddf7e2dcd..59e4c025a339 100644 --- a/compiler/src/dotty/tools/repl/ParseResult.scala +++ b/compiler/src/dotty/tools/repl/ParseResult.scala @@ -109,7 +109,7 @@ object ParseResult { @sharable private[this] val CommandExtract = """(:[\S]+)\s*(.*)""".r private def parseStats(sourceCode: String)(implicit ctx: Context): List[untpd.Tree] = { - val source = new SourceFile("", sourceCode) + val source = SourceFile.virtual("", sourceCode) val parser = new Parser(source)(ctx.withSource(source)) val stats = parser.blockStatSeq() parser.accept(Tokens.EOF) diff --git a/compiler/src/dotty/tools/repl/ReplCompiler.scala b/compiler/src/dotty/tools/repl/ReplCompiler.scala index 7e20f4e28313..b650f2e522c7 100644 --- a/compiler/src/dotty/tools/repl/ReplCompiler.scala +++ b/compiler/src/dotty/tools/repl/ReplCompiler.scala @@ -141,7 +141,7 @@ class ReplCompiler extends Compiler { } private def createUnit(defs: Definitions, sourceCode: String): CompilationUnit = { - val unit = new CompilationUnit(new SourceFile(objectName(defs.state).toString, sourceCode)) + val unit = new CompilationUnit(SourceFile.virtual(objectName(defs.state).toString, sourceCode)) unit.untpdTree = wrapped(defs) unit } @@ -267,7 +267,7 @@ class ReplCompiler extends Compiler { } - val src = new SourceFile("", expr) + val src = SourceFile.virtual("", expr) implicit val ctx: Context = state.context.fresh .setReporter(newStoreReporter) .setSetting(state.context.settings.YstopAfter, List("frontend")) diff --git a/compiler/src/dotty/tools/repl/ReplDriver.scala b/compiler/src/dotty/tools/repl/ReplDriver.scala index fce239acc405..1b8fb03bc2c4 100644 --- a/compiler/src/dotty/tools/repl/ReplDriver.scala +++ b/compiler/src/dotty/tools/repl/ReplDriver.scala @@ -165,7 +165,7 @@ class ReplDriver(settings: Array[String], compiler .typeCheck(expr, errorsAllowed = true) .map { tree => - val file = new SourceFile("", expr) + val file = SourceFile.virtual("", expr) val unit = new CompilationUnit(file) unit.tpdTree = tree implicit val ctx = state.context.fresh.setCompilationUnit(unit) diff --git a/compiler/test/dotty/tools/dotc/ast/UntypedTreeMapTest.scala b/compiler/test/dotty/tools/dotc/ast/UntypedTreeMapTest.scala index 251bc3ab07a8..1633cfaa9b57 100644 --- a/compiler/test/dotty/tools/dotc/ast/UntypedTreeMapTest.scala +++ b/compiler/test/dotty/tools/dotc/ast/UntypedTreeMapTest.scala @@ -14,7 +14,7 @@ class UntpdTreeMapTest extends DottyTest { import untpd._ def parse(code: String): Tree = { - val (_, stats) = new Parser(new SourceFile("", code)).templateStatSeq() + val (_, stats) = new Parser(SourceFile.virtual("", code)).templateStatSeq() stats match { case List(stat) => stat; case stats => untpd.Thicket(stats) } } diff --git a/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala b/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala index 4dab85983368..97bd20e8d5a4 100644 --- a/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala +++ b/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala @@ -17,7 +17,7 @@ object ModifiersParsingTest { implicit val ctx: Context = (new ContextBase).initialCtx def parse(code: String): Tree = { - val (_, stats) = new Parser(new SourceFile("", code)).templateStatSeq() + val (_, stats) = new Parser(SourceFile.virtual("", code)).templateStatSeq() stats match { case List(stat) => stat; case stats => Thicket(stats) } } diff --git a/doc-tool/test/dotty/tools/dottydoc/TypeRendering.scala b/doc-tool/test/dotty/tools/dottydoc/TypeRendering.scala index 630c0d09aead..5e4d50274ac3 100644 --- a/doc-tool/test/dotty/tools/dottydoc/TypeRendering.scala +++ b/doc-tool/test/dotty/tools/dottydoc/TypeRendering.scala @@ -13,7 +13,7 @@ class TypeRenderingTestFromTasty extends TypeRenderingTest with CheckFromTasty class TypeRenderingTestFromSource extends TypeRenderingTest with CheckFromSource abstract class TypeRenderingTest extends DottyDocTest { @Test def renderImplicitFunctionType = { - val source = new SourceFile( + val source = SourceFile.virtual( "ImplicitFunctionType.scala", """ |package scala From 84321ebd901453da3d55b49f42bc5ce48f21c733 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 14 Jan 2019 15:38:02 +0100 Subject: [PATCH 74/75] Sourcefile refactoring Don't check whether a sourcefile exists when creating it - it might lead to spurious errors. Do it instead at the point where we create a CompilationUnit from a source file. --- .../dotty/tools/dotc/CompilationUnit.scala | 23 +++++++++++++++---- compiler/src/dotty/tools/dotc/Run.scala | 6 ++--- .../src/dotty/tools/dotc/core/Contexts.scala | 16 +++---------- .../dotty/tools/dotc/core/SymbolLoaders.scala | 2 +- .../src/dotty/tools/dotc/core/Symbols.scala | 3 +-- .../tools/dotc/fromtasty/ReadTasty.scala | 3 +-- .../tools/dotc/quoted/QuoteCompiler.scala | 4 ++-- .../src/dotty/tools/repl/ReplCompiler.scala | 8 +++---- .../src/dotty/tools/repl/ReplDriver.scala | 4 ++-- 9 files changed, 36 insertions(+), 33 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/CompilationUnit.scala b/compiler/src/dotty/tools/dotc/CompilationUnit.scala index cdd92078d1db..bce33813fa70 100644 --- a/compiler/src/dotty/tools/dotc/CompilationUnit.scala +++ b/compiler/src/dotty/tools/dotc/CompilationUnit.scala @@ -9,8 +9,9 @@ import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.SymDenotations.ClassDenotation import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.transform.SymUtils._ +import util.{NoSource, SourceFile} -class CompilationUnit(val source: SourceFile) { +class CompilationUnit protected (val source: SourceFile) { override def toString: String = source.toString @@ -35,11 +36,11 @@ class CompilationUnit(val source: SourceFile) { object CompilationUnit { /** Make a compilation unit for top class `clsd` with the contents of the `unpickled` tree */ - def mkCompilationUnit(clsd: ClassDenotation, unpickled: Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit = - mkCompilationUnit(new SourceFile(clsd.symbol.associatedFile, Array.empty[Char]), unpickled, forceTrees) + def apply(clsd: ClassDenotation, unpickled: Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit = + apply(new SourceFile(clsd.symbol.associatedFile, Array.empty[Char]), unpickled, forceTrees) /** Make a compilation unit, given picked bytes and unpickled tree */ - def mkCompilationUnit(source: SourceFile, unpickled: Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit = { + def apply(source: SourceFile, unpickled: Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit = { assert(!unpickled.isEmpty, unpickled) val unit1 = new CompilationUnit(source) unit1.tpdTree = unpickled @@ -51,6 +52,20 @@ object CompilationUnit { unit1 } + def apply(source: SourceFile)(implicit ctx: Context): CompilationUnit = { + val src = + if (source.file.isDirectory) { + ctx.error(s"expected file, received directory '${source.file.path}'") + NoSource + } + else if (!source.file.exists) { + ctx.error(s"not found: ${source.file.path}") + NoSource + } + else source + new CompilationUnit(source) + } + /** Force the tree to be loaded */ private class Force extends TreeTraverser { var needsStaging = false diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index f5d1522749bc..a58ee0723107 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -100,7 +100,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint private[this] var finalizeActions = mutable.ListBuffer[() => Unit]() def compile(fileNames: List[String]): Unit = try { - val sources = fileNames.map(ctx.getSource) + val sources = fileNames.map(ctx.getSource(_)) compileSources(sources) } catch { case NonFatal(ex) => @@ -116,7 +116,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint */ def compileSources(sources: List[SourceFile]): Unit = if (sources forall (_.exists)) { - units = sources map (new CompilationUnit(_)) + units = sources.map(CompilationUnit(_)) compileUnits() } @@ -192,7 +192,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint def lateCompile(file: AbstractFile, typeCheck: Boolean)(implicit ctx: Context): Unit = if (!files.contains(file) && !lateFiles.contains(file)) { lateFiles += file - val unit = new CompilationUnit(ctx.getSource(file.path)) + val unit = CompilationUnit(ctx.getSource(file.path)) def process()(implicit ctx: Context) = { unit.untpdTree = if (unit.isJava) new JavaParser(unit.source).parse() diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 48fd7ebeaceb..31c8269d0da9 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -244,19 +244,9 @@ object Contexts { source case None => val f = new PlainFile(Path(path.toString)) - if (f.isDirectory) { - error(s"expected file, received directory '$path'") - NoSource - } - else if (f.exists) { - val src = getSource(f) - base.sourceNamed(path) = src - src - } - else { - error(s"not found: $path") - NoSource - } + val src = getSource(f) + base.sourceNamed(path) = src + src } /** Sourcefile with given path, memoized */ diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 5c262656d970..4876d8cf3fdb 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -159,7 +159,7 @@ object SymbolLoaders { Nil) } - val unit = new CompilationUnit(ctx.getSource(src.path)) + val unit = CompilationUnit(ctx.getSource(src.path)) enterScanned(unit)(ctx.run.runContext.fresh.setCompilationUnit(unit)) } } diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index ab569aba3996..d41b83ea054c 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -775,8 +775,7 @@ object Symbols { def sourceFromTopLevel(implicit ctx: Context) = denot.topLevelClass.unforcedAnnotation(defn.SourceFileAnnot) match { case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match { - case Some(Constant(path: String)) => - ctx.getSource(path) + case Some(Constant(path: String)) => ctx.getSource(path) case none => NoSource } case none => NoSource diff --git a/compiler/src/dotty/tools/dotc/fromtasty/ReadTasty.scala b/compiler/src/dotty/tools/dotc/fromtasty/ReadTasty.scala index 13fac7bbc19d..a44d3ad6b38a 100644 --- a/compiler/src/dotty/tools/dotc/fromtasty/ReadTasty.scala +++ b/compiler/src/dotty/tools/dotc/fromtasty/ReadTasty.scala @@ -9,7 +9,6 @@ import Symbols.{Symbol, ClassSymbol} import SymDenotations.ClassDenotation import NameOps._ import ast.Trees.Tree -import CompilationUnit.mkCompilationUnit import Phases.Phase @@ -44,7 +43,7 @@ class ReadTasty extends Phase { case unpickler: tasty.DottyUnpickler => if (cls.rootTree.isEmpty) None else { - val unit = mkCompilationUnit(cls, cls.rootTree, forceTrees = true) + val unit = CompilationUnit(cls, cls.rootTree, forceTrees = true) unit.pickled += (cls -> unpickler.unpickler.bytes) Some(unit) } diff --git a/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala b/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala index fd259f55a505..7d2650c5e0a6 100644 --- a/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala +++ b/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala @@ -52,12 +52,12 @@ class QuoteCompiler extends Compiler { if (putInClass) inClass(exprUnit.expr) else PickledQuotes.quotedExprToTree(exprUnit.expr) val source = SourceFile.virtual("", "") - CompilationUnit.mkCompilationUnit(source, tree, forceTrees = true) + CompilationUnit(source, tree, forceTrees = true) case typeUnit: TypeCompilationUnit => assert(!putInClass) val tree = PickledQuotes.quotedTypeToTree(typeUnit.tpe) val source = SourceFile.virtual("", "") - CompilationUnit.mkCompilationUnit(source, tree, forceTrees = true) + CompilationUnit(source, tree, forceTrees = true) } } diff --git a/compiler/src/dotty/tools/repl/ReplCompiler.scala b/compiler/src/dotty/tools/repl/ReplCompiler.scala index b650f2e522c7..7a3e8226c23d 100644 --- a/compiler/src/dotty/tools/repl/ReplCompiler.scala +++ b/compiler/src/dotty/tools/repl/ReplCompiler.scala @@ -140,8 +140,8 @@ class ReplCompiler extends Compiler { PackageDef(Ident(nme.EMPTY_PACKAGE), List(module)) } - private def createUnit(defs: Definitions, sourceCode: String): CompilationUnit = { - val unit = new CompilationUnit(SourceFile.virtual(objectName(defs.state).toString, sourceCode)) + private def createUnit(defs: Definitions, sourceCode: String)(implicit ctx: Context): CompilationUnit = { + val unit = CompilationUnit(SourceFile.virtual(objectName(defs.state).toString, sourceCode)) unit.untpdTree = wrapped(defs) unit } @@ -156,7 +156,7 @@ class ReplCompiler extends Compiler { final def compile(parsed: Parsed)(implicit state: State): Result[(CompilationUnit, State)] = { val defs = definitions(parsed.trees, state) - val unit = createUnit(defs, parsed.sourceCode) + val unit = createUnit(defs, parsed.sourceCode)(state.context) runCompilationUnit(unit, defs.state) } @@ -273,7 +273,7 @@ class ReplCompiler extends Compiler { .setSetting(state.context.settings.YstopAfter, List("frontend")) wrapped(expr, src, state).flatMap { pkg => - val unit = new CompilationUnit(src) + val unit = CompilationUnit(src) unit.untpdTree = pkg ctx.run.compileUnits(unit :: Nil, ctx) diff --git a/compiler/src/dotty/tools/repl/ReplDriver.scala b/compiler/src/dotty/tools/repl/ReplDriver.scala index 1b8fb03bc2c4..330247ab2a31 100644 --- a/compiler/src/dotty/tools/repl/ReplDriver.scala +++ b/compiler/src/dotty/tools/repl/ReplDriver.scala @@ -149,7 +149,7 @@ class ReplDriver(settings: Array[String], /** Extract possible completions at the index of `cursor` in `expr` */ protected[this] final def completions(cursor: Int, expr: String, state0: State): List[Candidate] = { - def makeCandidate(completion: Completion)(implicit ctx: Context) = { + def makeCandidate(completion: Completion) = { val displ = completion.label new Candidate( /* value = */ displ, @@ -166,7 +166,7 @@ class ReplDriver(settings: Array[String], .typeCheck(expr, errorsAllowed = true) .map { tree => val file = SourceFile.virtual("", expr) - val unit = new CompilationUnit(file) + val unit = CompilationUnit(file)(state.context) unit.tpdTree = tree implicit val ctx = state.context.fresh.setCompilationUnit(unit) val srcPos = SourcePosition(file, Span(cursor)) From f5e226dbfe3b3954539ddea59a23ce82718b2295 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 14 Jan 2019 17:38:11 +0100 Subject: [PATCH 75/75] Don't read contents when creating a source file --- compiler/src/dotty/tools/dotc/util/SourceFile.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index e1f3c9578f77..456d6a3d53a3 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -68,7 +68,7 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends def apply(idx: Int): Char = content().apply(idx) - val length: Int = content().length + def length: Int = content().length /** true for all source files except `NoSource` */ def exists: Boolean = true