Skip to content

Commit 66874ed

Browse files
Merge branch 'master' into ycheck-patterns
2 parents a506b50 + a09f385 commit 66874ed

File tree

2,327 files changed

+3709
-2869
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

2,327 files changed

+3709
-2869
lines changed

AUTHORS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ The majority of the dotty codebase is new code, with the exception of the compon
3434
> The lexical and syntactic analysis components were adapted from the current Scala compiler. They were originally authored by Martin Odersky,
3535
> Burak Emir, Paul Phillips, Lex Spoon, Sean McDirmid and others.
3636
37+
`dotty.tools.dotc.profile`
38+
39+
> The per-phase profiling support is taken mostly as is from [scala/scala](https://github.com/scala/scala).
40+
> The original author was Mike Skells.
41+
3742
`dotty.tools.dotc.reporting`
3843

3944
> Adapted from [scala/scala](https://github.com/scala/scala) with some heavy modifications. They were originally authored by Matthias Zenger, Martin Odersky, and others.

compiler/sjs/backend/sjs/JSCodeGen.scala

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ class JSCodeGen()(implicit ctx: Context) {
793793
throw new FatalError(s"Assignment to static member ${sym.fullName} not supported")
794794
val genRhs = genExpr(rhs)
795795
val lhs = lhs0 match {
796-
case lhs: Ident => desugarIdent(lhs).getOrElse(lhs)
796+
case lhs: Ident => desugarIdent(lhs)
797797
case lhs => lhs
798798
}
799799
lhs match {
@@ -850,21 +850,6 @@ class JSCodeGen()(implicit ctx: Context) {
850850
}
851851
} // end of genStatOrExpr()
852852

853-
// !!! DUPLICATE code with DottyBackendInterface
854-
private def desugarIdent(i: Ident): Option[Select] = {
855-
i.tpe match {
856-
case TermRef(prefix: TermRef, name) =>
857-
Some(tpd.ref(prefix).select(i.symbol))
858-
case TermRef(prefix: ThisType, name) =>
859-
Some(tpd.This(prefix.cls).select(i.symbol))
860-
/*case TermRef(NoPrefix, name) =>
861-
if (i.symbol is Method) Some(This(i.symbol.topLevelClass).select(i.symbol)) // workaround #342 todo: remove after fixed
862-
else None*/
863-
case _ =>
864-
None
865-
}
866-
}
867-
868853
private def qualifierOf(fun: Tree): Tree = fun match {
869854
case fun: Ident =>
870855
fun.tpe match {
@@ -907,7 +892,7 @@ class JSCodeGen()(implicit ctx: Context) {
907892
val sym = tree.fun.symbol
908893

909894
val fun = tree.fun match {
910-
case fun: Ident => desugarIdent(fun).getOrElse(fun)
895+
case fun: Ident => desugarIdent(fun)
911896
case fun => fun
912897
}
913898

@@ -1571,7 +1556,7 @@ class JSCodeGen()(implicit ctx: Context) {
15711556
implicit val pos = tree.pos
15721557

15731558
val fun = tree.fun match {
1574-
case fun: Ident => desugarIdent(fun).get
1559+
case fun: Ident => desugarIdent(fun).asInstanceOf[Select]
15751560
case fun: Select => fun
15761561
}
15771562
val receiver = fun.qualifier

compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -444,16 +444,12 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
444444
def desugarIdent(i: Ident): Option[tpd.Select] = {
445445
var found = desugared.get(i.tpe)
446446
if (found == null) {
447-
i.tpe match {
448-
case TermRef(prefix: TermRef, _) =>
449-
found = tpd.ref(prefix).select(i.symbol)
450-
case TermRef(prefix: ThisType, _) =>
451-
found = tpd.This(prefix.cls).select(i.symbol)
452-
case TermRef(NoPrefix, _) =>
453-
if (i.symbol is Flags.Method) found = This(i.symbol.topLevelClass).select(i.symbol) // workaround #342 todo: remove after fixed
447+
tpd.desugarIdent(i) match {
448+
case sel: tpd.Select =>
449+
desugared.put(i.tpe, sel)
450+
found = sel
454451
case _ =>
455452
}
456-
if (found != null) desugared.put(i.tpe, found)
457453
}
458454
if (found == null) None else Some(found)
459455
}
@@ -900,8 +896,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
900896

901897
def decls: List[Symbol] = tp.decls.toList
902898

903-
def members: List[Symbol] =
904-
tp.memberDenots(takeAllFilter, (name, buf) => buf ++= tp.member(name).alternatives).map(_.symbol).toList
899+
def members: List[Symbol] = tp.allMembers.map(_.symbol).toList
905900

906901
def typeSymbol: Symbol = tp.widenDealias.typeSymbol
907902

compiler/src/dotty/tools/dotc/CompilationUnit.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ object CompilationUnit {
3535
def mkCompilationUnit(clsd: ClassDenotation, unpickled: Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit =
3636
mkCompilationUnit(new SourceFile(clsd.symbol.associatedFile, Seq()), unpickled, forceTrees)
3737

38-
/** Make a compilation unit the given unpickled tree */
38+
/** Make a compilation unit, given picked bytes and unpickled tree */
3939
def mkCompilationUnit(source: SourceFile, unpickled: Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit = {
4040
assert(!unpickled.isEmpty, unpickled)
4141
val unit1 = new CompilationUnit(source)

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,11 @@ class Compiler {
111111
// Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
112112
new ElimStaticThis) :: // Replace `this` references to static objects by global identifiers
113113
List(new Flatten, // Lift all inner classes to package scope
114-
new RestoreScopes, // Repair scopes rendered invalid by moving definitions in prior phases of the group
115114
new RenameLifted, // Renames lifted classes to local numbering scheme
116115
new TransformWildcards, // Replace wildcards with default values
117116
new MoveStatics, // Move static methods to companion classes
118117
new ExpandPrivate, // Widen private definitions accessed from nested classes
118+
new RestoreScopes, // Repair scopes rendered invalid by moving definitions in prior phases of the group
119119
new SelectStatic, // get rid of selects that would be compiled into GetStatic
120120
new CollectEntryPoints, // Find classes with main methods
121121
new CollectSuperCalls, // Find classes that are called with super

compiler/src/dotty/tools/dotc/Run.scala

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,26 @@ import Symbols._
88
import Phases._
99
import Types._
1010
import Scopes._
11-
import typer.{FrontEnd, Typer, ImportInfo, RefChecks}
11+
import typer.{FrontEnd, ImportInfo, RefChecks, Typer}
1212
import Decorators._
1313
import io.{AbstractFile, PlainFile}
14+
1415
import scala.io.Codec
1516
import util.{Set => _, _}
1617
import reporting.Reporter
1718
import transform.TreeChecker
1819
import rewrite.Rewrites
1920
import java.io.{BufferedWriter, OutputStreamWriter}
21+
22+
import dotty.tools.dotc.profile.Profiler
2023
import printing.XprintMode
2124
import parsing.Parsers.Parser
2225
import typer.ImplicitRunInfo
2326
import collection.mutable
2427

2528
import scala.annotation.tailrec
2629
import dotty.tools.io.VirtualFile
30+
2731
import scala.util.control.NonFatal
2832

2933
/** A compiler run. Exports various methods to compile source files */
@@ -57,6 +61,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
5761
(start.setRun(this) /: defn.RootImportFns)(addImport)
5862
}
5963

64+
private[this] var compiling = false
65+
6066
private[this] var myCtx = rootContext(ictx)
6167

6268
/** The context created for this run */
@@ -68,8 +74,6 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
6874
private[this] var myUnits: List[CompilationUnit] = _
6975
private[this] var myUnitsCached: List[CompilationUnit] = _
7076
private[this] var myFiles: Set[AbstractFile] = _
71-
private[this] val myLateUnits = mutable.ListBuffer[CompilationUnit]()
72-
private[this] var myLateFiles = mutable.Set[AbstractFile]()
7377

7478
/** The compilation units currently being compiled, this may return different
7579
* results over time.
@@ -91,11 +95,11 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
9195
myFiles
9296
}
9397

94-
/** Units that are added from source completers but that are not compiled in current run. */
95-
def lateUnits: List[CompilationUnit] = myLateUnits.toList
98+
/** The source files of all late entered symbols, as a set */
99+
private[this] var lateFiles = mutable.Set[AbstractFile]()
96100

97-
/** The source files of all late units, as a set */
98-
def lateFiles: collection.Set[AbstractFile] = myLateFiles
101+
/** Actions that need to be performed at the end of the current compilation run */
102+
private[this] var finalizeActions = mutable.ListBuffer[() => Unit]()
99103

100104
def getSource(fileName: String): SourceFile = {
101105
val f = new PlainFile(io.Path(fileName))
@@ -144,6 +148,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
144148

145149
protected def compileUnits()(implicit ctx: Context) = Stats.maybeMonitored {
146150
ctx.checkSingleThreaded()
151+
compiling = true
147152

148153
// If testing pickler, make sure to stop after pickling phase:
149154
val stopAfter =
@@ -156,11 +161,15 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
156161

157162
def runPhases(implicit ctx: Context) = {
158163
var lastPrintedTree: PrintedTree = NoPrintedTree
164+
val profiler = ctx.profiler
165+
159166
for (phase <- ctx.allPhases)
160167
if (phase.isRunnable)
161168
Stats.trackTime(s"$phase ms ") {
162169
val start = System.currentTimeMillis
170+
val profileBefore = profiler.beforePhase(phase)
163171
units = phase.runOn(units)
172+
profiler.afterPhase(phase, profileBefore)
164173
if (ctx.settings.Xprint.value.containsPhase(phase)) {
165174
for (unit <- units) {
166175
lastPrintedTree =
@@ -172,30 +181,40 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
172181
for (unit <- units)
173182
Stats.record(s"retained typed trees at end of $phase", unit.tpdTree.treeSize)
174183
}
184+
185+
profiler.finished()
175186
}
176187

177188
val runCtx = ctx.fresh
189+
runCtx.setProfiler(Profiler())
178190
ctx.phases.foreach(_.initContext(runCtx))
179191
runPhases(runCtx)
180192
if (!ctx.reporter.hasErrors) Rewrites.writeBack()
193+
while (finalizeActions.nonEmpty) {
194+
val action = finalizeActions.remove(0)
195+
action()
196+
}
197+
compiling = false
181198
}
182199

183200
/** Enter top-level definitions of classes and objects contain in Scala source file `file`.
184201
* The newly added symbols replace any previously entered symbols.
202+
* If `typeCheck = true`, also run typer on the compilation unit.
185203
*/
186-
def enterRoots(file: AbstractFile)(implicit ctx: Context): Unit =
204+
def lateCompile(file: AbstractFile, typeCheck: Boolean)(implicit ctx: Context): Unit =
187205
if (!files.contains(file) && !lateFiles.contains(file)) {
206+
lateFiles += file
188207
val unit = new CompilationUnit(getSource(file.path))
189-
myLateUnits += unit
190-
myLateFiles += file
191-
enterRoots(unit)(runContext.fresh.setCompilationUnit(unit))
208+
def process()(implicit ctx: Context) = {
209+
unit.untpdTree = new Parser(unit.source).parse()
210+
ctx.typer.lateEnter(unit.untpdTree)
211+
def typeCheckUnit() = unit.tpdTree = ctx.typer.typedExpr(unit.untpdTree)
212+
if (typeCheck)
213+
if (compiling) finalizeActions += (() => typeCheckUnit()) else typeCheckUnit()
214+
}
215+
process()(runContext.fresh.setCompilationUnit(unit))
192216
}
193217

194-
private def enterRoots(unit: CompilationUnit)(implicit ctx: Context): Unit = {
195-
unit.untpdTree = new Parser(unit.source).parse()
196-
ctx.typer.lateEnter(unit.untpdTree)
197-
}
198-
199218
private sealed trait PrintedTree
200219
private /*final*/ case class SomePrintedTree(phase: String, tree: String) extends PrintedTree
201220
private object NoPrintedTree extends PrintedTree

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

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,21 @@ object desugar {
341341
(if (args.isEmpty) tycon else AppliedTypeTree(tycon, args))
342342
.withPos(cdef.pos.startPos)
343343

344-
def appliedRef(tycon: Tree, tparams: List[TypeDef] = constrTparams) =
345-
appliedTypeTree(tycon, tparams map refOfDef)
344+
def appliedRef(tycon: Tree, tparams: List[TypeDef] = constrTparams, widenHK: Boolean = false) = {
345+
val targs = for (tparam <- tparams) yield {
346+
val targ = refOfDef(tparam)
347+
def fullyApplied(tparam: Tree): Tree = tparam match {
348+
case TypeDef(_, LambdaTypeTree(tparams, body)) =>
349+
AppliedTypeTree(targ, tparams.map(_ => TypeBoundsTree(EmptyTree, EmptyTree)))
350+
case TypeDef(_, rhs: DerivedTypeTree) =>
351+
fullyApplied(rhs.watched)
352+
case _ =>
353+
targ
354+
}
355+
if (widenHK) fullyApplied(tparam) else targ
356+
}
357+
appliedTypeTree(tycon, targs)
358+
}
346359

347360
// a reference to the class type bound by `cdef`, with type parameters coming from the constructor
348361
val classTypeRef = appliedRef(classTycon)
@@ -431,12 +444,16 @@ object desugar {
431444
//
432445
// implicit def eqInstance[T1$1, ..., Tn$1, T1$2, ..., Tn$2](implicit
433446
// ev1: Eq[T1$1, T1$2], ..., evn: Eq[Tn$1, Tn$2]])
434-
// : Eq[C[T1$1, ..., Tn$1], C[T1$2, ..., Tn$2]] = Eq
447+
// : Eq[C[T1$, ..., Tn$1], C[T1$2, ..., Tn$2]] = Eq
448+
//
449+
// If any of the T_i are higher-kinded, say `Ti[X1 >: L1 <: U1, ..., Xm >: Lm <: Um]`,
450+
// the corresponding type parameters for $ev_i are `Ti$1[_, ..., _], Ti$2[_, ..., _]`
451+
// (with m underscores `_`).
435452
def eqInstance = {
436453
val leftParams = constrTparams.map(derivedTypeParam(_, "$1"))
437454
val rightParams = constrTparams.map(derivedTypeParam(_, "$2"))
438455
val subInstances = (leftParams, rightParams).zipped.map((param1, param2) =>
439-
appliedRef(ref(defn.EqType), List(param1, param2)))
456+
appliedRef(ref(defn.EqType), List(param1, param2), widenHK = true))
440457
DefDef(
441458
name = nme.eqInstance,
442459
tparams = leftParams ++ rightParams,
@@ -725,6 +742,31 @@ object desugar {
725742
tree
726743
}
727744

745+
/** Translate infix operation expression
746+
*
747+
* l op r ==> l.op(r) if op is left-associative
748+
* ==> r.op(l) if op is right-associative
749+
*/
750+
def binop(left: Tree, op: Ident, right: Tree)(implicit ctx: Context): Apply = {
751+
def assignToNamedArg(arg: Tree) = arg match {
752+
case Assign(Ident(name), rhs) => cpy.NamedArg(arg)(name, rhs)
753+
case _ => arg
754+
}
755+
def makeOp(fn: Tree, arg: Tree, selectPos: Position) = {
756+
val args: List[Tree] = arg match {
757+
case Parens(arg) => assignToNamedArg(arg) :: Nil
758+
case Tuple(args) => args.mapConserve(assignToNamedArg)
759+
case _ => arg :: Nil
760+
}
761+
Apply(Select(fn, op.name).withPos(selectPos), args)
762+
}
763+
764+
if (isLeftAssoc(op.name))
765+
makeOp(left, right, Position(left.pos.start, op.pos.end, op.pos.start))
766+
else
767+
makeOp(right, left, Position(op.pos.start, right.pos.end))
768+
}
769+
728770
/** Make closure corresponding to function.
729771
* params => body
730772
* ==>
@@ -832,30 +874,6 @@ object desugar {
832874
Block(ldef, call)
833875
}
834876

835-
/** Translate infix operation expression left op right
836-
*/
837-
def makeBinop(left: Tree, op: Ident, right: Tree): Tree = {
838-
def assignToNamedArg(arg: Tree) = arg match {
839-
case Assign(Ident(name), rhs) => cpy.NamedArg(arg)(name, rhs)
840-
case _ => arg
841-
}
842-
if (isLeftAssoc(op.name)) {
843-
val args: List[Tree] = right match {
844-
case Parens(arg) => assignToNamedArg(arg) :: Nil
845-
case Tuple(args) => args mapConserve assignToNamedArg
846-
case _ => right :: Nil
847-
}
848-
val selectPos = Position(left.pos.start, op.pos.end, op.pos.start)
849-
Apply(Select(left, op.name).withPos(selectPos), args)
850-
} else {
851-
val x = UniqueName.fresh()
852-
val selectPos = Position(op.pos.start, right.pos.end, op.pos.start)
853-
new InfixOpBlock(
854-
ValDef(x, TypeTree(), left).withMods(synthetic),
855-
Apply(Select(right, op.name).withPos(selectPos), Ident(x).withPos(left.pos)))
856-
}
857-
}
858-
859877
/** Create tree for for-comprehension `<for (enums) do body>` or
860878
* `<for (enums) yield body>` where mapName and flatMapName are chosen
861879
* corresponding to whether this is a for-do or a for-yield.
@@ -1066,10 +1084,10 @@ object desugar {
10661084
if (!op.isBackquoted && op.name == tpnme.raw.AMP) AndTypeTree(l, r) // l & r
10671085
else if (!op.isBackquoted && op.name == tpnme.raw.BAR) OrTypeTree(l, r) // l | r
10681086
else AppliedTypeTree(op, l :: r :: Nil) // op[l, r]
1069-
else if (ctx.mode is Mode.Pattern)
1087+
else {
1088+
assert(ctx.mode is Mode.Pattern) // expressions are handled separately by `binop`
10701089
Apply(op, l :: r :: Nil) // op(l, r)
1071-
else // l.op(r), or val x = r; l.op(x), plus handle named args specially
1072-
makeBinop(l, op, r)
1090+
}
10731091
case PostfixOp(t, op) =>
10741092
if ((ctx.mode is Mode.Type) && !op.isBackquoted && op.name == tpnme.raw.STAR) {
10751093
val seqType = if (ctx.compilationUnit.isJava) defn.ArrayType else defn.SeqType

0 commit comments

Comments
 (0)