KT-2498 Bridge method is not generated for method when generic parameters are substituted in superclass
#KT-2498 Fixed generateBridgeIfNeeded() now works as follows: for a given method, find which declared methods does this method override via breadth-first search. For each such declared method, generate a bridge if and only if its signature is different. Keep different methods' signatures in a set to avoid duplicated bridge signatures.
This commit is contained in:
@@ -341,13 +341,47 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
static void generateBridgeIfNeeded(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
||||
Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenDescriptors();
|
||||
if (kind != OwnerKind.TRAIT_IMPL) {
|
||||
for (FunctionDescriptor overriddenFunction : overriddenFunctions) {
|
||||
// TODO should we check params here as well?
|
||||
checkOverride(owner, state, v, jvmSignature, functionDescriptor, overriddenFunction.getOriginal());
|
||||
if (kind == OwnerKind.TRAIT_IMPL) {
|
||||
return;
|
||||
}
|
||||
|
||||
Method method = state.getInjector().getJetTypeMapper().mapSignature(functionDescriptor.getName(), functionDescriptor).getAsmMethod();
|
||||
|
||||
Queue<FunctionDescriptor> bfsQueue = new LinkedList<FunctionDescriptor>();
|
||||
Set<FunctionDescriptor> visited = new HashSet<FunctionDescriptor>();
|
||||
|
||||
bfsQueue.offer(functionDescriptor.getOriginal());
|
||||
visited.add(functionDescriptor.getOriginal());
|
||||
for (FunctionDescriptor overriddenDescriptor : functionDescriptor.getOverriddenDescriptors()) {
|
||||
FunctionDescriptor orig = overriddenDescriptor.getOriginal();
|
||||
if (!visited.contains(orig)) {
|
||||
bfsQueue.offer(overriddenDescriptor);
|
||||
visited.add(overriddenDescriptor);
|
||||
}
|
||||
checkOverride(owner, state, v, jvmSignature, functionDescriptor, functionDescriptor.getOriginal());
|
||||
}
|
||||
|
||||
Set<Method> bridgesToGenerate = new HashSet<Method>();
|
||||
while (!bfsQueue.isEmpty()) {
|
||||
FunctionDescriptor descriptor = bfsQueue.poll();
|
||||
if (descriptor.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
|
||||
Method overridden = state.getInjector().getJetTypeMapper().mapSignature(descriptor.getName(), descriptor.getOriginal()).getAsmMethod();
|
||||
if (differentMethods(method, overridden)) {
|
||||
bridgesToGenerate.add(overridden);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for (FunctionDescriptor overriddenDescriptor : descriptor.getOverriddenDescriptors()) {
|
||||
FunctionDescriptor orig = overriddenDescriptor.getOriginal();
|
||||
if (!visited.contains(orig)) {
|
||||
bfsQueue.offer(orig);
|
||||
visited.add(orig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Method overridden : bridgesToGenerate) {
|
||||
generateBridge(owner, state, v, jvmSignature, functionDescriptor, overridden);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,53 +550,43 @@ public class FunctionCodegen {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void checkOverride(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenFunction) {
|
||||
Method method = state.getInjector().getJetTypeMapper().mapSignature(functionDescriptor.getName(), functionDescriptor).getAsmMethod();
|
||||
Method overridden = state.getInjector().getJetTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal()).getAsmMethod();
|
||||
private static void generateBridge(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, Method overridden) {
|
||||
int flags = ACC_PUBLIC | ACC_BRIDGE; // TODO.
|
||||
|
||||
if (overriddenFunction.getModality() == Modality.ABSTRACT) {
|
||||
Set<? extends FunctionDescriptor> overriddenFunctions = overriddenFunction.getOverriddenDescriptors();
|
||||
for (FunctionDescriptor of : overriddenFunctions) {
|
||||
checkOverride(owner, state, v, jvmSignature, overriddenFunction, of.getOriginal());
|
||||
}
|
||||
final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overridden.getDescriptor(), null, null);
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
||||
StubCodegen.generateStubCode(mv);
|
||||
}
|
||||
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
mv.visitCode();
|
||||
|
||||
if (differentMethods(method, overridden)) {
|
||||
int flags = ACC_PUBLIC | ACC_BRIDGE; // TODO.
|
||||
|
||||
final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overridden.getDescriptor(), null, null);
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
||||
StubCodegen.generateStubCode(mv);
|
||||
}
|
||||
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
mv.visitCode();
|
||||
|
||||
Type[] argTypes = overridden.getArgumentTypes();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||
Type argType = argTypes[i];
|
||||
iv.load(reg, argType);
|
||||
if (argType.getSort() == Type.OBJECT) {
|
||||
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).put(jvmSignature.getArgumentTypes()[i], iv);
|
||||
}
|
||||
else if (argType.getSort() == Type.ARRAY) {
|
||||
StackValue.onStack(JetTypeMapper.ARRAY_GENERIC_TYPE).put(jvmSignature.getArgumentTypes()[i], iv);
|
||||
}
|
||||
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argType.getSize();
|
||||
Type[] argTypes = overridden.getArgumentTypes();
|
||||
Type[] originalArgTypes = jvmSignature.getArgumentTypes();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||
Type argType = argTypes[i];
|
||||
iv.load(reg, argType);
|
||||
if (argType.getSort() == Type.OBJECT) {
|
||||
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).put(originalArgTypes[i], iv);
|
||||
}
|
||||
else if (argType.getSort() == Type.ARRAY) {
|
||||
StackValue.onStack(JetTypeMapper.ARRAY_GENERIC_TYPE).put(originalArgTypes[i], iv);
|
||||
}
|
||||
|
||||
iv.invokevirtual(state.getInjector().getJetTypeMapper().mapType(((ClassDescriptor) owner.getContextDescriptor()).getDefaultType(), MapTypeMode.VALUE).getInternalName(),
|
||||
jvmSignature.getName(), jvmSignature.getDescriptor());
|
||||
if (JetTypeMapper.isPrimitive(jvmSignature.getReturnType()) && !JetTypeMapper.isPrimitive(overridden.getReturnType()))
|
||||
StackValue.valueOf(iv, jvmSignature.getReturnType());
|
||||
if (jvmSignature.getReturnType() == Type.VOID_TYPE)
|
||||
iv.aconst(null);
|
||||
iv.areturn(overridden.getReturnType());
|
||||
endVisit(mv, "bridge method", BindingContextUtils.callableDescriptorToDeclaration(state.getBindingContext(), functionDescriptor));
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argType.getSize();
|
||||
}
|
||||
|
||||
iv.invokevirtual(state.getInjector().getJetTypeMapper().mapType(
|
||||
((ClassDescriptor) owner.getContextDescriptor()).getDefaultType(), MapTypeMode.VALUE).getInternalName(),
|
||||
jvmSignature.getName(), jvmSignature.getDescriptor());
|
||||
if (JetTypeMapper.isPrimitive(jvmSignature.getReturnType()) && !JetTypeMapper.isPrimitive(overridden.getReturnType()))
|
||||
StackValue.valueOf(iv, jvmSignature.getReturnType());
|
||||
if (jvmSignature.getReturnType() == Type.VOID_TYPE)
|
||||
iv.aconst(null);
|
||||
iv.areturn(overridden.getReturnType());
|
||||
endVisit(mv, "bridge method", BindingContextUtils.callableDescriptorToDeclaration(state.getBindingContext(), functionDescriptor));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
trait A<T> {
|
||||
fun foo(t: T) = "A"
|
||||
}
|
||||
|
||||
class Z : A<String>
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo("") != "A" -> "Fail #1"
|
||||
(z : A<String>).foo("") != "A" -> "Fail #2"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
trait A<T, U> {
|
||||
fun foo(t: T, u: U) = "A"
|
||||
}
|
||||
|
||||
trait B<U> : A<String, U>
|
||||
|
||||
trait C<T> : A<T, Int>
|
||||
|
||||
class Z : B<Int>, C<String> {
|
||||
override fun foo(t: String, u: Int) = "Z"
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo("", 0) != "Z" -> "Fail #1"
|
||||
(z : C<String>).foo("", 0) != "Z" -> "Fail #2"
|
||||
(z : B<Int>).foo("", 0) != "Z" -> "Fail #3"
|
||||
(z : A<String, Int>).foo("", 0) != "Z" -> "Fail #4"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
open class A<T> {
|
||||
open fun foo(t: T) = "A"
|
||||
}
|
||||
|
||||
open class B<T> : A<T>()
|
||||
|
||||
open class C : B<String>() {
|
||||
override fun foo(t: String) = "C"
|
||||
}
|
||||
|
||||
open class D : C()
|
||||
|
||||
class Z : D() {
|
||||
override fun foo(t: String) = "Z"
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo("") != "Z" -> "Fail #1"
|
||||
(z : D).foo("") != "Z" -> "Fail #2"
|
||||
(z : C).foo("") != "Z" -> "Fail #3"
|
||||
(z : B<String>).foo("") != "Z" -> "Fail #4"
|
||||
(z : A<String>).foo("") != "Z" -> "Fail #5"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
open class A<T, U, V> {
|
||||
open fun foo(t: T, u: U, v: V) = "A"
|
||||
}
|
||||
|
||||
open class B<T, V> : A<T, Int, V>()
|
||||
|
||||
open class C<V> : B<String, V>()
|
||||
|
||||
class Z : C<Double>() {
|
||||
override fun foo(t: String, u: Int, v: Double) = "Z"
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo("", 0, 0.0) != "Z" -> "Fail #1"
|
||||
(z : C<Double>).foo("", 0, 0.0) != "Z" -> "Fail #2"
|
||||
(z : B<String, Double>).foo("", 0, 0.0) != "Z" -> "Fail #3"
|
||||
(z : A<String, Int, Double>).foo("", 0, 0.0) != "Z" -> "Fail #4"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
trait A<T, U> {
|
||||
fun foo(t: T, u: U) = "A"
|
||||
}
|
||||
|
||||
class Z<T> : A<T, Int> {
|
||||
override fun foo(t: T, u: Int) = "Z"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val z = Z<Int>()
|
||||
return when {
|
||||
z.foo(0, 0) != "Z" -> "Fail #1"
|
||||
(z : A<Int, Int>).foo(0, 0) != "Z" -> "Fail #2"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
open class A<T> {
|
||||
open fun foo(t: T) = "A"
|
||||
}
|
||||
|
||||
class Z : A<String>() {
|
||||
override fun foo(t: String) = "Z"
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo("") != "Z" -> "Fail #1"
|
||||
(z : A<String>).foo("") != "Z" -> "Fail #2"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
open enum class A<T> {
|
||||
open fun foo(t: T) = "A"
|
||||
}
|
||||
|
||||
enum class Z(val name: String) : A<String>() {
|
||||
Z1 : Z("Z1")
|
||||
Z2 : Z("Z2")
|
||||
override fun foo(t: String) = name
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
return when {
|
||||
Z.Z1.foo("") != "Z1" -> "Fail #1"
|
||||
Z.Z2.foo("") != "Z2" -> "Fail #2"
|
||||
(Z.Z1 : A<String>).foo("") != "Z1" -> "Fail #3"
|
||||
(Z.Z2 : A<String>).foo("") != "Z2" -> "Fail #4"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
open class A<T> {
|
||||
open fun <U> foo(t: T, u: U) = "A"
|
||||
}
|
||||
|
||||
class Z : A<String>() {
|
||||
override fun <U> foo(t: String, u: U) = "Z"
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo("", 0) != "Z" -> "Fail #1"
|
||||
(z : A<String>).foo("", 0) != "Z" -> "Fail #2"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
open class A<T> {
|
||||
open fun foo(t: T) = "A"
|
||||
}
|
||||
|
||||
object Z : A<String>() {
|
||||
override fun foo(t: String) = "Z"
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val z = object : A<String>() {
|
||||
override fun foo(t: String) = "z"
|
||||
}
|
||||
return when {
|
||||
Z.foo("") != "Z" -> "Fail #1"
|
||||
z.foo("") != "z" -> "Fail #2"
|
||||
(Z : A<String>).foo("") != "Z" -> "Fail #3"
|
||||
(z : A<String>).foo("") != "z" -> "Fail #4"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
open class A<T : Number>(val t: T) {
|
||||
open fun foo(): T = t
|
||||
}
|
||||
|
||||
class Z : A<Int>(17) {
|
||||
override fun foo() = 239
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo() != 239 -> "Fail #1"
|
||||
(z : A<Int>).foo() != 239 -> "Fail #2"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
open class A<T : Number> {
|
||||
open fun foo(t: T) = "A"
|
||||
}
|
||||
|
||||
class Z : A<Int>() {
|
||||
override fun foo(t: Int) = "Z"
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo(0) != "Z" -> "Fail #1"
|
||||
(z : A<Int>).foo(0) != "Z" -> "Fail #2"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
open class A<T> {
|
||||
open fun foo(t: T) = "A"
|
||||
}
|
||||
|
||||
open class B : A<String>()
|
||||
|
||||
class Z : B() {
|
||||
override fun foo(t: String) = "Z"
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo("") != "Z" -> "Fail #1"
|
||||
(z : B).foo("") != "Z" -> "Fail #2"
|
||||
(z : A<String>).foo("") != "Z" -> "Fail #3"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
abstract class A<T> {
|
||||
abstract fun foo(t: T): String
|
||||
}
|
||||
|
||||
abstract class B : A<String>()
|
||||
|
||||
class Z : B() {
|
||||
override fun foo(t: String) = "Z"
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo("") != "Z" -> "Fail #1"
|
||||
(z : B).foo("") != "Z" -> "Fail #2"
|
||||
(z : A<String>).foo("") != "Z" -> "Fail #3"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
open class A<T : U, U> {
|
||||
open fun foo(t: T, u: U) = "A"
|
||||
}
|
||||
|
||||
open class B : A<Int, Number>()
|
||||
|
||||
class Z : B() {
|
||||
override fun foo(t: Int, u: Number) = "Z"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo(0, 0) != "Z" -> "Fail #1"
|
||||
(z : B).foo(0, 0) != "Z" -> "Fail #2"
|
||||
(z : A<Int, Number>).foo(0, 0) != "Z" -> "Fail #3"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
open enum class A<T> {
|
||||
open fun foo(t: T) = "A"
|
||||
}
|
||||
|
||||
open enum class B : A<String>()
|
||||
|
||||
enum class Z(val name: String) : B() {
|
||||
Z1 : Z("Z1")
|
||||
Z2 : Z("Z2")
|
||||
override fun foo(t: String) = name
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
return when {
|
||||
Z.Z1.foo("") != "Z1" -> "Fail #1"
|
||||
Z.Z2.foo("") != "Z2" -> "Fail #2"
|
||||
(Z.Z1 : B).foo("") != "Z1" -> "Fail #3"
|
||||
(Z.Z2 : B).foo("") != "Z2" -> "Fail #4"
|
||||
(Z.Z1 : A<String>).foo("") != "Z1" -> "Fail #5"
|
||||
(Z.Z2 : A<String>).foo("") != "Z2" -> "Fail #6"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
open class A<T> {
|
||||
open fun <U> foo(t: T, u: U) = "A"
|
||||
}
|
||||
|
||||
open class B : A<String>()
|
||||
|
||||
class Z : B() {
|
||||
override fun <U> foo(t: String, u: U) = "Z"
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo("", 0) != "Z" -> "Fail #1"
|
||||
(z : B).foo("", 0) != "Z" -> "Fail #2"
|
||||
(z : A<String>).foo("", 0) != "Z" -> "Fail #3"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
open class A<T> {
|
||||
open fun foo(t: T) = "A"
|
||||
}
|
||||
|
||||
open class B : A<String>()
|
||||
|
||||
object Z : B() {
|
||||
override fun foo(t: String) = "Z"
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val o = object : B() {
|
||||
override fun foo(t: String) = "o"
|
||||
}
|
||||
return when {
|
||||
Z.foo("") != "Z" -> "Fail #1"
|
||||
o.foo("") != "o" -> "Fail #2"
|
||||
(Z : B).foo("") != "Z" -> "Fail #3"
|
||||
(o : B).foo("") != "o" -> "Fail #4"
|
||||
(Z : A<String>).foo("") != "Z" -> "Fail #5"
|
||||
(o : A<String>).foo("") != "o" -> "Fail #6"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
open class A<T : Number> {
|
||||
open fun foo(t: T) = "A"
|
||||
}
|
||||
|
||||
open class B : A<Int>()
|
||||
|
||||
class Z : B() {
|
||||
override fun foo(t: Int) = "Z"
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo(0) != "Z" -> "Fail #1"
|
||||
(z : B).foo(0) != "Z" -> "Fail #2"
|
||||
(z : A<Int>).foo(0) != "Z" -> "Fail #3"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
trait A<T> {
|
||||
fun foo(t: T, u: Int) = "A"
|
||||
}
|
||||
|
||||
trait B<T, U> {
|
||||
fun foo(t: T, u: U) = "B"
|
||||
}
|
||||
|
||||
class Z : A<String>, B<String, Int> {
|
||||
override fun foo(t: String, u: Int) = "Z"
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo("", 0) != "Z" -> "Fail #1"
|
||||
(z : A<String>).foo("", 0) != "Z" -> "Fail #2"
|
||||
(z : B<String, Int>).foo("", 0) != "Z" -> "Fail #3"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
trait A<T> {
|
||||
fun foo(t: T) = "A"
|
||||
}
|
||||
|
||||
trait B<T> {
|
||||
fun foo(t: T) = "B"
|
||||
}
|
||||
|
||||
class Z : A<Int>, B<Int> {
|
||||
override fun foo(t: Int) = "Z"
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val z = Z()
|
||||
return when {
|
||||
z.foo(0) != "Z" -> "Fail #1"
|
||||
(z : A<Int>).foo(0) != "Z" -> "Fail #2"
|
||||
(z : B<Int>).foo(0) != "Z" -> "Fail #3"
|
||||
else -> "OK"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import java.util.LinkedList
|
||||
|
||||
open class BaseStringList: LinkedList<String>() {
|
||||
}
|
||||
|
||||
class StringList: BaseStringList() {
|
||||
public override fun get(index: Int): String {
|
||||
return "StringList.get()"
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val myStringList = StringList()
|
||||
myStringList.add("first element")
|
||||
if (myStringList.get(0) != "StringList.get()") return "Fail #1"
|
||||
if ((myStringList: BaseStringList).get(0) != "StringList.get()") return "Fail #2"
|
||||
if ((myStringList: LinkedList<String>).get(0) != "StringList.get()") return "Fail #3"
|
||||
return "OK"
|
||||
}
|
||||
@@ -19,13 +19,119 @@ package org.jetbrains.jet.codegen;
|
||||
import org.jetbrains.jet.ConfigurationKind;
|
||||
|
||||
public class BridgeMethodGenTest extends CodegenTestCase {
|
||||
|
||||
public void testBridgeMethod () throws Exception {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridge.jet");
|
||||
}
|
||||
|
||||
|
||||
public void testKt1959() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("regressions/kt1959.kt");
|
||||
}
|
||||
|
||||
public void testDelegationToTraitImpl() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/delegationToTraitImpl.kt");
|
||||
}
|
||||
|
||||
public void testDiamond() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/diamond.kt");
|
||||
}
|
||||
|
||||
public void testLongChainOneBridge() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/longChainOneBridge.kt");
|
||||
}
|
||||
|
||||
public void testManyTypeArgumentsSubstitutedSuccessively() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/manyTypeArgumentsSubstitutedSuccessively.kt");
|
||||
}
|
||||
|
||||
public void testMethodFromTrait() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/methodFromTrait.kt");
|
||||
}
|
||||
|
||||
public void testSimple() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/simple.kt");
|
||||
}
|
||||
|
||||
public void testSimpleEnum() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/simpleEnum.kt");
|
||||
}
|
||||
|
||||
public void testSimpleGenericMethod() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/simpleGenericMethod.kt");
|
||||
}
|
||||
|
||||
public void testSimpleObject() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/simpleObject.kt");
|
||||
}
|
||||
|
||||
public void testSimpleReturnType() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/simpleReturnType.kt");
|
||||
}
|
||||
|
||||
public void testSimpleUpperBound() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/simpleUpperBound.kt");
|
||||
}
|
||||
|
||||
public void testSubstitutionInSuperClass() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/substitutionInSuperClass.kt");
|
||||
}
|
||||
|
||||
public void testSubstitutionInSuperClassAbstractFun() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/substitutionInSuperClassAbstractFun.kt");
|
||||
}
|
||||
|
||||
public void testSubstitutionInSuperClassBoundedTypeArguments() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/substitutionInSuperClassBoundedTypeArguments.kt");
|
||||
}
|
||||
|
||||
public void testSubstitutionInSuperClassEnum() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/substitutionInSuperClassEnum.kt");
|
||||
}
|
||||
|
||||
public void testSubstitutionInSuperClassGenericMethod() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/substitutionInSuperClassGenericMethod.kt");
|
||||
}
|
||||
|
||||
public void testSubstitutionInSuperClassObject() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/substitutionInSuperClassObject.kt");
|
||||
}
|
||||
|
||||
public void testSubstitutionInSuperClassUpperBound() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/substitutionInSuperClassUpperBound.kt");
|
||||
}
|
||||
|
||||
public void testTwoParentsWithDifferentMethodsTwoBridges() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/twoParentsWithDifferentMethodsTwoBridges.kt");
|
||||
}
|
||||
|
||||
public void testTwoParentsWithTheSameMethodOneBridge() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("bridges/twoParentsWithTheSameMethodOneBridge.kt");
|
||||
}
|
||||
|
||||
public void testKt2498() {
|
||||
createEnvironmentWithFullJdk();
|
||||
blackBoxFile("regressions/kt2498.kt");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user