Skip to content

Commit a7592b2

Browse files
Merge branch 'master' into cleanup-tests
2 parents 133b8ff + d2d7d99 commit a7592b2

Some content is hidden

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

44 files changed

+1207
-1146
lines changed

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

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,31 @@ object desugar {
725725
tree
726726
}
727727

728+
/** Translate infix operation expression
729+
*
730+
* l op r ==> l.op(r) if op is left-associative
731+
* ==> r.op(l) if op is right-associative
732+
*/
733+
def binop(left: Tree, op: Ident, right: Tree)(implicit ctx: Context): Apply = {
734+
def assignToNamedArg(arg: Tree) = arg match {
735+
case Assign(Ident(name), rhs) => cpy.NamedArg(arg)(name, rhs)
736+
case _ => arg
737+
}
738+
def makeOp(fn: Tree, arg: Tree, selectPos: Position) = {
739+
val args: List[Tree] = arg match {
740+
case Parens(arg) => assignToNamedArg(arg) :: Nil
741+
case Tuple(args) => args.mapConserve(assignToNamedArg)
742+
case _ => arg :: Nil
743+
}
744+
Apply(Select(fn, op.name).withPos(selectPos), args)
745+
}
746+
747+
if (isLeftAssoc(op.name))
748+
makeOp(left, right, Position(left.pos.start, op.pos.end, op.pos.start))
749+
else
750+
makeOp(right, left, Position(op.pos.start, right.pos.end))
751+
}
752+
728753
/** Make closure corresponding to function.
729754
* params => body
730755
* ==>
@@ -832,30 +857,6 @@ object desugar {
832857
Block(ldef, call)
833858
}
834859

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-
859860
/** Create tree for for-comprehension `<for (enums) do body>` or
860861
* `<for (enums) yield body>` where mapName and flatMapName are chosen
861862
* corresponding to whether this is a for-do or a for-yield.
@@ -1066,10 +1067,10 @@ object desugar {
10661067
if (!op.isBackquoted && op.name == tpnme.raw.AMP) AndTypeTree(l, r) // l & r
10671068
else if (!op.isBackquoted && op.name == tpnme.raw.BAR) OrTypeTree(l, r) // l | r
10681069
else AppliedTypeTree(op, l :: r :: Nil) // op[l, r]
1069-
else if (ctx.mode is Mode.Pattern)
1070+
else {
1071+
assert(ctx.mode is Mode.Pattern) // expressions are handled separately by `binop`
10701072
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)
1073+
}
10731074
case PostfixOp(t, op) =>
10741075
if ((ctx.mode is Mode.Type) && !op.isBackquoted && op.name == tpnme.raw.STAR) {
10751076
val seqType = if (ctx.compilationUnit.isJava) defn.ArrayType else defn.SeqType

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

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,9 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
311311
import tpd._
312312

313313
/** The purity level of this statement.
314-
* @return pure if statement has no side effects
315-
* idempotent if running the statement a second time has no side effects
316-
* impure otherwise
314+
* @return Pure if statement has no side effects
315+
* Idempotent if running the statement a second time has no side effects
316+
* Impure otherwise
317317
*/
318318
private def statPurity(tree: Tree)(implicit ctx: Context): PurityLevel = unsplice(tree) match {
319319
case EmptyTree
@@ -322,17 +322,18 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
322322
| DefDef(_, _, _, _, _) =>
323323
Pure
324324
case vdef @ ValDef(_, _, _) =>
325-
if (vdef.symbol.flags is Mutable) Impure else exprPurity(vdef.rhs)
325+
if (vdef.symbol.flags is Mutable) Impure else exprPurity(vdef.rhs) `min` Pure
326326
case _ =>
327327
Impure
328328
// TODO: It seem like this should be exprPurity(tree)
329329
// But if we do that the repl/vars test break. Need to figure out why that's the case.
330330
}
331331

332332
/** The purity level of this expression.
333-
* @return pure if expression has no side effects
334-
* idempotent if running the expression a second time has no side effects
335-
* impure otherwise
333+
* @return SimplyPure if expression has no side effects and cannot contain local definitions
334+
* Pure if expression has no side effects
335+
* Idempotent if running the expression a second time has no side effects
336+
* Impure otherwise
336337
*
337338
* Note that purity and idempotency are different. References to modules and lazy
338339
* vals are impure (side-effecting) both because side-effecting code may be executed and because the first reference
@@ -345,7 +346,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
345346
| Super(_, _)
346347
| Literal(_)
347348
| Closure(_, _, _) =>
348-
Pure
349+
SimplyPure
349350
case Ident(_) =>
350351
refPurity(tree)
351352
case Select(qual, _) =>
@@ -366,7 +367,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
366367
if (args.isEmpty && fn.symbol.is(Stable)) exprPurity(fn)
367368
else if (tree.tpe.isInstanceOf[ConstantType] && isKnownPureOp(tree.symbol))
368369
// A constant expression with pure arguments is pure.
369-
minOf(exprPurity(fn), args.map(exprPurity))
370+
minOf(exprPurity(fn), args.map(exprPurity)) `min` Pure
370371
else Impure
371372
case Typed(expr, _) =>
372373
exprPurity(expr)
@@ -382,25 +383,26 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
382383

383384
private def minOf(l0: PurityLevel, ls: List[PurityLevel]) = (l0 /: ls)(_ min _)
384385

385-
def isPureExpr(tree: Tree)(implicit ctx: Context) = exprPurity(tree) == Pure
386+
def isSimplyPure(tree: Tree)(implicit ctx: Context) = exprPurity(tree) == SimplyPure
387+
def isPureExpr(tree: Tree)(implicit ctx: Context) = exprPurity(tree) >= Pure
386388
def isIdempotentExpr(tree: Tree)(implicit ctx: Context) = exprPurity(tree) >= Idempotent
387389

388390
/** The purity level of this reference.
389391
* @return
390-
* pure if reference is (nonlazy and stable) or to a parameterized function
391-
* idempotent if reference is lazy and stable
392-
* impure otherwise
392+
* SimplyPure if reference is (nonlazy and stable) or to a parameterized function
393+
* Idempotent if reference is lazy and stable
394+
* Impure otherwise
393395
* @DarkDimius: need to make sure that lazy accessor methods have Lazy and Stable
394396
* flags set.
395397
*/
396398
private def refPurity(tree: Tree)(implicit ctx: Context): PurityLevel =
397-
if (!tree.tpe.widen.isParameterless) Pure
399+
if (!tree.tpe.widen.isParameterless) SimplyPure
398400
else if (!tree.symbol.isStable) Impure
399401
else if (tree.symbol.is(Lazy)) Idempotent // TODO add Module flag, sinxce Module vals or not Lazy from the start.
400-
else Pure
402+
else SimplyPure
401403

402404
def isPureRef(tree: Tree)(implicit ctx: Context) =
403-
refPurity(tree) == Pure
405+
refPurity(tree) == SimplyPure
404406
def isIdempotentRef(tree: Tree)(implicit ctx: Context) =
405407
refPurity(tree) >= Idempotent
406408

@@ -554,6 +556,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
554556
val acc = new TreeAccumulator[List[Symbol]] {
555557
def apply(syms: List[Symbol], tree: Tree)(implicit ctx: Context) = tree match {
556558
case Bind(_, body) => apply(tree.symbol :: syms, body)
559+
case Annotated(tree, id @ Ident(tpnme.BOUNDTYPE_ANNOT)) => apply(id.symbol :: syms, tree)
557560
case _ => foldOver(syms, tree)
558561
}
559562
}
@@ -724,6 +727,7 @@ object TreeInfo {
724727
def min(that: PurityLevel) = new PurityLevel(x min that.x)
725728
}
726729

730+
val SimplyPure = new PurityLevel(3)
727731
val Pure = new PurityLevel(2)
728732
val Idempotent = new PurityLevel(1)
729733
val Impure = new PurityLevel(0)

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

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Types._, Contexts._, Constants._, Names._, Flags._
77
import SymDenotations._, Symbols._, Annotations._, Trees._, Symbols._
88
import Denotations._, Decorators._
99
import dotty.tools.dotc.transform.SymUtils._
10+
import core.tasty.TreePickler.Hole
1011

1112
/** A map that applies three functions and a substitution together to a tree and
1213
* makes sure they are coordinated so that the result is well-typed. The functions are
@@ -115,6 +116,8 @@ class TreeTypeMap(
115116
val guard1 = tmap.transform(guard)
116117
val rhs1 = tmap.transform(rhs)
117118
cpy.CaseDef(cdef)(pat1, guard1, rhs1)
119+
case Hole(n, args) =>
120+
Hole(n, args.mapConserve(transform)).withPos(tree.pos).withType(mapType(tree.tpe))
118121
case tree1 =>
119122
super.transform(tree1)
120123
}
@@ -154,7 +157,7 @@ class TreeTypeMap(
154157
assert(!to.exists(substFrom contains _))
155158
assert(!from.exists(newOwners contains _))
156159
assert(!to.exists(oldOwners contains _))
157-
newMap(
160+
new TreeTypeMap(
158161
typeMap,
159162
treeMap,
160163
from ++ oldOwners,
@@ -163,16 +166,6 @@ class TreeTypeMap(
163166
to ++ substTo)
164167
}
165168

166-
/** A new map of the same class this one */
167-
protected def newMap(
168-
typeMap: Type => Type,
169-
treeMap: Tree => Tree,
170-
oldOwners: List[Symbol],
171-
newOwners: List[Symbol],
172-
substFrom: List[Symbol],
173-
substTo: List[Symbol])(implicit ctx: Context) =
174-
new TreeTypeMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo)
175-
176169
/** Apply `typeMap` and `ownerMap` to given symbols `syms`
177170
* and return a treemap that contains the substitution
178171
* between original and mapped symbols.

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

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
9696
override def isEmpty = true
9797
}
9898

99-
/** A block arising from a right-associative infix operation, where, e.g.
100-
*
101-
* a +: b
102-
*
103-
* is expanded to
104-
*
105-
* { val x = a; b.+:(x) }
106-
*/
107-
class InfixOpBlock(leftOperand: Tree, rightOp: Tree) extends Block(leftOperand :: Nil, rightOp)
108-
10999
/** A block generated by the XML parser, only treated specially by
110100
* `Positioned#checkPos` */
111101
class XMLBlock(stats: List[Tree], expr: Tree) extends Block(stats, expr)

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class ScalaSettings extends Settings.SettingGroup {
7777
val Ydebug = BooleanSetting("-Ydebug", "Increase the quantity of debugging output.")
7878
val YdebugTrace = BooleanSetting("-Ydebug-trace", "Trace core operations")
7979
val YdebugFlags = BooleanSetting("-Ydebug-flags", "Print all flags of definitions")
80+
val YdebugMissingRefs = BooleanSetting("-Ydebug-missing-refs", "Print a stacktrace when a required symbol is missing")
8081
val YdebugNames = BooleanSetting("-Ydebug-names", "Show internal representation of names")
8182
val YdebugOwners = BooleanSetting("-Ydebug-owners", "Print all owners of definitions (requires -Yprint-syms)")
8283
val YtermConflict = ChoiceSetting("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error")

compiler/src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ object Denotations {
277277
disambiguate(p) match {
278278
case m @ MissingRef(ownerd, name) =>
279279
if (generateStubs) {
280-
m.ex.printStackTrace()
280+
if (ctx.settings.YdebugMissingRefs.value) m.ex.printStackTrace()
281281
ctx.newStubSymbol(ownerd.symbol, name, source)
282282
}
283283
else NoSymbol
@@ -1115,7 +1115,7 @@ object Denotations {
11151115
* Produced by staticRef, consumed by requiredSymbol.
11161116
*/
11171117
case class MissingRef(val owner: SingleDenotation, name: Name)(implicit ctx: Context) extends ErrorDenotation {
1118-
val ex: Exception = new Exception
1118+
val ex: Exception = new Exception // DEBUG
11191119
}
11201120

11211121
/** An error denotation that provides more info about alternatives

compiler/src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ object StdNames {
143143
val INITIALIZER_PREFIX: N = "initial$"
144144
val COMPANION_MODULE_METHOD: N = "companion$module"
145145
val COMPANION_CLASS_METHOD: N = "companion$class"
146+
val BOUNDTYPE_ANNOT: N = "$boundType$"
146147
val QUOTE: N = "'"
147148
val TYPE_QUOTE: N = "type_'"
148149
val TRAIT_SETTER_SEPARATOR: N = str.TRAIT_SETTER_SEPARATOR

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package core
55
import Periods._, Contexts._, Symbols._, Denotations._, Names._, NameOps._, Annotations._
66
import Types._, Flags._, Decorators._, DenotTransformers._, StdNames._, Scopes._, Comments._
77
import NameOps._, NameKinds._, Phases._
8+
import TypeApplications.TypeParamInfo
89
import Scopes.Scope
910
import collection.mutable
1011
import collection.BitSet
@@ -1915,6 +1916,11 @@ object SymDenotations {
19151916
override def complete(denot: SymDenotation)(implicit ctx: Context) = self.complete(denot)
19161917
}
19171918

1919+
/** The type parameters computed by the completer before completion has finished */
1920+
def completerTypeParams(sym: Symbol)(implicit ctx: Context): List[TypeParamInfo] =
1921+
if (sym is Touched) Nil // return `Nil` instead of throwing a cyclic reference
1922+
else sym.info.typeParams
1923+
19181924
def decls: Scope = myDecls
19191925
def sourceModule(implicit ctx: Context): Symbol = mySourceModuleFn(ctx)
19201926
def moduleClass(implicit ctx: Context): Symbol = myModuleClassFn(ctx)
@@ -1924,12 +1930,12 @@ object SymDenotations {
19241930
def withModuleClass(moduleClassFn: Context => Symbol): this.type = { myModuleClassFn = moduleClassFn; this }
19251931
}
19261932

1927-
/** A subclass of LazyTypes where type parameters can be completed independently of
1928-
* the info.
1933+
/** A subtrait of LazyTypes where completerTypeParams yields a List[TypeSymbol], which
1934+
* should be completed independently of the info.
19291935
*/
19301936
trait TypeParamsCompleter extends LazyType {
1931-
/** The type parameters computed by the completer before completion has finished */
1932-
def completerTypeParams(sym: Symbol)(implicit ctx: Context): List[TypeSymbol]
1937+
override def completerTypeParams(sym: Symbol)(implicit ctx: Context): List[TypeSymbol] =
1938+
unsupported("completerTypeParams") // should be abstract, but Scala-2 will then compute the wrong type for it
19331939
}
19341940

19351941
val NoSymbolFn = (ctx: Context) => NoSymbol

compiler/src/dotty/tools/dotc/core/Symbols.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,6 @@ trait Symbols { this: Context =>
243243
case name: TypeName =>
244244
newClassSymbol(normalizedOwner, name, EmptyFlags, stubCompleter, assocFile = file)
245245
}
246-
stubs = stub :: stubs
247246
stub
248247
}
249248

@@ -377,7 +376,10 @@ trait Symbols { this: Context =>
377376
def requiredPackageRef(path: PreName): TermRef = requiredPackage(path).termRef
378377

379378
def requiredClass(path: PreName): ClassSymbol =
380-
base.staticRef(path.toTypeName).requiredSymbol(_.isClass).asClass
379+
base.staticRef(path.toTypeName).requiredSymbol(_.isClass) match {
380+
case cls: ClassSymbol => cls
381+
case sym => defn.AnyClass
382+
}
381383

382384
def requiredClassRef(path: PreName): TypeRef = requiredClass(path).typeRef
383385

@@ -700,8 +702,6 @@ object Symbols {
700702
/** The current class */
701703
def currentClass(implicit ctx: Context): ClassSymbol = ctx.owner.enclosingClass.asClass
702704

703-
@sharable var stubs: List[Symbol] = Nil // diagnostic only
704-
705705
/* Mutable map from symbols any T */
706706
class MutableSymbolMap[T](private[Symbols] val value: java.util.IdentityHashMap[Symbol, T]) extends AnyVal {
707707

compiler/src/dotty/tools/dotc/core/TypeApplications.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,11 @@ class TypeApplications(val self: Type) extends AnyVal {
172172
case self: TypeRef =>
173173
val tsym = self.symbol
174174
if (tsym.isClass) tsym.typeParams
175-
else if (!tsym.isCompleting) tsym.info.typeParams
176-
else Nil
175+
else if (!tsym.exists) self.info.typeParams
176+
else tsym.infoOrCompleter match {
177+
case info: LazyType => info.completerTypeParams(tsym)
178+
case info => info.typeParams
179+
}
177180
case self: AppliedType =>
178181
if (self.tycon.typeSymbol.isClass) Nil
179182
else self.superType.typeParams

0 commit comments

Comments
 (0)