Skip to content

Commit dfab5e5

Browse files
authored
Merge pull request #4435 from dotty-staging/fix-bridge
Fix bridge generation for object definitions
2 parents 9b42731 + b7fa358 commit dfab5e5

File tree

4 files changed

+63
-5
lines changed

4 files changed

+63
-5
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,9 @@ object Flags {
542542
/** Either method or lazy */
543543
final val MethodOrLazy = Method | Lazy
544544

545+
/** Either method or module */
546+
final val MethodOrModule = Method | Module
547+
545548
/** Either method or lazy or deferred */
546549
final val MethodOrLazyOrDeferred = Method | Lazy | Deferred
547550

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,16 @@ case class Signature(paramsSig: List[TypeName], resSig: TypeName) {
4242
* This is the case if all parameter names are _consistent_, i.e. they are either
4343
* equal or on of them is tpnme.Uninstantiated.
4444
*/
45-
final def consistentParams(that: Signature): Boolean = {
45+
final def consistentParams(that: Signature)(implicit ctx: Context): Boolean = {
4646
@tailrec def loop(names1: List[TypeName], names2: List[TypeName]): Boolean =
4747
if (names1.isEmpty) names2.isEmpty
4848
else !names2.isEmpty && consistent(names1.head, names2.head) && loop(names1.tail, names2.tail)
49-
loop(this.paramsSig, that.paramsSig)
49+
if (ctx.erasedTypes && (this == NotAMethod) != (that == NotAMethod))
50+
false // After erasure, we allow fields and parameterless methods with the same name.
51+
// This is needed to allow both a module field and a bridge method for an abstract val.
52+
// Test case is patmatch-classtag.scala
53+
else
54+
loop(this.paramsSig, that.paramsSig)
5055
}
5156

5257
/** `that` signature, but keeping all corresponding parts of `this` signature. */

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class Bridges(root: ClassSymbol)(implicit ctx: Context) {
2626
* only in classes, never in traits.
2727
*/
2828
override def parents = Array(root.superClass)
29-
override def exclude(sym: Symbol) = !sym.is(Method) || super.exclude(sym)
29+
override def exclude(sym: Symbol) = !sym.is(MethodOrModule) || super.exclude(sym)
3030
}
3131

3232
//val site = root.thisType
@@ -97,8 +97,13 @@ class Bridges(root: ClassSymbol)(implicit ctx: Context) {
9797
toBeRemoved += other
9898
}
9999

100-
bridges +=
101-
DefDef(bridge, This(root).select(member).appliedToArgss(_)).withPos(bridge.pos)
100+
def bridgeRhs(argss: List[List[Tree]]) = {
101+
val ref = This(root).select(member)
102+
if (member.info.isParameterless) ref // can happen if `member` is a module
103+
else ref.appliedToArgss(argss)
104+
}
105+
106+
bridges += DefDef(bridge, bridgeRhs(_).withPos(bridge.pos))
102107
}
103108

104109
/** Add all necessary bridges to template statements `stats`, and remove at the same

tests/run/patmatch-classtag.scala

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import reflect.ClassTag
2+
trait API {
3+
type CaseDef
4+
5+
implicit val tagForCaseDef: ClassTag[CaseDef]
6+
7+
trait CaseDefCompanion {
8+
def apply(x: String): CaseDef
9+
def unapply(x: CaseDef): Option[String]
10+
}
11+
lazy val CaseDef: CaseDefCompanion
12+
}
13+
14+
object dotc {
15+
case class CaseDef(str: String)
16+
}
17+
18+
object Impl extends API {
19+
type CaseDef = dotc.CaseDef
20+
21+
val tagForCaseDef: ClassTag[dotc.CaseDef] = implicitly[ClassTag[dotc.CaseDef]]
22+
23+
object CaseDef extends CaseDefCompanion {
24+
def apply(str: String): CaseDef = dotc.CaseDef(str)
25+
def unapply(x: CaseDef): Option[String] = Some(x.str)
26+
}
27+
}
28+
29+
object Test extends App {
30+
val api: API = Impl
31+
import api._
32+
33+
val x: Any = CaseDef("123")
34+
35+
x match {
36+
case cdef: CaseDef =>
37+
val x: CaseDef = cdef
38+
println(cdef)
39+
}
40+
x match {
41+
case cdef @ CaseDef(s) =>
42+
val x: CaseDef = cdef
43+
println(s)
44+
}
45+
}

0 commit comments

Comments
 (0)