Make $default methods non-private, avoid generating accessors for them
#KT-5786 Fixed
This commit is contained in:
@@ -2165,21 +2165,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
@Override
|
||||
public StackValue visitCallExpression(@NotNull JetCallExpression expression, StackValue receiver) {
|
||||
ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression, bindingContext);
|
||||
CallableDescriptor funDescriptor = resolvedCall.getResultingDescriptor();
|
||||
FunctionDescriptor descriptor = accessibleFunctionDescriptor(resolvedCall);
|
||||
|
||||
if (!(funDescriptor instanceof FunctionDescriptor)) {
|
||||
throw new UnsupportedOperationException("unknown type of callee descriptor: " + funDescriptor);
|
||||
}
|
||||
|
||||
funDescriptor = accessibleFunctionDescriptor((FunctionDescriptor) funDescriptor);
|
||||
|
||||
if (funDescriptor instanceof ConstructorDescriptor) {
|
||||
if (descriptor instanceof ConstructorDescriptor) {
|
||||
return generateNewCall(expression, resolvedCall);
|
||||
}
|
||||
|
||||
if (funDescriptor.getOriginal() instanceof SamConstructorDescriptor) {
|
||||
if (descriptor.getOriginal() instanceof SamConstructorDescriptor) {
|
||||
JetExpression argumentExpression = bindingContext.get(SAM_CONSTRUCTOR_TO_ARGUMENT, expression);
|
||||
assert argumentExpression != null : "Argument expression is not saved for a SAM constructor: " + funDescriptor;
|
||||
assert argumentExpression != null : "Argument expression is not saved for a SAM constructor: " + descriptor;
|
||||
return genSamInterfaceValue(argumentExpression, this);
|
||||
}
|
||||
|
||||
@@ -2233,13 +2227,26 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PropertyDescriptor accessiblePropertyDescriptor(PropertyDescriptor propertyDescriptor) {
|
||||
private PropertyDescriptor accessiblePropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||
return context.accessiblePropertyDescriptor(propertyDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected FunctionDescriptor accessibleFunctionDescriptor(FunctionDescriptor fd) {
|
||||
return context.accessibleFunctionDescriptor(fd);
|
||||
private FunctionDescriptor accessibleFunctionDescriptor(@NotNull ResolvedCall<?> resolvedCall) {
|
||||
FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor();
|
||||
// $default method is not private, so you need no accessor to call it
|
||||
return usesDefaultArguments(resolvedCall) ? descriptor : context.accessibleFunctionDescriptor(descriptor);
|
||||
}
|
||||
|
||||
private static boolean usesDefaultArguments(@NotNull ResolvedCall<?> resolvedCall) {
|
||||
List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex();
|
||||
if (valueArguments == null) return false;
|
||||
|
||||
for (ResolvedValueArgument argument : valueArguments) {
|
||||
if (argument instanceof DefaultValueArgument) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -2253,7 +2260,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
return invokeFunction(call, ((VariableAsFunctionResolvedCall) resolvedCall).getFunctionCall(), receiver);
|
||||
}
|
||||
|
||||
FunctionDescriptor fd = (FunctionDescriptor) resolvedCall.getResultingDescriptor();
|
||||
FunctionDescriptor fd = accessibleFunctionDescriptor(resolvedCall);
|
||||
JetSuperExpression superCallExpression = getSuperCallExpression(call);
|
||||
boolean superCall = superCallExpression != null;
|
||||
|
||||
@@ -2266,8 +2273,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
}
|
||||
}
|
||||
|
||||
FunctionDescriptor accessibleFunctionDescriptor = accessibleFunctionDescriptor(fd);
|
||||
Callable callable = resolveToCallable(accessibleFunctionDescriptor, superCall, resolvedCall);
|
||||
Callable callable = resolveToCallable(fd, superCall, resolvedCall);
|
||||
|
||||
return callable.invokeMethodWithArguments(resolvedCall, receiver, this);
|
||||
}
|
||||
|
||||
@@ -578,8 +578,12 @@ public class FunctionCodegen {
|
||||
|
||||
int flags = getVisibilityAccessFlag(functionDescriptor) |
|
||||
getDeprecatedAccessFlag(functionDescriptor) |
|
||||
ACC_SYNTHETIC |
|
||||
(functionDescriptor instanceof ConstructorDescriptor ? 0 : ACC_STATIC);
|
||||
ACC_SYNTHETIC;
|
||||
if (!(functionDescriptor instanceof ConstructorDescriptor)) {
|
||||
flags |= ACC_STATIC;
|
||||
}
|
||||
// $default methods are never private to be accessible from other class files (e.g. inner) without the need of synthetic accessors
|
||||
flags &= ~ACC_PRIVATE;
|
||||
|
||||
Method defaultMethod = typeMapper.mapDefaultMethod(functionDescriptor, kind, owner);
|
||||
|
||||
|
||||
@@ -1050,7 +1050,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
private void generateCompanionObjectInitializer(@NotNull ClassDescriptor companionObject) {
|
||||
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||
FunctionDescriptor constructor = codegen.accessibleFunctionDescriptor(KotlinPackage.single(companionObject.getConstructors()));
|
||||
FunctionDescriptor constructor = context.accessibleFunctionDescriptor(KotlinPackage.single(companionObject.getConstructors()));
|
||||
generateMethodCallTo(constructor, codegen.v);
|
||||
codegen.v.dup();
|
||||
StackValue instance = StackValue.onStack(typeMapper.mapClass(companionObject));
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
class A {
|
||||
private fun Int.foo(other: Int = 5): Int = this + other
|
||||
|
||||
inner class B {
|
||||
fun bar() = 37.foo()
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = if (A().B().bar() == 42) "OK" else "Fail"
|
||||
@@ -0,0 +1,11 @@
|
||||
// KT-5786 NoSuchMethodError: no accessor for private fun with default arguments
|
||||
|
||||
class A {
|
||||
private fun foo(result: String = "OK"): String = result
|
||||
|
||||
companion object {
|
||||
fun bar() = A().foo()
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = A.bar()
|
||||
@@ -0,0 +1,16 @@
|
||||
var state: String = "Fail"
|
||||
|
||||
class A private(x: String = "OK") {
|
||||
init {
|
||||
state = x
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun foo() = A()
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
A.foo()
|
||||
return state
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
var state: String = "Fail"
|
||||
|
||||
class A {
|
||||
private constructor(x: String = "OK") {
|
||||
state = x
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun foo() = A()
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
A.foo()
|
||||
return state
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fun box(): String {
|
||||
run {
|
||||
test("ok")
|
||||
test("ok", 200)
|
||||
}
|
||||
test("ok")
|
||||
test("ok", 300)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
private fun test(arg1: String, default: Int = 0) = Unit
|
||||
+33
@@ -2391,6 +2391,39 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/defaultArguments/private")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Private extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInPrivate() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/defaultArguments/private"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("memberExtensionFunction.kt")
|
||||
public void testMemberExtensionFunction() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/private/memberExtensionFunction.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("memberFunction.kt")
|
||||
public void testMemberFunction() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/private/memberFunction.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("primaryConstructor.kt")
|
||||
public void testPrimaryConstructor() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/private/primaryConstructor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("secondaryConstructor.kt")
|
||||
public void testSecondaryConstructor() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/private/secondaryConstructor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/delegatedProperty")
|
||||
|
||||
+6
@@ -3250,6 +3250,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt5786_privateWithDefault.kt")
|
||||
public void testKt5786_privateWithDefault() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/regressions/kt5786_privateWithDefault.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt5953.kt")
|
||||
public void testKt5953() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/regressions/kt5953.kt");
|
||||
|
||||
Reference in New Issue
Block a user