diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index 62c8bbe70cde..7794d36c87e3 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -10,14 +10,15 @@ import Types._ import Scopes._ import typer.{FrontEnd, Typer, ImportInfo, RefChecks} import Decorators._ -import io.PlainFile +import io.{AbstractFile, PlainFile} import scala.io.Codec -import util._ +import util.{Set => _, _} import reporting.Reporter import transform.TreeChecker import rewrite.Rewrites import java.io.{BufferedWriter, OutputStreamWriter} import printing.XprintMode +import typer.ImplicitRunInfo import scala.annotation.tailrec import dotty.tools.io.VirtualFile @@ -25,8 +26,7 @@ import scala.util.control.NonFatal /** A compiler run. Exports various methods to compile source files */ class Run(comp: Compiler, ictx: Context) { - - var units: List[CompilationUnit] = _ + import Run._ /** Produces the following contexts, from outermost to innermost * @@ -78,7 +78,7 @@ class Run(comp: Compiler, ictx: Context) { compileSources(sources) } catch { case NonFatal(ex) => - ctx.echo(i"exception occurred while compiling $units%, %") + ctx.echo(i"exception occurred while compiling ${ctx.runInfo.units}%, %") throw ex } @@ -90,17 +90,17 @@ class Run(comp: Compiler, ictx: Context) { */ def compileSources(sources: List[SourceFile]) = if (sources forall (_.exists)) { - units = sources map (new CompilationUnit(_)) + ctx.runInfo.units = sources map (new CompilationUnit(_)) compileUnits() } def compileUnits(us: List[CompilationUnit]): Unit = { - units = us + ctx.runInfo.units = us compileUnits() } def compileUnits(us: List[CompilationUnit], ctx: Context): Unit = { - units = us + ctx.runInfo.units = us compileUnits()(ctx) } @@ -122,16 +122,16 @@ class Run(comp: Compiler, ictx: Context) { if (phase.isRunnable) Stats.trackTime(s"$phase ms ") { val start = System.currentTimeMillis - units = phase.runOn(units) + ctx.runInfo.units = phase.runOn(ctx.runInfo.units) if (ctx.settings.Xprint.value.containsPhase(phase)) { - for (unit <- units) { + for (unit <- ctx.runInfo.units) { lastPrintedTree = printTree(lastPrintedTree)(ctx.fresh.setPhase(phase.next).setCompilationUnit(unit)) } } ctx.informTime(s"$phase ", start) Stats.record(s"total trees at end of $phase", ast.Trees.ntrees) - for (unit <- units) + for (unit <- ctx.runInfo.units) Stats.record(s"retained typed trees at end of $phase", unit.tpdTree.treeSize) } } @@ -191,3 +191,35 @@ class Run(comp: Compiler, ictx: Context) { r } } + +object Run { + /** Info that changes on each compiler run */ + class RunInfo(initctx: Context) extends ImplicitRunInfo with ConstraintRunInfo { + implicit val ctx: Context = initctx + + private[this] var myUnits: List[CompilationUnit] = _ + private[this] var myUnitsCached: List[CompilationUnit] = _ + private[this] var myFiles: Set[AbstractFile] = _ + + /** The compilation units currently being compiled, this may return different + * results over time. + */ + def units: List[CompilationUnit] = myUnits + + private[Run] def units_=(us: List[CompilationUnit]): Unit = + myUnits = us + + + /** The files currently being compiled, this may return different results over time. + * These files do not have to be source files since it's possible to compile + * from TASTY. + */ + def files: Set[AbstractFile] = { + if (myUnits ne myUnitsCached) { + myUnitsCached = myUnits + myFiles = myUnits.map(_.source.file).toSet + } + myFiles + } + } +} diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 826256b30c6f..b27c16d0eb00 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -196,7 +196,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { case tp: MethodType => def valueParam(name: TermName, info: Type): TermSymbol = { val maybeImplicit = if (tp.isImplicitMethod) Implicit else EmptyFlags - ctx.newSymbol(sym, name, TermParam | maybeImplicit, info) + ctx.newSymbol(sym, name, TermParam | maybeImplicit, info, coord = sym.coord) } val params = (tp.paramNames, tp.paramInfos).zipped.map(valueParam) val (paramss, rtp) = valueParamss(tp.instantiate(params map (_.termRef))) @@ -262,7 +262,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { val parents1 = if (parents.head.classSymbol.is(Trait)) parents.head.parents.head :: parents else parents - val cls = ctx.newNormalizedClassSymbol(owner, tpnme.ANON_FUN, Synthetic, parents1, + val cls = ctx.newNormalizedClassSymbol(owner, tpnme.ANON_CLASS, Synthetic, parents1, coord = fns.map(_.pos).reduceLeft(_ union _)) val constr = ctx.newConstructor(cls, Synthetic, Nil, Nil).entered def forwarder(fn: TermSymbol, name: TermName) = { diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index e4f3137458ef..edc1f89e5f62 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -96,6 +96,7 @@ class ScalaSettings extends Settings.SettingGroup { val YdetailedStats = BooleanSetting("-Ydetailed-stats", "show detailed internal compiler stats (needs Stats.enabled to be set to true).") val Yheartbeat = BooleanSetting("-Ydetailed-stats", "show heartbeat stack trace of compiler operations (needs Stats.enabled to be set to true).") val YprintPos = BooleanSetting("-Yprint-pos", "show tree positions.") + val YprintPosSyms = BooleanSetting("-Yprint-pos-syms", "show symbol definitions positions.") val YnoDeepSubtypes = BooleanSetting("-Yno-deep-subtypes", "throw an exception on deep subtyping call stacks.") val YnoPatmatOpt = BooleanSetting("-Yno-patmat-opt", "disable all pattern matching optimizations.") val YplainPrinter = BooleanSetting("-Yplain-printer", "Pretty-print using a plain printer.") diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintRunInfo.scala b/compiler/src/dotty/tools/dotc/core/ConstraintRunInfo.scala index 041faf911857..c2b44dd189c6 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintRunInfo.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintRunInfo.scala @@ -2,6 +2,7 @@ package dotty.tools.dotc package core import Contexts._ +import Run.RunInfo import config.Printers.typr trait ConstraintRunInfo { self: RunInfo => diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 439c04d502a0..fe5f5b6d4c62 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -14,11 +14,12 @@ import NameOps._ import Uniques._ import SymDenotations._ import Comments._ +import Run.RunInfo import util.Positions._ import ast.Trees._ import ast.untpd import util.{FreshNameCreator, SimpleIdentityMap, SourceFile, NoSource} -import typer.{Implicits, ImplicitRunInfo, ImportInfo, Inliner, NamerContextOps, SearchHistory, TypeAssigner, Typer} +import typer.{Implicits, ImportInfo, Inliner, NamerContextOps, SearchHistory, TypeAssigner, Typer} import Implicits.ContextualImplicits import config.Settings._ import config.Config @@ -675,11 +676,6 @@ object Contexts { // @sharable val theBase = new ContextBase // !!! DEBUG, so that we can use a minimal context for reporting even in code that normally cannot access a context } - /** Info that changes on each compiler run */ - class RunInfo(initctx: Context) extends ImplicitRunInfo with ConstraintRunInfo { - implicit val ctx: Context = initctx - } - class GADTMap(initBounds: SimpleIdentityMap[Symbol, TypeBounds]) extends util.DotClass { private[this] var myBounds = initBounds def setBounds(sym: Symbol, b: TypeBounds): Unit = diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 031146a80924..4b8730ead2f5 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -130,8 +130,8 @@ trait Symbols { this: Context => newClassSymbol(owner, name, flags, completer, privateWithin, coord, assocFile) } - def newRefinedClassSymbol = newCompleteClassSymbol( - ctx.owner, tpnme.REFINE_CLASS, NonMember, parents = Nil) + def newRefinedClassSymbol(coord: Coord = NoCoord) = + newCompleteClassSymbol(ctx.owner, tpnme.REFINE_CLASS, NonMember, parents = Nil, coord = coord) /** Create a module symbol with associated module class * from its non-info fields and a function producing the info @@ -288,7 +288,7 @@ trait Symbols { this: Context => val tparamBuf = new mutable.ListBuffer[TypeSymbol] val trefBuf = new mutable.ListBuffer[TypeRef] for (name <- names) { - val tparam = newNakedSymbol[TypeName](NoCoord) + val tparam = newNakedSymbol[TypeName](owner.coord) tparamBuf += tparam trefBuf += TypeRef(owner.thisType, tparam) } @@ -443,9 +443,11 @@ object Symbols { if (lastDenot == null) NoRunId else lastDenot.validFor.runId /** Does this symbol come from a currently compiled source file? */ - final def isDefinedInCurrentRun(implicit ctx: Context): Boolean = { - pos.exists && defRunId == ctx.runId - } + final def isDefinedInCurrentRun(implicit ctx: Context): Boolean = + pos.exists && defRunId == ctx.runId && { + val file = associatedFile + file != null && ctx.runInfo.files.contains(file) + } /** Is symbol valid in current run? */ final def isValidInCurrentRun(implicit ctx: Context): Boolean = @@ -539,7 +541,7 @@ object Symbols { * Overridden in ClassSymbol */ def associatedFile(implicit ctx: Context): AbstractFile = - denot.topLevelClass.symbol.associatedFile + if (lastDenot == null) null else lastDenot.topLevelClass.symbol.associatedFile /** The class file from which this class was generated, null if not applicable. */ final def binaryFile(implicit ctx: Context): AbstractFile = { @@ -563,8 +565,12 @@ object Symbols { } } - /** The position of this symbol, or NoPosition is symbol was not loaded - * from source. + /** The position of this symbol, or NoPosition 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`. */ def pos: Position = if (coord.isPosition) coord.toPosition else NoPosition diff --git a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala index 546894a9efca..6fec7b0337b1 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala @@ -41,11 +41,21 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: tpd.Tree => Option[Addr lastPos = pos } - /** True if x's position cannot be reconstructed automatically from its initialPos + /** True if x's position shouldn't be reconstructed automatically from its initialPos */ def alwaysNeedsPos(x: Positioned) = x match { - case _: WithLazyField[_] // initialPos is inaccurate for trees with lazy field - | _: Trees.PackageDef[_] => true // package defs might be split into several Tasty files + case + // initialPos 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. + // Instead, we always pickle the position of definitions. + | _: Trees.DefTree[_] + + // package defs might be split into several Tasty files + | _: Trees.PackageDef[_] => true case _ => false } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 735520ce3ac5..bd7beccf0855 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -259,7 +259,8 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi case TYPEARGtype => TypeArgRef(readType(), readType().asInstanceOf[TypeRef], readNat()) case BIND => - val sym = ctx.newSymbol(ctx.owner, readName().toTypeName, BindDefinedType, readType()) + val sym = ctx.newSymbol(ctx.owner, readName().toTypeName, BindDefinedType, readType(), + coord = coordAt(start)) registerSym(start, sym) if (currentAddr != end) readType() TypeRef(NoPrefix, sym) @@ -464,11 +465,14 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi rootd.symbol case _ => val completer = adjustIfModule(new Completer(ctx.owner, subReader(start, end))) + + val coord = coordAt(start) + if (isClass) - ctx.newClassSymbol(ctx.owner, name.asTypeName, flags, completer, privateWithin, coord = start.index) + ctx.newClassSymbol(ctx.owner, name.asTypeName, flags, completer, privateWithin, coord) else - ctx.newSymbol(ctx.owner, name, flags, completer, privateWithin, coord = start.index) - } // TODO set position somehow (but take care not to upset Symbol#isDefinedInCurrentRun) + ctx.newSymbol(ctx.owner, name, flags, completer, privateWithin, coord) + } sym.annotations = annots ctx.enter(sym) registerSym(start, sym) @@ -995,7 +999,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi case BIND => val name = readName() val info = readType() - val sym = ctx.newSymbol(ctx.owner, name, EmptyFlags, info) + val sym = ctx.newSymbol(ctx.owner, name, EmptyFlags, info, coord = coordAt(start)) registerSym(start, sym) Bind(sym, readTerm()) case ALTERNATIVE => @@ -1011,7 +1015,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi val argPats = until(end)(readTerm()) UnApply(fn, implicitArgs, argPats, patType) case REFINEDtpt => - val refineCls = ctx.newRefinedClassSymbol + val refineCls = ctx.newRefinedClassSymbol(coordAt(start)) typeAtAddr(start) = refineCls.typeRef val parent = readTpt() val refinements = readStats(refineCls, end)(localContext(refineCls)) @@ -1087,21 +1091,32 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi // ------ Setting positions ------------------------------------------------ - /** Set position of `tree` at given `addr`. */ - def setPos[T <: untpd.Tree](addr: Addr, tree: T)(implicit ctx: Context): tree.type = + /** Pickled position for `addr`. */ + def posAt(addr: Addr)(implicit ctx: Context): Position = if (ctx.mode.is(Mode.ReadPositions)) { posUnpicklerOpt match { case Some(posUnpickler) => - //println(i"setPos $tree / ${tree.getClass} at $addr to ${posUnpickler.posAt(addr)}") - val pos = posUnpickler.posAt(addr) - if (pos.exists) tree.setPosUnchecked(pos) - tree + posUnpickler.posAt(addr) case _ => - //println(i"no pos $tree") - tree + NoPosition } - } - else tree + } else NoPosition + + /** Coordinate for the symbol at `addr`. */ + def coordAt(addr: Addr)(implicit ctx: Context): Coord = { + val pos = posAt(addr) + if (pos.exists) + positionCoord(pos) + else + indexCoord(addr.index) + } + + /** 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) + tree + } } class LazyReader[T <: AnyRef](reader: TreeReader, op: TreeReader => Context => T) extends Trees.Lazy[T] { diff --git a/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala b/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala index 9b360ea1056f..08562b067e45 100644 --- a/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala +++ b/compiler/src/dotty/tools/dotc/fromtasty/TASTYRun.scala @@ -6,7 +6,7 @@ import core.Contexts._ class TASTYRun(comp: Compiler, ictx: Context) extends Run(comp, ictx) { override def compile(classNames: List[String]) = { - units = classNames.map(new TASTYCompilationUnit(_)) - compileUnits() + val units = classNames.map(new TASTYCompilationUnit(_)) + compileUnits(units) } } diff --git a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala index 6e3206ba684e..b55b34298f5f 100644 --- a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala +++ b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala @@ -226,7 +226,7 @@ class InteractiveDriver(settings: List[String]) extends Driver { run.compileSources(List(source)) run.printSummary() - val t = run.units.head.tpdTree + val t = ctx.runInfo.units.head.tpdTree cleanup(t) myOpenedTrees(uri) = topLevelClassTrees(t, source) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 311834121aa4..171ccb641e14 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1181,7 +1181,8 @@ object Parsers { t } - def ascription(t: Tree, location: Location.Value) = atPos(startOffset(t), in.skipToken()) { + def ascription(t: Tree, location: Location.Value) = atPos(startOffset(t)) { + in.skipToken() in.token match { case USCORE => val uscoreStart = in.skipToken() diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 705d94604c0b..3dabf69c2b67 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -13,6 +13,7 @@ import Trees._ import TypeApplications._ import Decorators._ import config.Config +import util.Positions._ import transform.SymUtils._ import scala.annotation.switch import language.implicitConversions @@ -630,14 +631,18 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { else if (tree.isType && !homogenizedView) txt = toText(tp) } - if (printPos && !suppressPositions) { - // add positions - val pos = - if (homogenizedView && !tree.isInstanceOf[MemberDef]) tree.pos.toSynthetic - else tree.pos - val clsStr = ""//if (tree.isType) tree.getClass.toString else "" - txt = (txt ~ "@" ~ pos.toString ~ clsStr).close - } + if (!suppressPositions) { + if (printPos) { + val pos = + if (homogenizedView && !tree.isInstanceOf[MemberDef]) tree.pos.toSynthetic + else tree.pos + val clsStr = ""//if (tree.isType) tree.getClass.toString else "" + txt = (txt ~ "@" ~ pos.toString ~ clsStr).close + } + if (ctx.settings.YprintPosSyms.value && tree.isDef) + txt = (txt ~ + s"@@(${tree.symbol.name}=" ~ tree.symbol.pos.toString ~ ")").close + } if (ctx.settings.YshowTreeIds.value) txt = (txt ~ "#" ~ tree.uniqueId.toString).close tree match { diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala index f49495c80d3f..34bc6c6e2694 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala @@ -90,8 +90,8 @@ class ExpandPrivate extends MiniPhase with IdentityDenotTransformer { thisPhase } assert(d.symbol.sourceFile != null && - isSimilar(d.symbol.sourceFile.path, ctx.source.file.path), - s"private ${d.symbol.showLocated} in ${d.symbol.sourceFile} accessed from ${ctx.owner.showLocated} in ${ctx.source.file}") + 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}") d.ensureNotPrivate.installAfter(thisPhase) } diff --git a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala index 52ef9b1d9a0a..b876a3a9b47e 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)) + DefDef(sym, superAcc.ensureConforms(sym.info.widen)).withPos(stat.pos) } return forwarder(ctx.withPhase(thisPhase.next)) } diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index 404709d2cc91..7049079e34b9 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -76,6 +76,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 superAcc = clazz.info.decl(superName) .suchThat(_.signature == superInfo.signature).symbol .orElse { @@ -83,11 +84,11 @@ class SuperAccessors(thisPhase: DenotTransformer) { val deferredOrPrivate = if (clazz is Trait) Deferred else Private val acc = ctx.newSymbol( clazz, superName, Artifact | Method | deferredOrPrivate, - superInfo, coord = sym.coord).enteredAfter(thisPhase) + 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) - else accDefs(clazz) += DefDef(acc, EmptyTree) + else accDefs(clazz) += DefDef(acc, EmptyTree).withPos(accPos) acc } @@ -181,13 +182,14 @@ class SuperAccessors(thisPhase: DenotTransformer) { } accTypeOf(sym.info) } + val accPos = sel.pos.focus val protectedAccessor = clazz.info.decl(accName).suchThat(_.signature == accType.signature).symbol orElse { val newAcc = ctx.newSymbol( - clazz, accName, Artifact | Method, accType, coord = sel.pos).enteredAfter(thisPhase) + clazz, accName, Artifact | Method, accType, coord = accPos).enteredAfter(thisPhase) val code = polyDefDef(newAcc, trefs => vrefss => { val (receiver :: _) :: tail = vrefss val base = receiver.select(sym).appliedToTypes(trefs) - (base /: tail)(Apply(_, _)) + (base /: tail)(Apply(_, _)).withPos(accPos) }) ctx.debuglog("created protected accessor: " + code) accDefs(clazz) += code @@ -233,13 +235,14 @@ class SuperAccessors(thisPhase: DenotTransformer) { MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, mt.newParamRef(0))) } val accType = accTypeOf(sym.info) + val accPos = tree.pos.focus val protectedAccessor = clazz.info.decl(accName).suchThat(_.signature == accType.signature).symbol orElse { val newAcc = ctx.newSymbol( - clazz, accName, Artifact, accType, coord = tree.pos).enteredAfter(thisPhase) + clazz, accName, Artifact, accType, coord = accPos).enteredAfter(thisPhase) val code = polyDefDef(newAcc, trefs => vrefss => { val (receiver :: _) :: tail = vrefss val base = receiver.select(sym).appliedToTypes(trefs) - (base /: vrefss)(Apply(_, _)) + (base /: vrefss)(Apply(_, _)).withPos(accPos) }) ctx.debuglog("created protected accessor: " + code) accDefs(clazz) += code @@ -265,12 +268,13 @@ class SuperAccessors(thisPhase: DenotTransformer) { val accName = ProtectedSetterName(field.name) val accType = MethodType(clazz.classInfo.selfType :: field.info :: Nil, defn.UnitType) + val accPos = tree.pos.focus val protectedAccessor = clazz.info.decl(accName).symbol orElse { val newAcc = ctx.newSymbol( - clazz, accName, Artifact, accType, coord = tree.pos).enteredAfter(thisPhase) + clazz, accName, Artifact, accType, coord = accPos).enteredAfter(thisPhase) val code = DefDef(newAcc, vrefss => { val (receiver :: value :: Nil) :: Nil = vrefss - Assign(receiver.select(field), value).withPos(tree.pos) + Assign(receiver.select(field), value).withPos(accPos) }) ctx.debuglog("created protected setter: " + code) accDefs(clazz) += code diff --git a/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala b/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala index ac87ffc91984..d2ca704d3612 100644 --- a/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala @@ -99,7 +99,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))) + DefDef(synthetic, syntheticRHS(ctx.withOwner(synthetic))).withPos(ctx.owner.pos.focus) } /** The class diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala index 828b559a47ae..d198341884d0 100644 --- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -28,8 +28,8 @@ object EtaExpansion { val name = UniqueName.fresh(prefix) val liftedType = fullyDefinedType(expr.tpe.widen, "lifted expression", expr.pos) val sym = ctx.newSymbol(ctx.owner, name, EmptyFlags, liftedType, coord = positionCoord(expr.pos)) - defs += ValDef(sym, expr) - ref(sym.termRef) + defs += ValDef(sym, expr).withPos(expr.pos.focus) + ref(sym.termRef).withPos(expr.pos) } /** Lift out common part of lhs tree taking part in an operator assignment such as diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 259fb1048cf4..1344daec0b31 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -9,6 +9,7 @@ import util.Stats.{track, record, monitored} import printing.{Showable, Printer} import printing.Texts._ import Contexts._ +import Run.RunInfo import Types._ import Flags._ import TypeErasure.{erasure, hasStableErasure} diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index e174c9a11b19..3240b3556e10 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -98,8 +98,8 @@ object Inliner { val accessorType = accessedType.ensureMethodic val accessor = accessorSymbol(tree, accessorType).asTerm val accessorDef = polyDefDef(accessor, tps => argss => - rhs(refPart, tps, argss)) - val accessorRef = ref(accessor).appliedToTypeTrees(targs).appliedToArgss(argss) + rhs(refPart, tps, argss).withPos(tree.pos.focus)) + val accessorRef = ref(accessor).appliedToTypeTrees(targs).appliedToArgss(argss).withPos(tree.pos) (accessorDef, accessorRef) } else { // Hard case: Reference needs to go via a dynamic prefix @@ -135,11 +135,14 @@ object Inliner { val accessor = accessorSymbol(tree, accessorType).asTerm val accessorDef = polyDefDef(accessor, tps => argss => - rhs(argss.head.head.select(refPart.symbol), tps.drop(localRefs.length), argss.tail)) + rhs(argss.head.head.select(refPart.symbol), tps.drop(localRefs.length), argss.tail) + .withPos(tree.pos.focus) + ) val accessorRef = ref(accessor) .appliedToTypeTrees(localRefs.map(TypeTree(_)) ++ targs) .appliedToArgss((qual :: Nil) :: argss) + .withPos(tree.pos) (accessorDef, accessorRef) } accessors += accessorDef @@ -168,8 +171,8 @@ object Inliner { // Draft code (incomplete): // // val accessor = accessorSymbol(tree, TypeAlias(tree.tpe)).asType - // myAccessors += TypeDef(accessor) - // ref(accessor) + // myAccessors += TypeDef(accessor).withPos(tree.pos.focus) + // ref(accessor).withPos(tree.pos) // tree } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 46f96d7d3354..1519780ea8be 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -759,7 +759,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit args match { case ValDef(_, _, _) :: _ => typedDependent(args.asInstanceOf[List[ValDef]])( - ctx.fresh.setOwner(ctx.newRefinedClassSymbol).setNewScope) + ctx.fresh.setOwner(ctx.newRefinedClassSymbol(tree.pos)).setNewScope) case _ => typed(cpy.AppliedTypeTree(tree)(untpd.TypeTree(funCls.typeRef), args :+ body), pt) } diff --git a/compiler/test/dotc/tests.scala b/compiler/test/dotc/tests.scala index 6de3a86d2054..09c12deee091 100644 --- a/compiler/test/dotc/tests.scala +++ b/compiler/test/dotc/tests.scala @@ -73,7 +73,7 @@ class tests extends CompilerTest { else List("-Ycheck:tailrec,resolveSuper,mixin,elimStaticThis,labelDef,simplify") } ++ checkOptions ++ classPath - val testPickling = List("-Xprint-types", "-Ytest-pickler", "-Ystop-after:pickler", "-Yprint-pos") + val testPickling = List("-Xprint-types", "-Ytest-pickler", "-Ystop-after:pickler", "-Yprint-pos", "-Yprint-pos-syms") val twice = List("#runs", "2") val staleSymbolError: List[String] = List() diff --git a/compiler/test/dotty/tools/dotc/CompilerTest.scala b/compiler/test/dotty/tools/dotc/CompilerTest.scala index d6c2bbbc80f1..259e1487c1a7 100644 --- a/compiler/test/dotty/tools/dotc/CompilerTest.scala +++ b/compiler/test/dotty/tools/dotc/CompilerTest.scala @@ -104,7 +104,7 @@ abstract class CompilerTest { else (fp, jfp) } val expErrors = expectedErrors(filePaths.toList) - (filePaths, javaFilePaths, normArgs, expErrors) + (filePaths.sorted, javaFilePaths.sorted, normArgs, expErrors) } if (runTest) log(s"WARNING: run tests can only be run by partest, JUnit just verifies compilation: $prefix$dirName") diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index 903a098c34d0..1c82ef2bd12d 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -151,7 +151,8 @@ trait ParallelTesting extends RunnerOrchestration { self => ) extends TestSource { /** Get the files grouped by `_X` as a list of groups, files missing this - * suffix will be put into the same group + * suffix will be put into the same group. + * Files in each group are sorted alphabetically. * * Filters out all none source files */ @@ -170,7 +171,7 @@ trait ParallelTesting extends RunnerOrchestration { self => .toOption .getOrElse("") } - .toList.sortBy(_._1).map(_._2.filter(isSourceFile)) + .toList.sortBy(_._1).map(_._2.filter(isSourceFile).sorted) } /** Each `Test` takes the `testSources` and performs the compilation and assertions diff --git a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala index 75c2f6c87089..23b4479f9fd4 100644 --- a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala +++ b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala @@ -54,7 +54,8 @@ object TestConfiguration { val picklingOptions = defaultUnoptimised and ( "-Xprint-types", "-Ytest-pickler", - "-Yprint-pos" + "-Yprint-pos", + "-Yprint-pos-syms" ) val scala2Mode = defaultOptions and "-language:Scala2" val explicitUTF8 = defaultOptions and ("-encoding", "UTF8") diff --git a/tests/neg/checkNoConflict/A1.scala b/tests/neg/checkNoConflict/A1.scala new file mode 100644 index 000000000000..f86f19f5009e --- /dev/null +++ b/tests/neg/checkNoConflict/A1.scala @@ -0,0 +1,2 @@ +package foo +class A diff --git a/tests/neg/checkNoConflict/A2.scala b/tests/neg/checkNoConflict/A2.scala new file mode 100644 index 000000000000..68cea1f71ab2 --- /dev/null +++ b/tests/neg/checkNoConflict/A2.scala @@ -0,0 +1,2 @@ +package foo +class A // error: class A in package foo has already been compiled once during this run diff --git a/tests/pos-from-tasty/anonBridge.scala b/tests/pos-from-tasty/anonBridge.scala new file mode 100644 index 000000000000..c11a46a8904f --- /dev/null +++ b/tests/pos-from-tasty/anonBridge.scala @@ -0,0 +1,3 @@ +class Test { + val x: PartialFunction[Int, Int] = { case x: Int => x } +}