diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala b/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala index 20d9e34f0ab0..2391574edeb2 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala @@ -918,7 +918,7 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { // (one that doesn't erase to the actual signature). See run/t3452b for a test case. val memberTpe = atPhase(erasurePhase) { moduleClass.denot.thisType.memberInfo(sym) } - val erasedMemberType = TypeErasure.erasure(memberTpe) + val erasedMemberType = TypeErasure.fullErasure(memberTpe) if (erasedMemberType =:= sym.denot.info) getGenericSignatureHelper(sym, moduleClass, memberTpe).orNull else null diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 0f935b21a5d4..4c85c684d144 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -341,7 +341,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling case TypeErasure.ErasedValueType(tycon1, underlying2) => def compareErasedValueType = tp1 match { case TypeErasure.ErasedValueType(tycon2, underlying1) => - (tycon1.symbol eq tycon2.symbol) && isSameType(underlying1, underlying2) + (tycon1.symbol eq tycon2.symbol) && isSubType(underlying1, underlying2) case _ => secondTry } diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index d142ccd5f5ac..b5bd1cfb92bc 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -36,7 +36,7 @@ import scala.annotation.tailrec object TypeErasure { private def erasureDependsOnArgs(sym: Symbol)(using Context) = - sym == defn.ArrayClass || sym == defn.PairClass + sym == defn.ArrayClass || sym == defn.PairClass || isDerivedValueClass(sym) def normalizeClass(cls: ClassSymbol)(using Context): ClassSymbol = { if (cls.owner == defn.ScalaPackageClass) { @@ -59,7 +59,7 @@ object TypeErasure { case tp: TypeRef => val sym = tp.symbol sym.isClass && - !erasureDependsOnArgs(sym) && + (!erasureDependsOnArgs(sym) || isDerivedValueClass(sym)) && !defn.specialErasure.contains(sym) && !defn.isSyntheticFunctionClass(sym) case _: TermRef => @@ -157,7 +157,7 @@ object TypeErasure { def sigName(tp: Type, isJava: Boolean)(using Context): TypeName = { val normTp = tp.translateFromRepeated(toArray = isJava) - val erase = erasureFn(isJava, semiEraseVCs = false, isConstructor = false, wildcardOK = true) + val erase = erasureFn(isJava, semiEraseVCs = true, isConstructor = false, wildcardOK = true) erase.sigName(normTp)(using preErasureCtx) } @@ -444,7 +444,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean case tp: TypeRef => val sym = tp.symbol if (!sym.isClass) this(tp.translucentSuperType) - else if (semiEraseVCs && isDerivedValueClass(sym)) eraseDerivedValueClassRef(tp) + else if (semiEraseVCs && isDerivedValueClass(sym)) eraseDerivedValueClass(tp) else if (defn.isSyntheticFunctionClass(sym)) defn.erasedFunctionType(sym) else eraseNormalClassRef(tp) case tp: AppliedType => @@ -452,6 +452,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean if (tycon.isRef(defn.ArrayClass)) eraseArray(tp) else if (tycon.isRef(defn.PairClass)) erasePair(tp) else if (tp.isRepeatedParam) apply(tp.translateFromRepeated(toArray = isJava)) + else if (semiEraseVCs && isDerivedValueClass(tycon.classSymbol)) eraseDerivedValueClass(tp) else apply(tp.translucentSuperType) case _: TermRef | _: ThisType => this(tp.widen) @@ -551,12 +552,34 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean case rt => MethodType(Nil, Nil, rt) case tp1 => this(tp1) - private def eraseDerivedValueClassRef(tref: TypeRef)(using Context): Type = { - val cls = tref.symbol.asClass - val underlying = underlyingOfValueClass(cls) - if underlying.exists && !isCyclic(cls) then - val erasedValue = valueErasure(underlying) - if erasedValue.exists then ErasedValueType(tref, erasedValue) + private def eraseDerivedValueClass(tp: Type)(using Context): Type = { + val cls = tp.classSymbol.asClass + val unbox = valueClassUnbox(cls) + if unbox.exists then + val genericUnderlying = unbox.info.resultType + val underlying = tp.select(unbox).widen.resultType + + val erasedUnderlying = erasure(underlying) + + // Ideally, we would just use `erasedUnderlying` as the erasure of `tp`, but to + // be binary-compatible with Scala 2 we need two special cases for polymorphic + // value classes: + // - Given `class Foo[A](x: A) extends AnyVal`, `Foo[X]` should erase like + // `X`, except if its a primitive in which case it erases to the boxed + // version of this primitive. + // - Given `class Bar[A](x: Array[A]) extends AnyVal`, `Bar[X]` will be + // erased like `Array[A]` as seen from its definition site, no matter + // the `X` (same if `A` is bounded). + // + // The binary compatibility is checked by sbt-dotty/sbt-test/scala2-compat/i8001 + val erasedValueClass = + if erasedUnderlying.isPrimitiveValueType && !genericUnderlying.isPrimitiveValueType then + defn.boxedType(erasedUnderlying) + else if genericUnderlying.derivesFrom(defn.ArrayClass) then + erasure(genericUnderlying) + else erasedUnderlying + + if erasedValueClass.exists then ErasedValueType(cls.typeRef, erasedValueClass) else assert(ctx.reporter.errorsReported, i"no erasure for $underlying") NoType @@ -569,22 +592,23 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean } /** The erasure of a function result type. */ - private def eraseResult(tp: Type)(using Context): Type = tp match { - case tp: TypeRef => - val sym = tp.symbol - if (sym eq defn.UnitClass) sym.typeRef - // For a value class V, "new V(x)" should have type V for type adaptation to work - // correctly (see SIP-15 and [[Erasure.Boxing.adaptToType]]), so the return type of a - // constructor method should not be semi-erased. - else if (isConstructor && isDerivedValueClass(sym)) eraseNormalClassRef(tp) - else this(tp) - case tp: AppliedType => - val sym = tp.tycon.typeSymbol - if (sym.isClass && !erasureDependsOnArgs(sym)) eraseResult(tp.tycon) - else this(tp) - case _ => - this(tp) - } + def eraseResult(tp: Type)(using Context): Type = + // For a value class V, "new V(x)" should have type V for type adaptation to work + // correctly (see SIP-15 and [[Erasure.Boxing.adaptToType]]), so the result type of a + // constructor method should not be semi-erased. + if semiEraseVCs && isConstructor && !tp.isInstanceOf[MethodOrPoly] then + erasureFn(isJava, semiEraseVCs = false, isConstructor, wildcardOK).eraseResult(tp) + else tp match + case tp: TypeRef => + val sym = tp.symbol + if (sym eq defn.UnitClass) sym.typeRef + else this(tp) + case tp: AppliedType => + val sym = tp.tycon.typeSymbol + if (sym.isClass && !erasureDependsOnArgs(sym)) eraseResult(tp.tycon) + else this(tp) + case _ => + this(tp) /** The name of the type as it is used in `Signature`s. * Need to ensure correspondence with erasure! @@ -602,7 +626,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean return sigName(info) } if (isDerivedValueClass(sym)) { - val erasedVCRef = eraseDerivedValueClassRef(tp) + val erasedVCRef = eraseDerivedValueClass(tp) if (erasedVCRef.exists) return sigName(erasedVCRef) } if (defn.isSyntheticFunctionClass(sym)) diff --git a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala index 89e085988131..20becf1cce35 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala @@ -84,7 +84,7 @@ enum ErrorMessageID extends java.lang.Enum[ErrorMessageID] { ValueClassesMayNotContainInitalizationID, ValueClassesMayNotBeAbstractID, ValueClassesMayNotBeContaintedID, - ValueClassesMayNotWrapItselfID, + ValueClassesMayNotWrapAnotherValueClassID, ValueClassParameterMayNotBeAVarID, ValueClassNeedsExactlyOneValParamID, OnlyCaseClassOrCaseObjectAllowedID, diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index 64cb29ac999b..20f97246b487 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -1617,9 +1617,9 @@ import transform.SymUtils._ def explain = "" } - class ValueClassesMayNotWrapItself(valueClass: Symbol)(using Context) - extends SyntaxMsg(ValueClassesMayNotWrapItselfID) { - def msg = """A value class may not wrap itself""" + class ValueClassesMayNotWrapAnotherValueClass(valueClass: Symbol)(using Context) + extends SyntaxMsg(ValueClassesMayNotWrapAnotherValueClassID) { + def msg = """A value class may not wrap another user-defined value class""" def explain = "" } diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 42a63e53fc3c..5d63510e71d4 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -302,7 +302,6 @@ object Erasure { * in ExtensionMethods#transform. */ def cast(tree: Tree, pt: Type)(using Context): Tree = trace(i"cast ${tree.tpe.widen} --> $pt", show = true) { - def wrap(tycon: TypeRef) = ref(u2evt(tycon.typeSymbol.asClass)).appliedTo(tree) def unwrap(tycon: TypeRef) = @@ -357,7 +356,10 @@ object Erasure { if (pt.isInstanceOf[ProtoType] || tree.tpe <:< pt) tree else if (tpw.isErasedValueType) - adaptToType(box(tree), pt) + if (pt.isErasedValueType) then + tree.asInstance(pt) + else + adaptToType(box(tree), pt) else if (pt.isErasedValueType) adaptToType(unbox(tree, pt), pt) else if (tpw.isPrimitiveValueType && !pt.isPrimitiveValueType) diff --git a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala index eb1f4816236e..3f6693440207 100644 --- a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala +++ b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala @@ -18,6 +18,7 @@ import NameOps._ import NameKinds.OuterSelectName import StdNames._ import NullOpsDecorator._ +import TypeUtils.isErasedValueType object FirstTransform { val name: String = "firstTransform" @@ -67,7 +68,7 @@ class FirstTransform extends MiniPhase with InfoTransformer { thisPhase => qual.tpe } assert( - qualTpe.derivesFrom(tree.symbol.owner) || + qualTpe.isErasedValueType || qualTpe.derivesFrom(tree.symbol.owner) || tree.symbol.is(JavaStatic) && qualTpe.derivesFrom(tree.symbol.enclosingClass), i"non member selection of ${tree.symbol.showLocated} from ${qualTpe} in $tree") case _: TypeTree => diff --git a/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala b/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala index 5b2592b5009b..1ec149d505be 100644 --- a/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala +++ b/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala @@ -212,12 +212,11 @@ object GenericSignatures { else if (sym == defn.UnitClass) jsig(defn.BoxedUnitClass.typeRef) else builder.append(defn.typeTag(sym.info)) else if (ValueClasses.isDerivedValueClass(sym)) { - val unboxed = ValueClasses.valueClassUnbox(sym.asClass).info.finalResultType - val unboxedSeen = tp.memberInfo(ValueClasses.valueClassUnbox(sym.asClass)).finalResultType - if (unboxedSeen.isPrimitiveValueType && !primitiveOK) + val erasedUnderlying = core.TypeErasure.fullErasure(tp) + if (erasedUnderlying.isPrimitiveValueType && !primitiveOK) classSig(sym, pre, args) else - jsig(unboxedSeen, toplevel, primitiveOK) + jsig(erasedUnderlying, toplevel, primitiveOK) } else if (defn.isSyntheticFunctionClass(sym)) { val erasedSym = defn.erasedFunctionClass(sym) diff --git a/compiler/src/dotty/tools/dotc/transform/ValueClasses.scala b/compiler/src/dotty/tools/dotc/transform/ValueClasses.scala index aba99f9d5b01..a86bf2c48fb5 100644 --- a/compiler/src/dotty/tools/dotc/transform/ValueClasses.scala +++ b/compiler/src/dotty/tools/dotc/transform/ValueClasses.scala @@ -13,7 +13,7 @@ import SymUtils._ /** Methods that apply to user-defined value classes */ object ValueClasses { - def isDerivedValueClass(sym: Symbol)(using Context): Boolean = { + def isDerivedValueClass(sym: Symbol)(using Context): Boolean = sym.isClass && { val d = sym.denot !d.isRefinementClass && d.isValueClass && @@ -54,15 +54,4 @@ object ValueClasses { /** The unboxed type that underlies a derived value class */ def underlyingOfValueClass(sym: ClassSymbol)(using Context): Type = valueClassUnbox(sym).info.resultType - - /** Whether a value class wraps itself */ - def isCyclic(cls: ClassSymbol)(using Context): Boolean = { - def recur(seen: Set[Symbol], clazz: ClassSymbol)(using Context): Boolean = - (seen contains clazz) || { - val unboxed = underlyingOfValueClass(clazz).typeSymbol - (isDerivedValueClass(unboxed)) && recur(seen + clazz, unboxed.asClass) - } - - recur(Set[Symbol](), cls) - } } diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index b31c14e60eee..1a50165eb0b7 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -610,8 +610,8 @@ object Checking { report.error(ValueClassesMayNotBeAbstract(clazz), clazz.srcPos) if (!clazz.isStatic) report.error(ValueClassesMayNotBeContainted(clazz), clazz.srcPos) - if (isCyclic(clazz.asClass)) - report.error(ValueClassesMayNotWrapItself(clazz), clazz.srcPos) + if (isDerivedValueClass(underlyingOfValueClass(clazz.asClass).classSymbol)) + report.error(ValueClassesMayNotWrapAnotherValueClass(clazz), clazz.srcPos) else { val clParamAccessors = clazz.asClass.paramAccessors.filter { param => param.isTerm && !param.is(Flags.Accessor) diff --git a/compiler/test/dotty/tools/dotc/MissingCoreLibTests.scala b/compiler/test/dotty/tools/dotc/MissingCoreLibTests.scala deleted file mode 100644 index f50e66cb49eb..000000000000 --- a/compiler/test/dotty/tools/dotc/MissingCoreLibTests.scala +++ /dev/null @@ -1,24 +0,0 @@ -package dotty -package tools -package dotc - -import org.junit.Test -import org.junit.Assert._ - -import vulpix.TestConfiguration.mkClasspath - -class MissingCoreLibTests { - - @Test def missingDottyLib: Unit = { - val classPath = mkClasspath(List(Properties.scalaLibrary)) // missing Properties.dottyLibrary - val source = "tests/pos/Foo.scala" - val options = Array("-classpath", classPath, source) - val reporter = Main.process(options) - assertEquals(1, reporter.errorCount) - val errorMessage = reporter.allErrors.head.message - // FIXME: We currently only detect if the scala library is missing but not the dotty library. - // See dotty.tools.dotc.MissingCoreLibraryException - // assertTrue(errorMessage.contains("Make sure the compiler core libraries are on the classpath")) - } - -} diff --git a/sbt-dotty/sbt-test/scala2-compat/i8001/build.sbt b/sbt-dotty/sbt-test/scala2-compat/i8001/build.sbt new file mode 100644 index 000000000000..818af971469f --- /dev/null +++ b/sbt-dotty/sbt-test/scala2-compat/i8001/build.sbt @@ -0,0 +1,15 @@ +val scala3Version = sys.props("plugin.scalaVersion") +val scala2Version = "2.13.4" + +lazy val lib = (project in file ("lib")) + .settings(scalaVersion := scala2Version) + +lazy val test = (project in file ("main")) + .dependsOn(lib) + .settings( + scalaVersion := scala3Version, + // https://github.com/sbt/sbt/issues/5369 + projectDependencies := { + projectDependencies.value.map(_.withDottyCompat(scalaVersion.value)) + } + ) diff --git a/sbt-dotty/sbt-test/scala2-compat/i8001/lib/lib.scala b/sbt-dotty/sbt-test/scala2-compat/i8001/lib/lib.scala new file mode 100644 index 000000000000..1a80c43e839e --- /dev/null +++ b/sbt-dotty/sbt-test/scala2-compat/i8001/lib/lib.scala @@ -0,0 +1,43 @@ +class Poly[A](val value: A) extends AnyVal + +class Arr[A](val value: Array[A]) extends AnyVal + +class ArrRef[A <: AnyRef](val value: Array[A]) extends AnyVal + +class A { + def poly1(x: Poly[Int]): Poly[Int] = + new Poly(x.value) + + def poly2(x: Poly[String]): Poly[String] = + new Poly(x.value) + + def poly3(x: Poly[Array[Int]]): Poly[Array[Int]] = + new Poly(x.value) + + def poly4(x: Poly[Array[String]]): Poly[Array[String]] = + new Poly(x.value) + + def arr1(x: Arr[Int]): Arr[Int] = + new Arr(x.value) + + def arr2(x: Arr[String]): Arr[String] = + new Arr(x.value) + + def arr3(x: Arr[Array[Int]]): Arr[Array[Int]] = + new Arr(x.value) + + def arr4(x: Arr[Array[String]]): Arr[Array[String]] = + new Arr(x.value) + + def arrRef1(x: ArrRef[Integer]): ArrRef[Integer] = + new ArrRef(x.value) + + def arrRef2(x: ArrRef[String]): ArrRef[String] = + new ArrRef(x.value) + + def arrRef3(x: ArrRef[Array[Int]]): ArrRef[Array[Int]] = + new ArrRef(x.value) + + def arrRef4(x: ArrRef[Array[String]]): ArrRef[Array[String]] = + new ArrRef(x.value) +} diff --git a/sbt-dotty/sbt-test/scala2-compat/i8001/main/test.scala b/sbt-dotty/sbt-test/scala2-compat/i8001/main/test.scala new file mode 100644 index 000000000000..2ab27c68d429 --- /dev/null +++ b/sbt-dotty/sbt-test/scala2-compat/i8001/main/test.scala @@ -0,0 +1,20 @@ +object B { + def main(args: Array[String]): Unit = { + val a = new A + + a.poly1(new Poly(1)) + a.poly2(new Poly("")) + a.poly3(new Poly(Array(1))) + a.poly4(new Poly(Array(""))) + + a.arr1(new Arr(Array(1))) + a.arr2(new Arr(Array(""))) + a.arr3(new Arr(Array(Array(1)))) + a.arr4(new Arr(Array(Array("")))) + + a.arrRef1(new ArrRef(Array(1))) + a.arrRef2(new ArrRef(Array(""))) + a.arrRef3(new ArrRef(Array(Array(1)))) + a.arrRef4(new ArrRef(Array(Array("")))) + } +} diff --git a/sbt-dotty/sbt-test/scala2-compat/i8001/project/plugins.sbt b/sbt-dotty/sbt-test/scala2-compat/i8001/project/plugins.sbt new file mode 100644 index 000000000000..c17caab2d98c --- /dev/null +++ b/sbt-dotty/sbt-test/scala2-compat/i8001/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version")) diff --git a/sbt-dotty/sbt-test/scala2-compat/i8001/test b/sbt-dotty/sbt-test/scala2-compat/i8001/test new file mode 100644 index 000000000000..8aedcd64cf5b --- /dev/null +++ b/sbt-dotty/sbt-test/scala2-compat/i8001/test @@ -0,0 +1 @@ +> test/run diff --git a/tests/pos/i5033a.scala b/tests/disabled/i5033a.scala similarity index 100% rename from tests/pos/i5033a.scala rename to tests/disabled/i5033a.scala diff --git a/tests/neg/i1642.scala b/tests/neg/i1642.scala index 2f7644698f0f..2d3216d66f02 100644 --- a/tests/neg/i1642.scala +++ b/tests/neg/i1642.scala @@ -1 +1,4 @@ -class Test2(val valueVal: Test2) extends AnyVal // error: value class cannot wrap itself +class Test0(val valueVal: Test0) extends AnyVal // error: value class cannot wrap itself + +class Test1(val x: Int) extends AnyVal +class Test2(val y: Test1) extends AnyVal // error: value class may not wrap another user-defined value class diff --git a/tests/neg/i5005.scala b/tests/neg/i5005.scala index 5dfcfc37b1a3..1734f79d934c 100644 --- a/tests/neg/i5005.scala +++ b/tests/neg/i5005.scala @@ -1,5 +1,5 @@ -case class i0 (i0: i1) extends AnyVal +case class i0 (i0: i1) extends AnyVal // error trait i1 extends i0 // error trait F[x] extends AnyVal // error diff --git a/tests/pos/i1642.scala b/tests/pos/i1642.scala deleted file mode 100644 index 2fe67cf18af7..000000000000 --- a/tests/pos/i1642.scala +++ /dev/null @@ -1,2 +0,0 @@ -class Test1(val x: Int) extends AnyVal -class Test2(val y: Test1) extends AnyVal diff --git a/tests/run/i8001/A_1.scala b/tests/run/i8001/A_1.scala new file mode 100644 index 000000000000..db6e6c0a3dd9 --- /dev/null +++ b/tests/run/i8001/A_1.scala @@ -0,0 +1,71 @@ +trait TC[A] { + def apply(a: A): Unit +} + +class Poly[A](val value: A) extends AnyVal + +class Arr[A](val value: Array[A]) extends AnyVal + +class ArrRef[A <: AnyRef](val value: Array[A]) extends AnyVal + +class A { + val tc = new TC[Poly[String]] { + def apply(a: Poly[String]): Unit = () + } + + def poly1(x: Poly[Int]): Poly[Int] = + new Poly(x.value) + + def poly2(x: Poly[String]): Poly[String] = + new Poly(x.value) + + def poly3(x: Poly[Array[Int]]): Poly[Array[Int]] = + new Poly(x.value) + + def poly4(x: Poly[Array[String]]): Poly[Array[String]] = + new Poly(x.value) + + def arr1(x: Arr[Int]): Arr[Int] = + new Arr(x.value) + + def arr2(x: Arr[String]): Arr[String] = + new Arr(x.value) + + def arr3(x: Arr[Array[Int]]): Arr[Array[Int]] = + new Arr(x.value) + + def arr4(x: Arr[Array[String]]): Arr[Array[String]] = + new Arr(x.value) + + def arrRef1(x: ArrRef[Integer]): ArrRef[Integer] = + new ArrRef(x.value) + + def arrRef2(x: ArrRef[String]): ArrRef[String] = + new ArrRef(x.value) + + def arrRef3(x: ArrRef[Array[Int]]): ArrRef[Array[Int]] = + new ArrRef(x.value) + + def arrRef4(x: ArrRef[Array[String]]): ArrRef[Array[String]] = + new ArrRef(x.value) + + + def test: Unit = { + tc.apply(new Poly("")) + + poly1(new Poly(1)) + poly2(new Poly("")) + poly3(new Poly(Array(1))) + poly4(new Poly(Array(""))) + + arr1(new Arr(Array(1))) + arr2(new Arr(Array(""))) + arr3(new Arr(Array(Array(1)))) + arr4(new Arr(Array(Array("")))) + + arrRef1(new ArrRef(Array(1))) + arrRef2(new ArrRef(Array(""))) + arrRef3(new ArrRef(Array(Array(1)))) + arrRef4(new ArrRef(Array(Array("")))) + } +} diff --git a/tests/run/i8001/B_2.java b/tests/run/i8001/B_2.java new file mode 100644 index 000000000000..bde79bae36fb --- /dev/null +++ b/tests/run/i8001/B_2.java @@ -0,0 +1,27 @@ +public class B_2 { + public static void test() { + A a = new A(); + a.test(); + + int[] intArr = { 1 }; + int[][] intArr2 = { { 1 } }; + String[] stringArr = { "" }; + String[][] stringArr2 = { { "" } }; + Integer[] integerArr = { 1 }; + + a.poly1(1); + a.poly2(""); + a.poly3(intArr); + a.poly4(stringArr); + + a.arr1(intArr); + a.arr2(stringArr); + a.arr3(intArr); + a.arr4(stringArr2); + + a.arrRef1(integerArr); + a.arrRef2(stringArr); + a.arrRef3(intArr2); + a.arrRef4(stringArr2); + } +} diff --git a/tests/run/i8001/Test_3.scala b/tests/run/i8001/Test_3.scala new file mode 100644 index 000000000000..b397d63ff166 --- /dev/null +++ b/tests/run/i8001/Test_3.scala @@ -0,0 +1,4 @@ +object Test { + def main(args: Array[String]): Unit = + B_2.test() +} diff --git a/tests/run/t7685-class-simple.scala b/tests/run/t7685-class-simple.scala deleted file mode 100644 index 5147a66c0543..000000000000 --- a/tests/run/t7685-class-simple.scala +++ /dev/null @@ -1,10 +0,0 @@ -object Test { - final class Foo(val x: String) extends AnyVal { override def toString = "" + x } - final class Bar(val f: Foo) extends AnyVal { override def toString = "" + f } - def main(args: Array[String]) = { - val x = "abc" - val f = new Foo(x) - val b = new Bar(f) - assert(b.toString == "abc") - } -}