Fix for KT-4250: IllegalAccessError when using protected java member from lambda function
#KT-4250 Fixed
This commit is contained in:
@@ -373,7 +373,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return labelTarget;
|
||||
}
|
||||
assert descriptor instanceof ClassDescriptor : "Don't know how to generate super-call to not a class";
|
||||
return getParentContextSubclassOf((ClassDescriptor) descriptor, context).getThisDescriptor();
|
||||
CodegenContext result = getParentContextSubclassOf((ClassDescriptor) descriptor, context);
|
||||
assert result != null : "Can't find parent context for " + descriptor;
|
||||
return result.getThisDescriptor();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -2397,17 +2399,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return callable.invokeMethodWithArguments(resolvedCall, receiver, this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
// Find the first parent of the current context which corresponds to a subclass of a given class
|
||||
@NotNull
|
||||
private static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) {
|
||||
public static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) {
|
||||
CodegenContext c = context;
|
||||
while (true) {
|
||||
while (c != null) {
|
||||
if (c instanceof ClassContext && DescriptorUtils.isSubclass(c.getThisDescriptor(), descriptor)) {
|
||||
return c;
|
||||
}
|
||||
c = c.getParentContext();
|
||||
assert c != null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
|
||||
import org.jetbrains.kotlin.fileClasses.FileClasses;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.name.SpecialNames;
|
||||
@@ -65,7 +66,7 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
|
||||
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isTopLevelDeclaration;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isStaticDeclaration;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt.Synthetic;
|
||||
@@ -637,7 +638,9 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||
boolean syntheticBackingField = accessor instanceof AccessorForPropertyBackingFieldFromLocal;
|
||||
boolean forceField = (AsmUtil.isPropertyWithBackingFieldInOuterClass(original) &&
|
||||
!isCompanionObject(accessor.getContainingDeclaration())) || syntheticBackingField;
|
||||
!isCompanionObject(accessor.getContainingDeclaration())) ||
|
||||
syntheticBackingField ||
|
||||
original.getVisibility() == JavaVisibilities.PROTECTED_STATIC_VISIBILITY;
|
||||
StackValue property = codegen.intermediateValueForProperty(
|
||||
original, forceField, syntheticBackingField, accessor.getSuperCallTarget(), true, StackValue.none()
|
||||
);
|
||||
@@ -696,15 +699,15 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallTarget() != null
|
||||
);
|
||||
|
||||
boolean isTopLevelDeclaration = isTopLevelDeclaration(functionDescriptor);
|
||||
int reg = isTopLevelDeclaration ? 0 : 1;
|
||||
boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor);
|
||||
int reg = hasDispatchReceiver ? 1 : 0;
|
||||
boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor;
|
||||
if (!accessorIsConstructor && functionDescriptor instanceof ConstructorDescriptor) {
|
||||
iv.anew(callableMethod.getOwner());
|
||||
iv.dup();
|
||||
reg = 0;
|
||||
}
|
||||
else if (accessorIsConstructor || (accessorDescriptor != null && JetTypeMapper.isAccessor(accessorDescriptor) && !isTopLevelDeclaration)) {
|
||||
else if (accessorIsConstructor || (accessorDescriptor != null && JetTypeMapper.isAccessor(accessorDescriptor) && hasDispatchReceiver)) {
|
||||
if (!AnnotationUtilKt.isPlatformStaticInObjectOrClass(functionDescriptor)) {
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
}
|
||||
|
||||
@@ -24,12 +24,15 @@ import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
||||
import org.jetbrains.kotlin.storage.NullableLazyValue;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.util.*;
|
||||
@@ -544,6 +547,14 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
}
|
||||
|
||||
if (descriptorContext == null &&
|
||||
JavaVisibilities.PROTECTED_STATIC_VISIBILITY == descriptor.getVisibility() &&
|
||||
!(descriptor instanceof SamConstructorDescriptor)) {
|
||||
//seems we need static receiver in resolved call
|
||||
descriptorContext = ExpressionCodegen.getParentContextSubclassOf((ClassDescriptor) enclosed, this);
|
||||
superCallTarget = (ClassDescriptor) enclosed;
|
||||
}
|
||||
|
||||
if (descriptorContext == null) {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
public class JavaClass {
|
||||
|
||||
public String runZ(Z z) {
|
||||
return z.run("O", "K");
|
||||
}
|
||||
|
||||
protected interface Z {
|
||||
String run(String s1, String s2);
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package zzz
|
||||
|
||||
import JavaClass
|
||||
import JavaClass.Z
|
||||
|
||||
class A : JavaClass() {
|
||||
fun test() = runZ(JavaClass.Z {a, b -> a + b})
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return A().test()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
public abstract class First {
|
||||
protected static String TEST = "OK";
|
||||
|
||||
protected static String test() {
|
||||
return TEST;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package anotherPackage
|
||||
|
||||
import First
|
||||
|
||||
class Second : First() {
|
||||
val some = { First.TEST }
|
||||
fun foo() = { First.test() }
|
||||
|
||||
val some2 = { TEST }
|
||||
fun foo2() = { test() }
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
if (Second().some.invoke() != "OK") return "fail 1"
|
||||
|
||||
if (Second().foo().invoke() != "OK") return "fail 2"
|
||||
|
||||
if (Second().some2.invoke() != "OK") return "fail 3"
|
||||
|
||||
if (Second().foo2().invoke() != "OK") return "fail 4"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
public class Base {
|
||||
|
||||
protected static String BASE_ONLY = "BASE";
|
||||
|
||||
protected static String baseOnly() {
|
||||
return BASE_ONLY;
|
||||
}
|
||||
|
||||
protected static String TEST = "BASE";
|
||||
|
||||
protected static String test() {
|
||||
return TEST;
|
||||
}
|
||||
|
||||
public static class Derived extends Base {
|
||||
protected static String TEST = "DERIVED";
|
||||
|
||||
protected static String test() {
|
||||
return TEST;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package anotherPackage
|
||||
|
||||
import Base.Derived
|
||||
import Base
|
||||
|
||||
class Kotlin : Base.Derived() {
|
||||
fun doTest(): String {
|
||||
|
||||
if ({ TEST }() != "DERIVED") return "fail 1"
|
||||
if ({ test() }() != "DERIVED") return "fail 2"
|
||||
|
||||
if ({ Derived.TEST }() != "DERIVED") return "fail 3"
|
||||
if ({ Derived.test() }() != "DERIVED") return "fail 4"
|
||||
|
||||
if ({ Base.TEST }() != "BASE") return "fail 5"
|
||||
if ({ Base.test() }() != "BASE") return "fail 6"
|
||||
|
||||
|
||||
if ({ Base.BASE_ONLY }() != "BASE") return "fail 7"
|
||||
if ({ Base.baseOnly() }() != "BASE") return "fail 8"
|
||||
|
||||
if ({ BASE_ONLY }() != "BASE") return "fail 9"
|
||||
if ({ baseOnly() }() != "BASE") return "fail 10"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return Kotlin().doTest()
|
||||
}
|
||||
+18
@@ -627,5 +627,23 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
|
||||
doTestWithJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("protectedSamConstructor")
|
||||
public void testProtectedSamConstructor() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/statics/protectedSamConstructor/");
|
||||
doTestWithJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("protectedStatic")
|
||||
public void testProtectedStatic() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/statics/protectedStatic/");
|
||||
doTestWithJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("protectedStatic2")
|
||||
public void testProtectedStatic2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/statics/protectedStatic2/");
|
||||
doTestWithJava(fileName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user