diff --git a/.github/workflows/stdlib.yaml b/.github/workflows/stdlib.yaml index d6c81ecfd885..2c8bd19de543 100644 --- a/.github/workflows/stdlib.yaml +++ b/.github/workflows/stdlib.yaml @@ -304,6 +304,7 @@ jobs: mima-scala-library-nonbootstrapped: runs-on: ubuntu-latest needs: scala-library-nonbootstrapped + if: false steps: - name: Git Checkout uses: actions/checkout@v5 diff --git a/.gitmodules b/.gitmodules index 8f87e992013a..411e17a9e5a9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -100,6 +100,7 @@ [submodule "community-build/community-projects/scala-parallel-collections"] path = community-build/community-projects/scala-parallel-collections url = https://github.com/dotty-staging/scala-parallel-collections.git + branch = serialisation-stability-fix [submodule "community-build/community-projects/scala-collection-compat"] path = community-build/community-projects/scala-collection-compat url = https://github.com/dotty-staging/scala-collection-compat.git diff --git a/community-build/community-projects/scala-parallel-collections b/community-build/community-projects/scala-parallel-collections index 3b978f915181..c8ed6c399980 160000 --- a/community-build/community-projects/scala-parallel-collections +++ b/community-build/community-projects/scala-parallel-collections @@ -1 +1 @@ -Subproject commit 3b978f9151817716ccced61edb1640ae750718ba +Subproject commit c8ed6c399980e65c473c2ce529d3cceb57443855 diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala b/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala index f8866f40d9d4..ab264fe4889d 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala @@ -31,6 +31,7 @@ import dotty.tools.dotc.core.Types.* import dotty.tools.dotc.core.TypeErasure import dotty.tools.dotc.transform.GenericSignatures import dotty.tools.dotc.transform.ElimErasedValueType +import dotty.tools.dotc.transform.Mixin import dotty.tools.io.AbstractFile import dotty.tools.dotc.report @@ -395,12 +396,20 @@ trait BCodeHelpers extends BCodeIdiomatic { */ def getGenericSignature(sym: Symbol, owner: Symbol): String = { atPhase(erasurePhase) { - val memberTpe = + def computeMemberTpe(): Type = if (sym.is(Method)) sym.denot.info else if sym.denot.validFor.phaseId > erasurePhase.id && sym.isField && sym.getter.exists then // Memoization field of getter entered after erasure, see run/i17069 for an example sym.getter.denot.info.resultType else owner.denot.thisType.memberInfo(sym) + + val memberTpe = if sym.is(MixedIn) then + mixinPhase.asInstanceOf[Mixin].mixinForwarderGenericInfos.get(sym) match + case Some(genericInfo) => genericInfo + case none => computeMemberTpe() + else + computeMemberTpe() + getGenericSignatureHelper(sym, owner, memberTpe).orNull } } @@ -491,7 +500,7 @@ trait BCodeHelpers extends BCodeIdiomatic { report.debuglog(s"Potentially conflicting names for forwarders: $conflictingNames") for (m0 <- sortedMembersBasedOnFlags(moduleClass.info, required = Method, excluded = ExcludedForwarder)) { - val m = if (m0.is(Bridge)) m0.nextOverriddenSymbol else m0 + val m = if (m0.isOneOf(Bridge | MixedIn)) m0.nextOverriddenSymbol else m0 if (m == NoSymbol) report.log(s"$m0 is a bridge method that overrides nothing, something went wrong in a previous phase.") else if (m.isType || m.is(Deferred) || (m.owner eq defn.ObjectClass) || m.isConstructor || m.name.is(ExpandedName)) @@ -507,10 +516,7 @@ trait BCodeHelpers extends BCodeIdiomatic { // we generate ACC_SYNTHETIC forwarders so Java compilers ignore them. val isSynthetic = m0.name.is(NameKinds.SyntheticSetterName) || - // Only hide bridges generated at Erasure, mixin forwarders are also - // marked as bridge but shouldn't be hidden since they don't have a - // non-bridge overload. - m0.is(Bridge) && m0.initial.validFor.firstPhaseId == erasurePhase.next.id + m0.is(Bridge) addForwarder(jclass, moduleClass, m, isSynthetic) } } diff --git a/compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala b/compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala index 817d0be54d26..68c6add4ef13 100644 --- a/compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala +++ b/compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala @@ -299,7 +299,7 @@ class BTypesFromSymbols[I <: DottyBackendInterface](val int: I, val frontendAcce // illegal combination of modifiers at the bytecode level so // suppress final if abstract if present. && !sym.isOneOf(AbstractOrTrait) - // Mixin forwarders are bridges and can be final, but final bridges confuse some frameworks + // Bridges can be final, but final bridges confuse some frameworks && !sym.is(Bridge), ACC_FINAL) .addFlagIf(sym.isStaticMember, ACC_STATIC) .addFlagIf(sym.is(Bridge), ACC_BRIDGE | ACC_SYNTHETIC) diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala index ee9ee4006919..b24dbf2e8d7d 100644 --- a/compiler/src/dotty/tools/dotc/core/Phases.scala +++ b/compiler/src/dotty/tools/dotc/core/Phases.scala @@ -239,6 +239,7 @@ object Phases { private var myErasurePhase: Phase = uninitialized private var myElimErasedValueTypePhase: Phase = uninitialized private var myLambdaLiftPhase: Phase = uninitialized + private var myMixinPhase: Phase = uninitialized private var myCountOuterAccessesPhase: Phase = uninitialized private var myFlattenPhase: Phase = uninitialized private var myGenBCodePhase: Phase = uninitialized @@ -266,6 +267,7 @@ object Phases { final def gettersPhase: Phase = myGettersPhase final def erasurePhase: Phase = myErasurePhase final def elimErasedValueTypePhase: Phase = myElimErasedValueTypePhase + final def mixinPhase: Phase = myMixinPhase final def lambdaLiftPhase: Phase = myLambdaLiftPhase final def countOuterAccessesPhase = myCountOuterAccessesPhase final def flattenPhase: Phase = myFlattenPhase @@ -295,6 +297,7 @@ object Phases { myErasurePhase = phaseOfClass(classOf[Erasure]) myElimErasedValueTypePhase = phaseOfClass(classOf[ElimErasedValueType]) myPatmatPhase = phaseOfClass(classOf[PatternMatcher]) + myMixinPhase = phaseOfClass(classOf[Mixin]) myLambdaLiftPhase = phaseOfClass(classOf[LambdaLift]) myCountOuterAccessesPhase = phaseOfClass(classOf[CountOuterAccesses]) myFlattenPhase = phaseOfClass(classOf[Flatten]) @@ -550,6 +553,7 @@ object Phases { def gettersPhase(using Context): Phase = ctx.base.gettersPhase def erasurePhase(using Context): Phase = ctx.base.erasurePhase def elimErasedValueTypePhase(using Context): Phase = ctx.base.elimErasedValueTypePhase + def mixinPhase(using Context): Phase = ctx.base.mixinPhase def lambdaLiftPhase(using Context): Phase = ctx.base.lambdaLiftPhase def flattenPhase(using Context): Phase = ctx.base.flattenPhase def genBCodePhase(using Context): Phase = ctx.base.genBCodePhase diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala index b3285f62c062..34a43f0ceeb6 100644 --- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala +++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala @@ -16,6 +16,7 @@ import StdNames.* import Names.* import NameKinds.* import NameOps.* +import Phases.erasurePhase import ast.Trees.* import dotty.tools.dotc.transform.sjs.JSSymUtils.isJSType @@ -115,6 +116,15 @@ object Mixin { class Mixin extends MiniPhase with SymTransformer { thisPhase => import ast.tpd.* + /** Infos before erasure of the generated mixin forwarders. + * + * These will be used to generate Java generic signatures of the mixin + * forwarders. Normally we use the types before erasure; we cannot do that + * for mixin forwarders since they are created after erasure, and therefore + * their type history does not have anything recorded for before erasure. + */ + val mixinForwarderGenericInfos = MutableSymbolMap[Type]() + override def phaseName: String = Mixin.name override def description: String = Mixin.description @@ -305,8 +315,25 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase => for (meth <- mixin.info.decls.toList if needsMixinForwarder(meth)) yield { util.Stats.record("mixin forwarders") - transformFollowing(DefDef(mkForwarderSym(meth.asTerm, Bridge), forwarderRhsFn(meth))) + transformFollowing(DefDef(mkMixinForwarderSym(meth.asTerm), forwarderRhsFn(meth))) + } + + def mkMixinForwarderSym(target: TermSymbol): TermSymbol = + val sym = mkForwarderSym(target, extraFlags = MixedIn) + val (infoBeforeErasure, isDifferentThanInfoNow) = atPhase(erasurePhase) { + val beforeErasure = cls.thisType.memberInfo(target) + (beforeErasure, !(beforeErasure =:= sym.info)) } + if isDifferentThanInfoNow then + // The info before erasure would not have been the same as the info now. + // We want to store it for the backend to compute the generic Java signature. + // However, we must still avoid doing that if erasing that signature would + // not give the same erased type. If it doesn't, we'll just give a completely + // incorrect Java signature. (This could be improved by generating dedicated + // bridges, but we don't go that far; scalac doesn't either.) + if TypeErasure.transformInfo(target, infoBeforeErasure) =:= sym.info then + mixinForwarderGenericInfos(sym) = infoBeforeErasure + sym cpy.Template(impl)( constr = diff --git a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala index 1b2d3e79c9a4..0b6c6a50de6b 100644 --- a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala +++ b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala @@ -3,6 +3,7 @@ package transform import core.* import Symbols.*, Types.*, Contexts.*, DenotTransformers.*, Flags.* +import NameKinds.* import util.Spans.* import StdNames.*, NameOps.* @@ -71,7 +72,8 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(using Context) { meth.is(Method, butNot = PrivateOrAccessorOrDeferred) && (ctx.settings.mixinForwarderChoices.isTruthy || meth.owner.is(Scala2x) || needsDisambiguation || hasNonInterfaceDefinition || generateJUnitForwarder || generateSerializationForwarder) && - isInImplementingClass(meth) + isInImplementingClass(meth) && + !meth.name.is(InlineAccessorName) } final val PrivateOrAccessor: FlagSet = Private | Accessor diff --git a/compiler/test/dotc/run-test-pickling.excludelist b/compiler/test/dotc/run-test-pickling.excludelist index 3cc9bc5a4a9e..0122276739c0 100644 --- a/compiler/test/dotc/run-test-pickling.excludelist +++ b/compiler/test/dotc/run-test-pickling.excludelist @@ -12,13 +12,11 @@ i9473.scala i13433.scala i13433b.scala macros-in-same-project1 -mixin-forwarder-overload t10889 t3452d t3452e t3452g t7374 -t8905 tuple-drop.scala tuple-ops.scala tuple-ops.scala diff --git a/project/MiMaFilters.scala b/project/MiMaFilters.scala index 4f8f8e8dc2d1..e2ca983081d2 100644 --- a/project/MiMaFilters.scala +++ b/project/MiMaFilters.scala @@ -559,28 +559,11 @@ object MiMaFilters { ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringView.compose"), ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringView.andThen"), - // This issue only arise in the non-bootstrapped stdlib - // It has to do with the fact that the special erasure of Pure was handled such as - // `scala.Pure`, not `scala.caps.Pure`. This filter should be removed once we move to 3.8.1 - ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.collection.Map.from"), - ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.collection.SeqMap.from"), - ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.collection.mutable.Map.from"), - ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.collection.mutable.SeqMap.from"), - // TO INVESTIGATE: This constructor changed, but it is private... why complaining? ProblemFilters.exclude[IncompatibleMethTypeProblem]("scala.collection.immutable.LazyList.this"), // This one should be fine, public class inside private object ProblemFilters.exclude[IncompatibleResultTypeProblem]("scala.collection.immutable.LazyList#LazyBuilder#DeferredState.eval"), - // MIX IN FORWARDERS ISSUE (SHOULD BE FIXED WHEN WE REMERGE THE PR) - ProblemFilters.exclude[NewMixinForwarderProblem]("scala.collection.StrictOptimizedSeqOps.prepended"), - ProblemFilters.exclude[NewMixinForwarderProblem]("scala.collection.StrictOptimizedSeqOps.appended"), - ProblemFilters.exclude[NewMixinForwarderProblem]("scala.collection.StrictOptimizedSeqOps.appendedAll"), - ProblemFilters.exclude[NewMixinForwarderProblem]("scala.collection.StrictOptimizedSeqOps.prependedAll"), - ProblemFilters.exclude[NewMixinForwarderProblem]("scala.collection.StrictOptimizedSeqOps.padTo"), - ProblemFilters.exclude[NewMixinForwarderProblem]("scala.collection.immutable.StrictOptimizedSeqOps.updated"), - ProblemFilters.exclude[NewMixinForwarderProblem]("scala.collection.immutable.StrictOptimizedSeqOps.patch"), - // NO IDEA FOR NOW :) ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.collection.mutable.ArrayDequeOps.scala$collection$mutable$ArrayDequeOps$$super$sliding"), ), diff --git a/sbt-bridge/src/dotty/tools/xsbt/CompilerBridgeDriver.java b/sbt-bridge/src/dotty/tools/xsbt/CompilerBridgeDriver.java index 20256d9e17cc..fbbe68235d13 100644 --- a/sbt-bridge/src/dotty/tools/xsbt/CompilerBridgeDriver.java +++ b/sbt-bridge/src/dotty/tools/xsbt/CompilerBridgeDriver.java @@ -179,22 +179,17 @@ private static AbstractFile asDottyFile(VirtualFile virtualFile) { } try { - return new dotty.tools.io.VirtualFile(virtualFile.name(), virtualFile.id()) { - { - // fill in the content - try (OutputStream output = output()) { - try (InputStream input = virtualFile.input()) { - Streamable.Bytes bytes = new Streamable.Bytes() { - @Override - public InputStream inputStream() { - return input; - } - }; - output.write(bytes.toByteArray()); - } + dotty.tools.io.VirtualFile file = new dotty.tools.io.VirtualFile(virtualFile.name(), virtualFile.id()); + try (java.io.OutputStream output = file.output(); java.io.InputStream input = virtualFile.input()) { + Streamable.Bytes bytes = new Streamable.Bytes() { + @Override + public InputStream inputStream() { + return input; } - } - }; + }; + output.write(bytes.toByteArray()); + } + return file; } catch (IOException e) { throw new IllegalArgumentException("invalid file " + virtualFile.name(), e); } diff --git a/tests/pos/11484/A_2.java b/tests/pos/11484/A_2.java new file mode 100644 index 000000000000..aa8ef2cf5a42 --- /dev/null +++ b/tests/pos/11484/A_2.java @@ -0,0 +1 @@ +public class A_2 extends C { } diff --git a/tests/pos/11484/C_1.scala b/tests/pos/11484/C_1.scala new file mode 100644 index 000000000000..48f5bd8174cf --- /dev/null +++ b/tests/pos/11484/C_1.scala @@ -0,0 +1,6 @@ +class B[A] +sealed trait T[A] { + def overloaded(that: List[T[A]]): T[A] = that.head + def overloaded(that: List[B[A]]): B[A] = that.head +} +abstract class C[A] extends T[A] diff --git a/tests/pos/11512/A_2.java b/tests/pos/11512/A_2.java new file mode 100644 index 000000000000..ed549568a5f4 --- /dev/null +++ b/tests/pos/11512/A_2.java @@ -0,0 +1 @@ +public class A_2 extends C { } diff --git a/tests/pos/11512/C_1.scala b/tests/pos/11512/C_1.scala new file mode 100644 index 000000000000..8e791e333a82 --- /dev/null +++ b/tests/pos/11512/C_1.scala @@ -0,0 +1,7 @@ +trait T { this: U => + def m: Int +} +trait U { + def m: Int = ??? +} +abstract class C extends U with T diff --git a/tests/pos/mixin-generic-extended-by-java/ExtensionId_1.scala b/tests/pos/mixin-generic-extended-by-java/ExtensionId_1.scala new file mode 100644 index 000000000000..f54f39879ac4 --- /dev/null +++ b/tests/pos/mixin-generic-extended-by-java/ExtensionId_1.scala @@ -0,0 +1,18 @@ +trait Extension + +class ClassicActorSystemProvider + +/** + * Identifies an Extension + * Lookup of Extensions is done by object identity, so the Id must be the same wherever it's used, + * otherwise you'll get the same extension loaded multiple times. + */ +trait ExtensionId[T <: Extension] { + + def get(system: ClassicActorSystemProvider): T = ??? +} + +/** + * Java API for ExtensionId + */ +abstract class AbstractExtensionId[T <: Extension] extends ExtensionId[T] diff --git a/tests/pos/mixin-generic-extended-by-java/JavaExtension_2.java b/tests/pos/mixin-generic-extended-by-java/JavaExtension_2.java new file mode 100644 index 000000000000..1711379d039e --- /dev/null +++ b/tests/pos/mixin-generic-extended-by-java/JavaExtension_2.java @@ -0,0 +1,8 @@ + +public class JavaExtension_2 { + static class TestExtensionId extends AbstractExtensionId { + } + + static class TestExtension implements Extension { + } +} diff --git a/tests/run/i19270.scala b/tests/run/i19270.scala new file mode 100644 index 000000000000..128e5c108f94 --- /dev/null +++ b/tests/run/i19270.scala @@ -0,0 +1,17 @@ +// scalajs: --skip + +trait T { + def foo(x: Int): Int = x + 1 +} + +class C extends T + +object Test { + def main(args: Array[String]): Unit = { + println("i19270") + val m = classOf[C].getDeclaredMethod("foo", classOf[Int]) + assert(m.getDeclaringClass() == classOf[C], m.getDeclaringClass()) + assert(!m.isBridge(), "foo should not have the ACC_BRIDGE flag") + assert(!m.isSynthetic(), "foo should not have the ACC_SYNTHETIC flag") + } +} diff --git a/tests/run/mixin-bridge-methods.scala b/tests/run/mixin-bridge-methods.scala new file mode 100644 index 000000000000..b14cd0caf150 --- /dev/null +++ b/tests/run/mixin-bridge-methods.scala @@ -0,0 +1,16 @@ +// scalajs: --skip + +trait Foo { + def getFoo() = "foo" +} + +class Sub extends Foo { + def getBar() = "bar" +} + +object Test { + def main(args: Array[String]): Unit = { + val ms = classOf[Sub].getDeclaredMethods + assert(ms forall (x => !x.isBridge), ms mkString " ") + } +} diff --git a/tests/run/mixin-final-def-object-lucre.scala b/tests/run/mixin-final-def-object-lucre.scala new file mode 100644 index 000000000000..676efb46c977 --- /dev/null +++ b/tests/run/mixin-final-def-object-lucre.scala @@ -0,0 +1,19 @@ +trait EventLike + +trait GrandParent: + def changed: EventLike + +trait HasChanged extends GrandParent: + override def changed: EventLike + +abstract class Parent extends GrandParent: + object changed extends EventLike + +class Child extends Parent with HasChanged + +object Test: + def main(args: Array[String]): Unit = + val child = Child() + println(child.changed) + println((child: HasChanged).changed) +end Test diff --git a/tests/run/mixin-forwarder-overload/A.scala b/tests/run/mixin-forwarder-overload/A.scala deleted file mode 100644 index 9eb20ac21414..000000000000 --- a/tests/run/mixin-forwarder-overload/A.scala +++ /dev/null @@ -1,9 +0,0 @@ -case class Foo(x: Int) - -trait A[X] { - def concat[Dummy](suffix: Int): Dummy = ??? -} - -class Bar extends A[Foo] { - def concat(suffix: Int): Foo = Foo(0) -} diff --git a/tests/run/mixin-forwarder-overload/Test.java b/tests/run/mixin-forwarder-overload/Test.java deleted file mode 100644 index 7bbd8dc9c7cb..000000000000 --- a/tests/run/mixin-forwarder-overload/Test.java +++ /dev/null @@ -1,9 +0,0 @@ -// scalajs: --skip - -public class Test { - public static void main(String[] args) { - Bar bar = new Bar(); - Foo x = bar.concat(0); - System.out.println(x); - } -} diff --git a/tests/run/mixin-signatures.check b/tests/run/mixin-signatures.check index 98979ab8d99b..77bff79ac8f1 100644 --- a/tests/run/mixin-signatures.check +++ b/tests/run/mixin-signatures.check @@ -1,19 +1,19 @@ class Test$bar1$ { + public java.lang.String Test$bar1$.f(java.lang.Object) public java.lang.Object Test$bar1$.f(java.lang.Object) - public java.lang.String Test$bar1$.f(java.lang.Object) public java.lang.String Test$bar1$.g(java.lang.String) public java.lang.Object Test$bar1$.g(java.lang.Object) public java.lang.String Test$bar1$.g(java.lang.Object) - public java.lang.Object Test$bar1$.h(java.lang.Object) + public java.lang.Object Test$bar1$.h(java.lang.Object) } class Test$bar2$ { + public java.lang.Object Test$bar2$.f(java.lang.String) public java.lang.Object Test$bar2$.f(java.lang.Object) - public java.lang.Object Test$bar2$.f(java.lang.String) public java.lang.String Test$bar2$.g(java.lang.String) public java.lang.Object Test$bar2$.g(java.lang.Object) public java.lang.Object Test$bar2$.g(java.lang.String) - public java.lang.Object Test$bar2$.h(java.lang.Object) + public java.lang.Object Test$bar2$.h(java.lang.Object) } class Test$bar3$ { @@ -23,7 +23,7 @@ class Test$bar3$ { public java.lang.String Test$bar3$.g(java.lang.String) public java.lang.Object Test$bar3$.g(java.lang.Object) public java.lang.String Test$bar3$.g(java.lang.Object) - public java.lang.Object Foo3.h(java.lang.Object) + public java.lang.Object Foo3.h(java.lang.Object) } class Test$bar4$ { @@ -33,7 +33,7 @@ class Test$bar4$ { public java.lang.String Test$bar4$.g(java.lang.String) public java.lang.Object Test$bar4$.g(java.lang.Object) public java.lang.Object Test$bar4$.g(java.lang.String) - public java.lang.Object Foo4.h(java.lang.Object) + public java.lang.Object Foo4.h(java.lang.Object) } class Test$bar5$ { @@ -45,7 +45,7 @@ class Test$bar5$ { public java.lang.Object Test$bar5$.g(java.lang.Object) public java.lang.Object Test$bar5$.g(java.lang.String) public java.lang.String Test$bar5$.g(java.lang.Object) - public java.lang.Object Test$bar5$.h(java.lang.Object) + public java.lang.Object Test$bar5$.h(java.lang.Object) } interface Foo1 { diff --git a/tests/run/t11485.scala b/tests/run/t11485.scala deleted file mode 100644 index 3e339577b4a8..000000000000 --- a/tests/run/t11485.scala +++ /dev/null @@ -1,18 +0,0 @@ -// scalajs: --skip - -import java.lang.reflect.Modifier - -trait HaveFinalMethod { - final def finalMethod: String = "final" -} - -class Child extends HaveFinalMethod - -object Test { - def main(args: Array[String]): Unit = { - val meth = classOf[Child].getMethod("finalMethod") - assert(meth.isBridge) - val mods = meth.getModifiers - assert(!Modifier.isFinal(mods)) - } -} diff --git a/tests/run/t3452b-bcode/J_2.java b/tests/run/t3452b-bcode/J_2.java new file mode 100644 index 000000000000..839f334508e7 --- /dev/null +++ b/tests/run/t3452b-bcode/J_2.java @@ -0,0 +1,6 @@ +public class J_2 { + public static void j() { + StringSearch.search("test"); + StringSearch.searchC("test"); + } +} diff --git a/tests/run/t3452b-bcode/S_1.scala b/tests/run/t3452b-bcode/S_1.scala new file mode 100644 index 000000000000..a209f1203539 --- /dev/null +++ b/tests/run/t3452b-bcode/S_1.scala @@ -0,0 +1,17 @@ +trait Search[M] { + def search(input: M): C[Int] = { + println("Search received: " + input) + null + } +} + +class SearchC[M] { + def searchC(input: M): C[Int] = { + println("SearchC received: " + input) + null + } +} + +object StringSearch extends SearchC[String] with Search[String] + +trait C[T] diff --git a/tests/run/t3452b-bcode/S_3.scala b/tests/run/t3452b-bcode/S_3.scala new file mode 100644 index 000000000000..6373d39e9137 --- /dev/null +++ b/tests/run/t3452b-bcode/S_3.scala @@ -0,0 +1,7 @@ +// scalajs: --skip + +object Test { + def main(args: Array[String]): Unit = { + J_2.j() + } +} diff --git a/tests/run/t3452d/A.scala b/tests/run/t3452d/A.scala index fd88a98793ab..67a2080d273b 100644 --- a/tests/run/t3452d/A.scala +++ b/tests/run/t3452d/A.scala @@ -2,6 +2,6 @@ trait TraversableLike[A, Repr] { def tail: Repr = null.asInstanceOf[Repr] } -abstract class AbstractTrav[A] extends TraversableLike[A, Iterable[A]] +abstract class AbstractTrav[A] extends TraversableLike[A, Traversable[A]] class C[A] extends AbstractTrav[A] diff --git a/tests/run/t3452d/Test.java b/tests/run/t3452d/Test.java index 9ee02ed092a8..5760bc6460eb 100644 --- a/tests/run/t3452d/Test.java +++ b/tests/run/t3452d/Test.java @@ -3,6 +3,8 @@ public class Test { public static void main(String[] args) { C c = new C(); - scala.collection.Iterable ls = c.tail(); + // TODO add a bridge during mixin so we can expose + // sharper generic signature for `tail`. + /*Traversable*/ Object ls = c.tail(); } } diff --git a/tests/run/t3452g/A.scala b/tests/run/t3452g/A.scala index df151d5313b3..a3f74c1e1e4c 100644 --- a/tests/run/t3452g/A.scala +++ b/tests/run/t3452g/A.scala @@ -4,8 +4,6 @@ trait TraversableLike[A, Repr] { abstract class AbstractTrav[A] extends TraversableLike[A, AbstractTrav[A]] -class C1 extends AbstractTrav[String] - object O extends AbstractTrav[String] -class C2[A] extends AbstractTrav[A] +class C[A] extends AbstractTrav[A] diff --git a/tests/run/t3452g/Test.java b/tests/run/t3452g/Test.java index 594abc898ffe..8f4cf96e45c8 100644 --- a/tests/run/t3452g/Test.java +++ b/tests/run/t3452g/Test.java @@ -1,12 +1,15 @@ // scalajs: --skip public class Test { - public static void main(String[] args) { - AbstractTrav lsSharp1 = new C1().tail(); + public static void main(String[] args) { + // To get better types here, we would need to + // add bridge during mixin so we can expose + // a generic return type of Traversable, because the erasure + // of this (Traversable) differs from the erasure of the mixed + // method (erasure(Repr) = Object) - // Object is the result type for the static forwarder (might be because of #11305) - Object lsSharp2 = O.tail(); + Object lsSharp = O.tail(); - AbstractTrav lsSharp3 = new C2().tail(); - } + Object lsSharp2 = new C().tail(); + } } diff --git a/tests/run/t3452h.scala b/tests/run/t3452h.scala index 6237d3ea641a..5ccc8aecc10e 100644 --- a/tests/run/t3452h.scala +++ b/tests/run/t3452h.scala @@ -1,8 +1,17 @@ -class Mix___eFoo_I_wBar__f extends Foo_I_ with Bar__f { f; } +class Mix extends Foo with Bar { f; } trait T -abstract class Foo_I_ { class I extends T ; def f: I ; f; } -trait Bar__f { type I>:Null<:T; def f: I = {null}; f; def gobble: I = {null}} +abstract class Foo { + class I extends T + def f: I + f +} +trait Bar { + type I >: Null <: T + def f: I = null + f + def gobble: I = null +} object Test extends App { - new Mix___eFoo_I_wBar__f + new Mix } diff --git a/tests/run/t7932.check b/tests/run/t7932.check index 5ba7ec1a3216..b7e516d73a41 100644 --- a/tests/run/t7932.check +++ b/tests/run/t7932.check @@ -1,5 +1,5 @@ -public Category C.category() -public Category C.category1() +public Category C.category() +public Category C.category1() public abstract Category M2.category3() public abstract Category M2.category2() public default Category M1.category() diff --git a/tests/run/t8905/DoubleRDD.scala b/tests/run/t8905/DoubleRDD.scala deleted file mode 100644 index 65e993ffe02b..000000000000 --- a/tests/run/t8905/DoubleRDD.scala +++ /dev/null @@ -1,9 +0,0 @@ -import java.util.Comparator - -trait RDDLike[T] { - def max(comp: Comparator[T]): T = { - (1.0).asInstanceOf[T] - } -} - -class DoubleRDD extends RDDLike[java.lang.Double] { } diff --git a/tests/run/t8905/Test.java b/tests/run/t8905/Test.java deleted file mode 100644 index e327beb3c819..000000000000 --- a/tests/run/t8905/Test.java +++ /dev/null @@ -1,22 +0,0 @@ -// scalajs: --skip - -import java.util.Comparator; - -public class Test { - private static class DoubleComparator implements Comparator { - public int compare(Double o1, Double o2) { - return o1.compareTo(o2); - } - } - - public static void main(String[] args) { - DoubleRDD rdd = new DoubleRDD(); - RDDLike rddLike = rdd; - - // This call works fine: - double rddLikeMax = rddLike.max(new DoubleComparator()); - // In Scala 2.10.4, this code compiles but this call fails at runtime: - // java.lang.NoSuchMethodError: DoubleRDD.max(Ljava/util/Comparator;)Ljava/lang/Double; - double rddMax = rdd.max(new DoubleComparator()); - } -}