diff options
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 - } - } -} |