diff options
author | Paul Phillips <paulp@improving.org> | 2012-09-20 09:53:39 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-09-20 09:53:39 -0700 |
commit | 3136e53e0ce4d73e1d2b3e8d043fff7892b2f439 (patch) | |
tree | 69e6e4c21241e174942bce493aec289b46a6dce9 | |
parent | d834d90d88e1dab6a8621b13c9d4b64d3417a94e (diff) | |
parent | d87592da76eb555f0e3fc3732169e56b1852fba1 (diff) | |
download | scala-3136e53e0ce4d73e1d2b3e8d043fff7892b2f439.tar.gz scala-3136e53e0ce4d73e1d2b3e8d043fff7892b2f439.tar.bz2 scala-3136e53e0ce4d73e1d2b3e8d043fff7892b2f439.zip |
Merge branch 'pull-1352-reformatted' into 2.10.x
# By Martin Odersky
* pull-1352-reformatted:
Disabled failing build manager tests.
New test case for SI-6337
New test case for closing SI-6385
Value classes: eliminated half-boxing
Cleanup of OverridingPairs
Fixes SI-6260
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)) + } +} |