Skip to content

Commit

Permalink
Only allow erased parameters in erased definitions (#19686)
Browse files Browse the repository at this point in the history
So far, we do not have any use case for them. We could enable them in a
later version.

The current implementation does not handle correctly the non-erased
arguments to erased definitions. These should always be evaluated, but
in some cases we can dorp them by mistake.
  • Loading branch information
nicolasstucki authored Apr 11, 2024
2 parents bfc8a0d + f4ff6e3 commit a14c79e
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 72 deletions.
7 changes: 7 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/PostTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,14 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
report.error("classes that extend MacroAnnotation must not be inner/local classes", sym.srcPos)

private def checkErasedDef(tree: ValOrDefDef)(using Context): Unit =
def checkOnlyErasedParams(): Unit = tree match
case tree: DefDef =>
for params <- tree.paramss; param <- params if !param.symbol.isType && !param.symbol.is(Erased) do
report.error("erased definition can only have erased parameters", param.srcPos)
case _ =>

if tree.symbol.is(Erased, butNot = Macro) then
checkOnlyErasedParams()
val tpe = tree.rhs.tpe
if tpe.derivesFrom(defn.NothingClass) then
report.error("`erased` definition cannot be implemented with en expression of type Nothing", tree.srcPos)
Expand Down
2 changes: 1 addition & 1 deletion tests/coverage/run/erased/test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import scala.language.experimental.erasedDefinitions

erased def parameterless: String = "y"

erased def e(x: String): String = "x"
erased def e(erased x: String): String = "x"
def foo(erased a: String)(b: String): String =
println(s"foo(a)($b)")
b
Expand Down
42 changes: 21 additions & 21 deletions tests/coverage/run/erased/test.scoverage.check
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ test$package
Object
<empty>.test$package
foo
181
203
188
210
7
println
Apply
Expand All @@ -42,8 +42,8 @@ test$package
Object
<empty>.test$package
foo
189
202
196
209
7
s
Apply
Expand All @@ -59,8 +59,8 @@ test$package
Object
<empty>.test$package
foo
132
139
146
6
foo
DefDef
Expand All @@ -76,8 +76,8 @@ test$package
Object
<empty>.test$package
identity
245
269
252
276
11
println
Apply
Expand All @@ -93,8 +93,8 @@ test$package
Object
<empty>.test$package
identity
253
268
260
275
11
s
Apply
Expand All @@ -110,8 +110,8 @@ test$package
Object
<empty>.test$package
identity
209
221
216
228
10
identity
DefDef
Expand All @@ -127,8 +127,8 @@ test$package
Object
<empty>.test$package
Test
300
323
307
330
16
foo
Apply
Expand All @@ -144,8 +144,8 @@ test$package
Object
<empty>.test$package
Test
326
342
333
349
17
foo
Apply
Expand All @@ -161,8 +161,8 @@ test$package
Object
<empty>.test$package
Test
345
374
352
381
18
foo
Apply
Expand All @@ -178,8 +178,8 @@ test$package
Object
<empty>.test$package
Test
357
373
364
380
18
identity
Apply
Expand All @@ -195,8 +195,8 @@ test$package
Object
<empty>.test$package
Test
275
289
282
296
15
Test
DefDef
Expand Down
17 changes: 3 additions & 14 deletions tests/neg/erased-1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,14 @@ object Test {
})
foo1(a) // OK
foo2( // error
a // error
)
foo3( // error
a
a // Ok
)
a // error
}
erased def foo2(a: Int): Int = {
foo0(a) // OK
foo1(a) // OK
foo2(a) // OK
foo3(a) // OK
a // OK
}
erased def foo3(erased a: Int): Int = {
erased def foo2(erased a: Int): Int = {
foo0(a) // OK
foo1(a) // OK
foo2(a) // OK
foo3(a) // OK
a // OK
}
}
}
21 changes: 4 additions & 17 deletions tests/neg/erased-2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,26 @@ object Test {
)
foo1(u) // OK
foo2( // error
u // error
)
foo3( // error
u
u // Ok
)
u // error
u // error
}
erased def foo2(a: Int): Int = {
foo0(u) // OK
foo1(u) // OK
foo2(u) // OK
foo3(u) // OK
u // warn
u // OK
}
erased def foo3(erased a: Int): Int = {
erased def foo2(erased a: Int): Int = {
foo0(u) // OK
foo1(u) // OK
foo2(u) // OK
foo3(u) // OK
u // warn
u // OK
}

erased val foo4: Int = {
erased val foo3: Int = {
foo0(u) // OK
foo1(u) // OK
foo2(u) // OK
foo3(u) // OK
u // warn
u // OK
}

erased def u: Int = 42
}
}
21 changes: 4 additions & 17 deletions tests/neg/erased-3.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,27 @@ object Test {
)
foo1(u()) // OK
foo2( // error
u() // error
)
foo3( // error
u()
u() // Ok
)
u() // error
u() // error
}
erased def foo2(a: Int): Int = {
foo0(u()) // OK
foo1(u()) // OK
foo2(u()) // OK
foo3(u()) // OK
u() // warn
u() // OK
}
erased def foo3(erased a: Int): Int = {
erased def foo2(erased a: Int): Int = {
foo0(u()) // OK
foo1(u()) // OK
foo2(u()) // OK
foo3(u()) // OK
u() // warn
u() // OK
}

erased val foo4: Int = {
erased val foo3: Int = {
foo0(u()) // OK
foo1(u()) // OK
foo2(u()) // OK
foo3(u()) // OK
println()
u() // warn
u() // OK
}

erased def u(): Int = 42
}
}
2 changes: 1 addition & 1 deletion tests/neg/erased-args-lifted.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

object Test {
def foo(a: Int)(b: Int, c: Int) = 42
erased def bar(i: Int): Int = {
erased def bar(erased i: Int): Int = {
println(1)
42
}
Expand Down
12 changes: 12 additions & 0 deletions tests/neg/erased-params.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import scala.language.experimental.erasedDefinitions

erased def test1(x: Int): Int = x // error
erased def test2(erased x: Int): Int = x
erased def test3(erased x: Int, erased y: Int): Int = x
erased def test4(erased x: Int, y: Int): Int = x // error
erased def test5(x: Int, erased y: Int): Int = y // error
erased def test6(x: Int, y: Int): Int = y // error // error
erased def test7(erased x: Int)(erased y: Int): Int = x
erased def test8(erased x: Int)(y: Int): Int = x // error
erased def test9(x: Int)(erased y: Int): Int = y // error
erased def test10(x: Int)(y: Int): Int = y // error // error
2 changes: 1 addition & 1 deletion tests/pos/i7741.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class A1 {
@native private def a: Unit
}
trait A2 {
erased def i(a: Int): Int
erased def i(erased a: Int): Int
}
trait A3 {
erased val a: Int
Expand Down

0 comments on commit a14c79e

Please sign in to comment.