@@ -18,8 +18,10 @@ import typer.ProtoTypes._
18
18
import typer .ErrorReporting ._
19
19
import core .transform .Erasure ._
20
20
import core .Decorators ._
21
- import ast .{tpd , untpd }
21
+ import dotty . tools . dotc . ast .{Trees , tpd , untpd }
22
22
import ast .Trees ._
23
+ import scala .collection .mutable .ListBuffer
24
+ import dotty .tools .dotc .core .Flags
23
25
24
26
class Erasure extends Phase with DenotTransformer {
25
27
@@ -257,12 +259,95 @@ object Erasure {
257
259
override def typedTypeDef (tdef : untpd.TypeDef , sym : Symbol )(implicit ctx : Context ) =
258
260
EmptyTree
259
261
260
- /*
261
- override def transformStats(stats: List[Tree], exprOwner: Symbol)(implicit ctx: Context) = {
262
- val stats1 = super.transform(stats, exprOwner)
263
- if (ctx.owner.isClass) addBridges(stats1) else stats1
262
+ override def typedStats (stats : List [untpd.Tree ], exprOwner : Symbol )(implicit ctx : Context ): List [tpd.Tree ] = {
263
+ val statsFlatten = Trees .flatten(stats)
264
+ val stats1 = super .typedStats(statsFlatten, exprOwner)
265
+
266
+ if (ctx.owner.isClass) addBridges(statsFlatten, stats1)(ctx) else stats1
267
+ }
268
+
269
+ // this implementation doesn't check for bridge clashes with value types!
270
+ def addBridges (oldStats : List [untpd.Tree ], newStats : List [tpd.Tree ])(implicit ctx : Context ): List [tpd.Tree ] = {
271
+ val beforeCtx = ctx.withPhase(ctx.erasurePhase)
272
+ def traverse (after : List [Tree ], before : List [untpd.Tree ],
273
+ emittedBridges : ListBuffer [tpd.DefDef ] = ListBuffer [tpd.DefDef ]()): List [tpd.DefDef ] = {
274
+ after match {
275
+ case Nil => emittedBridges.toList
276
+ case (member : DefDef ) :: newTail =>
277
+ before match {
278
+ case Nil => emittedBridges.toList
279
+ case (oldMember : untpd.DefDef ) :: oldTail =>
280
+ val oldSymbol = oldMember.symbol(beforeCtx)
281
+ val newSymbol = member.symbol(ctx)
282
+ assert(oldSymbol.name(beforeCtx) == newSymbol.name,
283
+ s " ${oldSymbol.name(beforeCtx)} bridging with ${newSymbol.name}" )
284
+ val newOverriden = oldSymbol.denot.allOverriddenSymbols.toSet
285
+ val oldOverriden = newSymbol.allOverriddenSymbols(beforeCtx).toSet
286
+ val neededBridges = oldOverriden -- newOverriden
287
+
288
+ var minimalSet = Set [Symbol ]()
289
+ // compute minimal set of bridges that are needed:
290
+ for (bridge <- neededBridges) {
291
+ val isRequired = minimalSet.forall(nxtBridge => ! (bridge.info =:= nxtBridge.info))
292
+
293
+ if (isRequired) {
294
+ // check for clashes
295
+ val clash : Option [Symbol ] = oldSymbol.owner.decls.lookupAll(bridge.name).find {
296
+ sym =>
297
+ (sym.name eq bridge.name) && sym.info.widen =:= bridge.info.widen
298
+ }.orElse(
299
+ emittedBridges.find(stat => (stat.name == bridge.name) && stat.tpe.widen =:= bridge.info.widen)
300
+ .map(_.symbol)
301
+ )
302
+ clash match {
303
+ case Some (cl) =>
304
+ ctx.error(s " bridge for method ${newSymbol.show(beforeCtx)}\n " +
305
+ s " clashes with ${cl.symbol.show(beforeCtx)}\n " +
306
+ s " both have same type after erasure: ${bridge.symbol.info.show}" )
307
+ case None => minimalSet += bridge
308
+ }
309
+ }
310
+ }
311
+
312
+ val bridgeImplementations = minimalSet.map {
313
+ sym => makeBridgeDef(member, sym)(ctx)
314
+ }
315
+ emittedBridges ++= bridgeImplementations
316
+ traverse(newTail, oldTail)
317
+ case notADefDef :: oldTail =>
318
+ traverse(after, oldTail)
319
+ }
320
+ case notADefDef :: newTail =>
321
+ traverse(newTail, before)
322
+ }
323
+ }
324
+
325
+ traverse(newStats, oldStats)
326
+ }
327
+
328
+ def makeBridgeDef (newDef : tpd.DefDef , parentSym : Symbol )(implicit ctx : Context ): tpd.DefDef = {
329
+ def error (reason : String ) = {
330
+ assert(false , s " failure creating bridge from ${newDef.symbol} to ${parentSym}, reason: $reason" )
331
+ ???
332
+ }
333
+ val bridge = ctx.newSymbol(newDef.symbol.owner,
334
+ parentSym.name, parentSym.flags | Flags .Bridge , parentSym.info, coord = newDef.symbol.owner.coord).asTerm
335
+ bridge.entered // this should be safe, as we're executing in context of next phase
336
+ ctx.debuglog(s " generating bridge from ${newDef.symbol} to $bridge" )
337
+
338
+ val sel : Tree = tpd.Select (This (newDef.symbol.owner.asClass), newDef.symbol.termRef)
339
+
340
+ val resultType = bridge.info.widen.resultType
341
+ tpd.DefDef (bridge, { paramss : List [List [tpd.Tree ]] =>
342
+ val rhs = paramss.foldLeft(sel)((fun, vparams) =>
343
+ fun.tpe.widen match {
344
+ case MethodType (names, types) => Apply (fun, (vparams, types).zipped.map(adapt))
345
+ case a => error(s " can not resolve apply type $a" )
346
+
347
+ })
348
+ adapt(rhs, resultType)
349
+ })
264
350
}
265
- */
266
351
267
352
override def adapt (tree : Tree , pt : Type )(implicit ctx : Context ): Tree =
268
353
ctx.traceIndented(i " adapting ${tree.showSummary}: ${tree.tpe} to $pt" , show = true ) {
0 commit comments