Fix for KT-11590: IllegalAccessError: SAM adapter generated with invalid accessibility for inline function
#KT-11590 Fixed
This commit is contained in:
@@ -2317,7 +2317,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
final Type asmType =
|
||||
state.getSamWrapperClasses().getSamWrapperClass(samType, expression.getContainingKtFile(), getParentCodegen());
|
||||
state.getSamWrapperClasses().getSamWrapperClass(samType, expression.getContainingKtFile(), this);
|
||||
|
||||
return StackValue.operation(asmType, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.openapi.util.Factory;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class SamWrapperClasses {
|
||||
private final GenerationState state;
|
||||
|
||||
private final Map<Pair<SamType, KtFile>, Type> samInterfaceToWrapperClass = Maps.newHashMap();
|
||||
|
||||
public SamWrapperClasses(@NotNull GenerationState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type getSamWrapperClass(@NotNull final SamType samType, @NotNull final KtFile file, @NotNull final MemberCodegen<?> parentCodegen) {
|
||||
return ContainerUtil.getOrCreate(samInterfaceToWrapperClass, Pair.create(samType, file),
|
||||
new Factory<Type>() {
|
||||
@Override
|
||||
public Type create() {
|
||||
return new SamWrapperCodegen(state, samType, parentCodegen).genWrapper(file);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
class SamWrapperClasses(private val state: GenerationState) {
|
||||
|
||||
private data class WrapperKey(val samType: SamType, val file: KtFile, val insideInline: Boolean)
|
||||
|
||||
private val samInterfaceToWrapperClass = hashMapOf<WrapperKey, Type>()
|
||||
|
||||
fun getSamWrapperClass(samType: SamType, file: KtFile, expressionCodegen: ExpressionCodegen): Type {
|
||||
val isInsideInline = InlineUtil.isInlineOrContainingInline(expressionCodegen.context.contextDescriptor)
|
||||
return samInterfaceToWrapperClass.getOrPut(WrapperKey(samType, file, isInsideInline)) {
|
||||
SamWrapperCodegen(state, samType, expressionCodegen.parentCodegen, isInsideInline).genWrapper(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,17 +49,27 @@ public class SamWrapperCodegen {
|
||||
private static final String FUNCTION_FIELD_NAME = "function";
|
||||
|
||||
private final GenerationState state;
|
||||
private final boolean isInsideInline;
|
||||
private final KotlinTypeMapper typeMapper;
|
||||
private final SamType samType;
|
||||
private final MemberCodegen<?> parentCodegen;
|
||||
private final int visibility;
|
||||
|
||||
public SamWrapperCodegen(@NotNull GenerationState state, @NotNull SamType samType, @NotNull MemberCodegen<?> parentCodegen) {
|
||||
public SamWrapperCodegen(
|
||||
@NotNull GenerationState state,
|
||||
@NotNull SamType samType,
|
||||
@NotNull MemberCodegen<?> parentCodegen,
|
||||
boolean isInsideInline
|
||||
) {
|
||||
this.state = state;
|
||||
this.isInsideInline = isInsideInline;
|
||||
this.typeMapper = state.getTypeMapper();
|
||||
this.samType = samType;
|
||||
this.parentCodegen = parentCodegen;
|
||||
visibility = isInsideInline ? ACC_PUBLIC : NO_FLAG_PACKAGE_PRIVATE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type genWrapper(@NotNull KtFile file) {
|
||||
// Name for generated class, in form of whatever$1
|
||||
FqName fqName = getWrapperName(file);
|
||||
@@ -88,7 +98,7 @@ public class SamWrapperCodegen {
|
||||
ClassBuilder cv = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(erasedInterfaceFunction), asmType, file);
|
||||
cv.defineClass(file,
|
||||
V1_6,
|
||||
ACC_FINAL | ACC_SUPER,
|
||||
ACC_FINAL | ACC_SUPER | visibility,
|
||||
asmType.getInternalName(),
|
||||
null,
|
||||
OBJECT_TYPE.getInternalName(),
|
||||
@@ -118,7 +128,7 @@ public class SamWrapperCodegen {
|
||||
|
||||
private void generateConstructor(Type ownerType, Type functionType, ClassBuilder cv) {
|
||||
MethodVisitor mv = cv.newMethod(JvmDeclarationOriginKt.OtherOrigin(samType.getJavaClassDescriptor()),
|
||||
NO_FLAG_PACKAGE_PRIVATE, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType), null, null);
|
||||
visibility, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType), null, null);
|
||||
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
mv.visitCode();
|
||||
@@ -177,9 +187,10 @@ public class SamWrapperCodegen {
|
||||
int hash = PackagePartClassUtils.getPathHashCode(containingFile.getVirtualFile()) * 31 +
|
||||
DescriptorUtils.getFqNameSafe(descriptor).hashCode();
|
||||
String shortName = String.format(
|
||||
"%s$sam$%s$%08x",
|
||||
"%s$sam$%s%s$%08x",
|
||||
fileClassFqName.shortName().asString(),
|
||||
descriptor.getName().asString(),
|
||||
(isInsideInline ? "$i" : ""),
|
||||
hash
|
||||
);
|
||||
return fileClassFqName.parent().child(Name.identifier(shortName));
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// FILE: 1.kt
|
||||
package test
|
||||
|
||||
inline fun <reified T> makeRunnable(noinline lambda: ()->Unit) : Runnable {
|
||||
return Runnable(lambda)
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
var result = "fail"
|
||||
|
||||
makeRunnable<String> { result = "OK" }.run()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package test
|
||||
|
||||
inline fun <reified T> makeRunnable(noinline lambda: ()->Unit) : Runnable {
|
||||
return Runnable(lambda)
|
||||
}
|
||||
|
||||
inline fun makeRunnable2(noinline lambda: ()->Unit) : Runnable {
|
||||
return Runnable(lambda)
|
||||
}
|
||||
|
||||
|
||||
fun noInline(lambda: ()->Unit) : Runnable {
|
||||
return Runnable(lambda)
|
||||
}
|
||||
|
||||
|
||||
fun noInline2(lambda: ()->Unit) : Runnable {
|
||||
return Runnable(lambda)
|
||||
}
|
||||
|
||||
// 1 final class test/_1Kt\$sam\$Runnable\$89f9321c
|
||||
// 1 public final class test/_1Kt\$sam\$Runnable\$i\$89f9321c
|
||||
// 2 class test/_1Kt\$sam\$
|
||||
@@ -0,0 +1,21 @@
|
||||
@kotlin.Metadata
|
||||
final class test/SamAdapterAndInlinedOneKt$sam$Runnable$82391ccd {
|
||||
private synthetic final field function: kotlin.jvm.functions.Function0
|
||||
method <init>(p0: kotlin.jvm.functions.Function0): void
|
||||
public synthetic final method run(): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class test/SamAdapterAndInlinedOneKt$sam$Runnable$i$82391ccd {
|
||||
private synthetic final field function: kotlin.jvm.functions.Function0
|
||||
public method <init>(p0: kotlin.jvm.functions.Function0): void
|
||||
public synthetic final method run(): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class test/SamAdapterAndInlinedOneKt {
|
||||
private final static method makeRunnable(p0: kotlin.jvm.functions.Function0): java.lang.Runnable
|
||||
public final static @org.jetbrains.annotations.NotNull method makeRunnable2(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Runnable
|
||||
public final static @org.jetbrains.annotations.NotNull method noInline(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Runnable
|
||||
public final static @org.jetbrains.annotations.NotNull method noInline2(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): java.lang.Runnable
|
||||
}
|
||||
@@ -175,6 +175,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("sam.kt")
|
||||
public void testSam() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/sam.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/anonymousObject/enumWhen")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -59,6 +59,12 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("samAdapterAndInlinedOne.kt")
|
||||
public void testSamAdapterAndInlinedOne() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/samAdapterAndInlinedOne.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/bytecodeListing/annotations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+6
@@ -175,6 +175,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("sam.kt")
|
||||
public void testSam() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/sam.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/anonymousObject/enumWhen")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user