Skip to content

Commit

Permalink
Only allow erased parameters in erased definitions
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 committed Apr 10, 2024
1 parent adf089b commit d335e93
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 71 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 @@ -537,7 +537,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

0 comments on commit d335e93

Please sign in to comment.