diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java index b7cb263786b..c861c9f4658 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java @@ -255,7 +255,10 @@ public class AsmUtil { For other cases use getVisibilityAccessFlag(MemberDescriptor descriptor) Classes in byte code should be public or package private */ - public static int getVisibilityAccessFlagForClass(ClassDescriptor descriptor) { + public static int getVisibilityAccessFlagForClass(@NotNull ClassDescriptor descriptor) { + if (descriptor instanceof SyntheticClassDescriptorForLambda) { + return getVisibilityAccessFlagForAnonymous(descriptor); + } if (descriptor.getVisibility() == Visibilities.PUBLIC || // TODO: should be package private, but for now Kotlin's reflection can't access members of such classes descriptor.getVisibility() == Visibilities.LOCAL || @@ -265,12 +268,17 @@ public class AsmUtil { return NO_FLAG_PACKAGE_PRIVATE; } - public static int getVisibilityAccessFlagForAnonymous(@NotNull ClassDescriptor descriptor) { + private static int getVisibilityAccessFlagForAnonymous(@NotNull ClassDescriptor descriptor) { return InlineUtil.isInlineOrContainingInline(descriptor.getContainingDeclaration()) ? ACC_PUBLIC : NO_FLAG_PACKAGE_PRIVATE; } public static int calculateInnerClassAccessFlags(@NotNull ClassDescriptor innerClass) { - int visibility = (innerClass.getVisibility() == Visibilities.LOCAL) ? ACC_PUBLIC : getVisibilityAccessFlag(innerClass); + int visibility = + innerClass instanceof SyntheticClassDescriptorForLambda + ? getVisibilityAccessFlagForAnonymous(innerClass) + : innerClass.getVisibility() == Visibilities.LOCAL + ? ACC_PUBLIC + : getVisibilityAccessFlag(innerClass); return visibility | innerAccessFlagsForModalityAndKind(innerClass) | (innerClass.isInner() ? 0 : ACC_STATIC); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java index eb240ffb124..2fccd8fc91b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java @@ -126,7 +126,7 @@ public class ClosureCodegen extends MemberCodegen { this.asmType = typeMapper.mapClass(classDescriptor); - visibilityFlag = AsmUtil.getVisibilityAccessFlagForAnonymous(classDescriptor); + visibilityFlag = AsmUtil.getVisibilityAccessFlagForClass(classDescriptor); } @Override diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt index eb6e2b86fe3..092accb4129 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt @@ -66,7 +66,7 @@ class PropertyReferenceCodegen( v.defineClass( element, V1_6, - ACC_FINAL or ACC_SUPER or AsmUtil.getVisibilityAccessFlagForAnonymous(classDescriptor), + ACC_FINAL or ACC_SUPER or AsmUtil.getVisibilityAccessFlagForClass(classDescriptor), asmType.internalName, null, superAsmType.internalName, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/SyntheticClassDescriptorForLambda.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/SyntheticClassDescriptorForLambda.kt new file mode 100644 index 00000000000..e181deb3ba8 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/SyntheticClassDescriptorForLambda.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2016 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.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.resolve.source.toSourceElement +import org.jetbrains.kotlin.types.KotlinType + +class SyntheticClassDescriptorForLambda( + containingDeclaration: DeclarationDescriptor, + name: Name, + supertypes: Collection, + element: KtElement +) : ClassDescriptorImpl(containingDeclaration, name, Modality.FINAL, ClassKind.CLASS, supertypes, element.toSourceElement()) { + init { + initialize(MemberScope.Empty, emptySet(), null) + } +} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java index 131076aa263..78fe4a8bd66 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java @@ -24,10 +24,7 @@ import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.cfg.WhenChecker; -import org.jetbrains.kotlin.codegen.AsmUtil; -import org.jetbrains.kotlin.codegen.JvmRuntimeTypes; -import org.jetbrains.kotlin.codegen.SamCodegenUtil; -import org.jetbrains.kotlin.codegen.SamType; +import org.jetbrains.kotlin.codegen.*; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil; import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping; @@ -94,15 +91,12 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid { @NotNull String name ) { String simpleName = name.substring(name.lastIndexOf('/') + 1); - ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl( + ClassDescriptor classDescriptor = new SyntheticClassDescriptorForLambda( correctContainerForLambda(callableDescriptor, element), Name.special(""), - Modality.FINAL, - ClassKind.CLASS, supertypes, - KotlinSourceElementKt.toSourceElement(element) + element ); - classDescriptor.initialize(MemberScope.Empty.INSTANCE, Collections.emptySet(), null); bindingTrace.record(CLASS_FOR_CALLABLE, callableDescriptor, classDescriptor); return classDescriptor; diff --git a/compiler/testData/codegen/innerClassInfo/lambdaClassFlags.kt b/compiler/testData/codegen/innerClassInfo/lambdaClassFlags.kt new file mode 100644 index 00000000000..3380be2832f --- /dev/null +++ b/compiler/testData/codegen/innerClassInfo/lambdaClassFlags.kt @@ -0,0 +1,4 @@ +class A { + fun foo() = fun() {} + fun bar() = {} +} diff --git a/compiler/testData/writeFlags/lambda/lambdaInInlineFunction.kt b/compiler/testData/writeFlags/lambda/lambdaInInlineFunction.kt new file mode 100644 index 00000000000..456b219aa0b --- /dev/null +++ b/compiler/testData/writeFlags/lambda/lambdaInInlineFunction.kt @@ -0,0 +1,7 @@ +class Foo { + inline fun foo() = { } +} + +// TESTED_OBJECT_KIND: class +// TESTED_OBJECTS: Foo$foo$1 +// FLAGS: ACC_PUBLIC, ACC_FINAL, ACC_SUPER diff --git a/compiler/testData/writeFlags/lambda/simpleLambda.kt b/compiler/testData/writeFlags/lambda/simpleLambda.kt new file mode 100644 index 00000000000..eea052bd0b9 --- /dev/null +++ b/compiler/testData/writeFlags/lambda/simpleLambda.kt @@ -0,0 +1,7 @@ +class Foo { + fun foo() = { } +} + +// TESTED_OBJECT_KIND: class +// TESTED_OBJECTS: Foo$foo$1 +// FLAGS: ACC_FINAL, ACC_SUPER diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/InnerClassInfoGenTest.java b/compiler/tests/org/jetbrains/kotlin/codegen/InnerClassInfoGenTest.java index 6a2fcb5cf59..39d45d334b4 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/InnerClassInfoGenTest.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/InnerClassInfoGenTest.java @@ -103,6 +103,15 @@ public class InnerClassInfoGenTest extends CodegenTestCase { checkAccess("A", "PublicClass", ACC_PUBLIC); } + public void testLambdaClassFlags() { + InnerClassAttribute foo = new InnerClassAttribute("A$foo$1", null, null, ACC_STATIC | ACC_FINAL); + InnerClassAttribute bar = new InnerClassAttribute("A$bar$1", null, null, ACC_STATIC | ACC_FINAL); + + extractAndCompareInnerClasses("A", foo, bar); + extractAndCompareInnerClasses("A$foo$1", foo); + extractAndCompareInnerClasses("A$bar$1", bar); + } + private void checkAccess(@NotNull String outerName, @NotNull final String innerName, int accessFlags) { diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/flags/WriteFlagsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/flags/WriteFlagsTestGenerated.java index b9fa8d0f337..cfd7f30fb8c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/flags/WriteFlagsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/flags/WriteFlagsTestGenerated.java @@ -644,6 +644,27 @@ public class WriteFlagsTestGenerated extends AbstractWriteFlagsTest { } } + @TestMetadata("compiler/testData/writeFlags/lambda") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Lambda extends AbstractWriteFlagsTest { + public void testAllFilesPresentInLambda() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/writeFlags/lambda"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("lambdaInInlineFunction.kt") + public void testLambdaInInlineFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeFlags/lambda/lambdaInInlineFunction.kt"); + doTest(fileName); + } + + @TestMetadata("simpleLambda.kt") + public void testSimpleLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeFlags/lambda/simpleLambda.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/writeFlags/lateinit") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ClassDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ClassDescriptorImpl.java index 3760b80cfca..f8057c68de7 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ClassDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ClassDescriptorImpl.java @@ -81,10 +81,6 @@ public class ClassDescriptorImpl extends ClassDescriptorBase { this.primaryConstructor = primaryConstructor; } - public void setPrimaryConstructor(@NotNull ConstructorDescriptor primaryConstructor) { - this.primaryConstructor = primaryConstructor; - } - @NotNull @Override public Annotations getAnnotations() {