diff --git a/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala b/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala index c70826a71934..03251110f006 100644 --- a/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala +++ b/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala @@ -73,6 +73,37 @@ class InlineBytecodeTests extends DottyBytecodeTest { } } + @Test def inlineLocally = { + val source = + """ + |class Foo { + | def meth1: Unit = locally { + | val a = 5 + | a + | } + | + | def meth2: Unit = { + | val a = 5 + | a + | } + |} + """.stripMargin + + checkBCode(source) { dir => + val clsIn = dir.lookupName("Foo.class", directory = false).input + val clsNode = loadClassNode(clsIn) + val meth1 = getMethod(clsNode, "meth1") + val meth2 = getMethod(clsNode, "meth2") + + val instructions1 = instructionsFromMethod(meth1) + val instructions2 = instructionsFromMethod(meth2) + + assert(instructions1 == instructions2, + "`locally` was not properly inlined in `meth1`\n" + + diffInstructions(instructions1, instructions2)) + } + } + @Test def i4947 = { val source = """class Foo { | inline def track[T](inline f: T) <: T = { diff --git a/library/src/dotty/DottyPredef.scala b/library/src/dotty/DottyPredef.scala index d3f317b0381e..8e334dfd99a5 100644 --- a/library/src/dotty/DottyPredef.scala +++ b/library/src/dotty/DottyPredef.scala @@ -18,7 +18,36 @@ object DottyPredef { inline final def implicitly[T](implicit ev: T): T = ev - inline def locally[T](body: => T): T = body + /** Used to mark code blocks as being expressions, instead of being taken as part of anonymous classes and the like. + * This is just a different name for [[identity]]. + * + * @example Separating code blocks from `new`: + * {{{ + * val x = new AnyRef + * { + * val y = ... + * println(y) + * } + * // the { ... } block is seen as the body of an anonymous class + * + * val x = new AnyRef + * + * { + * val y = ... + * println(y) + * } + * // an empty line is a brittle "fix" + * + * val x = new AnyRef + * locally { + * val y = ... + * println(y) + * } + * // locally guards the block and helps communicate intent + * }}} + * @group utilities + */ + inline def locally[T](inline body: T): T = body /** * Retrieve the single value of a type with a unique inhabitant.