From 5994bfa12ff248449b195708e09c00a614329b34 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 14 Jan 2019 17:49:54 +0100 Subject: [PATCH 1/3] Fix #5350: Fix purity of local lazy vals --- compiler/src/dotty/tools/dotc/ast/TreeInfo.scala | 4 +++- compiler/test-resources/repl/i5350 | 7 +++++++ tests/run/i5350.check | 1 + tests/run/i5350.scala | 10 ++++++++++ 4 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 compiler/test-resources/repl/i5350 create mode 100644 tests/run/i5350.check create mode 100644 tests/run/i5350.scala diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 903c7aa9897b..7db82df9e723 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -400,10 +400,12 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => def isKnownPureOp(sym: Symbol) = sym.owner.isPrimitiveValueClass || sym.owner == defn.StringClass if (tree.tpe.isInstanceOf[ConstantType] && isKnownPureOp(tree.symbol) // A constant expression with pure arguments is pure. - || fn.symbol.isStable + || (fn.symbol.isStable && !fn.symbol.is(Lazy)) || fn.symbol.isPrimaryConstructor && fn.symbol.owner.isNoInitsClass) // TODO: include in isStable? minOf(exprPurity(fn), args.map(exprPurity)) `min` Pure else if (fn.symbol.is(Erased)) Pure + else if (fn.symbol.isStable /* && fn.symbol.is(Lazy) */) + minOf(exprPurity(fn), args.map(exprPurity)) `min` Idempotent else Impure case Typed(expr, _) => exprPurity(expr) diff --git a/compiler/test-resources/repl/i5350 b/compiler/test-resources/repl/i5350 new file mode 100644 index 000000000000..8b50edc42ab2 --- /dev/null +++ b/compiler/test-resources/repl/i5350 @@ -0,0 +1,7 @@ +scala> def foo = { lazy val bar: Unit = { println("Hello") }; bar } +def foo: Unit +scala> foo +Hello +scala> { lazy val bar: Unit = { println("Hello") }; bar } +Hello +val bar: Unit = diff --git a/tests/run/i5350.check b/tests/run/i5350.check new file mode 100644 index 000000000000..e965047ad7c5 --- /dev/null +++ b/tests/run/i5350.check @@ -0,0 +1 @@ +Hello diff --git a/tests/run/i5350.scala b/tests/run/i5350.scala new file mode 100644 index 000000000000..557d2ae45155 --- /dev/null +++ b/tests/run/i5350.scala @@ -0,0 +1,10 @@ +object Test { + def foo = { + lazy val bar: Unit = println("Hello") + bar + } + + def main(args: Array[String]): Unit = { + foo + } +} From 511caeb17f56034bee79b9ff6b77138b789b0728 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 14 Jan 2019 18:02:24 +0100 Subject: [PATCH 2/3] Fix printing of lazy vals in the REPL --- compiler/src/dotty/tools/dotc/printing/ReplPrinter.scala | 1 + compiler/src/dotty/tools/repl/Rendering.scala | 7 ++----- compiler/test-resources/repl/i5350 | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/printing/ReplPrinter.scala b/compiler/src/dotty/tools/dotc/printing/ReplPrinter.scala index a66555423e64..526e32fd07e8 100644 --- a/compiler/src/dotty/tools/dotc/printing/ReplPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/ReplPrinter.scala @@ -29,6 +29,7 @@ class ReplPrinter(_ctx: Context) extends DecompilerPrinter(_ctx) { else Str(const.value.toString) override def dclText(sym: Symbol): Text = { + ("lazy": Text).provided(sym.is(Lazy)) ~~ toText(sym) ~ { if (sym.is(Method)) toText(sym.info) else if (sym.isType && sym.info.isTypeAlias) toText(sym.info) diff --git a/compiler/src/dotty/tools/repl/Rendering.scala b/compiler/src/dotty/tools/repl/Rendering.scala index 9d130b5166fc..127936dca36b 100644 --- a/compiler/src/dotty/tools/repl/Rendering.scala +++ b/compiler/src/dotty/tools/repl/Rendering.scala @@ -76,11 +76,8 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None) { val dcl = d.symbol.showUser try { - val resultValue = - if (d.symbol.is(Flags.Lazy)) Some("") - else valueOf(d.symbol) - - resultValue.map(value => s"$dcl = $value") + if (d.symbol.is(Flags.Lazy)) Some(dcl) + else valueOf(d.symbol).map(value => s"$dcl = $value") } catch { case ex: InvocationTargetException => Some(renderError(ex)) } } diff --git a/compiler/test-resources/repl/i5350 b/compiler/test-resources/repl/i5350 index 8b50edc42ab2..c2f11565a695 100644 --- a/compiler/test-resources/repl/i5350 +++ b/compiler/test-resources/repl/i5350 @@ -4,4 +4,4 @@ scala> foo Hello scala> { lazy val bar: Unit = { println("Hello") }; bar } Hello -val bar: Unit = +lazy val bar: Unit From ec3b3e1793778d7ec8bcfe2d2598af7c8409927f Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 15 Jan 2019 17:51:29 +0100 Subject: [PATCH 3/3] Add tests --- tests/run/i5350b.check | 1 + tests/run/i5350b.scala | 10 ++++++++++ tests/run/i5350c.check | 1 + tests/run/i5350c.scala | 10 ++++++++++ tests/run/i5350d.check | 2 ++ tests/run/i5350d.scala | 13 +++++++++++++ 6 files changed, 37 insertions(+) create mode 100644 tests/run/i5350b.check create mode 100644 tests/run/i5350b.scala create mode 100644 tests/run/i5350c.check create mode 100644 tests/run/i5350c.scala create mode 100644 tests/run/i5350d.check create mode 100644 tests/run/i5350d.scala diff --git a/tests/run/i5350b.check b/tests/run/i5350b.check new file mode 100644 index 000000000000..e965047ad7c5 --- /dev/null +++ b/tests/run/i5350b.check @@ -0,0 +1 @@ +Hello diff --git a/tests/run/i5350b.scala b/tests/run/i5350b.scala new file mode 100644 index 000000000000..72dbaf588ea7 --- /dev/null +++ b/tests/run/i5350b.scala @@ -0,0 +1,10 @@ +object Test { + def foo: Unit = { + object bar { println("Hello") } + bar + } + + def main(args: Array[String]): Unit = { + foo + } +} diff --git a/tests/run/i5350c.check b/tests/run/i5350c.check new file mode 100644 index 000000000000..e965047ad7c5 --- /dev/null +++ b/tests/run/i5350c.check @@ -0,0 +1 @@ +Hello diff --git a/tests/run/i5350c.scala b/tests/run/i5350c.scala new file mode 100644 index 000000000000..e1d6989ed063 --- /dev/null +++ b/tests/run/i5350c.scala @@ -0,0 +1,10 @@ +object Test { + def foo: Unit = { + bar + } + + def main(args: Array[String]): Unit = { + foo + } +} +object bar { println("Hello") } diff --git a/tests/run/i5350d.check b/tests/run/i5350d.check new file mode 100644 index 000000000000..c3ace6f60ae3 --- /dev/null +++ b/tests/run/i5350d.check @@ -0,0 +1,2 @@ +Hello +apply diff --git a/tests/run/i5350d.scala b/tests/run/i5350d.scala new file mode 100644 index 000000000000..3a0019eba1d3 --- /dev/null +++ b/tests/run/i5350d.scala @@ -0,0 +1,13 @@ +object Test { + def foo: Unit = { + bar() + } + + def main(args: Array[String]): Unit = { + foo + } +} +object bar { + println("Hello") + def apply(): Unit = println("apply") +}