aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--project/Build.scala12
-rw-r--r--src/dotty/tools/dotc/Compiler.scala10
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala2
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala9
-rw-r--r--src/dotty/tools/dotc/core/Annotations.scala4
-rw-r--r--src/dotty/tools/dotc/core/Decorators.scala5
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala20
-rw-r--r--src/dotty/tools/dotc/core/DenotTransformers.scala16
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala2
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala9
-rw-r--r--src/dotty/tools/dotc/core/Phases.scala23
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala6
-rw-r--r--src/dotty/tools/dotc/core/Symbols.scala4
-rw-r--r--src/dotty/tools/dotc/core/Types.scala16
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala5
-rw-r--r--src/dotty/tools/dotc/transform/Erasure.scala5
-rw-r--r--src/dotty/tools/dotc/transform/InterceptedMethods.scala2
-rw-r--r--src/dotty/tools/dotc/transform/LazyVals.scala14
-rw-r--r--src/dotty/tools/dotc/transform/Nullarify.scala148
-rw-r--r--src/dotty/tools/dotc/transform/PatternMatcher.scala1
-rw-r--r--src/dotty/tools/dotc/transform/TailRec.scala341
-rw-r--r--src/dotty/tools/dotc/transform/TreeTransform.scala4
-rw-r--r--src/dotty/tools/dotc/transform/TypeTestsCasts.scala1
-rw-r--r--src/dotty/tools/dotc/transform/UncurryTreeTransform.scala13
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala11
-rw-r--r--test/dotc/tests.scala8
-rw-r--r--test/test/transform/LazyValsTest.scala19
-rw-r--r--tests/neg/tailcall/t1672b.check (renamed from tests/untried/neg/t1672b.check)0
-rw-r--r--tests/neg/tailcall/t1672b.scala (renamed from tests/untried/neg/t1672b.scala)2
-rw-r--r--tests/neg/tailcall/t3275.check (renamed from tests/untried/neg/t3275.check)0
-rw-r--r--tests/neg/tailcall/t3275.scala (renamed from tests/untried/neg/t3275.scala)0
-rw-r--r--tests/neg/tailcall/t6574.check (renamed from tests/untried/neg/t6574.check)0
-rw-r--r--tests/neg/tailcall/t6574.scala (renamed from tests/untried/neg/t6574.scala)2
-rw-r--r--tests/neg/tailcall/tailrec-2.check (renamed from tests/untried/neg/tailrec-2.check)0
-rw-r--r--tests/neg/tailcall/tailrec-2.scala (renamed from tests/untried/neg/tailrec-2.scala)0
-rw-r--r--tests/neg/tailcall/tailrec-3.check (renamed from tests/untried/neg/tailrec-3.check)0
-rw-r--r--tests/neg/tailcall/tailrec-3.scala (renamed from tests/untried/neg/tailrec-3.scala)0
-rw-r--r--tests/neg/tailcall/tailrec.check (renamed from tests/untried/neg/tailrec.check)0
-rw-r--r--tests/neg/tailcall/tailrec.scala (renamed from tests/untried/neg/tailrec.scala)0
-rw-r--r--tests/pos/implicits2.scala19
-rw-r--r--tests/pos/nullarify.scala13
-rw-r--r--tests/pos/tailcall/t1672.scala10
-rw-r--r--tests/pos/tailcall/t4649.flags (renamed from tests/untried/pos/t4649.flags)0
-rw-r--r--tests/pos/tailcall/t4649.scala (renamed from tests/untried/pos/t4649.scala)2
-rw-r--r--tests/pos/tailcall/t6479.scala (renamed from tests/untried/pos/t6479.scala)0
-rw-r--r--tests/pos/tailcall/t6574.scala (renamed from tests/untried/pos/t6574.scala)2
-rw-r--r--tests/pos/tailcall/t6891.flags (renamed from tests/untried/pos/t6891.flags)0
-rw-r--r--tests/pos/tailcall/t6891.scala (renamed from tests/untried/pos/t6891.scala)2
-rw-r--r--tests/pos/tailcall/tailcall.scala5
-rw-r--r--tests/pos/typers.scala2
-rw-r--r--tests/untried/pos/t1672.scala10
51 files changed, 703 insertions, 76 deletions
diff --git a/project/Build.scala b/project/Build.scala
index c7e1518aa..145e3eb85 100644
--- a/project/Build.scala
+++ b/project/Build.scala
@@ -6,6 +6,12 @@ object DottyBuild extends Build {
val TRAVIS_BUILD = "dotty.travis.build"
+ val agentOptions = List(
+ // "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005",
+ // "-agentpath:/home/dark/opt/yjp-2013-build-13072/bin/linux-x86-64/libyjpagent.so"
+ )
+
+
val defaults = Defaults.defaultSettings ++ Seq(
// set sources to src/, tests to test/ and resources to resources/
scalaSource in Compile := baseDirectory.value / "src",
@@ -55,12 +61,12 @@ object DottyBuild extends Build {
// System.err.println("BOOTPATH: " + fullpath)
val travis_build = // propagate if this is a travis build
- if (sys.props.isDefinedAt(TRAVIS_BUILD))
+ if (sys.props.isDefinedAt(TRAVIS_BUILD))
List(s"-D$TRAVIS_BUILD=${sys.props(TRAVIS_BUILD)}")
- else
+ else
List()
- travis_build ::: fullpath
+ agentOptions ::: travis_build ::: fullpath
}
)
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index 8bcd919c2..457238da4 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -20,8 +20,14 @@ class Compiler {
def phases: List[List[Phase]] =
List(
List(new FrontEnd),
- List(new LazyValsCreateCompanionObjects, new PatternMatcher), //force separataion between lazyVals and LVCreateCO
- List(new LazyValTranformContext().transformer, new Splitter, new TypeTestsCasts, new InterceptedMethods),
+ List(new LazyValsCreateCompanionObjects,
+ new TailRec), //force separataion between lazyVals and LVCreateCO
+ List(new PatternMatcher,
+ new LazyValTranformContext().transformer,
+ new Splitter),
+ List(new Nullarify,
+ new TypeTestsCasts,
+ new InterceptedMethods),
List(new Erasure),
List(new UncurryTreeTransform)
)
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index f69ee265e..2ae494d55 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -639,7 +639,7 @@ object Trees {
/** => T */
case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T])
- extends Tree[T] {
+ extends TypTree[T] {
type ThisTree[-T >: Untyped] = ByNameTypeTree[T]
}
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index 9a9ffe243..e9775f1dc 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -30,7 +30,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def Select(qualifier: Tree, sym: Symbol)(implicit ctx: Context): Select =
untpd.Select(qualifier, sym.name).withType(
- TermRef.withSig(qualifier.tpe, sym.name.asTermName, sym.signature, sym.denot))
+ TermRef.withSig(qualifier.tpe, sym.name.asTermName, sym.signature, sym.denot.asSeenFrom(qualifier.tpe)))
def SelectWithSig(qualifier: Tree, name: Name, sig: Signature)(implicit ctx: Context) =
untpd.SelectWithSig(qualifier, name, sig)
@@ -103,11 +103,14 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
* where the closure's type is the target type of the expression (FunctionN, unless
* otherwise specified).
*/
- def Closure(meth: TermSymbol, rhsFn: List[List[Tree]] => Tree, targetType: Type = NoType)(implicit ctx: Context): Block = {
+ def Closure(meth: TermSymbol, rhsFn: List[List[Tree]] => Tree, targs: List[Tree] = Nil, targetType: Type = NoType)(implicit ctx: Context): Block = {
val targetTpt = if (targetType.exists) TypeTree(targetType) else EmptyTree
+ val call =
+ if (targs.isEmpty) Ident(TermRef(NoPrefix, meth))
+ else TypeApply(Ident(TermRef(NoPrefix, meth)), targs)
Block(
DefDef(meth, rhsFn) :: Nil,
- Closure(Nil, Ident(TermRef(NoPrefix, meth)), targetTpt))
+ Closure(Nil, call, targetTpt))
}
def CaseDef(pat: Tree, guard: Tree, body: Tree)(implicit ctx: Context): CaseDef =
diff --git a/src/dotty/tools/dotc/core/Annotations.scala b/src/dotty/tools/dotc/core/Annotations.scala
index 947593ca4..b4b7ebd24 100644
--- a/src/dotty/tools/dotc/core/Annotations.scala
+++ b/src/dotty/tools/dotc/core/Annotations.scala
@@ -7,7 +7,9 @@ object Annotations {
abstract class Annotation {
def tree(implicit ctx: Context): Tree
- def symbol(implicit ctx: Context): Symbol = tree.tpe.typeSymbol
+ def symbol(implicit ctx: Context): Symbol =
+ if (tree.symbol.isConstructor) tree.symbol.owner
+ else tree.tpe.typeSymbol
def matches(cls: Symbol)(implicit ctx: Context): Boolean = symbol.derivesFrom(cls)
def appliesToModule: Boolean = true // for now; see remark in SymDenotations
diff --git a/src/dotty/tools/dotc/core/Decorators.scala b/src/dotty/tools/dotc/core/Decorators.scala
index 25b5dbabc..155ea87e0 100644
--- a/src/dotty/tools/dotc/core/Decorators.scala
+++ b/src/dotty/tools/dotc/core/Decorators.scala
@@ -125,12 +125,13 @@ object Decorators {
/** Implements a test whether a list of strings representing phases contains
* a given phase. The test returns true if the given phase starts with
- * one of the names in the list of strings.
+ * one of the names in the list of strings, or if the list of strings
+ * contains "all".
*/
implicit class PhaseListDecorator(val names: List[String]) extends AnyVal {
def containsPhase(phase: Phase): Boolean = phase match {
case phase: TreeTransformer => phase.transformations.exists(containsPhase)
- case _ => names exists (phase.name.startsWith)
+ case _ => names exists (n => n == "all" || phase.name.startsWith(n))
}
}
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index 40fd33671..f1c69027e 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -77,8 +77,8 @@ class Definitions {
newPolyMethod(cls, name, 1, pt => MethodType(Nil, Nil, resultTypeFn(pt)), flags)
private def mkArityArray(name: String, arity: Int, countFrom: Int): Array[ClassSymbol] = {
- val arr = new Array[ClassSymbol](arity)
- for (i <- countFrom until arity) arr(i) = ctx.requiredClass("scala." + name + i)
+ val arr = new Array[ClassSymbol](arity + 1)
+ for (i <- countFrom to arity) arr(i) = ctx.requiredClass(name + i)
arr
}
@@ -172,8 +172,9 @@ class Definitions {
lazy val UnitClass = valueClassSymbol("scala.Unit", BoxedUnitClass, java.lang.Void.TYPE, UnitEnc)
lazy val BooleanClass = valueClassSymbol("scala.Boolean", BoxedBooleanClass, java.lang.Boolean.TYPE, BooleanEnc)
- lazy val Boolean_! = BooleanClass.requiredMethod(nme.UNARY_!)
+ lazy val Boolean_! = BooleanClass.requiredMethod(nme.UNARY_!)
lazy val Boolean_and = BooleanClass.requiredMethod(nme.ZAND)
+ lazy val Boolean_or = BooleanClass.requiredMethod(nme.ZOR)
lazy val ByteClass = valueClassSymbol("scala.Byte", BoxedByteClass, java.lang.Byte.TYPE, ByteEnc)
lazy val ShortClass = valueClassSymbol("scala.Short", BoxedShortClass, java.lang.Short.TYPE, ShortEnc)
@@ -236,6 +237,7 @@ class Definitions {
lazy val AnnotationClass = ctx.requiredClass("scala.annotation.Annotation")
lazy val ClassfileAnnotationClass = ctx.requiredClass("scala.annotation.ClassfileAnnotation")
lazy val StaticAnnotationClass = ctx.requiredClass("scala.annotation.StaticAnnotation")
+ lazy val TailrecAnnotationClass = ctx.requiredClass("scala.annotation.tailrec")
// Annotation classes
lazy val AliasAnnot = ctx.requiredClass("dotty.annotation.internal.Alias")
@@ -337,9 +339,12 @@ class Definitions {
// ----- Symbol sets ---------------------------------------------------
- lazy val FunctionClass = mkArityArray("Function", MaxFunctionArity, 0)
- lazy val TupleClass = mkArityArray("Tuple", MaxTupleArity, 2)
- lazy val ProductNClass = mkArityArray("Product", MaxTupleArity, 2)
+ lazy val AbstractFunctionClass = mkArityArray("scala.runtime.AbstractFunction", MaxFunctionArity, 0)
+ lazy val FunctionClass = mkArityArray("scala.Function", MaxFunctionArity, 0)
+ lazy val Function0_apply = FunctionClass(0).requiredMethod(nme.apply)
+
+ lazy val TupleClass = mkArityArray("scala.Tuple", MaxTupleArity, 2)
+ lazy val ProductNClass = mkArityArray("scala.Product", MaxTupleArity, 2)
lazy val FunctionClasses: Set[Symbol] = FunctionClass.toSet
lazy val TupleClasses: Set[Symbol] = TupleClass.toSet
@@ -354,6 +359,7 @@ class Definitions {
lazy val asInstanceOfMethods = Set[Symbol](Any_asInstanceOf, Object_asInstanceOf)
lazy val isInstanceOfMethods = Set[Symbol](Any_isInstanceOf, Object_isInstanceOf)
+ lazy val typeTestsOrCasts = asInstanceOfMethods ++ isInstanceOfMethods
lazy val RootImports = List[Symbol](JavaLangPackageVal, ScalaPackageVal, ScalaPredefModule, DottyPredefModule)
@@ -437,7 +443,7 @@ class Definitions {
LongClass,
FloatClass,
DoubleClass)
-
+
lazy val ScalaValueClasses: collection.Set[Symbol] = ScalaNumericValueClasses + UnitClass + BooleanClass
lazy val ScalaBoxedClasses = ScalaValueClasses map boxedClass
diff --git a/src/dotty/tools/dotc/core/DenotTransformers.scala b/src/dotty/tools/dotc/core/DenotTransformers.scala
index e1ee355d8..6daa028fc 100644
--- a/src/dotty/tools/dotc/core/DenotTransformers.scala
+++ b/src/dotty/tools/dotc/core/DenotTransformers.scala
@@ -5,6 +5,7 @@ import Periods._
import SymDenotations._
import Contexts._
import Types._
+import Symbols._
import Denotations._
import Phases._
import java.lang.AssertionError
@@ -30,4 +31,19 @@ object DenotTransformers {
/** The transformation method */
def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation
}
+
+ trait InfoTransformer extends DenotTransformer {
+
+ def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type
+
+ /** The transformation method */
+ def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = {
+ val info1 = transformInfo(ref.info, ref.symbol)
+ if (info1 eq ref.info) ref
+ else ref match {
+ case ref: SymDenotation => ref.copySymDenotation(info = info1)
+ case _ => ref.derivedSingleDenotation(ref.symbol, info1)
+ }
+ }
+ }
}
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 63b94efbd..e5f5e6f87 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -512,7 +512,7 @@ object Denotations {
def current(implicit ctx: Context): SingleDenotation = {
val currentPeriod = ctx.period
val valid = myValidFor
- assert(valid.code > 0, s"negative period $valid: ${valid.code}")
+ assert(valid.code > 0)
if (valid.runId != currentPeriod.runId) bringForward.current
else {
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index 68125f73e..9f87120f8 100644
--- a/src/dotty/tools/dotc/core/Flags.scala
+++ b/src/dotty/tools/dotc/core/Flags.scala
@@ -470,6 +470,15 @@ object Flags {
/** Labeled `private` or `protected[local]` */
final val PrivateOrLocal = Private | Local
+ /** Either a module or a final class */
+ final val ModuleOrFinal = ModuleClass | Final
+
+ /** Either mutable or lazy */
+ final val MutableOrLazy = Mutable | Lazy
+
+ /** Labeled `private` or `final` */
+ final val PrivateOrFinal = Private | Final
+
/** A type parameter with synthesized name */
final val ExpandedTypeParam = allOf(ExpandedName, TypeParam)
diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala
index eb3b1d7fc..f76b83db6 100644
--- a/src/dotty/tools/dotc/core/Phases.scala
+++ b/src/dotty/tools/dotc/core/Phases.scala
@@ -74,12 +74,24 @@ object Phases {
*/
private def squashPhases(phasess: List[List[Phase]]): Array[Phase] = {
val squashedPhases = ListBuffer[Phase]()
+ var prevPhases: Set[String] = Set.empty
var postTyperEmmited = false
var i = 0
while (i < phasess.length) {
if (phasess(i).length > 1) {
- assert(phasess(i).forall(x => x.isInstanceOf[TreeTransform]), "Only tree transforms can be squashed")
+ val phasesInBlock: Set[String] = phasess(i).map(_.name).toSet
+ for(phase<-phasess(i)) {
+ phase match {
+ case p: TreeTransform =>
+ val unmetRequirements = p.runsAfterGroupsOf &~ prevPhases
+ assert(unmetRequirements.isEmpty,
+ s"${phase.name} requires ${unmetRequirements.mkString(", ")} to be in different TreeTransformer")
+
+ case _ =>
+ assert(false, s"Only tree transforms can be squashed, ${phase.name} can not be squashed")
+ }
+ }
val transforms = phasess(i).asInstanceOf[List[TreeTransform]]
val block =
if (!postTyperEmmited) {
@@ -93,6 +105,7 @@ object Phases {
override def transformations: Array[TreeTransform] = transforms.toArray
}
squashedPhases += block
+ prevPhases ++= phasess(i).map(_.name)
block.init(this, phasess(i).head.id, phasess(i).last.id)
} else squashedPhases += phasess(i).head
i += 1
@@ -106,11 +119,16 @@ object Phases {
*/
def usePhases(phasess: List[List[Phase]], squash: Boolean = true) = {
phases = (NoPhase :: phasess.flatten ::: new TerminalPhase :: Nil).toArray
+ var phasesAfter:Set[String] = Set.empty
nextDenotTransformerId = new Array[Int](phases.length)
denotTransformers = new Array[DenotTransformer](phases.length)
var i = 0
while (i < phases.length) {
phases(i).init(this, i)
+ val unmetPreceedeRequirements = phases(i).runsAfter -- phasesAfter
+ assert(unmetPreceedeRequirements.isEmpty,
+ s"phase ${phases(i)} has unmet requirement: ${unmetPreceedeRequirements.mkString(", ")} should precede this phase")
+ phasesAfter += phases(i).name
i += 1
}
var lastTransformerId = i
@@ -170,6 +188,9 @@ object Phases {
def name: String
+ /** List of names of phases that should precede this phase */
+ def runsAfter: Set[String] = Set.empty
+
def run(implicit ctx: Context): Unit
def runOn(units: List[CompilationUnit])(implicit ctx: Context): Unit =
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index dc76999f6..9cf06ec47 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -586,6 +586,12 @@ object SymDenotations {
final def enclosingClass(implicit ctx: Context): Symbol =
if (isClass || !exists) symbol else owner.enclosingClass
+ final def isEffectivelyFinal(implicit ctx: Context): Boolean = {
+ (this.flags is Flags.PrivateOrFinal) || (!this.owner.isClass) ||
+ ((this.owner.flags is (Flags.ModuleOrFinal)) && (!this.flags.is(Flags.MutableOrLazy))) ||
+ (this.owner.isAnonymousClass)
+ }
+
/** The class containing this denotation which has the given effective name.
*/
final def enclosingClassNamed(name: Name)(implicit ctx: Context): Symbol = {
diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala
index 8f66830e8..26553ddff 100644
--- a/src/dotty/tools/dotc/core/Symbols.scala
+++ b/src/dotty/tools/dotc/core/Symbols.scala
@@ -245,7 +245,7 @@ trait Symbols { this: Context =>
for (name <- names) {
val tparam = newNakedSymbol[TypeName](NoCoord)
tparamBuf += tparam
- trefBuf += TypeRef(owner.thisType, name).withSym(tparam, Signature.NotAMethod)
+ trefBuf += TypeRef.withSymAndName(owner.thisType, tparam, name)
}
val tparams = tparamBuf.toList
val bounds = boundsFn(trefBuf.toList)
@@ -319,7 +319,7 @@ object Symbols {
type ThisName <: Name
private[this] var _id: Int = nextId
- //assert(_id != 12325)
+ //assert(_id != 5859)
/** The unique id of this symbol */
def id = _id
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index c348e246c..66f027915 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -352,6 +352,12 @@ object Types {
goThis(tp)
case tp: TypeRef =>
tp.denot.findMember(name, pre, excluded)
+ case tp: TermRef =>
+ go (tp.underlying match {
+ case mt: MethodType
+ if mt.paramTypes.isEmpty && (tp.symbol is Stable) => mt.resultType
+ case tp1 => tp1
+ })
case tp: TypeProxy =>
go(tp.underlying)
case tp: ClassInfo =>
@@ -449,7 +455,7 @@ object Types {
final def implicitMembers(implicit ctx: Context): List[TermRef] = track("implicitMembers") {
memberDenots(implicitFilter,
(name, buf) => buf ++= member(name).altsWith(_ is Implicit))
- .toList.map(_.termRefWithSig)
+ .toList.map(d => TermRef.withSig(this, d.symbol.asTerm))
}
/** The info of `sym`, seen as a member of this type. */
@@ -1101,14 +1107,14 @@ object Types {
private def withSig(sig: Signature)(implicit ctx: Context): NamedType =
TermRef.withSig(prefix, name.asTermName, sig)
- protected def loadDenot(implicit ctx: Context) = {
+ protected def loadDenot(implicit ctx: Context): Denotation = {
val d =
if (name.isInheritedName) prefix.nonPrivateMember(name.revertInherited)
else prefix.member(name)
- if (d.exists || ctx.phaseId == FirstPhaseId)
+ if (d.exists || ctx.phaseId == FirstPhaseId || !lastDenotation.isInstanceOf[SymDenotation])
d
else {// name has changed; try load in earlier phase and make current
- val d = denot(ctx.withPhase(ctx.phaseId - 1)).current
+ val d = loadDenot(ctx.withPhase(ctx.phaseId - 1)).current
if (d.exists) d
else throw new Error(s"failure to reload $this")
}
@@ -1311,7 +1317,7 @@ object Types {
if (prefix eq NoPrefix) withNonMemberSym(prefix, name, sym)
else {
if (sym.defRunId != NoRunId && sym.isCompleted) withSig(prefix, name, sym.signature)
- else apply(prefix, name)
+ else apply(prefix, name)
} withSym (sym, Signature.NotAMethod)
def withSig(prefix: Type, sym: TermSymbol)(implicit ctx: Context): TermRef =
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index f9cd9ec72..dd8f04d92 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -54,13 +54,14 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}
override def toTextPrefix(tp: Type): Text = controlled {
+ def isOmittable(sym: Symbol) = isOmittablePrefix(sym) && !ctx.settings.verbose.value
tp match {
case ThisType(cls) =>
- if (isOmittablePrefix(cls)) return ""
+ if (isOmittable(cls)) return ""
case tp @ TermRef(pre, _) =>
val sym = tp.symbol
if (sym.isPackageObject) return toTextPrefix(pre)
- if (isOmittablePrefix(sym)) return ""
+ if (isOmittable(sym)) return ""
case _ =>
}
super.toTextPrefix(tp)
diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala
index 1f618b9f6..562a30682 100644
--- a/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/src/dotty/tools/dotc/transform/Erasure.scala
@@ -27,6 +27,9 @@ class Erasure extends Phase with DenotTransformer {
override def name: String = "erasure"
+ /** List of names of phases that should precede this phase */
+ override def runsAfter: Set[String] = Set("typeTestsCasts", "intercepted", "splitter", "nullarify")
+
def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref match {
case ref: SymDenotation =>
assert(ctx.phase == this, s"transforming $ref at ${ctx.phase}")
@@ -263,7 +266,7 @@ object Erasure {
val statsFlatten = Trees.flatten(stats)
val stats1 = super.typedStats(statsFlatten, exprOwner)
- if (ctx.owner.isClass) addBridges(statsFlatten, stats1)(ctx) else stats1
+ if (ctx.owner.isClass) stats1:::addBridges(statsFlatten, stats1)(ctx) else stats1
}
// this implementation doesn't check for bridge clashes with value types!
diff --git a/src/dotty/tools/dotc/transform/InterceptedMethods.scala b/src/dotty/tools/dotc/transform/InterceptedMethods.scala
index b56985ffe..d5a4377d0 100644
--- a/src/dotty/tools/dotc/transform/InterceptedMethods.scala
+++ b/src/dotty/tools/dotc/transform/InterceptedMethods.scala
@@ -2,7 +2,6 @@ package dotty.tools.dotc
package transform
import TreeTransforms._
-import core.DenotTransformers._
import core.Denotations._
import core.SymDenotations._
import core.Contexts._
@@ -27,7 +26,6 @@ import dotty.runtime.LazyVals
import scala.collection.mutable.ListBuffer
import dotty.tools.dotc.core.Denotations.SingleDenotation
import dotty.tools.dotc.core.SymDenotations.SymDenotation
-import dotty.tools.dotc.core.DenotTransformers.DenotTransformer
import StdNames._
/** Replace member references as follows:
diff --git a/src/dotty/tools/dotc/transform/LazyVals.scala b/src/dotty/tools/dotc/transform/LazyVals.scala
index 8ed09b4b2..840ca0cdb 100644
--- a/src/dotty/tools/dotc/transform/LazyVals.scala
+++ b/src/dotty/tools/dotc/transform/LazyVals.scala
@@ -32,7 +32,7 @@ class LazyValsCreateCompanionObjects extends CreateCompanionObjects {
val body = forClass.rhs.asInstanceOf[Template].body
body.exists {
case x: ValDef =>
- (x.mods is Flags.Lazy) && x.mods.annotations.exists(_.tpe == defn.VolatileAnnotType)
+ (x.mods is Flags.Lazy) && x.symbol.hasAnnotation(defn.VolatileAnnot)
case _ => false
}
}
@@ -63,6 +63,16 @@ class LazyValTranformContext {
override def name: String = "LazyVals"
+ /** List of names of phases that should have finished their processing of all compilation units
+ * before this phase starts */
+ override def runsAfterGroupsOf: Set[String] = Set("lazyValsModules")
+ /** List of names of phases that should have finished their processing of all compilation units
+ * before this phase starts */
+
+ /** List of names of phases that should have finished processing of tree
+ * before this phase starts processing same tree */
+ // override def ensureAfter: Set[String] = Set("mixin")
+
def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = {
ref match {
case ref: SymDenotation if ref.symbol.isClass =>
@@ -84,7 +94,7 @@ class LazyValTranformContext {
if (!(tree.mods is Flags.Lazy)) tree
else {
val isField = tree.symbol.owner.isClass
- val isVolatile = tree.mods.annotations.exists(_.tpe == defn.VolatileAnnotType)
+ val isVolatile = tree.symbol.hasAnnotation(defn.VolatileAnnot)
if (isField) {
if (isVolatile) transformFieldValDefVolatile(tree)
diff --git a/src/dotty/tools/dotc/transform/Nullarify.scala b/src/dotty/tools/dotc/transform/Nullarify.scala
new file mode 100644
index 000000000..664b4bee1
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/Nullarify.scala
@@ -0,0 +1,148 @@
+package dotty.tools.dotc
+package transform
+
+import TreeTransforms._
+import core.DenotTransformers._
+import core.Symbols._
+import core.Contexts._
+import core.Types._
+import core.Flags._
+import core.Decorators._
+import core.StdNames.nme
+import ast.Trees._
+
+/** This phase eliminates ExprTypes `=> T` and PolyTypes over value types `[X]T`.
+ * They are expressed in terms of nullary method or function types. More precisely:
+ *
+ * For types:
+ *
+ * => T ==> () => T if T is the type of a parameter
+ * ==> ()T otherwise
+ * [X]T ==> [X]()T
+ *
+ * For definitions:
+ *
+ * def f: R ==> def f(): R
+ * def f[X]: R ==> def f[X](): R
+ * (x: => T) ==> (x: () => T)
+ *
+ * For terms:
+ *
+ * f ==> f() if f had type => T and is not a parameter
+ * x ==> x.apply() if x is a parameter that had type => T
+ * e.apply() ==> e if e.apply() is an argument to a call-by-name parameter
+ * expr ==> () => expr if other expr is an argument to a call-by-name parameter
+ *
+ */
+class Nullarify extends TreeTransform with InfoTransformer {
+ import ast.tpd._
+
+ override def name: String = "nullarify"
+
+ override def runsAfterGroupsOf: Set[String] = Set("splitter")
+ // assumes idents and selects have symbols; interferes with splitter distribution
+ // that's why it's "after group".
+
+ override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree =
+ ctx.traceIndented(s"transforming ${tree.show} at phase ${ctx.phase}", show = true) {
+
+ def transformArg(arg: Tree, formal: Type): Tree = formal match {
+ case _: ExprType =>
+ arg match {
+ case Apply(Select(qual, nme.apply), Nil) if qual.tpe <:< defn.FunctionClass(0).typeRef => qual
+ case _ =>
+ val meth = ctx.newSymbol(ctx.owner, nme.ANON_FUN, Synthetic,
+ MethodType(Nil, Nil, arg.tpe.widen))
+ Closure(meth, _ => arg)
+ }
+ case _ =>
+ arg
+ }
+
+ // Compute the method type tree had before this phase is run.
+ // This is needed to find out which parameters are by-name.
+ val funType = tree.fun.symbol.info match {
+ case info: PolyType => info.resultType
+ case info => info
+ }
+ def methType(info: Type, tree: Tree): Type = tree match {
+ case Apply(fn, args) => methType(info.resultType, fn)
+ case _ => info
+ }
+ val MethodType(_, formals) = methType(funType, tree.fun)
+
+ val args1 = tree.args.zipWithConserve(formals)(transformArg)
+ cpy.Apply(tree, tree.fun, args1) withType nullarify(tree.tpe)
+ }
+
+ /** Insert () or .apply() if the term refers to something that was converted to a
+ * nullary method. Also, transform its type.
+ */
+ def insertParens(tree: Tree)(implicit ctx: Context): Tree = {
+ val tp1 = transformInfo(tree.tpe, tree.symbol)
+ val tree1 = tree.withType(tp1)
+ val origType = tree.tpe.widenSingleton
+ def result(implicit ctx: Context) = {
+ tp1.widen match {
+ case MethodType(Nil, _) if origType.widenExpr.isInstanceOf[ValueType] =>
+ Apply(tree1, Nil)
+ case _ =>
+ origType match {
+ case _: ExprType => // it's a by-name parameter
+ Apply(Select(tree1, defn.Function0_apply), Nil)
+ case _ =>
+ tree1
+ }
+ }
+ }
+ result(ctx.withPhase(ctx.phase.next))
+ }
+
+ override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree =
+ insertParens(tree)
+
+ override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree =
+ insertParens(tree)
+
+ override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree =
+ insertParens(tree)
+
+ override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ val DefDef(mods, name, tparams, vparamss, tpt, rhs) = tree
+ val vparamss1 =
+ if (vparamss.isEmpty) Nil :: Nil
+ else vparamss nestedMap { vparam =>
+ val tp = vparam.tpt.tpe
+ val tp1 = nullarifyParam(tp)
+ if (tp eq tp1) vparam
+ else cpy.ValDef(vparam, vparam.mods, vparam.name, vparam.tpt.withType(tp1), vparam.rhs)
+ }
+ cpy.DefDef(tree, mods, name, tparams, vparamss1, tpt, rhs)
+ }
+
+ def nullarify(tp: Type)(implicit ctx: Context): Type = tp match {
+ case ExprType(rt) =>
+ MethodType(Nil, Nil, rt)
+ case pt: PolyType =>
+ val rt = pt.resultType match {
+ case mt: MethodType => nullarify(mt)
+ case rt => MethodType(Nil, Nil, rt)
+ }
+ pt.derivedPolyType(pt.paramNames, pt.paramBounds, rt)
+ case mt: MethodType =>
+ mt.derivedMethodType(mt.paramNames, mt.paramTypes mapConserve nullarifyParam,
+ nullarify(mt.resultType))
+ case _ =>
+ tp
+ }
+
+ def nullarifyParam(tp: Type)(implicit ctx: Context) = tp match {
+ case ExprType(rt) => defn.FunctionType(Nil, rt)
+ case _ => tp
+ }
+
+ def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type =
+ if (defn.typeTestsOrCasts contains sym) tp
+ else if (sym is Param) nullarifyParam(tp)
+ else nullarify(tp)
+} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/transform/PatternMatcher.scala b/src/dotty/tools/dotc/transform/PatternMatcher.scala
index ff25a94de..40a157483 100644
--- a/src/dotty/tools/dotc/transform/PatternMatcher.scala
+++ b/src/dotty/tools/dotc/transform/PatternMatcher.scala
@@ -2,7 +2,6 @@ package dotty.tools.dotc
package transform
import TreeTransforms._
-import core.DenotTransformers._
import core.Denotations._
import core.SymDenotations._
import core.Contexts._
diff --git a/src/dotty/tools/dotc/transform/TailRec.scala b/src/dotty/tools/dotc/transform/TailRec.scala
new file mode 100644
index 000000000..543510dd7
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/TailRec.scala
@@ -0,0 +1,341 @@
+package dotty.tools.dotc.transform
+
+import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransform, TreeTransformer}
+import dotty.tools.dotc.ast.{Trees, tpd}
+import dotty.tools.dotc.core.Contexts.Context
+import scala.collection.mutable.ListBuffer
+import dotty.tools.dotc.core._
+import dotty.tools.dotc.core.Symbols.NoSymbol
+import scala.annotation.tailrec
+import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._
+import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
+import Decorators._
+import Symbols._
+import scala.Some
+import dotty.tools.dotc.transform.TreeTransforms.{NXTransformations, TransformerInfo, TreeTransform, TreeTransformer}
+import dotty.tools.dotc.core.Contexts.Context
+import scala.collection.mutable
+import dotty.tools.dotc.core.Names.Name
+import NameOps._
+import dotty.tools.dotc.CompilationUnit
+import dotty.tools.dotc.util.Positions.{Position, Coord}
+import dotty.tools.dotc.util.Positions.NoPosition
+import dotty.tools.dotc.core.DenotTransformers.DenotTransformer
+import dotty.tools.dotc.core.Denotations.SingleDenotation
+import dotty.tools.dotc.transform.TailRec._
+
+/**
+ * A Tail Rec Transformer
+ *
+ * @author Erik Stenman, Iulian Dragos,
+ * ported to dotty by Dmitry Petrashko
+ * @version 1.1
+ *
+ * What it does:
+ * <p>
+ * Finds method calls in tail-position and replaces them with jumps.
+ * A call is in a tail-position if it is the last instruction to be
+ * executed in the body of a method. This is done by recursing over
+ * the trees that may contain calls in tail-position (trees that can't
+ * contain such calls are not transformed). However, they are not that
+ * many.
+ * </p>
+ * <p>
+ * Self-recursive calls in tail-position are replaced by jumps to a
+ * label at the beginning of the method. As the JVM provides no way to
+ * jump from a method to another one, non-recursive calls in
+ * tail-position are not optimized.
+ * </p>
+ * <p>
+ * A method call is self-recursive if it calls the current method and
+ * the method is final (otherwise, it could
+ * be a call to an overridden method in a subclass).
+ *
+ * Recursive calls on a different instance
+ * are optimized. Since 'this' is not a local variable it s added as
+ * a label parameter.
+ * </p>
+ * <p>
+ * This phase has been moved before pattern matching to catch more
+ * of the common cases of tail recursive functions. This means that
+ * more cases should be taken into account (like nested function, and
+ * pattern cases).
+ * </p>
+ * <p>
+ * If a method contains self-recursive calls, a label is added to at
+ * the beginning of its body and the calls are replaced by jumps to
+ * that label.
+ * </p>
+ * <p>
+ *
+ * In scalac, If the method had type parameters, the call must contain same
+ * parameters as type arguments. This is no longer case in dotc.
+ * In scalac, this is named tailCall but it does only provide optimization for
+ * self recursive functions, that's why it's renamed to tailrec
+ * </p>
+ */
+class TailRec extends TreeTransform with DenotTransformer {
+
+ import tpd._
+
+ override def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref
+
+ override def name: String = "tailrec"
+
+ final val labelPrefix = "tailLabel"
+
+ private def mkLabel(method: Symbol, tp: Type)(implicit c: Context): TermSymbol = {
+ val name = c.freshName(labelPrefix)
+ c.newSymbol(method, name.toTermName, Flags.Synthetic, tp)
+ }
+
+ override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
+ tree match {
+ case dd@DefDef(mods, name, tparams, vparamss0, tpt, rhs0)
+ if (dd.symbol.isEffectivelyFinal) && !((dd.symbol is Flags.Accessor) || (rhs0 eq EmptyTree)) =>
+ val mandatory = dd.symbol.hasAnnotation(defn.TailrecAnnotationClass)
+ cpy.DefDef(tree, mods, name, tparams, vparamss0, tpt, rhs = {
+ val owner = ctx.owner.enclosingClass
+
+ val thisTpe = owner.thisType
+
+ val newType: Type = dd.tpe.widen match {
+ case t: PolyType => PolyType(t.paramNames)(x => t.paramBounds,
+ x => MethodType(List(nme.THIS), List(thisTpe), t.resultType))
+ case t => MethodType(List(nme.THIS), List(thisTpe), t)
+ }
+
+ val label = mkLabel(dd.symbol, newType)
+ var rewrote = false
+
+ // Note: this can be split in two separate transforms(in different groups),
+ // than first one will collect info about which transformations and rewritings should be applied
+ // and second one will actually apply,
+ // now this speculatively transforms tree and throws away result in many cases
+ val res = tpd.Closure(label, args => {
+ val thiz = args.head.head
+ val argMapping: Map[Symbol, Tree] = (vparamss0.flatten.map(_.symbol) zip args.tail.flatten).toMap
+ val transformer = new TailRecElimination(dd.symbol, thiz, argMapping, owner, mandatory, label)
+ val rhs = transformer.transform(rhs0)(ctx.withPhase(ctx.phase.next))
+ rewrote = transformer.rewrote
+ rhs
+ }, tparams)
+
+ if (rewrote) res
+ else {
+ if (mandatory)
+ ctx.error("TailRec optimisation not applicable, method not tail recursive", dd.pos)
+ rhs0
+ }
+ })
+ case d: DefDef if d.symbol.hasAnnotation(defn.TailrecAnnotationClass) =>
+ ctx.error("TailRec optimisation not applicable, method is neither private nor final so can be overridden", d.pos)
+ d
+ case d if d.symbol.hasAnnotation(defn.TailrecAnnotationClass) =>
+ ctx.error("TailRec optimisation not applicable, not a method", d.pos)
+ d
+ case _ => tree
+ }
+
+ }
+
+ class TailRecElimination(method: Symbol, thiz: Tree, argMapping: Map[Symbol, Tree],
+ enclosingClass: Symbol, isMandatory: Boolean, label: Symbol) extends tpd.TreeMap {
+
+ import tpd._
+
+
+ var rewrote = false
+
+ private val defaultReason = "it contains a recursive call not in tail position"
+
+ private var ctx: TailContext = yesTailContext
+
+ /** Rewrite this tree to contain no tail recursive calls */
+ def transform(tree: Tree, nctx: TailContext)(implicit c: Context): Tree = {
+ if (ctx == nctx) transform(tree)
+ else {
+ val saved = ctx
+ ctx = nctx
+ try transform(tree)
+ finally this.ctx = saved
+ }
+ }
+
+ def yesTailTransform(tree: Tree)(implicit c: Context): Tree =
+ transform(tree, yesTailContext)
+
+ def noTailTransform(tree: Tree)(implicit c: Context): Tree =
+ transform(tree, noTailContext)
+
+
+ def noTailTransforms(trees: List[Tree])(implicit c: Context) =
+ trees map (noTailTransform)
+
+
+ override def transform(tree: Tree)(implicit c: Context): Tree = {
+ /* A possibly polymorphic apply to be considered for tail call transformation. */
+ def rewriteApply(tree: Tree, sym: Symbol): Tree = {
+ def receiverArgumentsAndSymbol(t: Tree, accArgs: List[List[Tree]] = Nil, accT: List[Tree] = Nil):
+ (Tree, Tree, List[List[Tree]], List[Tree], Symbol) = t match {
+ case TypeApply(fun, targs) if fun.symbol eq t.symbol => receiverArgumentsAndSymbol(fun, accArgs, targs)
+ case Apply(fn, args) if fn.symbol == t.symbol => receiverArgumentsAndSymbol(fn, args :: accArgs, accT)
+ case Select(qual, _) => (qual, t, accArgs, accT, t.symbol)
+ case x: This => (x, x, accArgs, accT, x.symbol)
+ case x: Ident if x.symbol eq method => (EmptyTree, x, accArgs, accT, x.symbol)
+ case x => (x, x, accArgs, accT, x.symbol)
+ }
+
+ val (reciever, call, arguments, typeArguments, symbol) = receiverArgumentsAndSymbol(tree)
+ val recv = noTailTransform(reciever)
+
+ val targs = typeArguments.map(noTailTransform)
+ val argumentss = arguments.map(noTailTransforms)
+
+ val receiverIsSame = enclosingClass.typeRef.widen =:= recv.tpe.widen
+ val receiverIsSuper = (method.name eq sym) && enclosingClass.typeRef.widen <:< recv.tpe.widen
+ val receiverIsThis = recv.tpe.widen =:= thiz.tpe.widen
+
+ val isRecursiveCall = (method eq sym)
+
+ def continue = {
+ val method = noTailTransform(call)
+ val methodWithTargs = if (targs.nonEmpty) TypeApply(method, targs) else method
+ if (methodWithTargs.tpe.widen.isParameterless) methodWithTargs
+ else argumentss.foldLeft(methodWithTargs) {
+ case (method, args) => Apply(method, args)
+ }
+ }
+ def fail(reason: String) = {
+ if (isMandatory) c.error(s"Cannot rewrite recursive call: $reason", tree.pos)
+ else c.debuglog("Cannot rewrite recursive call at: " + tree.pos + " because: " + reason)
+ continue
+ }
+
+ def rewriteTailCall(recv: Tree): Tree = {
+ c.debuglog("Rewriting tail recursive call: " + tree.pos)
+ rewrote = true
+ val method = if (targs.nonEmpty) TypeApply(Ident(label.termRef), targs) else Ident(label.termRef)
+ val recv = noTailTransform(reciever)
+ if (recv.tpe.widen.isParameterless) method
+ else argumentss.foldLeft(Apply(method, List(recv))) {
+ case (method, args) => Apply(method, args)
+ }
+ }
+
+ if (isRecursiveCall) {
+ if (ctx.tailPos) {
+ if (recv eq EmptyTree) rewriteTailCall(thiz)
+ else if (receiverIsSame || receiverIsThis) rewriteTailCall(recv)
+ else fail("it changes type of 'this' on a polymorphic recursive call")
+ }
+ else fail(defaultReason)
+ } else {
+ if (receiverIsSuper) fail("it contains a recursive call targeting a supertype")
+ else continue
+ }
+ }
+
+ def rewriteTry(tree: Try): Tree = {
+ def transformHandlers(t: Tree): Tree = {
+ t match {
+ case Block(List((d: DefDef)), cl@Closure(Nil, _, EmptyTree)) =>
+ val newDef = cpy.DefDef(d, d.mods, d.name, d.tparams, d.vparamss, d.tpt, transform(d.rhs))
+ Block(List(newDef), cl)
+ case _ => assert(false, s"failed to deconstruct try handler ${t.show}"); ???
+ }
+ }
+ if (tree.finalizer eq EmptyTree) {
+ // SI-1672 Catches are in tail position when there is no finalizer
+ tpd.cpy.Try(tree,
+ noTailTransform(tree.expr),
+ transformHandlers(tree.handler),
+ EmptyTree
+ )
+ }
+ else {
+ tpd.cpy.Try(tree,
+ noTailTransform(tree.expr),
+ noTailTransform(tree.handler),
+ noTailTransform(tree.finalizer)
+ )
+ }
+ }
+
+ val res: Tree = tree match {
+ case Block(stats, expr) =>
+ tpd.cpy.Block(tree,
+ noTailTransforms(stats),
+ transform(expr)
+ )
+
+ case t@CaseDef(pat, guard, body) =>
+ cpy.CaseDef(t, pat, guard, transform(body))
+
+ case If(cond, thenp, elsep) =>
+ tpd.cpy.If(tree,
+ transform(cond),
+ transform(thenp),
+ transform(elsep)
+ )
+
+ case Match(selector, cases) =>
+ tpd.cpy.Match(tree,
+ noTailTransform(selector),
+ transformSub(cases)
+ )
+
+ case t: Try =>
+ rewriteTry(t)
+
+ case Apply(fun, args) if fun.symbol == defn.Boolean_or || fun.symbol == defn.Boolean_and =>
+ tpd.cpy.Apply(tree, fun, transform(args))
+
+ case Apply(fun, args) =>
+ rewriteApply(tree, fun.symbol)
+ case Alternative(_) | Bind(_, _) =>
+ assert(false, "We should've never gotten inside a pattern")
+ tree
+ case This(cls) if cls eq enclosingClass =>
+ thiz
+ case Select(qual, name) =>
+ val sym = tree.symbol
+ if (sym == method && ctx.tailPos) rewriteApply(tree, sym)
+ else tpd.cpy.Select(tree, noTailTransform(qual), name)
+ case ValDef(_, _, _, _) | EmptyTree | Super(_, _) | This(_) |
+ Literal(_) | TypeTree(_) | DefDef(_, _, _, _, _, _) | TypeDef(_, _, _) =>
+ tree
+ case Ident(qual) =>
+ val sym = tree.symbol
+ if (sym == method && ctx.tailPos) rewriteApply(tree, sym)
+ else argMapping.get(sym) match {
+ case Some(rewrite) => rewrite
+ case None => tree.tpe match {
+ case TermRef(ThisType(`enclosingClass`), _) =>
+ if (sym.flags is Flags.Local) {
+ // trying to access private[this] member. toggle flag in order to access.
+ val d = sym.denot
+ val newDenot = d.copySymDenotation(initFlags = sym.flags &~ Flags.Local)
+ newDenot.installAfter(TailRec.this)
+ }
+ Select(thiz, sym)
+ case _ => tree
+ }
+ }
+ case _ =>
+ super.transform(tree)
+ }
+
+ res
+ }
+ }
+
+}
+
+object TailRec {
+
+ final class TailContext(val tailPos: Boolean) extends AnyVal
+
+ final val noTailContext = new TailContext(false)
+ final val yesTailContext = new TailContext(true)
+}
diff --git a/src/dotty/tools/dotc/transform/TreeTransform.scala b/src/dotty/tools/dotc/transform/TreeTransform.scala
index 5cbc73e8d..c0ce68e95 100644
--- a/src/dotty/tools/dotc/transform/TreeTransform.scala
+++ b/src/dotty/tools/dotc/transform/TreeTransform.scala
@@ -53,6 +53,10 @@ object TreeTransforms {
/** id of this treeTransform in group */
var idx: Int = _
+ /** List of names of phases that should have finished their processing of all compilation units
+ * before this phase starts */
+ def runsAfterGroupsOf: Set[String] = Set.empty
+
def prepareForIdent(tree: Ident)(implicit ctx: Context) = this
def prepareForSelect(tree: Select)(implicit ctx: Context) = this
def prepareForThis(tree: This)(implicit ctx: Context) = this
diff --git a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
index aba674d1c..a36bf6500 100644
--- a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
+++ b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
@@ -2,7 +2,6 @@ package dotty.tools.dotc
package transform
import TreeTransforms._
-import core.DenotTransformers._
import core.Denotations._
import core.SymDenotations._
import core.Contexts._
diff --git a/src/dotty/tools/dotc/transform/UncurryTreeTransform.scala b/src/dotty/tools/dotc/transform/UncurryTreeTransform.scala
index fe50e41cd..ccfaaa0dc 100644
--- a/src/dotty/tools/dotc/transform/UncurryTreeTransform.scala
+++ b/src/dotty/tools/dotc/transform/UncurryTreeTransform.scala
@@ -7,10 +7,11 @@ import core.Denotations._
import core.SymDenotations._
import core.Contexts._
import core.Types._
+import core.Symbols._
import ast.Trees._
import ast.tpd.{Apply, Tree, cpy}
-class UncurryTreeTransform extends TreeTransform with DenotTransformer {
+class UncurryTreeTransform extends TreeTransform with InfoTransformer {
override def name: String = "uncurry"
override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree =
@@ -40,12 +41,6 @@ class UncurryTreeTransform extends TreeTransform with DenotTransformer {
tp
}
- def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = {
- val info1 = uncurry(ref.info)
- if (info1 eq ref.info) ref
- else ref match {
- case ref: SymDenotation => ref.copySymDenotation(info = info1)
- case _ => ref.derivedSingleDenotation(ref.symbol, info1)
- }
- }
+ def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type =
+ uncurry(tp)
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 6e613975b..165ae70dd 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -738,8 +738,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
assignType(cpy.Alternative(tree, trees1), trees1)
}
- def typedModifiers(mods: untpd.Modifiers)(implicit ctx: Context): Modifiers = track("typedModifiers") {
+ def typedModifiers(mods: untpd.Modifiers, sym: Symbol)(implicit ctx: Context): Modifiers = track("typedModifiers") {
val annotations1 = mods.annotations mapconserve typedAnnotation
+ for (tree <- annotations1) sym.addAnnotation(Annotation(tree))
if (annotations1 eq mods.annotations) mods.asInstanceOf[Modifiers]
else Modifiers(mods.flags, mods.privateWithin, annotations1)
}
@@ -750,7 +751,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedValDef(vdef: untpd.ValDef, sym: Symbol)(implicit ctx: Context) = track("typedValDef") {
val ValDef(mods, name, tpt, rhs) = vdef
- val mods1 = typedModifiers(mods)
+ val mods1 = typedModifiers(mods, sym)
val tpt1 = typedType(tpt)
if ((sym is Implicit) && sym.owner.isType) checkImplicitTptNonEmpty(vdef)
val rhs1 = rhs match {
@@ -762,7 +763,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context) = track("typedDefDef") {
val DefDef(mods, name, tparams, vparamss, tpt, rhs) = ddef
- val mods1 = typedModifiers(mods)
+ val mods1 = typedModifiers(mods, sym)
val tparams1 = tparams mapconserve (typed(_).asInstanceOf[TypeDef])
val vparamss1 = vparamss nestedMapconserve (typed(_).asInstanceOf[ValDef])
if (sym is Implicit) {
@@ -777,7 +778,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(implicit ctx: Context): Tree = track("typedTypeDef") {
val TypeDef(mods, name, rhs) = tdef
- val mods1 = typedModifiers(mods)
+ val mods1 = typedModifiers(mods, sym)
val _ = typedType(rhs) // unused, typecheck only to remove from typedTree
assignType(cpy.TypeDef(tdef, mods1, name, TypeTree(sym.info)), sym)
}
@@ -804,7 +805,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
val TypeDef(mods, name, impl @ Template(constr, parents, self, body)) = cdef
- val mods1 = typedModifiers(mods)
+ val mods1 = typedModifiers(mods, cls)
val constr1 = typed(constr).asInstanceOf[DefDef]
val parents1 = ensureConstrCall(ensureFirstIsClass(
parents mapconserve typedParent, cdef.pos.toSynthetic))
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index 3228c3474..c6fbcabf4 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -47,6 +47,8 @@ class tests extends CompilerTest {
@Test def pos_i39 = compileFile(posDir, "i39", doErase)
@Test def pos_overloadedAccess = compileFile(posDir, "overloadedAccess", doErase)
@Test def pos_approximateUnion = compileFile(posDir, "approximateUnion", doErase)
+ @Test def pos_tailcall = compileDir(posDir + "tailcall/", doErase)
+ @Test def pos_nullarify = compileFile(posDir, "nullarify", "-Ycheck:nullarify" :: doErase)
@Test def pos_all = compileFiles(posDir, twice)
@Test def new_all = compileFiles(newDir, twice)
@@ -69,6 +71,12 @@ class tests extends CompilerTest {
@Test def neg_t0625_structural = compileFile(negDir, "t0625", xerrors = 1)
@Test def neg_t0654_polyalias = compileFile(negDir, "t0654", xerrors = 2)
@Test def neg_t1192_legalPrefix = compileFile(negDir, "t1192", xerrors = 1)
+ @Test def neg_tailcall_t1672b = compileFile(negDir, "tailcall/t1672b", xerrors = 6)
+ @Test def neg_tailcall_t3275 = compileFile(negDir, "tailcall/t3275", xerrors = 1)
+ @Test def neg_tailcall_t6574 = compileFile(negDir, "tailcall/t6574", xerrors = 4)
+ @Test def neg_tailcall = compileFile(negDir, "tailcall/tailrec", xerrors = 7)
+ @Test def neg_tailcall2 = compileFile(negDir, "tailcall/tailrec-2", xerrors = 2)
+ @Test def neg_tailcall3 = compileFile(negDir, "tailcall/tailrec-3", xerrors = 2)
@Test def dotc = compileDir(dotcDir + "tools/dotc", twice)
@Test def dotc_ast = compileDir(dotcDir + "tools/dotc/ast", twice)
diff --git a/test/test/transform/LazyValsTest.scala b/test/test/transform/LazyValsTest.scala
index 32cd84b99..98853ad60 100644
--- a/test/test/transform/LazyValsTest.scala
+++ b/test/test/transform/LazyValsTest.scala
@@ -181,7 +181,7 @@ class LazyValsTest extends DottyTest {
def volatileFieldRef = {
checkCompile("LazyVals", "class LV { @volatile lazy val s = \"a\" }") {
(tree, ctx) =>
- val accessor = "DefDef(Modifiers(,,List()),s,List(),List(),TypeTree[TypeRef(ThisType(module class lang),String)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(null))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(a))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
+ val accessor = "DefDef(Modifiers(,,List(Apply(Select(New(Ident(volatile)),<init>),List()))),s,List(),List(),TypeTree[TypeRef(ThisType(module class lang),String)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(null))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(a))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
val fields = "ValDef(Modifiers(,,List()),s$lzy1,TypeTree[TypeRef(ThisType(module class lang),String)],Literal(Constant(null))), ValDef(Modifiers(,,List()),bitmap$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0)))"
val moduleField = "TypeDef(Modifiers(final module <synthetic>,,List()),LV$,Template(DefDef(Modifiers(,,List()),<init>,List(),List(List()),TypeTree[TypeRef(ThisType(module class <empty>),LV$)],EmptyTree),List(TypeTree[TypeRef(ThisType(module class lang),Object)]),ValDef(Modifiers(,,List()),_,TypeTree[TermRef(ThisType(module class <empty>),LV)],EmptyTree),List(ValDef(Modifiers(,,List()),OFFSET$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Apply(Select(Ident(LazyVals),getOffset),List(This(LV), Literal(Constant(bitmap$0))))))))"
val treeS = tree.toString
@@ -194,7 +194,7 @@ class LazyValsTest extends DottyTest {
def volatileFieldInt = {
checkCompile("LazyVals", "class LV { @volatile lazy val s = 1 }") {
(tree, ctx) =>
- val accessor = "DefDef(Modifiers(,,List()),s,List(),List(),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(0))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(1))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
+ val accessor = "DefDef(Modifiers(,,List(Apply(Select(New(Ident(volatile)),<init>),List()))),s,List(),List(),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(0))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(1))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
val fields = "ValDef(Modifiers(,,List()),s$lzy1,TypeTree[TypeRef(ThisType(module class scala),Int)],Literal(Constant(0))), ValDef(Modifiers(,,List()),bitmap$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0)))"
val moduleField = "TypeDef(Modifiers(final module <synthetic>,,List()),LV$,Template(DefDef(Modifiers(,,List()),<init>,List(),List(List()),TypeTree[TypeRef(ThisType(module class <empty>),LV$)],EmptyTree),List(TypeTree[TypeRef(ThisType(module class lang),Object)]),ValDef(Modifiers(,,List()),_,TypeTree[TermRef(ThisType(module class <empty>),LV)],EmptyTree),List(ValDef(Modifiers(,,List()),OFFSET$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Apply(Select(Ident(LazyVals),getOffset),List(This(LV), Literal(Constant(bitmap$0))))))))"
val treeS = tree.toString
@@ -207,7 +207,7 @@ class LazyValsTest extends DottyTest {
def volatileFieldLong = {
checkCompile("LazyVals", "class LV { @volatile lazy val s = 1L }") {
(tree, ctx) =>
- val accessor = "DefDef(Modifiers(,,List()),s,List(),List(),TypeTree[TypeRef(ThisType(module class scala),Long)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(0))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(1))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
+ val accessor = "DefDef(Modifiers(,,List(Apply(Select(New(Ident(volatile)),<init>),List()))),s,List(),List(),TypeTree[TypeRef(ThisType(module class scala),Long)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(0))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(1))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
val fields = "ValDef(Modifiers(,,List()),s$lzy1,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), ValDef(Modifiers(,,List()),bitmap$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0)))"
val moduleField = "TypeDef(Modifiers(final module <synthetic>,,List()),LV$,Template(DefDef(Modifiers(,,List()),<init>,List(),List(List()),TypeTree[TypeRef(ThisType(module class <empty>),LV$)],EmptyTree),List(TypeTree[TypeRef(ThisType(module class lang),Object)]),ValDef(Modifiers(,,List()),_,TypeTree[TermRef(ThisType(module class <empty>),LV)],EmptyTree),List(ValDef(Modifiers(,,List()),OFFSET$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Apply(Select(Ident(LazyVals),getOffset),List(This(LV), Literal(Constant(bitmap$0))))))))"
val treeS = tree.toString
@@ -220,7 +220,7 @@ class LazyValsTest extends DottyTest {
def volatileFieldFloat = {
checkCompile("LazyVals", "class LV { @volatile lazy val s = 1.0f }") {
(tree, ctx) =>
- val accessor = "DefDef(Modifiers(,,List()),s,List(),List(),TypeTree[TypeRef(ThisType(module class scala),Float)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(0.0))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(1.0))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
+ val accessor = "DefDef(Modifiers(,,List(Apply(Select(New(Ident(volatile)),<init>),List()))),s,List(),List(),TypeTree[TypeRef(ThisType(module class scala),Float)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(0.0))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(1.0))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
val fields = "ValDef(Modifiers(,,List()),s$lzy1,TypeTree[TypeRef(ThisType(module class scala),Float)],Literal(Constant(0.0))), ValDef(Modifiers(,,List()),bitmap$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0)))"
val moduleField = "TypeDef(Modifiers(final module <synthetic>,,List()),LV$,Template(DefDef(Modifiers(,,List()),<init>,List(),List(List()),TypeTree[TypeRef(ThisType(module class <empty>),LV$)],EmptyTree),List(TypeTree[TypeRef(ThisType(module class lang),Object)]),ValDef(Modifiers(,,List()),_,TypeTree[TermRef(ThisType(module class <empty>),LV)],EmptyTree),List(ValDef(Modifiers(,,List()),OFFSET$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Apply(Select(Ident(LazyVals),getOffset),List(This(LV), Literal(Constant(bitmap$0))))))))"
val treeS = tree.toString
@@ -233,7 +233,7 @@ class LazyValsTest extends DottyTest {
def volatileFieldDouble = {
checkCompile("LazyVals", "class LV { @volatile lazy val s = 1.0 }") {
(tree, ctx) =>
- val accessor = "DefDef(Modifiers(,,List()),s,List(),List(),TypeTree[TypeRef(ThisType(module class scala),Double)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(0.0))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(1.0))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
+ val accessor = "DefDef(Modifiers(,,List(Apply(Select(New(Ident(volatile)),<init>),List()))),s,List(),List(),TypeTree[TypeRef(ThisType(module class scala),Double)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(0.0))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(1.0))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
val fields = "ValDef(Modifiers(,,List()),s$lzy1,TypeTree[TypeRef(ThisType(module class scala),Double)],Literal(Constant(0.0))), ValDef(Modifiers(,,List()),bitmap$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0)))"
val moduleField = "TypeDef(Modifiers(final module <synthetic>,,List()),LV$,Template(DefDef(Modifiers(,,List()),<init>,List(),List(List()),TypeTree[TypeRef(ThisType(module class <empty>),LV$)],EmptyTree),List(TypeTree[TypeRef(ThisType(module class lang),Object)]),ValDef(Modifiers(,,List()),_,TypeTree[TermRef(ThisType(module class <empty>),LV)],EmptyTree),List(ValDef(Modifiers(,,List()),OFFSET$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Apply(Select(Ident(LazyVals),getOffset),List(This(LV), Literal(Constant(bitmap$0))))))))"
val treeS = tree.toString
@@ -246,7 +246,7 @@ class LazyValsTest extends DottyTest {
def volatileFieldBoolean = {
checkCompile("LazyVals", "class LV { @volatile lazy val s = true }") {
(tree, ctx) =>
- val accessor = "DefDef(Modifiers(,,List()),s,List(),List(),TypeTree[TypeRef(ThisType(module class scala),Boolean)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(false))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(true))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
+ val accessor = "DefDef(Modifiers(,,List(Apply(Select(New(Ident(volatile)),<init>),List()))),s,List(),List(),TypeTree[TypeRef(ThisType(module class scala),Boolean)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(false))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(true))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
val fields = "ValDef(Modifiers(,,List()),s$lzy1,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(false))), ValDef(Modifiers(,,List()),bitmap$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0)))"
val moduleField = "TypeDef(Modifiers(final module <synthetic>,,List()),LV$,Template(DefDef(Modifiers(,,List()),<init>,List(),List(List()),TypeTree[TypeRef(ThisType(module class <empty>),LV$)],EmptyTree),List(TypeTree[TypeRef(ThisType(module class lang),Object)]),ValDef(Modifiers(,,List()),_,TypeTree[TermRef(ThisType(module class <empty>),LV)],EmptyTree),List(ValDef(Modifiers(,,List()),OFFSET$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Apply(Select(Ident(LazyVals),getOffset),List(This(LV), Literal(Constant(bitmap$0))))))))"
val treeS = tree.toString
@@ -259,7 +259,7 @@ class LazyValsTest extends DottyTest {
def volatileFieldByte = {
checkCompile("LazyVals", "class LV { @volatile lazy val s:Byte = 1 }") {
(tree, ctx) =>
- val accessor = "DefDef(Modifiers(,,List()),s,List(),List(),TypeTree[TypeRef(TermRef(ThisType(module class <root>),scala),Byte)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(0))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(1))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
+ val accessor = "DefDef(Modifiers(,,List(Apply(Select(New(Ident(volatile)),<init>),List()))),s,List(),List(),TypeTree[TypeRef(TermRef(ThisType(module class <root>),scala),Byte)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(0))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(1))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
val fields = "ValDef(Modifiers(,,List()),s$lzy1,TypeTree[TypeRef(TermRef(ThisType(module class <root>),scala),Byte)],Literal(Constant(0))), ValDef(Modifiers(,,List()),bitmap$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0)))"
val moduleField = "TypeDef(Modifiers(final module <synthetic>,,List()),LV$,Template(DefDef(Modifiers(,,List()),<init>,List(),List(List()),TypeTree[TypeRef(ThisType(module class <empty>),LV$)],EmptyTree),List(TypeTree[TypeRef(ThisType(module class lang),Object)]),ValDef(Modifiers(,,List()),_,TypeTree[TermRef(ThisType(module class <empty>),LV)],EmptyTree),List(ValDef(Modifiers(,,List()),OFFSET$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Apply(Select(Ident(LazyVals),getOffset),List(This(LV), Literal(Constant(bitmap$0))))))))"
val treeS = tree.toString
@@ -272,7 +272,7 @@ class LazyValsTest extends DottyTest {
def volatileFieldShort = {
checkCompile("LazyVals", "class LV { @volatile lazy val s:Short = 1 }") {
(tree, ctx) =>
- val accessor = "DefDef(Modifiers(,,List()),s,List(),List(),TypeTree[TypeRef(TermRef(ThisType(module class <root>),scala),Short)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(0))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(1))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
+ val accessor = "DefDef(Modifiers(,,List(Apply(Select(New(Ident(volatile)),<init>),List()))),s,List(),List(),TypeTree[TypeRef(TermRef(ThisType(module class <root>),scala),Short)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(0))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(1))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
val fields = "ValDef(Modifiers(,,List()),s$lzy1,TypeTree[TypeRef(TermRef(ThisType(module class <root>),scala),Short)],Literal(Constant(0))), ValDef(Modifiers(,,List()),bitmap$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0)))"
val moduleField = "TypeDef(Modifiers(final module <synthetic>,,List()),LV$,Template(DefDef(Modifiers(,,List()),<init>,List(),List(List()),TypeTree[TypeRef(ThisType(module class <empty>),LV$)],EmptyTree),List(TypeTree[TypeRef(ThisType(module class lang),Object)]),ValDef(Modifiers(,,List()),_,TypeTree[TermRef(ThisType(module class <empty>),LV)],EmptyTree),List(ValDef(Modifiers(,,List()),OFFSET$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Apply(Select(Ident(LazyVals),getOffset),List(This(LV), Literal(Constant(bitmap$0))))))))"
val treeS = tree.toString
@@ -285,9 +285,10 @@ class LazyValsTest extends DottyTest {
def volatileFieldChar = {
checkCompile("LazyVals", "class LV { @volatile lazy val s = 'a' }") {
(tree, ctx) =>
- val accessor = "DefDef(Modifiers(,,List()),s,List(),List(),TypeTree[TypeRef(ThisType(module class scala),Char)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(\u0000))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(a))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
+ val accessor = "DefDef(Modifiers(,,List(Apply(Select(New(Ident(volatile)),<init>),List()))),s,List(),List(),TypeTree[TypeRef(ThisType(module class scala),Char)],Block(List(ValDef(Modifiers(,,List()),result,TypeTree[TermRef(ThisType(class LV),s)],Literal(Constant(\u0000))), ValDef(Modifiers(,,List()),retry,TypeTree[TypeRef(ThisType(module class scala),Boolean)],Literal(Constant(true))), ValDef(Modifiers(,,List()),flag,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0))), WhileDo(Ident(retry),Block(List(Assign(Ident(flag),Apply(Select(Ident(LazyVals),get),List(This(LV), Select(Ident(LV),OFFSET$0))))),Match(Apply(Select(Ident(LazyVals),STATE),List(Ident(flag), Literal(Constant(0)))),List(CaseDef(Literal(Constant(0)),EmptyTree,If(Apply(Select(Ident(LazyVals),CAS),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(1)), Literal(Constant(0)))),Block(List(Try(Assign(Ident(result),Literal(Constant(a))),Block(List(DefDef(Modifiers(,,List()),$anonfun,List(),List(List(ValDef(Modifiers(,,List()),x$1,TypeTree[TypeRef(ThisType(module class lang),Throwable)],EmptyTree))),TypeTree[TypeRef(ThisType(module class scala),Int)],Block(List(Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(0)), Literal(Constant(0))))),Throw(Ident(x$1))))),Closure(List(),Ident($anonfun),EmptyTree)),EmptyTree), Assign(Ident(s$lzy1),Ident(result)), Apply(Select(Ident(LazyVals),setFlag),List(This(LV), Select(Ident(LV),OFFSET$0), Literal(Constant(3)), Literal(Constant(0)))), Assign(Ident(retry),Literal(Constant(false)))),Literal(Constant(()))),Literal(Constant(())))), CaseDef(Literal(Constant(1)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(2)),EmptyTree,Apply(Select(Ident(LazyVals),wait4Notification),List(This(LV), Select(Ident(LV),OFFSET$0), Ident(flag), Literal(Constant(0))))), CaseDef(Literal(Constant(3)),EmptyTree,Block(List(Assign(Ident(retry),Literal(Constant(false))), Assign(Ident(result),Ident(s$lzy1))),Literal(Constant(()))))))))),Ident(result)))"
val fields = "ValDef(Modifiers(,,List()),s$lzy1,TypeTree[TypeRef(ThisType(module class scala),Char)],Literal(Constant(\u0000))), ValDef(Modifiers(,,List()),bitmap$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Literal(Constant(0)))"
val moduleField = "TypeDef(Modifiers(final module <synthetic>,,List()),LV$,Template(DefDef(Modifiers(,,List()),<init>,List(),List(List()),TypeTree[TypeRef(ThisType(module class <empty>),LV$)],EmptyTree),List(TypeTree[TypeRef(ThisType(module class lang),Object)]),ValDef(Modifiers(,,List()),_,TypeTree[TermRef(ThisType(module class <empty>),LV)],EmptyTree),List(ValDef(Modifiers(,,List()),OFFSET$0,TypeTree[TypeRef(ThisType(module class scala),Long)],Apply(Select(Ident(LazyVals),getOffset),List(This(LV), Literal(Constant(bitmap$0))))))))"
+
val treeS = tree.toString
Assert.assertTrue("volatile field lazy ref rewritten to class creation",
treeS.contains(accessor) && treeS.contains(fields) && treeS.contains(moduleField))
diff --git a/tests/untried/neg/t1672b.check b/tests/neg/tailcall/t1672b.check
index 60ccf7717..60ccf7717 100644
--- a/tests/untried/neg/t1672b.check
+++ b/tests/neg/tailcall/t1672b.check
diff --git a/tests/untried/neg/t1672b.scala b/tests/neg/tailcall/t1672b.scala
index 0ccdd0363..f05d05c34 100644
--- a/tests/untried/neg/t1672b.scala
+++ b/tests/neg/tailcall/t1672b.scala
@@ -1,4 +1,4 @@
-object Test {
+object Test1772B {
@annotation.tailrec
def bar : Nothing = {
try {
diff --git a/tests/untried/neg/t3275.check b/tests/neg/tailcall/t3275.check
index 117c79232..117c79232 100644
--- a/tests/untried/neg/t3275.check
+++ b/tests/neg/tailcall/t3275.check
diff --git a/tests/untried/neg/t3275.scala b/tests/neg/tailcall/t3275.scala
index 18e38a1a9..18e38a1a9 100644
--- a/tests/untried/neg/t3275.scala
+++ b/tests/neg/tailcall/t3275.scala
diff --git a/tests/untried/neg/t6574.check b/tests/neg/tailcall/t6574.check
index c67b4ed80..c67b4ed80 100644
--- a/tests/untried/neg/t6574.check
+++ b/tests/neg/tailcall/t6574.check
diff --git a/tests/untried/neg/t6574.scala b/tests/neg/tailcall/t6574.scala
index 9e1d624e5..59f3108ad 100644
--- a/tests/untried/neg/t6574.scala
+++ b/tests/neg/tailcall/t6574.scala
@@ -4,7 +4,7 @@ class Bad[X, Y](val v: Int) extends AnyVal {
println("tail")
}
- @annotation.tailrec final def differentTypeArgs {: Unit =
+ @annotation.tailrec final def differentTypeArgs : Unit = {
{(); new Bad[String, Unit](0)}.differentTypeArgs
}
}
diff --git a/tests/untried/neg/tailrec-2.check b/tests/neg/tailcall/tailrec-2.check
index 1daad6922..1daad6922 100644
--- a/tests/untried/neg/tailrec-2.check
+++ b/tests/neg/tailcall/tailrec-2.check
diff --git a/tests/untried/neg/tailrec-2.scala b/tests/neg/tailcall/tailrec-2.scala
index d6b8b1355..d6b8b1355 100644
--- a/tests/untried/neg/tailrec-2.scala
+++ b/tests/neg/tailcall/tailrec-2.scala
diff --git a/tests/untried/neg/tailrec-3.check b/tests/neg/tailcall/tailrec-3.check
index a3542fb56..a3542fb56 100644
--- a/tests/untried/neg/tailrec-3.check
+++ b/tests/neg/tailcall/tailrec-3.check
diff --git a/tests/untried/neg/tailrec-3.scala b/tests/neg/tailcall/tailrec-3.scala
index 20361658e..20361658e 100644
--- a/tests/untried/neg/tailrec-3.scala
+++ b/tests/neg/tailcall/tailrec-3.scala
diff --git a/tests/untried/neg/tailrec.check b/tests/neg/tailcall/tailrec.check
index 946d3421e..946d3421e 100644
--- a/tests/untried/neg/tailrec.check
+++ b/tests/neg/tailcall/tailrec.check
diff --git a/tests/untried/neg/tailrec.scala b/tests/neg/tailcall/tailrec.scala
index 83a0c1a9e..83a0c1a9e 100644
--- a/tests/untried/neg/tailrec.scala
+++ b/tests/neg/tailcall/tailrec.scala
diff --git a/tests/pos/implicits2.scala b/tests/pos/implicits2.scala
new file mode 100644
index 000000000..8e566c19f
--- /dev/null
+++ b/tests/pos/implicits2.scala
@@ -0,0 +1,19 @@
+/* Compile with
+
+ dotc implicits2.scala -Xprint:front -Xprint-types -verbose
+
+ and verify that the inserted wrapString comes from Predef. You should see
+
+ val x: <root>.scala.collection.immutable.WrappedString =
+ <
+ <scala.Predef.wrapString:
+ ((s: java.lang.String)scala.collection.immutable.WrappedString)
+ >
+ (<"abc":java.lang.String("abc")>):scala.collection.immutable.WrappedString
+ >
+*/
+object implicits2 {
+
+ val x: scala.collection.immutable.WrappedString = "abc"
+
+}
diff --git a/tests/pos/nullarify.scala b/tests/pos/nullarify.scala
new file mode 100644
index 000000000..62d16ba11
--- /dev/null
+++ b/tests/pos/nullarify.scala
@@ -0,0 +1,13 @@
+object Test {
+
+ def foo: Int = 2
+
+ println(foo)
+
+ def bar(x: => Int) = x + baz(x)
+
+ def baz(y: => Int) = y
+
+ bar(foo)
+
+}
diff --git a/tests/pos/tailcall/t1672.scala b/tests/pos/tailcall/t1672.scala
new file mode 100644
index 000000000..9be5c6066
--- /dev/null
+++ b/tests/pos/tailcall/t1672.scala
@@ -0,0 +1,10 @@
+object Test1672 {
+ @annotation.tailrec
+ def bar(x: Int)(y: Int) : Nothing = {
+ try {
+ throw new RuntimeException
+ } catch {
+ case _: Throwable => bar(x)(y)
+ }
+ }
+}
diff --git a/tests/untried/pos/t4649.flags b/tests/pos/tailcall/t4649.flags
index e8fb65d50..e8fb65d50 100644
--- a/tests/untried/pos/t4649.flags
+++ b/tests/pos/tailcall/t4649.flags
diff --git a/tests/untried/pos/t4649.scala b/tests/pos/tailcall/t4649.scala
index 0d6caa8d7..5f009b7a4 100644
--- a/tests/untried/pos/t4649.scala
+++ b/tests/pos/tailcall/t4649.scala
@@ -1,4 +1,4 @@
-object Test {
+object Test4649 {
// @annotation.tailrec
def lazyFilter[E](s: Stream[E], p: E => Boolean): Stream[E] = s match {
case h #:: t => if (p(h)) h #:: lazyFilter(t, p) else lazyFilter(t, p)
diff --git a/tests/untried/pos/t6479.scala b/tests/pos/tailcall/t6479.scala
index e4a4ff601..e4a4ff601 100644
--- a/tests/untried/pos/t6479.scala
+++ b/tests/pos/tailcall/t6479.scala
diff --git a/tests/untried/pos/t6574.scala b/tests/pos/tailcall/t6574.scala
index 6bb0042c6..cd0fdbb8d 100644
--- a/tests/untried/pos/t6574.scala
+++ b/tests/pos/tailcall/t6574.scala
@@ -4,7 +4,7 @@ class Bad[X, Y](val v: Int) extends AnyVal {
this.foo[Z](a)(b)
}
- @annotation.tailrec final def differentReceiver {: Unit =
+ @annotation.tailrec final def differentReceiver : Unit = {
{(); new Bad[X, Y](0)}.differentReceiver
}
diff --git a/tests/untried/pos/t6891.flags b/tests/pos/tailcall/t6891.flags
index fe048006a..fe048006a 100644
--- a/tests/untried/pos/t6891.flags
+++ b/tests/pos/tailcall/t6891.flags
diff --git a/tests/untried/pos/t6891.scala b/tests/pos/tailcall/t6891.scala
index bed2d0d77..edbe6f097 100644
--- a/tests/untried/pos/t6891.scala
+++ b/tests/pos/tailcall/t6891.scala
@@ -1,4 +1,4 @@
-object O {
+object O6891 {
implicit class Foo[A](val value: String) extends AnyVal {
def bippy() = {
@annotation.tailrec def loop(x: A): Unit = loop(x)
diff --git a/tests/pos/tailcall/tailcall.scala b/tests/pos/tailcall/tailcall.scala
new file mode 100644
index 000000000..9cf373cf0
--- /dev/null
+++ b/tests/pos/tailcall/tailcall.scala
@@ -0,0 +1,5 @@
+class tailcall {
+ val shift = 1
+ final def fact(x: Int, acc: Int = 1): Int = if (x == 0) acc else fact(x - shift, acc * x)
+ def id[T <: AnyRef](x: T): T = if (x eq null) x else id(x)
+}
diff --git a/tests/pos/typers.scala b/tests/pos/typers.scala
index 4f012e7bf..a95af558e 100644
--- a/tests/pos/typers.scala
+++ b/tests/pos/typers.scala
@@ -77,7 +77,7 @@ object typers {
class C {
- @tailrec def factorial(acc: Int, n: Int): Int = (n: @switch) match {
+ @tailrec final def factorial(acc: Int, n: Int): Int = (n: @switch) match {
case 0 => acc
case _ => factorial(acc * n, n - 1)
}
diff --git a/tests/untried/pos/t1672.scala b/tests/untried/pos/t1672.scala
deleted file mode 100644
index 5ee6bb175..000000000
--- a/tests/untried/pos/t1672.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-object Test {
- @annotation.tailrec
- def bar : Nothing = {
- try {
- throw new RuntimeException
- } catch {
- case _: Throwable => bar
- }
- }
-}