@@ -67,7 +67,7 @@ class Erasure extends Phase with DenotTransformer { thisTransformer =>
6767 val oldOwner = ref.owner
6868 val newOwner = if (oldOwner eq defn.AnyClass ) defn.ObjectClass else oldOwner
6969 val oldInfo = ref.info
70- val newInfo = transformInfo(ref.symbol , oldInfo)
70+ val newInfo = transformInfo(oldSymbol , oldInfo)
7171 val oldFlags = ref.flags
7272 val newFlags =
7373 if (oldSymbol.is(Flags .TermParam ) && isCompacted(oldSymbol.owner)) oldFlags &~ Flags .Param
@@ -594,117 +594,10 @@ object Erasure extends TypeTestsCasts{
594594 EmptyTree
595595
596596 override def typedStats (stats : List [untpd.Tree ], exprOwner : Symbol )(implicit ctx : Context ): List [Tree ] = {
597- val stats1 = Trees .flatten(super .typedStats(stats, exprOwner))
598- if (ctx.owner.isClass) stats1 ::: addBridges(stats, stats1)(ctx) else stats1
599- }
600-
601- // this implementation doesn't check for bridge clashes with value types!
602- def addBridges (oldStats : List [untpd.Tree ], newStats : List [tpd.Tree ])(implicit ctx : Context ): List [tpd.Tree ] = {
603- val beforeCtx = ctx.withPhase(ctx.erasurePhase)
604- def traverse (after : List [Tree ], before : List [untpd.Tree ],
605- emittedBridges : ListBuffer [tpd.DefDef ] = ListBuffer [tpd.DefDef ]()): List [tpd.DefDef ] = {
606- after match {
607- case Nil => emittedBridges.toList
608- case (member : DefDef ) :: newTail =>
609- before match {
610- case Nil => emittedBridges.toList
611- case (oldMember : untpd.DefDef ) :: oldTail =>
612- try {
613- val oldSymbol = oldMember.symbol(beforeCtx)
614- val newSymbol = member.symbol(ctx)
615- assert(oldSymbol.name(beforeCtx) == newSymbol.name,
616- s " ${oldSymbol.name(beforeCtx)} bridging with ${newSymbol.name}" )
617- val newOverridden = oldSymbol.denot.allOverriddenSymbols.toSet // TODO: clarify new <-> old in a comment; symbols are swapped here
618- val oldOverridden = newSymbol.allOverriddenSymbols(beforeCtx).toSet // TODO: can we find a more efficient impl? newOverridden does not have to be a set!
619- def stillInBaseClass (sym : Symbol ) = ctx.owner derivesFrom sym.owner
620- val neededBridges = (oldOverridden -- newOverridden).filter(stillInBaseClass)
621-
622- var minimalSet = Set [Symbol ]()
623- // compute minimal set of bridges that are needed:
624- for (bridge <- neededBridges) {
625- val isRequired = minimalSet.forall(nxtBridge => ! (bridge.info =:= nxtBridge.info))
626-
627- if (isRequired) {
628- // check for clashes
629- val clash : Option [Symbol ] = oldSymbol.owner.info.decls.lookupAll(bridge.name).find {
630- sym =>
631- (sym.name eq bridge.name) && sym.info.widen =:= bridge.info.widen
632- }.orElse(
633- emittedBridges.find(stat => (stat.name == bridge.name) && stat.tpe.widen =:= bridge.info.widen)
634- .map(_.symbol))
635- clash match {
636- case Some (cl) =>
637- ctx.error(i " bridge for method ${newSymbol.showLocated(beforeCtx)} of type ${newSymbol.info(beforeCtx)}\n " +
638- i " clashes with ${cl.symbol.showLocated(beforeCtx)} of type ${cl.symbol.info(beforeCtx)}\n " +
639- i " both have same type after erasure: ${bridge.symbol.info}" )
640- case None => minimalSet += bridge
641- }
642- }
643- }
644-
645- val bridgeImplementations = minimalSet.map {
646- sym => makeBridgeDef(member, sym)(ctx)
647- }
648- emittedBridges ++= bridgeImplementations
649- } catch {
650- case ex : MergeError => ctx.error(ex.getMessage, member.pos)
651- }
652-
653- traverse(newTail, oldTail, emittedBridges)
654- case notADefDef :: oldTail =>
655- traverse(after, oldTail, emittedBridges)
656- }
657- case notADefDef :: newTail =>
658- traverse(newTail, before, emittedBridges)
659- }
660- }
661-
662- traverse(newStats, oldStats)
663- }
664-
665- private final val NoBridgeFlags = Flags .Accessor | Flags .Deferred | Flags .Lazy | Flags .ParamAccessor
666-
667- /** Create a bridge DefDef which overrides a parent method.
668- *
669- * @param newDef The DefDef which needs bridging because its signature
670- * does not match the parent method signature
671- * @param parentSym A symbol corresponding to the parent method to override
672- * @return A new DefDef whose signature matches the parent method
673- * and whose body only contains a call to newDef
674- */
675- def makeBridgeDef (newDef : tpd.DefDef , parentSym : Symbol )(implicit ctx : Context ): tpd.DefDef = {
676- val newDefSym = newDef.symbol
677- val currentClass = newDefSym.owner.asClass
678-
679- def error (reason : String ) = {
680- assert(false , s " failure creating bridge from ${newDefSym} to ${parentSym}, reason: $reason" )
681- ???
682- }
683- var excluded = NoBridgeFlags
684- if (! newDefSym.is(Flags .Protected )) excluded |= Flags .Protected // needed to avoid "weaker access" assertion failures in expandPrivate
685- val bridge = ctx.newSymbol(currentClass,
686- parentSym.name, parentSym.flags &~ excluded | Flags .Bridge , parentSym.info, coord = newDefSym.owner.coord).asTerm
687- bridge.enteredAfter(ctx.phase.prev.asInstanceOf [DenotTransformer ]) // this should be safe, as we're executing in context of next phase
688- ctx.debuglog(s " generating bridge from ${newDefSym} to $bridge" )
689-
690- val sel : Tree = This (currentClass).select(newDefSym.termRef)
691-
692- val resultType = parentSym.info.widen.resultType
693-
694- val bridgeCtx = ctx.withOwner(bridge)
695-
696- tpd.DefDef (bridge, { paramss : List [List [tpd.Tree ]] =>
697- implicit val ctx = bridgeCtx
698-
699- val rhs = paramss.foldLeft(sel)((fun, vparams) =>
700- fun.tpe.widen match {
701- case mt : MethodType =>
702- Apply (fun, (vparams, mt.paramInfos).zipped.map(adapt(_, _, untpd.EmptyTree )))
703- case a =>
704- error(s " can not resolve apply type $a" )
705- })
706- adapt(rhs, resultType)
707- })
597+ val stats1 =
598+ if (takesBridges(ctx.owner)) new Bridges (ctx.owner.asClass).add(stats)
599+ else stats
600+ super .typedStats(stats1, exprOwner)
708601 }
709602
710603 override def adapt (tree : Tree , pt : Type , original : untpd.Tree )(implicit ctx : Context ): Tree =
@@ -715,4 +608,7 @@ object Erasure extends TypeTestsCasts{
715608 else adaptToType(tree, pt)
716609 }
717610 }
611+
612+ def takesBridges (sym : Symbol )(implicit ctx : Context ) =
613+ sym.isClass && ! sym.is(Flags .Trait | Flags .Package )
718614}
0 commit comments