From bf779b4ca59e8f765ac46bed0a313ee7d69f2687 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 2 Oct 2012 22:44:57 +0400 Subject: [PATCH] Generate not-null assertions only for descriptors coming from Java Introduce BindingContext.IS_DECLARED_IN_JAVA, store that info in JavaDescriptorResolver --- .../org/jetbrains/jet/codegen/AsmUtil.java | 10 +++- .../java/resolver/FunctionResolver.java | 4 ++ .../java/resolver/PropertiesResolver.java | 3 + .../jet/lang/resolve/BindingContext.java | 2 + .../noAssertionsForKotlin.kt | 13 +++++ .../noAssertionsForKotlinMain.kt | 7 +++ .../GenerateNotNullAssertionsTest.java | 55 ++++++++++++++++++- 7 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/codegen/notNullAssertions/noAssertionsForKotlin.kt create mode 100644 compiler/testData/codegen/notNullAssertions/noAssertionsForKotlinMain.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java index dbcc8385065..5c8fe2378da 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java @@ -30,10 +30,12 @@ import org.jetbrains.jet.codegen.binding.CalculatedClosure; import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.JetTypeMapper; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; -import org.jetbrains.jet.lang.resolve.java.*; -import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; +import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants; +import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; +import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; import org.jetbrains.jet.lexer.JetTokens; @@ -447,6 +449,8 @@ public class AsmUtil { ) { if (!state.isGenerateNotNullAssertions()) return; + if (!Boolean.TRUE.equals(state.getBindingContext().get(BindingContext.IS_DECLARED_IN_JAVA, descriptor))) return; + JetType type = descriptor.getReturnType(); if (type == null || type.isNullable()) return; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/FunctionResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/FunctionResolver.java index f7338d47952..6949876c1ec 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/FunctionResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/FunctionResolver.java @@ -130,6 +130,10 @@ public final class FunctionResolver { BindingContextUtils.recordFunctionDeclarationToDescriptor(javaDescriptorResolver.getTrace(), psiMethod, functionDescriptorImpl); } + if (!scopeData.isKotlin()) { + javaDescriptorResolver.getTrace().record(BindingContext.IS_DECLARED_IN_JAVA, functionDescriptorImpl); + } + if (containingClass != psiClass && !method.isStatic()) { throw new IllegalStateException("non-static method in subclass"); } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/PropertiesResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/PropertiesResolver.java index 23c21410f3f..9341092d896 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/PropertiesResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/PropertiesResolver.java @@ -275,6 +275,9 @@ public final class PropertiesResolver { trace.record(BindingContext.OBJECT_DECLARATION_CLASS, propertyDescriptor, objectDescriptor); } + if (!scopeData.isKotlin()) { + trace.record(BindingContext.IS_DECLARED_IN_JAVA, propertyDescriptor); + } propertiesFromCurrent.add(propertyDescriptor); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java index 0cd11b2fba6..a1e01e64c91 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -254,6 +254,8 @@ public interface BindingContext { WritableSlice ALTERNATIVE_SIGNATURE_DATA_ERROR = Slices.createSimpleSlice(); + WritableSlice IS_DECLARED_IN_JAVA = Slices.createSimpleSlice(); + @SuppressWarnings("UnusedDeclaration") @Deprecated // This field is needed only for the side effects of its initializer Void _static_initializer = BasicWritableSlice.initSliceDebugNames(BindingContext.class); diff --git a/compiler/testData/codegen/notNullAssertions/noAssertionsForKotlin.kt b/compiler/testData/codegen/notNullAssertions/noAssertionsForKotlin.kt new file mode 100644 index 00000000000..06d0afcf744 --- /dev/null +++ b/compiler/testData/codegen/notNullAssertions/noAssertionsForKotlin.kt @@ -0,0 +1,13 @@ +class A { + val x: Int = 42 + + fun foo(): String = "" + + class object { + val y: Any? = 239 + + fun bar(): String = "" + } +} + +fun baz(): String = "" diff --git a/compiler/testData/codegen/notNullAssertions/noAssertionsForKotlinMain.kt b/compiler/testData/codegen/notNullAssertions/noAssertionsForKotlinMain.kt new file mode 100644 index 00000000000..ccb8936627d --- /dev/null +++ b/compiler/testData/codegen/notNullAssertions/noAssertionsForKotlinMain.kt @@ -0,0 +1,7 @@ +fun bar() { + val x = A().x + val foo = A().foo() + val y = A.y + val bar = A.bar() + val baz = baz() +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/GenerateNotNullAssertionsTest.java b/compiler/tests/org/jetbrains/jet/codegen/GenerateNotNullAssertionsTest.java index 54d459cb29d..f646452daec 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/GenerateNotNullAssertionsTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/GenerateNotNullAssertionsTest.java @@ -16,13 +16,18 @@ package org.jetbrains.jet.codegen; -import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.util.io.FileUtil; +import org.jetbrains.asm4.ClassReader; +import org.jetbrains.asm4.ClassVisitor; +import org.jetbrains.asm4.MethodVisitor; +import org.jetbrains.asm4.Opcodes; import org.jetbrains.jet.CompileCompilerDependenciesTest; import org.jetbrains.jet.ConfigurationKind; -import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.TestJdkKind; import org.jetbrains.jet.cli.jvm.JVMConfigurationKeys; +import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentUtil; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; +import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.config.CompilerConfiguration; import java.io.File; @@ -60,4 +65,50 @@ public class GenerateNotNullAssertionsTest extends CodegenTestCase { public void testDoNotGenerateAssertions() throws Exception { doTestGenerateAssertions(false, "notNullAssertions/doNotGenerateAssertions.kt"); } + + public void testNoAssertionsForKotlinFromSource() throws Exception { + setUpEnvironment(true); + + loadFiles("notNullAssertions/noAssertionsForKotlin.kt", "notNullAssertions/noAssertionsForKotlinMain.kt"); + + assertNoIntrinsicsMethodIsCalled("namespace"); + } + + public void testNoAssertionsForKotlinFromBinary() throws Exception { + CompilerConfiguration configuration = CompileCompilerDependenciesTest.compilerConfigurationForTests( + ConfigurationKind.JDK_ONLY, TestJdkKind.MOCK_JDK); + JetCoreEnvironment tmpEnvironment = new JetCoreEnvironment(getTestRootDisposable(), configuration); + GenerationState state = generateCommon(ClassBuilderFactories.TEST, tmpEnvironment, + CodegenTestFiles.create(tmpEnvironment.getProject(), new String[] {"notNullAssertions/noAssertionsForKotlin.kt"})); + File compiledDirectory = new File(FileUtil.getTempDirectory(), "kotlin-classes"); + CompileEnvironmentUtil.writeToOutputDirectory(state.getFactory(), compiledDirectory); + + setUpEnvironment(true, compiledDirectory); + + loadFile("notNullAssertions/noAssertionsForKotlinMain.kt"); + + assertNoIntrinsicsMethodIsCalled("namespace"); + } + + private void assertNoIntrinsicsMethodIsCalled(String className) { + ClassFileFactory classes = generateClassesInFile(); + ClassReader reader = new ClassReader(classes.asBytes(className + ".class")); + + reader.accept(new ClassVisitor(Opcodes.ASM4) { + @Override + public MethodVisitor visitMethod( + int access, final String callerName, final String callerDesc, String signature, String[] exceptions + ) { + return new MethodVisitor(Opcodes.ASM4) { + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc) { + assertFalse( + "jet/Intrinsics method is called: " + name + desc + " Caller: " + callerName + callerDesc, + "jet/Intrinsics".equals(owner) + ); + } + }; + } + }, 0); + } }