From d30e213f85629f4767b1d3a3e9dd013f61d715c2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 9 Mar 2016 09:46:12 +0100 Subject: [PATCH] Fix two rewrite patches. 1. trailing `_`: `x _` is rewritten to `(() => x)` not to `x` 2. lazy vals: Rewrites are done in Typer, not LazyVals. Later on we are too much at risk to hit synthetically generated lazy vals. --- src/dotty/tools/dotc/transform/LazyVals.scala | 18 ++++++------------ src/dotty/tools/dotc/typer/Typer.scala | 19 +++++++++++++++++-- tests/pos-scala2/rewrites.scala | 1 + 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/dotty/tools/dotc/transform/LazyVals.scala b/src/dotty/tools/dotc/transform/LazyVals.scala index 26c76c8510ae..9a1ab9a31a20 100644 --- a/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/src/dotty/tools/dotc/transform/LazyVals.scala @@ -14,7 +14,6 @@ import StdNames.nme import rewrite.Rewrites.patch import util.Positions.Position import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransformer, MiniPhaseTransform} -import dotty.tools.dotc.ast.NavigateAST._ import dotty.tools.dotc.ast.Trees._ import dotty.tools.dotc.ast.{untpd, tpd} import dotty.tools.dotc.core.Constants.Constant @@ -70,19 +69,14 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer with Nee val isField = sym.owner.isClass if (isField) { if (sym.isVolatile || - ctx.scala2Mode && { - if (ctx.settings.rewrite.value.isDefined) - patch(ctx.compilationUnit.source, Position(toUntyped(tree).envelope.start), "@volatile ") - false // cannot assume volatile because of problems with compilestdlib. See #1149 - } || - (sym.is(Flags.Module) && !sym.is(Flags.Synthetic))) - // module class is user-defined. - // Should be threadsafe, to mimic safety guaranteed by global object + (sym.is(Flags.Module)/* || ctx.scala2Mode*/) && !sym.is(Flags.Synthetic)) // TODO assume @voliat + // module class is user-defined. + // Should be threadsafe, to mimic safety guaranteed by global object transformMemberDefVolatile(tree) - else if (sym.is(Flags.Module)) { // synthetic module + else if (sym.is(Flags.Module)) // synthetic module transformSyntheticModule(tree) - } - else transformMemberDefNonVolatile(tree) + else + transformMemberDefNonVolatile(tree) } else transformLocalDef(tree) } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index b4b1bcc64401..397943c15c21 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -34,6 +34,8 @@ import Implicits._ import util.Stats.{track, record} import config.Printers._ import rewrite.Rewrites.patch +import NavigateAST._ +import transform.SymUtils._ import language.implicitConversions object Typer { @@ -984,7 +986,18 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case rhs @ Ident(nme.WILDCARD) => rhs withType tpt1.tpe case rhs => typedExpr(rhs, tpt1.tpe) } - assignType(cpy.ValDef(vdef)(name, tpt1, rhs1), sym) + val vdef1 = assignType(cpy.ValDef(vdef)(name, tpt1, rhs1), sym) + patchIfLazy(vdef1) + vdef1 + } + + /** Add a @volitile to lazy vals when rewriting from Scala2 */ + private def patchIfLazy(vdef: ValDef)(implicit ctx: Context): Unit = { + val sym = vdef.symbol + if (sym.is(Lazy, butNot = Deferred | Module | Synthetic) && !sym.isVolatile && + ctx.scala2Mode && ctx.settings.rewrite.value.isDefined && + !ctx.isAfterTyper) + patch(ctx.compilationUnit.source, Position(toUntyped(vdef).envelope.start), "@volatile ") } def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context) = track("typedDefDef") { @@ -1142,8 +1155,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit if (pt1.eq(AnyFunctionProto) && !defn.isFunctionClass(res.tpe.classSymbol)) { def msg = i"not a function: ${res.tpe}; cannot be followed by `_'" if (ctx.scala2Mode) { + // Under -rewrite, patch `x _` to `(() => x)` ctx.migrationWarning(msg, tree.pos) - patch(ctx.compilationUnit.source, Position(qual.pos.end, tree.pos.end), "") + patch(ctx.compilationUnit.source, Position(tree.pos.start), "(() => ") + patch(ctx.compilationUnit.source, Position(qual.pos.end, tree.pos.end), ")") res = typed(untpd.Function(Nil, untpd.TypedSplice(res))) } else ctx.error(msg, tree.pos) diff --git a/tests/pos-scala2/rewrites.scala b/tests/pos-scala2/rewrites.scala index 6ce1f33a464d..3987821f1586 100644 --- a/tests/pos-scala2/rewrites.scala +++ b/tests/pos-scala2/rewrites.scala @@ -24,6 +24,7 @@ object Test { @deprecated private lazy val (x2, y2) = (1, 2) val yy = x1 _ + val zz: () => Int = yy }