Skip to content

Commit fba2445

Browse files
committed
better error when multiple parameter lists with unroll
1 parent 1f98384 commit fba2445

File tree

4 files changed

+46
-26
lines changed

4 files changed

+46
-26
lines changed

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

+16-12
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import reporting.*
2121
import NameKinds.WildcardParamName
2222
import cc.*
2323
import dotty.tools.dotc.transform.MacroAnnotations.hasMacroAnnotation
24+
import dotty.tools.dotc.core.NameKinds.DefaultGetterName
2425

2526
object PostTyper {
2627
val name: String = "posttyper"
@@ -133,18 +134,21 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
133134
else
134135
local
135136
seenMethods.getOrElseUpdate(method, {
136-
var res = true
137-
if method.is(Deferred) then
138-
report.error("Unrolled method must be final and concrete", method.srcPos)
139-
res = false
140-
val isCtor = method.isConstructor
141-
if isCtor && method.owner.is(Trait) then
142-
report.error("implementation restriction: Unrolled method cannot be a trait constructor", method.srcPos)
143-
res = false
144-
if !(isCtor || method.is(Final) || method.owner.is(ModuleClass)) then
145-
report.error("Unrolled method must be final", method.srcPos)
146-
res = false
147-
res
137+
if method.name.is(DefaultGetterName) then
138+
false // not an error, but not an expandable unrolled method
139+
else
140+
var res = true
141+
if method.is(Deferred) then
142+
report.error("Unrolled method must be final and concrete", method.srcPos)
143+
res = false
144+
val isCtor = method.isConstructor
145+
if isCtor && method.owner.is(Trait) then
146+
report.error("implementation restriction: Unrolled method cannot be a trait constructor", method.srcPos)
147+
res = false
148+
if !(isCtor || method.is(Final) || method.owner.is(ModuleClass)) then
149+
report.error(s"Unrolled method ${method} must be final", method.srcPos)
150+
res = false
151+
res
148152
})
149153

150154
def withNoCheckNews[T](ts: List[New])(op: => T): T = {

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

+19-14
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,21 @@ class UnrollDefinitions extends MacroTransform, IdentityDenotTransformer {
6565

6666
def computeIndices(annotated: Symbol)(using Context): ComputedIndicies =
6767
unrolledDefs.getOrElseUpdate(annotated, {
68-
val indices = annotated
69-
.paramSymss
70-
.zipWithIndex
71-
.flatMap: (paramClause, paramClauseIndex) =>
72-
val annotationIndices = findUnrollAnnotations(paramClause)
73-
if (annotationIndices.isEmpty) None
74-
else Some((paramClauseIndex, annotationIndices))
75-
if indices.nonEmpty then
76-
// pre-validation should have occurred in posttyper
77-
assert(annotated.is(Final, butNot = Deferred) || annotated.isConstructor || annotated.owner.is(ModuleClass),
78-
i"$annotated is not final&concrete, or a constructor")
79-
indices
68+
if annotated.name.is(DefaultGetterName) then
69+
Nil // happens in curried methods where more than one parameter list has @unroll
70+
else
71+
val indices = annotated
72+
.paramSymss
73+
.zipWithIndex
74+
.flatMap: (paramClause, paramClauseIndex) =>
75+
val annotationIndices = findUnrollAnnotations(paramClause)
76+
if (annotationIndices.isEmpty) None
77+
else Some((paramClauseIndex, annotationIndices))
78+
if indices.nonEmpty then
79+
// pre-validation should have occurred in posttyper
80+
assert(annotated.is(Final, butNot = Deferred) || annotated.isConstructor || annotated.owner.is(ModuleClass) || annotated.name.is(DefaultGetterName),
81+
i"$annotated is not final&concrete, or a constructor")
82+
indices
8083
})
8184
end computeIndices
8285

@@ -103,7 +106,7 @@ class UnrollDefinitions extends MacroTransform, IdentityDenotTransformer {
103106
params
104107
.zipWithIndex
105108
.collect {
106-
case (v, i) if v.annotations.exists(_.symbol.fullName.toString == "scala.annotation.unroll") =>
109+
case (v, i) if v.hasAnnotation(defn.UnrollAnnot) =>
107110
i
108111
}
109112
}
@@ -303,7 +306,9 @@ class UnrollDefinitions extends MacroTransform, IdentityDenotTransformer {
303306
case _ => unreachable("sliding with at least 2 elements")
304307
Some((defdef.symbol, None, generatedDefs))
305308

306-
case multiple => sys.error("Cannot have multiple parameter lists containing `@unroll` annotation")
309+
case multiple =>
310+
report.error("Cannot have multiple parameter lists containing `@unroll` annotation", defdef.srcPos)
311+
None
307312
}
308313

309314
case _ => None

tests/neg/unroll-multipleParams.check

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- Error: tests/neg/unroll-multipleParams.scala:6:12 -------------------------------------------------------------------
2+
6 | final def foo(x: Int, @unroll y: Int = 0)(@unroll z: Int = 0) = x + y + z // error
3+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
| Cannot have multiple parameter lists containing `@unroll` annotation

tests/neg/unroll-multipleParams.scala

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//> using options -experimental
2+
3+
import scala.annotation.unroll
4+
5+
class Foo {
6+
final def foo(x: Int, @unroll y: Int = 0)(@unroll z: Int = 0) = x + y + z // error
7+
}

0 commit comments

Comments
 (0)