Skip to content

Commit e7f171c

Browse files
committed
Fix #6750: Use semi-erased by name parameter signature
Before `Erasure` the signatures will contain `=>X` instead of `Function0`. This makes signature clashes of by-name parameters only show up after `Erasure`. This allows for `inline` methods to have by-name parameter overloads.
1 parent 195597e commit e7f171c

File tree

5 files changed

+44
-1
lines changed

5 files changed

+44
-1
lines changed

compiler/src/dotty/tools/dotc/core/TypeErasure.scala

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,19 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
608608
case tp: TermRef =>
609609
sigName(tp.widen)
610610
case ExprType(rt) =>
611-
sigName(defn.FunctionOf(Nil, rt))
611+
// Before erasure the signature will be `=>X` and after erasure it will be `Function0`.
612+
// This is to support overriding inline methods with by-name parameters we slghtly modify the signature before erasure.
613+
// By-name arguments are necesarry in all inline methods that may want to elide the evaluation of the arguments.
614+
// Without this signature modification, the following two inline methods would have the same signature.
615+
// `inline def foo(x: => Int): Unit = ???`
616+
// `inline def foo(x: => Long): Unit = ???`
617+
// Note that the decalrataions of `inline` method do not reach passed erasure.
618+
//
619+
// It would not be possible to make this change only to `inline` methods because then overriding would be affected.
620+
// This would make merge error logic is quite complex to hadle as is signature based for performance.
621+
// It was deemed to tricky to get right.
622+
if (ctx.phase.erasedTypes) sigName(defn.FunctionOf(Nil, rt))
623+
else tpnme.ARROWkw ++ sigName(rt)
612624
case tp: TypeVar =>
613625
val inst = tp.instanceOpt
614626
if (inst.exists) sigName(inst) else tpnme.Uninstantiated

tests/neg/i6750.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
object Foo {
2+
def bar(i: => Int): Unit = ???
3+
def bar(l: => Long): Unit = ??? // error
4+
}

tests/neg/i6750b.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
object Foo {
2+
def bar(i: => Int): Unit = ???
3+
def bar(l: () => Long): Unit = ??? // error
4+
}

tests/pos/i6750.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
object Foo {
2+
inline def foo(i: => Int): Unit = ???
3+
inline def foo(l: => Long): Unit = ???
4+
5+
foo(2)
6+
foo(3L)
7+
}

tests/run/i6750.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
object Test {
3+
4+
inline def foo(i: => Int) = i + i
5+
inline def foo(l: => Long) = l * l
6+
7+
inline def bar(i: () => Int) = ???
8+
inline def bar[T](x: () => T) = ???
9+
10+
def main(args: Array[String]): Unit = {
11+
assert(10 == foo(5))
12+
assert(25L == foo(5L))
13+
14+
}
15+
16+
}

0 commit comments

Comments
 (0)