Fix for KT-4250: IllegalAccessError when using protected java member from lambda function

#KT-4250 Fixed
This commit is contained in:
Michael Bogdanov
2015-10-27 10:33:28 +03:00
parent 0a70c80af3
commit f3e6fab68e
10 changed files with 149 additions and 10 deletions
@@ -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;
}