@@ -169,7 +169,33 @@ abstract class Mixin extends Transform with ast.TreeDSL with AccessorSynthesis {
169
169
clazz.info.decls enter member setFlag MIXEDIN resetFlag JAVA_DEFAULTMETHOD
170
170
}
171
171
def cloneAndAddMember (mixinClass : Symbol , mixinMember : Symbol , clazz : Symbol ): Symbol =
172
- addMember(clazz, mixinMember.cloneSymbol(clazz).setFlag(BRIDGE ))
172
+ addMember(clazz, cloneBeforeErasure(mixinClass, mixinMember, clazz).setFlag(BRIDGE ))
173
+
174
+ def cloneBeforeErasure (mixinClass : Symbol , mixinMember : Symbol , clazz : Symbol ): Symbol = {
175
+ val newSym = enteringErasure {
176
+ // since we used `mixinMember` from the interface that represents the trait that's
177
+ // being mixed in, have to instantiate the interface type params (that may occur in mixinMember's
178
+ // info) as they are seen from the class. We can't use the member that we get from the
179
+ // implementation class, as it's a clone that was made after erasure, and thus it does not
180
+ // know its info at the beginning of erasure anymore.
181
+ val sym = mixinMember cloneSymbol clazz
182
+
183
+ val erasureMap = erasure.erasure(mixinMember)
184
+ val erasedInterfaceInfo : Type = erasureMap(mixinMember.info)
185
+ val specificForwardInfo = (clazz.thisType baseType mixinClass) memberInfo mixinMember
186
+ val forwarderInfo =
187
+ if (erasureMap(specificForwardInfo) =:= erasedInterfaceInfo)
188
+ specificForwardInfo
189
+ else {
190
+ erasedInterfaceInfo
191
+ }
192
+ // Optimize: no need if mixinClass has no typeparams.
193
+ // !!! JZ Really? What about the effect of abstract types, prefix?
194
+ if (mixinClass.typeParams.isEmpty) sym
195
+ else sym modifyInfo (_ => forwarderInfo)
196
+ }
197
+ newSym
198
+ }
173
199
174
200
def publicizeTraitMethods (clazz : Symbol ): Unit = {
175
201
if (treatedClassInfos(clazz) != clazz.info) {
0 commit comments