summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala98
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/OverridingPairs.scala39
-rw-r--r--src/reflect/scala/reflect/internal/transform/Erasure.scala22
-rw-r--r--test/files/disabled/A.scala (renamed from test/files/buildmanager/overloaded_1/A.scala)2
-rw-r--r--test/files/disabled/overloaded_1.check (renamed from test/files/buildmanager/overloaded_1/overloaded_1.check)0
-rw-r--r--test/files/disabled/overloaded_1.test (renamed from test/files/buildmanager/overloaded_1/overloaded_1.test)0
-rw-r--r--test/files/disabled/t4245/A.scala (renamed from test/files/buildmanager/t4245/A.scala)0
-rw-r--r--test/files/disabled/t4245/t4245.check (renamed from test/files/buildmanager/t4245/t4245.check)0
-rw-r--r--test/files/disabled/t4245/t4245.test (renamed from test/files/buildmanager/t4245/t4245.test)0
-rw-r--r--test/files/neg/t6260.check13
-rw-r--r--test/files/neg/t6260.scala17
-rw-r--r--test/files/neg/t6385.check7
-rw-r--r--test/files/neg/t6385.scala13
-rw-r--r--test/files/neg/valueclasses-pavlov.check7
-rw-r--r--test/files/neg/valueclasses-pavlov.scala23
-rw-r--r--test/files/run/Meter.scala6
-rw-r--r--test/files/run/MeterCaseClass.scala6
-rw-r--r--test/files/run/t6260.check1
-rw-r--r--test/files/run/t6260.scala12
-rw-r--r--test/files/run/t6337a.scala16
-rw-r--r--test/files/run/valueclasses-pavlov.check2
-rw-r--r--test/files/run/valueclasses-pavlov.scala26
24 files changed, 258 insertions, 57 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 6fb6b1736b..58fcee4b30 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -1094,6 +1094,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
// TODO - trim these to the absolute minimum.
@inline final def afterErasure[T](op: => T): T = afterPhase(currentRun.erasurePhase)(op)
+ @inline final def afterPostErasure[T](op: => T): T = afterPhase(currentRun.posterasurePhase)(op)
@inline final def afterExplicitOuter[T](op: => T): T = afterPhase(currentRun.explicitouterPhase)(op)
@inline final def afterFlatten[T](op: => T): T = afterPhase(currentRun.flattenPhase)(op)
@inline final def afterIcode[T](op: => T): T = afterPhase(currentRun.icodePhase)(op)
@@ -1403,6 +1404,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
val specializePhase = phaseNamed("specialize")
val explicitouterPhase = phaseNamed("explicitouter")
val erasurePhase = phaseNamed("erasure")
+ val posterasurePhase = phaseNamed("posterasure")
// val lazyvalsPhase = phaseNamed("lazyvals")
val lambdaliftPhase = phaseNamed("lambdalift")
// val constructorsPhase = phaseNamed("constructors")
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index b3b0c82d38..072d823c60 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -167,6 +167,8 @@ abstract class Erasure extends AddInterfaces
case tp => tp :: Nil
}
+ private def isErasedValueType(tpe: Type) = tpe.isInstanceOf[ErasedValueType]
+
/** The Java signature of type 'info', for symbol sym. The symbol is used to give the right return
* type for constructors.
*/
@@ -373,18 +375,18 @@ abstract class Erasure extends AddInterfaces
}
}
- class ComputeBridges(owner: Symbol) {
+ class ComputeBridges(unit: CompilationUnit, root: Symbol) {
assert(phase == currentRun.erasurePhase, phase)
var toBeRemoved = immutable.Set[Symbol]()
- val site = owner.thisType
+ val site = root.thisType
val bridgesScope = newScope
val bridgeTarget = mutable.HashMap[Symbol, Symbol]()
var bridges = List[Tree]()
val opc = beforeExplicitOuter {
- new overridingPairs.Cursor(owner) {
- override def parents = List(owner.info.firstParent)
+ new overridingPairs.Cursor(root) {
+ override def parents = List(root.info.firstParent)
override def exclude(sym: Symbol) = !sym.isMethod || sym.isPrivate || super.exclude(sym)
}
}
@@ -402,8 +404,58 @@ abstract class Erasure extends AddInterfaces
(bridges, toBeRemoved)
}
+ /** Check that a bridge only overrides members that are also overridden by the original member.
+ * This test is necessary only for members that have a value class in their type.
+ * Such members are special because their types after erasure and after post-erasure differ/.
+ * This means we generate them after erasure, but the post-erasure transform might introduce
+ * a name clash. The present method guards against these name clashes.
+ *
+ * @param member The original member
+ * @param other The overidden symbol for which the bridge was generated
+ * @param bridge The bridge
+ */
+ def checkBridgeOverrides(member: Symbol, other: Symbol, bridge: Symbol): Boolean = {
+ def fulldef(sym: Symbol) =
+ if (sym == NoSymbol) sym.toString
+ else s"$sym: ${sym.tpe} in ${sym.owner}"
+ var noclash = true
+ def clashError(what: String) = {
+ noclash = false
+ unit.error(
+ if (member.owner == root) member.pos else root.pos,
+ s"""bridge generated for member ${fulldef(member)}
+ |which overrides ${fulldef(other)}
+ |clashes with definition of $what;
+ |both have erased type ${afterPostErasure(bridge.tpe)}""".stripMargin)
+ }
+ for (bc <- root.baseClasses) {
+ if (settings.debug.value)
+ afterPostErasure(println(
+ s"""check bridge overrides in $bc
+ ${bc.info.nonPrivateDecl(bridge.name)}
+ ${site.memberType(bridge)}
+ ${site.memberType(bc.info.nonPrivateDecl(bridge.name) orElse IntClass)}
+ ${(bridge.matchingSymbol(bc, site))}""".stripMargin))
+
+ def overriddenBy(sym: Symbol) =
+ sym.matchingSymbol(bc, site).alternatives filter (sym => !sym.isBridge)
+ for (overBridge <- afterPostErasure(overriddenBy(bridge))) {
+ if (overBridge == member) {
+ clashError("the member itself")
+ } else {
+ val overMembers = overriddenBy(member)
+ if (!overMembers.exists(overMember =>
+ afterPostErasure(overMember.tpe =:= overBridge.tpe))) {
+ clashError(fulldef(overBridge))
+ }
+ }
+ }
+ }
+ noclash
+ }
+
def checkPair(member: Symbol, other: Symbol) {
- val otpe = erasure(owner)(other.tpe)
+ val otpe = erasure(root)(other.tpe)
val bridgeNeeded = afterErasure (
!(other.tpe =:= member.tpe) &&
!(deconstMap(other.tpe) =:= deconstMap(member.tpe)) &&
@@ -417,24 +469,29 @@ abstract class Erasure extends AddInterfaces
return
val newFlags = (member.flags | BRIDGE) & ~(ACCESSOR | DEFERRED | LAZY | lateDEFERRED)
- val bridge = other.cloneSymbolImpl(owner, newFlags) setPos owner.pos
+ val bridge = other.cloneSymbolImpl(root, newFlags) setPos root.pos
debuglog("generating bridge from %s (%s): %s to %s: %s".format(
other, flagsToString(newFlags),
otpe + other.locationString, member,
- erasure(owner)(member.tpe) + member.locationString)
+ erasure(root)(member.tpe) + member.locationString)
)
// the parameter symbols need to have the new owner
bridge setInfo (otpe cloneInfo bridge)
bridgeTarget(bridge) = member
- afterErasure(owner.info.decls enter bridge)
- if (other.owner == owner) {
- afterErasure(owner.info.decls.unlink(other))
- toBeRemoved += other
+
+ if (!(member.tpe exists (_.typeSymbol.isDerivedValueClass)) ||
+ checkBridgeOverrides(member, other, bridge)) {
+ afterErasure(root.info.decls enter bridge)
+ if (other.owner == root) {
+ afterErasure(root.info.decls.unlink(other))
+ toBeRemoved += other
+ }
+
+ bridgesScope enter bridge
+ bridges ::= makeBridgeDefDef(bridge, member, other)
}
- bridgesScope enter bridge
- bridges ::= makeBridgeDefDef(bridge, member, other)
}
def makeBridgeDefDef(bridge: Symbol, member: Symbol, other: Symbol) = afterErasure {
@@ -466,7 +523,7 @@ abstract class Erasure extends AddInterfaces
val rhs = member.tpe match {
case MethodType(Nil, ConstantType(c)) => Literal(c)
case _ =>
- val sel: Tree = Select(This(owner), member)
+ val sel: Tree = Select(This(root), member)
val bridgingCall = (sel /: bridge.paramss)((fun, vparams) => Apply(fun, vparams map Ident))
maybeWrap(bridgingCall)
@@ -480,8 +537,6 @@ abstract class Erasure extends AddInterfaces
private def isPrimitiveValueType(tpe: Type) = isPrimitiveValueClass(tpe.typeSymbol)
- private def isErasedValueType(tpe: Type) = tpe.isInstanceOf[ErasedValueType]
-
private def isDifferentErasedValueType(tpe: Type, other: Type) =
isErasedValueType(tpe) && (tpe ne other)
@@ -814,7 +869,6 @@ abstract class Erasure extends AddInterfaces
* but their erased types are the same.
*/
private def checkNoDoubleDefs(root: Symbol) {
- def afterErasure[T](op: => T): T = atPhase(phase.next.next)(op)
def doubleDefError(sym1: Symbol, sym2: Symbol) {
// the .toString must also be computed at the earlier phase
val tpe1 = afterRefchecks(root.thisType.memberType(sym1))
@@ -830,7 +884,7 @@ abstract class Erasure extends AddInterfaces
sym2 + ":" + afterRefchecks(tpe2.toString) +
(if (sym2.owner == root) " at line " + (sym2.pos).line else sym2.locationString) +
"\nhave same type" +
- (if (afterRefchecks(tpe1 =:= tpe2)) "" else " after erasure: " + afterErasure(sym1.tpe)))
+ (if (afterRefchecks(tpe1 =:= tpe2)) "" else " after erasure: " + afterPostErasure(sym1.tpe)))
sym1.setInfo(ErrorType)
}
@@ -840,7 +894,7 @@ abstract class Erasure extends AddInterfaces
if (e.sym.isTerm) {
var e1 = decls.lookupNextEntry(e)
while (e1 ne null) {
- if (afterErasure(e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym)
+ if (afterPostErasure(e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym)
e1 = decls.lookupNextEntry(e1)
}
}
@@ -854,7 +908,7 @@ abstract class Erasure extends AddInterfaces
|| !sym.hasTypeAt(currentRun.refchecksPhase.id))
override def matches(sym1: Symbol, sym2: Symbol): Boolean =
- afterErasure(sym1.tpe =:= sym2.tpe)
+ afterPostErasure(sym1.tpe =:= sym2.tpe)
}
while (opc.hasNext) {
if (!afterRefchecks(
@@ -902,7 +956,7 @@ abstract class Erasure extends AddInterfaces
private def bridgeDefs(owner: Symbol): (List[Tree], immutable.Set[Symbol]) = {
assert(phase == currentRun.erasurePhase, phase)
debuglog("computing bridges for " + owner)
- new ComputeBridges(owner) compute()
+ new ComputeBridges(unit, owner) compute()
}
def addBridges(stats: List[Tree], base: Symbol): List[Tree] =
@@ -1000,7 +1054,7 @@ abstract class Erasure extends AddInterfaces
preEraseIsInstanceOf
} else if (fn.symbol.owner.isRefinementClass && !fn.symbol.isOverridingSymbol) {
ApplyDynamic(qualifier, args) setSymbol fn.symbol setPos tree.pos
- } else if (fn.symbol.isMethodWithExtension) {
+ } else if (fn.symbol.isMethodWithExtension && !fn.symbol.tpe.isErroneous) {
Apply(gen.mkAttributedRef(extensionMethods.extensionMethod(fn.symbol)), qualifier :: args)
} else {
tree
diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
index 0820d3e714..c72fd3681f 100644
--- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
@@ -70,7 +70,8 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
val companionInfo = imeth.owner.companionModule.info
val candidates = extensionNames(imeth) map (companionInfo.decl(_))
val matching = candidates filter (alt => normalize(alt.tpe, imeth.owner) matches imeth.tpe)
- assert(matching.nonEmpty, "no extension method found for "+imeth+" among "+candidates+"/"+extensionNames(imeth))
+ assert(matching.nonEmpty,
+ s"no extension method found for $imeth:${imeth.tpe}+among ${candidates map (c => c.name+":"+c.tpe)} / ${extensionNames(imeth)}")
matching.head
}
diff --git a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
index f9d8d19b10..0b58292f28 100644
--- a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
+++ b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
@@ -104,8 +104,11 @@ abstract class OverridingPairs {
/** A map from baseclasses of <base> to ints, with smaller ints meaning lower in
* linearization order.
+ * symbols that are not baseclasses map to -1.
*/
- private val index = new mutable.HashMap[Symbol, Int]
+ private val index = new mutable.HashMap[Symbol, Int] {
+ override def default(key: Symbol) = -1
+ }
// Note: overridingPairs can be called at odd instances by the Eclipse plugin
// Soemtimes symbols are not yet defined and we get missing keys.
@@ -133,28 +136,30 @@ abstract class OverridingPairs {
{ for (i <- List.range(0, size))
subParents(i) = new BitSet(size);
for (p <- parents) {
- index get p.typeSymbol match {
- case Some(pIndex) =>
- for (bc <- p.baseClasses)
- if (p.baseType(bc) =:= self.baseType(bc))
- index get bc match {
- case Some(bcIndex) =>
- include(subParents(bcIndex), pIndex)
- case None =>
- }
- else debuglog("SKIPPING "+p+" -> "+p.baseType(bc)+" / "+self.baseType(bc)+" from "+base)
- case None =>
- }
+ val pIndex = index(p.typeSymbol)
+ if (pIndex >= 0)
+ for (bc <- p.baseClasses)
+ if (p.baseType(bc) =:= self.baseType(bc)) {
+ val bcIndex = index(bc)
+ if (bcIndex >= 0)
+ include(subParents(bcIndex), pIndex)
+ }
}
}
/** Do `sym1` and `sym2` have a common subclass in `parents`?
* In that case we do not follow their overriding pairs
*/
- private def hasCommonParentAsSubclass(sym1: Symbol, sym2: Symbol) = (
- for (index1 <- index get sym1.owner ; index2 <- index get sym2.owner) yield
- intersectionContainsElementLeq(subParents(index1), subParents(index2), index1 min index2)
- ).exists(_ == true)
+ private def hasCommonParentAsSubclass(sym1: Symbol, sym2: Symbol) = {
+ val index1 = index(sym1.owner)
+ (index1 >= 0) && {
+ val index2 = index(sym2.owner)
+ (index2 >= 0) && {
+ intersectionContainsElementLeq(
+ subParents(index1), subParents(index2), index1 min index2)
+ }
+ }
+ }
/** The scope entries that have already been visited as overridden
* (maybe excluded because of hasCommonParentAsSubclass).
diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala
index cc5b5bb406..977398909f 100644
--- a/src/reflect/scala/reflect/internal/transform/Erasure.scala
+++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala
@@ -203,28 +203,26 @@ trait Erasure {
def specialErasure(sym: Symbol)(tp: Type): Type =
if (sym != NoSymbol && sym.enclClass.isJavaDefined)
erasure(sym)(tp)
- else if (sym.isTerm && sym.owner.isDerivedValueClass)
- specialErasureAvoiding(sym.owner, tp)
- else if (sym.isValue && sym.owner.isMethodWithExtension)
- specialErasureAvoiding(sym.owner.owner, tp)
+ else if (sym.isClassConstructor)
+ specialConstructorErasure(sym.owner, tp)
else
specialScalaErasure(tp)
- def specialErasureAvoiding(clazz: Symbol, tpe: Type): Type = {
+ def specialConstructorErasure(clazz: Symbol, tpe: Type): Type = {
tpe match {
case PolyType(tparams, restpe) =>
- specialErasureAvoiding(clazz, restpe)
+ specialConstructorErasure(clazz, restpe)
case ExistentialType(tparams, restpe) =>
- specialErasureAvoiding(clazz, restpe)
+ specialConstructorErasure(clazz, restpe)
case mt @ MethodType(params, restpe) =>
MethodType(
- cloneSymbolsAndModify(params, specialErasureAvoiding(clazz, _)),
- if (restpe.typeSymbol == UnitClass) erasedTypeRef(UnitClass)
- else specialErasureAvoiding(clazz, (mt.resultType(mt.paramTypes))))
+ cloneSymbolsAndModify(params, specialScalaErasure),
+ specialConstructorErasure(clazz, restpe))
case TypeRef(pre, `clazz`, args) =>
typeRef(pre, clazz, List())
- case _ =>
- specialScalaErasure(tpe)
+ case tp =>
+ assert(clazz == ArrayClass || tp.isError, s"unexpected constructor erasure $tp for $clazz")
+ specialScalaErasure(tp)
}
}
diff --git a/test/files/buildmanager/overloaded_1/A.scala b/test/files/disabled/A.scala
index 33b63b8006..c070faf978 100644
--- a/test/files/buildmanager/overloaded_1/A.scala
+++ b/test/files/disabled/A.scala
@@ -3,7 +3,7 @@ trait As {
override def foo = this /// Shouldn't cause the change
override def foo(act: List[D]) = this
}
-
+
abstract class D{
def foo: D = this
def foo(act: List[D]) = this
diff --git a/test/files/buildmanager/overloaded_1/overloaded_1.check b/test/files/disabled/overloaded_1.check
index 4d643ce6b4..4d643ce6b4 100644
--- a/test/files/buildmanager/overloaded_1/overloaded_1.check
+++ b/test/files/disabled/overloaded_1.check
diff --git a/test/files/buildmanager/overloaded_1/overloaded_1.test b/test/files/disabled/overloaded_1.test
index 392e0d365f..392e0d365f 100644
--- a/test/files/buildmanager/overloaded_1/overloaded_1.test
+++ b/test/files/disabled/overloaded_1.test
diff --git a/test/files/buildmanager/t4245/A.scala b/test/files/disabled/t4245/A.scala
index 7c4efe1b4b..7c4efe1b4b 100644
--- a/test/files/buildmanager/t4245/A.scala
+++ b/test/files/disabled/t4245/A.scala
diff --git a/test/files/buildmanager/t4245/t4245.check b/test/files/disabled/t4245/t4245.check
index 3d3898c671..3d3898c671 100644
--- a/test/files/buildmanager/t4245/t4245.check
+++ b/test/files/disabled/t4245/t4245.check
diff --git a/test/files/buildmanager/t4245/t4245.test b/test/files/disabled/t4245/t4245.test
index 392e0d365f..392e0d365f 100644
--- a/test/files/buildmanager/t4245/t4245.test
+++ b/test/files/disabled/t4245/t4245.test
diff --git a/test/files/neg/t6260.check b/test/files/neg/t6260.check
new file mode 100644
index 0000000000..2b7f1a8bfb
--- /dev/null
+++ b/test/files/neg/t6260.check
@@ -0,0 +1,13 @@
+t6260.scala:3: error: bridge generated for member method apply: (x$1: Box[X])Box[Y] in anonymous class $anonfun
+which overrides method apply: (v1: T1)R in trait Function1
+clashes with definition of the member itself;
+both have erased type (v1: Object)Object
+ ((bx: Box[X]) => new Box(f(bx.x)))(this)
+ ^
+t6260.scala:8: error: bridge generated for member method apply: (x$1: Box[X])Box[Y] in anonymous class $anonfun
+which overrides method apply: (v1: T1)R in trait Function1
+clashes with definition of the member itself;
+both have erased type (v1: Object)Object
+ ((bx: Box[X]) => new Box(f(bx.x)))(self)
+ ^
+two errors found
diff --git a/test/files/neg/t6260.scala b/test/files/neg/t6260.scala
new file mode 100644
index 0000000000..93b5448227
--- /dev/null
+++ b/test/files/neg/t6260.scala
@@ -0,0 +1,17 @@
+class Box[X](val x: X) extends AnyVal {
+ def map[Y](f: X => Y): Box[Y] =
+ ((bx: Box[X]) => new Box(f(bx.x)))(this)
+}
+
+object Test {
+ def map2[X, Y](self: Box[X], f: X => Y): Box[Y] =
+ ((bx: Box[X]) => new Box(f(bx.x)))(self)
+
+ def main(args: Array[String]) {
+ val f = (x: Int) => x + 1
+ val g = (x: String) => x + x
+
+ map2(new Box(42), f)
+ new Box("abc") map g
+ }
+}
diff --git a/test/files/neg/t6385.check b/test/files/neg/t6385.check
new file mode 100644
index 0000000000..93e51e8927
--- /dev/null
+++ b/test/files/neg/t6385.check
@@ -0,0 +1,7 @@
+t6385.scala:12: error: bridge generated for member method x: ()C[T] in class C
+which overrides method x: ()C[T] in trait AA
+clashes with definition of the member itself;
+both have erased type ()Object
+ def x = this
+ ^
+one error found
diff --git a/test/files/neg/t6385.scala b/test/files/neg/t6385.scala
new file mode 100644
index 0000000000..cec58eec9e
--- /dev/null
+++ b/test/files/neg/t6385.scala
@@ -0,0 +1,13 @@
+object N {
+ def main(args: Array[String]) {
+ val y: AA[Int] = C(2)
+ val c: Int = y.x.y
+ println(c)
+ }
+}
+trait AA[T] extends Any {
+ def x: C[T]
+}
+case class C[T](val y: T) extends AnyVal with AA[T] {
+ def x = this
+}
diff --git a/test/files/neg/valueclasses-pavlov.check b/test/files/neg/valueclasses-pavlov.check
new file mode 100644
index 0000000000..031589edad
--- /dev/null
+++ b/test/files/neg/valueclasses-pavlov.check
@@ -0,0 +1,7 @@
+valueclasses-pavlov.scala:8: error: double definition:
+method foo:(x: Box2)String and
+method foo:(x: String)String at line 7
+have same type after erasure: (x: String)String
+ def foo(x: Box2) = "foo(Box2): ok"
+ ^
+one error found
diff --git a/test/files/neg/valueclasses-pavlov.scala b/test/files/neg/valueclasses-pavlov.scala
new file mode 100644
index 0000000000..a5858b2cf0
--- /dev/null
+++ b/test/files/neg/valueclasses-pavlov.scala
@@ -0,0 +1,23 @@
+trait Foo[T <: AnyVal] extends Any {
+ def foo(x: String): String
+ def foo(x: T): String
+}
+
+class Box1(val value: String) extends AnyVal with Foo[Box2] {
+ def foo(x: String) = "foo(String): ok"
+ def foo(x: Box2) = "foo(Box2): ok"
+}
+
+class Box2(val value: String) extends AnyVal
+
+
+object test2a {
+
+ def main(args: Array[String]) {
+ val b1 = new Box1(null)
+ val b2 = new Box2(null)
+ val f: Foo[Box2] = b1
+ println(f.foo(""))
+ println(f.foo(b2))
+ }
+}
diff --git a/test/files/run/Meter.scala b/test/files/run/Meter.scala
index d94f338ca9..a0c04cc2a7 100644
--- a/test/files/run/Meter.scala
+++ b/test/files/run/Meter.scala
@@ -2,7 +2,7 @@ package a {
class Meter(val underlying: Double) extends AnyVal with _root_.b.Printable {
def + (other: Meter): Meter =
new Meter(this.underlying + other.underlying)
- def / (other: Meter): Double = this.underlying / other.underlying
+ def / (other: Meter)(implicit dummy: Meter.MeterArg = null): Double = this.underlying / other.underlying
def / (factor: Double): Meter = new Meter(this.underlying / factor)
def < (other: Meter): Boolean = this.underlying < other.underlying
def toFoot: Foot = new Foot(this.underlying * 0.3048)
@@ -12,6 +12,8 @@ package a {
object Meter extends (Double => Meter) {
+ private[a] trait MeterArg
+
def apply(x: Double): Meter = new Meter(x)
implicit val boxings = new BoxingConversions[Meter, Double] {
@@ -80,7 +82,7 @@ object Test extends App {
println(m)
foo(arr)
}
- //
+ //
// { println("testing wrapped arrays")
// import collection.mutable.FlatArray
// val arr = FlatArray(x, y + x)
diff --git a/test/files/run/MeterCaseClass.scala b/test/files/run/MeterCaseClass.scala
index e5979cf761..18f8e23f89 100644
--- a/test/files/run/MeterCaseClass.scala
+++ b/test/files/run/MeterCaseClass.scala
@@ -2,7 +2,7 @@ package a {
case class Meter(underlying: Double) extends AnyVal with _root_.b.Printable {
def + (other: Meter): Meter =
new Meter(this.underlying + other.underlying)
- def / (other: Meter): Double = this.underlying / other.underlying
+ def / (other: Meter)(implicit dummy: Meter.MeterArg = null): Double = this.underlying / other.underlying
def / (factor: Double): Meter = new Meter(this.underlying / factor)
def < (other: Meter): Boolean = this.underlying < other.underlying
def toFoot: Foot = new Foot(this.underlying * 0.3048)
@@ -11,6 +11,8 @@ package a {
object Meter extends (Double => Meter) {
+ private[a] trait MeterArg
+
implicit val boxings = new BoxingConversions[Meter, Double] {
def box(x: Double) = new Meter(x)
def unbox(m: Meter) = m.underlying
@@ -77,7 +79,7 @@ object Test extends App {
println(m)
foo(arr)
}
- //
+ //
// { println("testing wrapped arrays")
// import collection.mutable.FlatArray
// val arr = FlatArray(x, y + x)
diff --git a/test/files/run/t6260.check b/test/files/run/t6260.check
new file mode 100644
index 0000000000..54f98a10f0
--- /dev/null
+++ b/test/files/run/t6260.check
@@ -0,0 +1 @@
+Box(abcabc)
diff --git a/test/files/run/t6260.scala b/test/files/run/t6260.scala
new file mode 100644
index 0000000000..cfe9e1e640
--- /dev/null
+++ b/test/files/run/t6260.scala
@@ -0,0 +1,12 @@
+class Box[X <: CharSequence](val x: X) extends AnyVal {
+ def map[Y <: CharSequence](f: X => Y): Box[Y] =
+ ((bx: Box[X]) => new Box(f(bx.x)))(this)
+ override def toString = s"Box($x)"
+}
+
+object Test {
+ def main(args: Array[String]) {
+ val g = (x: String) => x + x
+ println(new Box("abc") map g)
+ }
+}
diff --git a/test/files/run/t6337a.scala b/test/files/run/t6337a.scala
new file mode 100644
index 0000000000..f5490f5cf0
--- /dev/null
+++ b/test/files/run/t6337a.scala
@@ -0,0 +1,16 @@
+object Test {
+ def main(args: Array[String]) {
+ val x = X(XX(3))
+ assert(x.q.x.x + 9 == 13)
+ }
+}
+trait Q extends Any {
+ def x: Int
+ def inc: XX
+}
+case class X(val x: Q) extends AnyVal {
+ def q = X(x.inc)
+}
+case class XX(val x: Int) extends AnyVal with Q {
+ def inc = XX(x + 1)
+}
diff --git a/test/files/run/valueclasses-pavlov.check b/test/files/run/valueclasses-pavlov.check
new file mode 100644
index 0000000000..b112e5507e
--- /dev/null
+++ b/test/files/run/valueclasses-pavlov.check
@@ -0,0 +1,2 @@
+box1: ok
+box2: ok
diff --git a/test/files/run/valueclasses-pavlov.scala b/test/files/run/valueclasses-pavlov.scala
new file mode 100644
index 0000000000..e73897f653
--- /dev/null
+++ b/test/files/run/valueclasses-pavlov.scala
@@ -0,0 +1,26 @@
+trait Foo extends Any {
+ def box1(x: Box1): String
+ def box2(x: Box2): String
+}
+
+class Box1(val value: String) extends AnyVal
+
+class Box2(val value: String) extends AnyVal with Foo {
+ def box1(x: Box1) = "box1: ok"
+ def box2(x: Box2) = "box2: ok"
+}
+
+class C(x: String) {
+ def this() = this("")
+}
+
+object Test {
+
+ def main(args: Array[String]) {
+ val b1 = new Box1("")
+ val b2 = new Box2("")
+ val f: Foo = b2
+ println(f.box1(b1))
+ println(f.box2(b2))
+ }
+}