Skip to content

Commit 9956adf

Browse files
olhotakhamzaremmallrytz
authored
fix #22833: allow unroll annotation in methods of final class (#22926)
Closes #22833 --------- Co-authored-by: Hamza Remmal <[email protected]> Co-authored-by: Lukas Rytz <[email protected]>
1 parent 5b4b5c2 commit 9956adf

File tree

6 files changed

+18
-12
lines changed

6 files changed

+18
-12
lines changed

compiler/src/dotty/tools/dotc/reporting/messages.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -3430,12 +3430,12 @@ extends DeclarationMsg(IllegalUnrollPlacementID):
34303430
val isCtor = method.isConstructor
34313431
def what = if isCtor then i"a ${if method.owner.is(Trait) then "trait" else "class"} constructor" else i"method ${method.name}"
34323432
val prefix = s"Cannot unroll parameters of $what"
3433-
if method.is(Deferred) then
3434-
i"$prefix: it must not be abstract"
3433+
if method.isLocal then
3434+
i"$prefix because it is a local method"
3435+
else if !method.isEffectivelyFinal then
3436+
i"$prefix because it can be overridden"
34353437
else if isCtor && method.owner.is(Trait) then
34363438
i"implementation restriction: $prefix"
3437-
else if !(isCtor || method.is(Final) || method.owner.is(ModuleClass)) then
3438-
i"$prefix: it is not final"
34393439
else if method.owner.companionClass.is(CaseClass) then
34403440
i"$prefix of a case class companion object: please annotate the class constructor instead"
34413441
else

compiler/src/dotty/tools/dotc/transform/PostTyper.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,9 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
132132
then
133133
false // not an error, but not an expandable unrolled method
134134
else if
135-
method.is(Deferred)
135+
method.isLocal
136+
|| !method.isEffectivelyFinal
136137
|| isCtor && method.owner.is(Trait)
137-
|| !(isCtor || method.is(Final) || method.owner.is(ModuleClass))
138138
|| method.owner.companionClass.is(CaseClass)
139139
&& (method.name == nme.apply || method.name == nme.fromProduct)
140140
|| method.owner.is(CaseClass) && method.name == nme.copy

compiler/src/dotty/tools/dotc/transform/UnrollDefinitions.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ class UnrollDefinitions extends MacroTransform, IdentityDenotTransformer {
7979
else Some((paramClauseIndex, annotationIndices))
8080
if indices.nonEmpty then
8181
// pre-validation should have occurred in posttyper
82-
assert(annotated.is(Final, butNot = Deferred) || annotated.isConstructor || annotated.owner.is(ModuleClass) || annotated.name.is(DefaultGetterName),
82+
assert(!annotated.isLocal, i"$annotated is local")
83+
assert(annotated.isEffectivelyFinal || annotated.name.is(DefaultGetterName),
8384
i"$annotated is not final&concrete, or a constructor")
8485
indices
8586
})

tests/neg/unroll-abstractMethod.check

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
-- [E207] Declaration Error: tests/neg/unroll-abstractMethod.scala:6:41 ------------------------------------------------
22
6 | def foo(s: String, n: Int = 1, @unroll b: Boolean = true): String // error
33
| ^
4-
| Cannot unroll parameters of method foo: it must not be abstract
4+
| Cannot unroll parameters of method foo because it can be overridden
55
-- [E207] Declaration Error: tests/neg/unroll-abstractMethod.scala:10:41 -----------------------------------------------
66
10 | def foo(s: String, n: Int = 1, @unroll b: Boolean = true): String // error
77
| ^
8-
| Cannot unroll parameters of method foo: it must not be abstract
8+
| Cannot unroll parameters of method foo because it can be overridden

tests/neg/unroll-illegal3.check

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
-- [E207] Declaration Error: tests/neg/unroll-illegal3.scala:7:31 ------------------------------------------------------
22
7 | def foo(s: String, @unroll y: Boolean) = s + y // error
33
| ^
4-
| Cannot unroll parameters of method foo: it is not final
4+
| Cannot unroll parameters of method foo because it is a local method
55
-- [E207] Declaration Error: tests/neg/unroll-illegal3.scala:12:29 -----------------------------------------------------
66
12 | def foo(s: String, @unroll y: Boolean) = s + y // error
77
| ^
8-
| Cannot unroll parameters of method foo: it is not final
8+
| Cannot unroll parameters of method foo because it can be overridden
99
-- [E207] Declaration Error: tests/neg/unroll-illegal3.scala:16:29 -----------------------------------------------------
1010
16 | def foo(s: String, @unroll y: Boolean): String // error
1111
| ^
12-
| Cannot unroll parameters of method foo: it must not be abstract
12+
| Cannot unroll parameters of method foo because it can be overridden
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import scala.annotation.{experimental,unroll}
2+
3+
@experimental final class Foo {
4+
def bar(@unroll x: Int = 0) = x + 1
5+
}

0 commit comments

Comments
 (0)