Correctly apply SAM conversions in superclass constructor calls
#KT-5452 Fixed
This commit is contained in:
@@ -1446,9 +1446,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
if (superCall != null) {
|
||||
// For an anonymous object, we should also generate all non-default arguments that it captures for its super call
|
||||
ConstructorDescriptor superConstructor = superCall.getResultingDescriptor();
|
||||
ConstructorDescriptor constructorToCall = SamCodegenUtil.resolveSamAdapter(superConstructor);
|
||||
List<ValueParameterDescriptor> superValueParameters = superConstructor.getValueParameters();
|
||||
int params = superValueParameters.size();
|
||||
List<Type> superMappedTypes = typeMapper.mapToCallableMethod(superConstructor).getValueParameterTypes();
|
||||
List<Type> superMappedTypes = typeMapper.mapToCallableMethod(constructorToCall).getValueParameterTypes();
|
||||
assert superMappedTypes.size() >= params : String
|
||||
.format("Incorrect number of mapped parameters vs arguments: %d < %d for %s",
|
||||
superMappedTypes.size(), params, classDescriptor);
|
||||
@@ -1474,7 +1475,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
assert constructors.size() == 1 : "Unexpected number of constructors for class: " + classDescriptor + " " + constructors;
|
||||
ConstructorDescriptor constructorDescriptor = KotlinPackage.single(constructors);
|
||||
|
||||
JvmMethodSignature constructor = typeMapper.mapSignature(constructorDescriptor);
|
||||
JvmMethodSignature constructor = typeMapper.mapSignature(SamCodegenUtil.resolveSamAdapter(constructorDescriptor));
|
||||
v.invokespecial(type.getInternalName(), "<init>", constructor.getAsmMethod().getDescriptor(), false);
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
@@ -2313,8 +2314,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
@NotNull
|
||||
private CallableMethod resolveToCallableMethod(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull CodegenContext context) {
|
||||
SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(fd);
|
||||
return typeMapper.mapToCallableMethod(originalOfSamAdapter != null ? originalOfSamAdapter : fd, superCall, context);
|
||||
return typeMapper.mapToCallableMethod(SamCodegenUtil.resolveSamAdapter(fd), superCall, context);
|
||||
}
|
||||
|
||||
public void invokeMethodWithArguments(
|
||||
@@ -3593,8 +3593,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
// See StackValue.receiver for more info
|
||||
pushClosureOnStack(constructor.getContainingDeclaration(), dispatchReceiver == null, defaultCallGenerator);
|
||||
|
||||
ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(constructor);
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructor : originalOfSamAdapter);
|
||||
constructor = SamCodegenUtil.resolveSamAdapter(constructor);
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(constructor);
|
||||
invokeMethodWithArguments(method, resolvedCall, StackValue.none());
|
||||
|
||||
return Unit.INSTANCE$;
|
||||
|
||||
@@ -1466,7 +1466,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
return;
|
||||
}
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
ConstructorDescriptor delegateConstructor = delegationConstructorCall.getResultingDescriptor();
|
||||
ConstructorDescriptor delegateConstructor = SamCodegenUtil.resolveSamAdapter(delegationConstructorCall.getResultingDescriptor());
|
||||
|
||||
CallableMethod delegateConstructorCallable = typeMapper.mapToCallableMethod(delegateConstructor);
|
||||
CallableMethod callable = typeMapper.mapToCallableMethod(constructorDescriptor);
|
||||
|
||||
@@ -42,6 +42,11 @@ public class SamCodegenUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T extends FunctionDescriptor> T resolveSamAdapter(@NotNull T descriptor) {
|
||||
FunctionDescriptor original = getOriginalIfSamAdapter(descriptor);
|
||||
return original != null ? (T) original : descriptor;
|
||||
}
|
||||
|
||||
private SamCodegenUtil() {
|
||||
}
|
||||
}
|
||||
|
||||
+11
-1
@@ -386,6 +386,10 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
||||
@Override
|
||||
public void visitCallExpression(@NotNull JetCallExpression expression) {
|
||||
super.visitCallExpression(expression);
|
||||
checkSamCall(expression);
|
||||
}
|
||||
|
||||
private void checkSamCall(@NotNull JetCallElement expression) {
|
||||
ResolvedCall<?> call = CallUtilPackage.getResolvedCall(expression, bindingContext);
|
||||
if (call == null) return;
|
||||
|
||||
@@ -416,7 +420,13 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
||||
}
|
||||
}
|
||||
|
||||
private void recordSamConstructorIfNeeded(@NotNull JetCallExpression expression, @NotNull ResolvedCall<?> call) {
|
||||
@Override
|
||||
public void visitDelegationToSuperCallSpecifier(@NotNull JetDelegatorToSuperCall call) {
|
||||
super.visitDelegationToSuperCallSpecifier(call);
|
||||
checkSamCall(call);
|
||||
}
|
||||
|
||||
private void recordSamConstructorIfNeeded(@NotNull JetCallElement expression, @NotNull ResolvedCall<?> call) {
|
||||
CallableDescriptor callableDescriptor = call.getResultingDescriptor();
|
||||
if (!(callableDescriptor.getOriginal() instanceof SamConstructorDescriptor)) return;
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ public class CodegenBinding {
|
||||
|
||||
public static final WritableSlice<JetExpression, SamType> SAM_VALUE = Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<JetCallExpression, JetExpression> SAM_CONSTRUCTOR_TO_ARGUMENT = Slices.createSimpleSlice();
|
||||
public static final WritableSlice<JetCallElement, JetExpression> SAM_CONSTRUCTOR_TO_ARGUMENT = Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<JetWhenExpression, WhenByEnumsMapping> MAPPING_FOR_WHEN_BY_ENUM =
|
||||
Slices.<JetWhenExpression, WhenByEnumsMapping>sliceBuilder().build();
|
||||
|
||||
@@ -924,7 +924,7 @@ public class JetTypeMapper {
|
||||
@NotNull ResolvedCall<ConstructorDescriptor> superCall,
|
||||
boolean hasOuter
|
||||
) {
|
||||
ConstructorDescriptor superDescriptor = superCall.getResultingDescriptor();
|
||||
ConstructorDescriptor superDescriptor = SamCodegenUtil.resolveSamAdapter(superCall.getResultingDescriptor());
|
||||
List<ResolvedValueArgument> valueArguments = superCall.getValueArgumentsByIndex();
|
||||
assert valueArguments != null : "Failed to arrange value arguments by index: " + superDescriptor;
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
class JavaClass {
|
||||
private Runnable r;
|
||||
|
||||
public JavaClass(Runnable r) {
|
||||
this.r = r;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
var status: String = "fail" // global property to avoid issues with accessing closure from local class (KT-4174)
|
||||
|
||||
fun box(): String {
|
||||
class C() : JavaClass({status = "OK"}) {}
|
||||
C().run()
|
||||
return status
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
class JavaClass {
|
||||
private Runnable r;
|
||||
|
||||
public JavaClass(Runnable r) {
|
||||
this.r = r;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
fun box(): String {
|
||||
var v = "FAIL"
|
||||
val x = object : JavaClass({-> v = "OK"}) {}
|
||||
x.run()
|
||||
return v
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class JavaClass {
|
||||
private Runnable r;
|
||||
|
||||
public JavaClass(Runnable r) {
|
||||
this.r = r;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
fun box(): String {
|
||||
var v = "FAIL"
|
||||
val f = {-> v = "OK"}
|
||||
val x = object : JavaClass(f) {}
|
||||
x.run()
|
||||
return v
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class JavaClass {
|
||||
JavaClass(Runnable r) {
|
||||
if (r != null) r.run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
var status: String = "fail" // global property to avoid issues with accessing closure from local class (KT-4174)
|
||||
|
||||
class KotlinClass(): JavaClass({status="OK"}) {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
KotlinClass()
|
||||
return status
|
||||
}
|
||||
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.JetCoreEnvironment;
|
||||
import org.jetbrains.kotlin.codegen.CodegenTestCase;
|
||||
import org.jetbrains.kotlin.codegen.GenerationUtils;
|
||||
import org.jetbrains.kotlin.codegen.InlineTestUtil;
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration;
|
||||
import org.jetbrains.kotlin.psi.JetFile;
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind;
|
||||
|
||||
+24
@@ -499,6 +499,24 @@ public class BlackBoxAgainstJavaCodegenTestGenerated extends AbstractBlackBoxCod
|
||||
doTestAgainstJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("localClass.kt")
|
||||
public void testLocalClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/sam/adapters/localClass.kt");
|
||||
doTestAgainstJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("localObjectConstructor.kt")
|
||||
public void testLocalObjectConstructor() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/sam/adapters/localObjectConstructor.kt");
|
||||
doTestAgainstJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("localObjectConstructorWithFnValue.kt")
|
||||
public void testLocalObjectConstructorWithFnValue() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/sam/adapters/localObjectConstructorWithFnValue.kt");
|
||||
doTestAgainstJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nonLiteralAndLiteralRunnable.kt")
|
||||
public void testNonLiteralAndLiteralRunnable() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/sam/adapters/nonLiteralAndLiteralRunnable.kt");
|
||||
@@ -547,6 +565,12 @@ public class BlackBoxAgainstJavaCodegenTestGenerated extends AbstractBlackBoxCod
|
||||
doTestAgainstJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("superconstructorWithClosure.kt")
|
||||
public void testSuperconstructorWithClosure() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/sam/adapters/superconstructorWithClosure.kt");
|
||||
doTestAgainstJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("typeParameterOfClass.kt")
|
||||
public void testTypeParameterOfClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/sam/adapters/typeParameterOfClass.kt");
|
||||
|
||||
Reference in New Issue
Block a user