@@ -167,6 +167,8 @@ abstract class Erasure extends AddInterfaces
167
167
case tp => tp :: Nil
168
168
}
169
169
170
+ private def isErasedValueType (tpe : Type ) = tpe.isInstanceOf [ErasedValueType ]
171
+
170
172
/** The Java signature of type 'info', for symbol sym. The symbol is used to give the right return
171
173
* type for constructors.
172
174
*/
@@ -373,18 +375,18 @@ abstract class Erasure extends AddInterfaces
373
375
}
374
376
}
375
377
376
- class ComputeBridges (owner : Symbol ) {
378
+ class ComputeBridges (unit : CompilationUnit , root : Symbol ) {
377
379
assert(phase == currentRun.erasurePhase, phase)
378
380
379
381
var toBeRemoved = immutable.Set [Symbol ]()
380
- val site = owner .thisType
382
+ val site = root .thisType
381
383
val bridgesScope = newScope
382
384
val bridgeTarget = mutable.HashMap [Symbol , Symbol ]()
383
385
var bridges = List [Tree ]()
384
386
385
387
val opc = beforeExplicitOuter {
386
- new overridingPairs.Cursor (owner ) {
387
- override def parents = List (owner .info.firstParent)
388
+ new overridingPairs.Cursor (root ) {
389
+ override def parents = List (root .info.firstParent)
388
390
override def exclude (sym : Symbol ) = ! sym.isMethod || sym.isPrivate || super .exclude(sym)
389
391
}
390
392
}
@@ -402,8 +404,58 @@ abstract class Erasure extends AddInterfaces
402
404
(bridges, toBeRemoved)
403
405
}
404
406
407
+ /** Check that a bridge only overrides members that are also overridden by the original member.
408
+ * This test is necessary only for members that have a value class in their type.
409
+ * Such members are special because their types after erasure and after post-erasure differ/.
410
+ * This means we generate them after erasure, but the post-erasure transform might introduce
411
+ * a name clash. The present method guards against these name clashes.
412
+ *
413
+ * @param member The original member
414
+ * @param other The overidden symbol for which the bridge was generated
415
+ * @param bridge The bridge
416
+ */
417
+ def checkBridgeOverrides (member : Symbol , other : Symbol , bridge : Symbol ): Boolean = {
418
+ def fulldef (sym : Symbol ) =
419
+ if (sym == NoSymbol ) sym.toString
420
+ else s " $sym: ${sym.tpe} in ${sym.owner}"
421
+ var noclash = true
422
+ def clashError (what : String ) = {
423
+ noclash = false
424
+ unit.error(
425
+ if (member.owner == root) member.pos else root.pos,
426
+ s """ bridge generated for member ${fulldef(member)}
427
+ |which overrides ${fulldef(other)}
428
+ |clashes with definition of $what;
429
+ |both have erased type ${afterPostErasure(bridge.tpe)}""" .stripMargin)
430
+ }
431
+ for (bc <- root.baseClasses) {
432
+ if (settings.debug.value)
433
+ afterPostErasure(println(
434
+ s """ check bridge overrides in $bc
435
+ ${bc.info.nonPrivateDecl(bridge.name)}
436
+ ${site.memberType(bridge)}
437
+ ${site.memberType(bc.info.nonPrivateDecl(bridge.name) orElse IntClass )}
438
+ ${(bridge.matchingSymbol(bc, site))}""" .stripMargin))
439
+
440
+ def overriddenBy (sym : Symbol ) =
441
+ sym.matchingSymbol(bc, site).alternatives filter (sym => ! sym.isBridge)
442
+ for (overBridge <- afterPostErasure(overriddenBy(bridge))) {
443
+ if (overBridge == member) {
444
+ clashError(" the member itself" )
445
+ } else {
446
+ val overMembers = overriddenBy(member)
447
+ if (! overMembers.exists(overMember =>
448
+ afterPostErasure(overMember.tpe =:= overBridge.tpe))) {
449
+ clashError(fulldef(overBridge))
450
+ }
451
+ }
452
+ }
453
+ }
454
+ noclash
455
+ }
456
+
405
457
def checkPair (member : Symbol , other : Symbol ) {
406
- val otpe = erasure(owner )(other.tpe)
458
+ val otpe = erasure(root )(other.tpe)
407
459
val bridgeNeeded = afterErasure (
408
460
! (other.tpe =:= member.tpe) &&
409
461
! (deconstMap(other.tpe) =:= deconstMap(member.tpe)) &&
@@ -417,24 +469,29 @@ abstract class Erasure extends AddInterfaces
417
469
return
418
470
419
471
val newFlags = (member.flags | BRIDGE ) & ~ (ACCESSOR | DEFERRED | LAZY | lateDEFERRED)
420
- val bridge = other.cloneSymbolImpl(owner , newFlags) setPos owner .pos
472
+ val bridge = other.cloneSymbolImpl(root , newFlags) setPos root .pos
421
473
422
474
debuglog(" generating bridge from %s (%s): %s to %s: %s" .format(
423
475
other, flagsToString(newFlags),
424
476
otpe + other.locationString, member,
425
- erasure(owner )(member.tpe) + member.locationString)
477
+ erasure(root )(member.tpe) + member.locationString)
426
478
)
427
479
428
480
// the parameter symbols need to have the new owner
429
481
bridge setInfo (otpe cloneInfo bridge)
430
482
bridgeTarget(bridge) = member
431
- afterErasure(owner.info.decls enter bridge)
432
- if (other.owner == owner) {
433
- afterErasure(owner.info.decls.unlink(other))
434
- toBeRemoved += other
483
+
484
+ if (! (member.tpe exists (_.typeSymbol.isDerivedValueClass)) ||
485
+ checkBridgeOverrides(member, other, bridge)) {
486
+ afterErasure(root.info.decls enter bridge)
487
+ if (other.owner == root) {
488
+ afterErasure(root.info.decls.unlink(other))
489
+ toBeRemoved += other
490
+ }
491
+
492
+ bridgesScope enter bridge
493
+ bridges ::= makeBridgeDefDef(bridge, member, other)
435
494
}
436
- bridgesScope enter bridge
437
- bridges ::= makeBridgeDefDef(bridge, member, other)
438
495
}
439
496
440
497
def makeBridgeDefDef (bridge : Symbol , member : Symbol , other : Symbol ) = afterErasure {
@@ -466,7 +523,7 @@ abstract class Erasure extends AddInterfaces
466
523
val rhs = member.tpe match {
467
524
case MethodType (Nil , ConstantType (c)) => Literal (c)
468
525
case _ =>
469
- val sel : Tree = Select (This (owner ), member)
526
+ val sel : Tree = Select (This (root ), member)
470
527
val bridgingCall = (sel /: bridge.paramss)((fun, vparams) => Apply (fun, vparams map Ident ))
471
528
472
529
maybeWrap(bridgingCall)
@@ -480,8 +537,6 @@ abstract class Erasure extends AddInterfaces
480
537
481
538
private def isPrimitiveValueType (tpe : Type ) = isPrimitiveValueClass(tpe.typeSymbol)
482
539
483
- private def isErasedValueType (tpe : Type ) = tpe.isInstanceOf [ErasedValueType ]
484
-
485
540
private def isDifferentErasedValueType (tpe : Type , other : Type ) =
486
541
isErasedValueType(tpe) && (tpe ne other)
487
542
@@ -814,7 +869,6 @@ abstract class Erasure extends AddInterfaces
814
869
* but their erased types are the same.
815
870
*/
816
871
private def checkNoDoubleDefs (root : Symbol ) {
817
- def afterErasure [T ](op : => T ): T = atPhase(phase.next.next)(op)
818
872
def doubleDefError (sym1 : Symbol , sym2 : Symbol ) {
819
873
// the .toString must also be computed at the earlier phase
820
874
val tpe1 = afterRefchecks(root.thisType.memberType(sym1))
@@ -830,7 +884,7 @@ abstract class Erasure extends AddInterfaces
830
884
sym2 + " :" + afterRefchecks(tpe2.toString) +
831
885
(if (sym2.owner == root) " at line " + (sym2.pos).line else sym2.locationString) +
832
886
" \n have same type" +
833
- (if (afterRefchecks(tpe1 =:= tpe2)) " " else " after erasure: " + afterErasure (sym1.tpe)))
887
+ (if (afterRefchecks(tpe1 =:= tpe2)) " " else " after erasure: " + afterPostErasure (sym1.tpe)))
834
888
sym1.setInfo(ErrorType )
835
889
}
836
890
@@ -840,7 +894,7 @@ abstract class Erasure extends AddInterfaces
840
894
if (e.sym.isTerm) {
841
895
var e1 = decls.lookupNextEntry(e)
842
896
while (e1 ne null ) {
843
- if (afterErasure (e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym)
897
+ if (afterPostErasure (e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym)
844
898
e1 = decls.lookupNextEntry(e1)
845
899
}
846
900
}
@@ -854,7 +908,7 @@ abstract class Erasure extends AddInterfaces
854
908
|| ! sym.hasTypeAt(currentRun.refchecksPhase.id))
855
909
856
910
override def matches (sym1 : Symbol , sym2 : Symbol ): Boolean =
857
- afterErasure (sym1.tpe =:= sym2.tpe)
911
+ afterPostErasure (sym1.tpe =:= sym2.tpe)
858
912
}
859
913
while (opc.hasNext) {
860
914
if (! afterRefchecks(
@@ -902,7 +956,7 @@ abstract class Erasure extends AddInterfaces
902
956
private def bridgeDefs (owner : Symbol ): (List [Tree ], immutable.Set [Symbol ]) = {
903
957
assert(phase == currentRun.erasurePhase, phase)
904
958
debuglog(" computing bridges for " + owner)
905
- new ComputeBridges (owner) compute()
959
+ new ComputeBridges (unit, owner) compute()
906
960
}
907
961
908
962
def addBridges (stats : List [Tree ], base : Symbol ): List [Tree ] =
@@ -1000,7 +1054,7 @@ abstract class Erasure extends AddInterfaces
1000
1054
preEraseIsInstanceOf
1001
1055
} else if (fn.symbol.owner.isRefinementClass && ! fn.symbol.isOverridingSymbol) {
1002
1056
ApplyDynamic (qualifier, args) setSymbol fn.symbol setPos tree.pos
1003
- } else if (fn.symbol.isMethodWithExtension) {
1057
+ } else if (fn.symbol.isMethodWithExtension && ! fn.symbol.tpe.isErroneous ) {
1004
1058
Apply (gen.mkAttributedRef(extensionMethods.extensionMethod(fn.symbol)), qualifier :: args)
1005
1059
} else {
1006
1060
tree
0 commit comments