Skip to content

Commit 7a28eef

Browse files
Merge pull request #8636 from dotty-staging/properly-optimize-locally
Properly inline DottyPredef.locally
2 parents 8a42819 + 3b20476 commit 7a28eef

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,37 @@ class InlineBytecodeTests extends DottyBytecodeTest {
7373
}
7474
}
7575

76+
@Test def inlineLocally = {
77+
val source =
78+
"""
79+
|class Foo {
80+
| def meth1: Unit = locally {
81+
| val a = 5
82+
| a
83+
| }
84+
|
85+
| def meth2: Unit = {
86+
| val a = 5
87+
| a
88+
| }
89+
|}
90+
""".stripMargin
91+
92+
checkBCode(source) { dir =>
93+
val clsIn = dir.lookupName("Foo.class", directory = false).input
94+
val clsNode = loadClassNode(clsIn)
95+
val meth1 = getMethod(clsNode, "meth1")
96+
val meth2 = getMethod(clsNode, "meth2")
97+
98+
val instructions1 = instructionsFromMethod(meth1)
99+
val instructions2 = instructionsFromMethod(meth2)
100+
101+
assert(instructions1 == instructions2,
102+
"`locally` was not properly inlined in `meth1`\n" +
103+
diffInstructions(instructions1, instructions2))
104+
}
105+
}
106+
76107
@Test def i4947 = {
77108
val source = """class Foo {
78109
| transparent inline def track[T](inline f: T): T = {

library/src/dotty/DottyPredef.scala

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,36 @@ object DottyPredef {
1818

1919
inline final def implicitly[T](implicit ev: T): T = ev
2020

21-
inline def locally[T](body: => T): T = body
21+
/** Used to mark code blocks as being expressions, instead of being taken as part of anonymous classes and the like.
22+
* This is just a different name for [[identity]].
23+
*
24+
* @example Separating code blocks from `new`:
25+
* {{{
26+
* val x = new AnyRef
27+
* {
28+
* val y = ...
29+
* println(y)
30+
* }
31+
* // the { ... } block is seen as the body of an anonymous class
32+
*
33+
* val x = new AnyRef
34+
*
35+
* {
36+
* val y = ...
37+
* println(y)
38+
* }
39+
* // an empty line is a brittle "fix"
40+
*
41+
* val x = new AnyRef
42+
* locally {
43+
* val y = ...
44+
* println(y)
45+
* }
46+
* // locally guards the block and helps communicate intent
47+
* }}}
48+
* @group utilities
49+
*/
50+
inline def locally[T](inline body: T): T = body
2251

2352
/**
2453
* Retrieve the single value of a type with a unique inhabitant.

0 commit comments

Comments
 (0)