Fix for KT-16614: Report inability to inline 1.8 bytecode into 1.6 bytecode as an error, no as an exception
This commit is contained in:
-1
@@ -66,7 +66,6 @@ public class AnonymousObjectTransformer extends ObjectTransformer<AnonymousObjec
|
|||||||
createClassReader().accept(new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) {
|
createClassReader().accept(new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) {
|
||||||
@Override
|
@Override
|
||||||
public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) {
|
public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) {
|
||||||
InlineCodegenUtil.assertVersionNotGreaterThanGeneratedOne(version, name, inliningContext.state);
|
|
||||||
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces);
|
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces);
|
||||||
if(CoroutineCodegenUtilKt.COROUTINE_IMPL_ASM_TYPE.getInternalName().equals(superName)) {
|
if(CoroutineCodegenUtilKt.COROUTINE_IMPL_ASM_TYPE.getInternalName().equals(superName)) {
|
||||||
inliningContext.setContinuation(true);
|
inliningContext.setContinuation(true);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache;
|
|||||||
import org.jetbrains.kotlin.name.ClassId;
|
import org.jetbrains.kotlin.name.ClassId;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
@@ -202,7 +203,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
MethodNode node = nodeAndSmap != null ? nodeAndSmap.getNode() : null;
|
MethodNode node = nodeAndSmap != null ? nodeAndSmap.getNode() : null;
|
||||||
throw new CompilationException(
|
throw new CompilationException(
|
||||||
"Couldn't inline method call '" + functionDescriptor.getName() + "' into\n" +
|
"Couldn't inline method call '" + functionDescriptor.getName() + "' into\n" +
|
||||||
contextDescriptor + "\n" +
|
DescriptorRenderer.DEBUG_TEXT.render(contextDescriptor) + "\n" +
|
||||||
(element != null ? element.getText() : "<no source>") +
|
(element != null ? element.getText() : "<no source>") +
|
||||||
(generateNodeText ? ("\nCause: " + InlineCodegenUtil.getNodeText(node)) : ""),
|
(generateNodeText ? ("\nCause: " + InlineCodegenUtil.getNodeText(node)) : ""),
|
||||||
e, callElement
|
e, callElement
|
||||||
@@ -321,7 +322,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), classId, state);
|
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), classId);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert callableDescriptor instanceof DeserializedCallableMemberDescriptor : "Not a deserialized function or proper: " + callableDescriptor;
|
assert callableDescriptor instanceof DeserializedCallableMemberDescriptor : "Not a deserialized function or proper: " + callableDescriptor;
|
||||||
@@ -348,7 +349,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), containerId, state);
|
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), containerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -92,8 +92,7 @@ public class InlineCodegenUtil {
|
|||||||
byte[] classData,
|
byte[] classData,
|
||||||
final String methodName,
|
final String methodName,
|
||||||
final String methodDescriptor,
|
final String methodDescriptor,
|
||||||
ClassId classId,
|
ClassId classId
|
||||||
final @NotNull GenerationState state
|
|
||||||
) {
|
) {
|
||||||
ClassReader cr = new ClassReader(classData);
|
ClassReader cr = new ClassReader(classData);
|
||||||
final MethodNode[] node = new MethodNode[1];
|
final MethodNode[] node = new MethodNode[1];
|
||||||
@@ -103,10 +102,6 @@ public class InlineCodegenUtil {
|
|||||||
lines[1] = Integer.MIN_VALUE;
|
lines[1] = Integer.MIN_VALUE;
|
||||||
//noinspection PointlessBitwiseExpression
|
//noinspection PointlessBitwiseExpression
|
||||||
cr.accept(new ClassVisitor(API) {
|
cr.accept(new ClassVisitor(API) {
|
||||||
@Override
|
|
||||||
public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) {
|
|
||||||
assertVersionNotGreaterThanGeneratedOne(version, name, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitSource(String source, String debug) {
|
public void visitSource(String source, String debug) {
|
||||||
@@ -151,16 +146,6 @@ public class InlineCodegenUtil {
|
|||||||
return new SMAPAndMethodNode(node[0], smap);
|
return new SMAPAndMethodNode(node[0], smap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertVersionNotGreaterThanGeneratedOne(int version, String internalName, @NotNull GenerationState state) {
|
|
||||||
// TODO: report a proper diagnostic
|
|
||||||
if (version > state.getClassFileVersion() && !"true".equals(System.getProperty("kotlin.skip.bytecode.version.check"))) {
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Cannot inline bytecode of class " + internalName + " which has version " + version + ". " +
|
|
||||||
"This compiler can only inline Java 1.6 bytecode (version " + Opcodes.V1_6 + ")"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void initDefaultSourceMappingIfNeeded(
|
public static void initDefaultSourceMappingIfNeeded(
|
||||||
@NotNull CodegenContext context, @NotNull MemberCodegen codegen, @NotNull GenerationState state
|
@NotNull CodegenContext context, @NotNull MemberCodegen codegen, @NotNull GenerationState state
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ class WhenMappingTransformer(
|
|||||||
val fieldNode = transformationInfo.fieldNode
|
val fieldNode = transformationInfo.fieldNode
|
||||||
classReader.accept(object : ClassVisitor(InlineCodegenUtil.API, classBuilder.visitor) {
|
classReader.accept(object : ClassVisitor(InlineCodegenUtil.API, classBuilder.visitor) {
|
||||||
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
|
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
|
||||||
InlineCodegenUtil.assertVersionNotGreaterThanGeneratedOne(version, name, state)
|
|
||||||
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces)
|
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,8 @@ class GenerationState @JvmOverloads constructor(
|
|||||||
extraJvmDiagnosticsTrace.bindingContext.diagnostics
|
extraJvmDiagnosticsTrace.bindingContext.diagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
val isJvm8Target: Boolean = configuration.get(JVMConfigurationKeys.JVM_TARGET) == JvmTarget.JVM_1_8
|
val target = configuration.get(JVMConfigurationKeys.JVM_TARGET) ?: JvmTarget.DEFAULT
|
||||||
|
val isJvm8Target: Boolean = target == JvmTarget.JVM_1_8
|
||||||
val isJvm8TargetWithDefaults: Boolean = isJvm8Target && configuration.getBoolean(JVMConfigurationKeys.JVM8_TARGET_WITH_DEFAULTS)
|
val isJvm8TargetWithDefaults: Boolean = isJvm8Target && configuration.getBoolean(JVMConfigurationKeys.JVM8_TARGET_WITH_DEFAULTS)
|
||||||
val generateDefaultImplsForJvm8: Boolean = configuration.getBoolean(JVMConfigurationKeys.INTERFACE_COMPATIBILITY)
|
val generateDefaultImplsForJvm8: Boolean = configuration.getBoolean(JVMConfigurationKeys.INTERFACE_COMPATIBILITY)
|
||||||
|
|
||||||
@@ -162,7 +163,7 @@ class GenerationState @JvmOverloads constructor(
|
|||||||
|
|
||||||
val rootContext: CodegenContext<*> = RootContext(this)
|
val rootContext: CodegenContext<*> = RootContext(this)
|
||||||
|
|
||||||
val classFileVersion: Int = if (isJvm8Target) Opcodes.V1_8 else Opcodes.V1_6
|
val classFileVersion: Int = target.bytecodeVersion
|
||||||
|
|
||||||
val generateParametersMetadata: Boolean = configuration.getBoolean(JVMConfigurationKeys.PARAMETERS_METADATA)
|
val generateParametersMetadata: Boolean = configuration.getBoolean(JVMConfigurationKeys.PARAMETERS_METADATA)
|
||||||
|
|
||||||
|
|||||||
+92
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 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.resolve.jvm.checkers
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.config.JvmTarget
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassOrPackageFragmentDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryPackageSourceElement
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
||||||
|
|
||||||
|
class InlinePlatformCompatibilityChecker: CallChecker {
|
||||||
|
|
||||||
|
private val doCheck = doCheck()
|
||||||
|
|
||||||
|
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||||
|
if (!doCheck) return
|
||||||
|
|
||||||
|
val resultingDescriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return
|
||||||
|
if (!InlineUtil.isInline(resultingDescriptor)) {
|
||||||
|
if (resultingDescriptor is PropertyDescriptor && InlineUtil.isInline(resultingDescriptor.getter)) {
|
||||||
|
//TODO: we should distinguish setter usage from getter one, now we could report wrong diagnostic on non-inline setter
|
||||||
|
//var prop: Int
|
||||||
|
// inline get
|
||||||
|
// set
|
||||||
|
//
|
||||||
|
// prop - resolved call with property descriptor and we should report error
|
||||||
|
// prop = 1 - resolved call with setter for whole expression and property descriptor for left part,
|
||||||
|
// so we couldn't distinguish is this expression for setter or for getter and will report wrong diagnostic
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val propertyOrFun = DescriptorUtils.getDirectMember(resultingDescriptor)
|
||||||
|
val inliningBytecodeVersion = getBytecodeVersionIfDeserializedDescriptor(propertyOrFun) ?: return
|
||||||
|
|
||||||
|
val compilingTarget = context.compilerConfiguration[JVMConfigurationKeys.JVM_TARGET] ?: JvmTarget.DEFAULT
|
||||||
|
val compilingBytecodeVersion = compilingTarget.bytecodeVersion
|
||||||
|
if (compilingBytecodeVersion < inliningBytecodeVersion) {
|
||||||
|
context.trace.report(ErrorsJvm.INLINE_FROM_HIGHER_PLATFORM.on(reportOn, JvmTarget.getDescription(inliningBytecodeVersion), JvmTarget.getDescription(compilingBytecodeVersion)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun doCheck() = "true" != System.getProperty("kotlin.skip.bytecode.version.check")
|
||||||
|
|
||||||
|
fun getBytecodeVersionIfDeserializedDescriptor(funOrProperty: DeclarationDescriptor): Int? {
|
||||||
|
if (funOrProperty !is DeserializedCallableMemberDescriptor) return null
|
||||||
|
|
||||||
|
val containingDeclaration = funOrProperty.containingDeclaration as ClassOrPackageFragmentDescriptor
|
||||||
|
|
||||||
|
val source = containingDeclaration.source
|
||||||
|
val binaryClass =
|
||||||
|
when (source) {
|
||||||
|
is KotlinJvmBinarySourceElement -> source.binaryClass
|
||||||
|
is KotlinJvmBinaryPackageSourceElement -> source.getContainingBinaryClass(funOrProperty)
|
||||||
|
else -> null
|
||||||
|
} as? FileBasedKotlinClass ?: return null
|
||||||
|
|
||||||
|
return binaryClass.classVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+2
@@ -115,6 +115,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
|||||||
|
|
||||||
MAP.put(ErrorsJvm.DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET, "Super calls to Java default methods are deprecated in JVM target 1.6. Recompile with '-jvm-target 1.8'");
|
MAP.put(ErrorsJvm.DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET, "Super calls to Java default methods are deprecated in JVM target 1.6. Recompile with '-jvm-target 1.8'");
|
||||||
MAP.put(ErrorsJvm.INTERFACE_STATIC_METHOD_CALL_FROM_JAVA6_TARGET, "Calls to static methods in Java interfaces are deprecated in JVM target 1.6. Recompile with '-jvm-target 1.8'");
|
MAP.put(ErrorsJvm.INTERFACE_STATIC_METHOD_CALL_FROM_JAVA6_TARGET, "Calls to static methods in Java interfaces are deprecated in JVM target 1.6. Recompile with '-jvm-target 1.8'");
|
||||||
|
|
||||||
|
MAP.put(ErrorsJvm.INLINE_FROM_HIGHER_PLATFORM, "Cannot inline bytecode built with {0} into bytecode that is being built with {1}. Please specify proper ''-jvm-target'' option", Renderers.TO_STRING, Renderers.TO_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -92,6 +92,8 @@ public interface ErrorsJvm {
|
|||||||
DiagnosticFactory0<PsiElement> DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET = DiagnosticFactory0.create(WARNING);
|
DiagnosticFactory0<PsiElement> DEFAULT_METHOD_CALL_FROM_JAVA6_TARGET = DiagnosticFactory0.create(WARNING);
|
||||||
DiagnosticFactory0<PsiElement> INTERFACE_STATIC_METHOD_CALL_FROM_JAVA6_TARGET = DiagnosticFactory0.create(WARNING);
|
DiagnosticFactory0<PsiElement> INTERFACE_STATIC_METHOD_CALL_FROM_JAVA6_TARGET = DiagnosticFactory0.create(WARNING);
|
||||||
|
|
||||||
|
DiagnosticFactory2<PsiElement, String, String> INLINE_FROM_HIGHER_PLATFORM = DiagnosticFactory2.create(ERROR);
|
||||||
|
|
||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
Object _initializer = new Object() {
|
Object _initializer = new Object() {
|
||||||
{
|
{
|
||||||
|
|||||||
+3
-1
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.container.useImpl
|
|||||||
import org.jetbrains.kotlin.container.useInstance
|
import org.jetbrains.kotlin.container.useInstance
|
||||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||||
import org.jetbrains.kotlin.resolve.PlatformConfigurator
|
import org.jetbrains.kotlin.resolve.PlatformConfigurator
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.checkers.InlineCheckerWrapper
|
||||||
import org.jetbrains.kotlin.resolve.calls.checkers.ReifiedTypeParameterSubstitutionChecker
|
import org.jetbrains.kotlin.resolve.calls.checkers.ReifiedTypeParameterSubstitutionChecker
|
||||||
import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker
|
import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker
|
||||||
import org.jetbrains.kotlin.resolve.checkers.MissingDependencyClassChecker
|
import org.jetbrains.kotlin.resolve.checkers.MissingDependencyClassChecker
|
||||||
@@ -55,7 +56,8 @@ object JvmPlatformConfigurator : PlatformConfigurator(
|
|||||||
UnsupportedSyntheticCallableReferenceChecker(),
|
UnsupportedSyntheticCallableReferenceChecker(),
|
||||||
SuperCallWithDefaultArgumentsChecker(),
|
SuperCallWithDefaultArgumentsChecker(),
|
||||||
ProtectedSyntheticExtensionCallChecker,
|
ProtectedSyntheticExtensionCallChecker,
|
||||||
ReifiedTypeParameterSubstitutionChecker()
|
ReifiedTypeParameterSubstitutionChecker(),
|
||||||
|
InlinePlatformCompatibilityChecker()
|
||||||
),
|
),
|
||||||
|
|
||||||
additionalTypeCheckers = listOf(
|
additionalTypeCheckers = listOf(
|
||||||
|
|||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
// JVM_TARGET: 1.8
|
||||||
|
package a
|
||||||
|
|
||||||
|
inline fun inlineFun(p: () -> Unit) {
|
||||||
|
p()
|
||||||
|
}
|
||||||
|
|
||||||
|
var inlineGetter: Int
|
||||||
|
inline get() = 1
|
||||||
|
set(varue) {}
|
||||||
|
|
||||||
|
var inlineSetter: Int
|
||||||
|
get() = 1
|
||||||
|
inline set(varue) {}
|
||||||
|
|
||||||
|
var allInline: Int
|
||||||
|
inline get() = 1
|
||||||
|
inline set(varue) {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class A {
|
||||||
|
inline fun inlineFun(p: () -> Unit) {
|
||||||
|
p()
|
||||||
|
}
|
||||||
|
|
||||||
|
var inlineGetter: Int
|
||||||
|
inline get() = 1
|
||||||
|
set(varue) {}
|
||||||
|
|
||||||
|
var inlineSetter: Int
|
||||||
|
get() = 1
|
||||||
|
inline set(varue) {}
|
||||||
|
|
||||||
|
var allInline: Int
|
||||||
|
inline get() = 1
|
||||||
|
inline set(varue) {}
|
||||||
|
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:6:5: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option
|
||||||
|
inlineFun {}
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:7:5: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option
|
||||||
|
inlineGetter
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:8:5: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option
|
||||||
|
inlineGetter = 1
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:11:5: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option
|
||||||
|
inlineSetter = 1
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:13:5: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option
|
||||||
|
allInline
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:14:5: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option
|
||||||
|
allInline = 1
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:17:7: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option
|
||||||
|
a.inlineFun {}
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:18:7: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option
|
||||||
|
a.inlineGetter
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:19:7: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option
|
||||||
|
a.inlineGetter = 1
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:22:7: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option
|
||||||
|
a.inlineSetter = 1
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:24:7: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option
|
||||||
|
a.allInline
|
||||||
|
^
|
||||||
|
compiler/testData/compileKotlinAgainstCustomBinaries/wrongInlineTarget/source.kt:25:7: error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6. Please specify proper '-jvm-target' option
|
||||||
|
a.allInline = 1
|
||||||
|
^
|
||||||
|
COMPILATION_ERROR
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package usage
|
||||||
|
|
||||||
|
import a.*
|
||||||
|
|
||||||
|
fun baz() {
|
||||||
|
inlineFun {}
|
||||||
|
inlineGetter
|
||||||
|
inlineGetter = 1
|
||||||
|
|
||||||
|
inlineSetter
|
||||||
|
inlineSetter = 1
|
||||||
|
|
||||||
|
allInline
|
||||||
|
allInline = 1
|
||||||
|
|
||||||
|
val a = A()
|
||||||
|
a.inlineFun {}
|
||||||
|
a.inlineGetter
|
||||||
|
a.inlineGetter = 1
|
||||||
|
|
||||||
|
a.inlineSetter
|
||||||
|
a.inlineSetter = 1
|
||||||
|
|
||||||
|
a.allInline
|
||||||
|
a.allInline = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -83,13 +83,10 @@ class ReplCompilerJava8Test : TestCase() {
|
|||||||
val configuration = makeConfiguration().apply {
|
val configuration = makeConfiguration().apply {
|
||||||
put(JVMConfigurationKeys.JVM_TARGET, JvmTarget.JVM_1_6)
|
put(JVMConfigurationKeys.JVM_TARGET, JvmTarget.JVM_1_6)
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
runTest(configuration)
|
val result = runTest(configuration)
|
||||||
Assert.fail("Should fail due to bytecode incompatibility check")
|
Assert.assertTrue(result is ReplCompileResult.Error)
|
||||||
}
|
Assert.assertTrue((result as ReplCompileResult.Error).message.contains("error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6"))
|
||||||
catch (e: CompilationException) {
|
|
||||||
Assert.assertTrue(e.message!!.contains("This compiler can only inline Java 1.6 bytecode (version 50)"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -98,11 +95,9 @@ class ReplCompilerJava8Test : TestCase() {
|
|||||||
val configuration = makeConfiguration()
|
val configuration = makeConfiguration()
|
||||||
System.setProperty(KOTLIN_REPL_JVM_TARGET_PROPERTY, "1.6")
|
System.setProperty(KOTLIN_REPL_JVM_TARGET_PROPERTY, "1.6")
|
||||||
try {
|
try {
|
||||||
runTest(configuration)
|
val result = runTest(configuration)
|
||||||
Assert.fail("Should fail due to bytecode incompatibility check")
|
Assert.assertTrue(result is ReplCompileResult.Error)
|
||||||
}
|
Assert.assertTrue((result as ReplCompileResult.Error).message.contains("error: cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6"))
|
||||||
catch (e: CompilationException) {
|
|
||||||
Assert.assertTrue(e.message!!.contains("This compiler can only inline Java 1.6 bytecode (version 50)"))
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
System.clearProperty(KOTLIN_REPL_JVM_TARGET_PROPERTY)
|
System.clearProperty(KOTLIN_REPL_JVM_TARGET_PROPERTY)
|
||||||
|
|||||||
+18
-4
@@ -89,15 +89,19 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private File compileLibrary(@NotNull String sourcePath, @NotNull File... extraClassPath) {
|
private File compileLibrary(@NotNull String sourcePath, @NotNull File... extraClassPath) {
|
||||||
|
return compileLibrary(sourcePath, Collections.<String>emptyList(), extraClassPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private File compileLibrary(@NotNull String sourcePath, List<String> additionalOptions, @NotNull File... extraClassPath) {
|
||||||
File destination = new File(tmpdir, sourcePath + ".jar");
|
File destination = new File(tmpdir, sourcePath + ".jar");
|
||||||
compileLibrary(new K2JVMCompiler(), sourcePath, destination, extraClassPath);
|
compileLibrary(new K2JVMCompiler(), sourcePath, destination, additionalOptions, extraClassPath);
|
||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void compileLibrary(
|
private void compileLibrary(
|
||||||
@NotNull CLICompiler<?> compiler, @NotNull String sourcePath, @NotNull File destination, @NotNull File... extraClassPath
|
@NotNull CLICompiler<?> compiler, @NotNull String sourcePath, @NotNull File destination, List<String> additionalOptions, @NotNull File... extraClassPath
|
||||||
) {
|
) {
|
||||||
Pair<String, ExitCode> output = compileKotlin(compiler, sourcePath, destination, Collections.<String>emptyList(), extraClassPath);
|
Pair<String, ExitCode> output = compileKotlin(compiler, sourcePath, destination, additionalOptions, extraClassPath);
|
||||||
Assert.assertEquals(normalizeOutput(new Pair<String, ExitCode>("", ExitCode.OK)), normalizeOutput(output));
|
Assert.assertEquals(normalizeOutput(new Pair<String, ExitCode>("", ExitCode.OK)), normalizeOutput(output));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +328,7 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
System.setProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY, "true");
|
System.setProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY, "true");
|
||||||
compileLibrary(compiler, libraryName, destination);
|
compileLibrary(compiler, libraryName, destination, Collections.<String>emptyList());
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
System.clearProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY);
|
System.clearProperty(TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY);
|
||||||
@@ -629,4 +633,14 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir {
|
|||||||
Pair<String, ExitCode> output = compileKotlin("source.kt", tmpdir, library1);
|
Pair<String, ExitCode> output = compileKotlin("source.kt", tmpdir, library1);
|
||||||
KotlinTestUtils.assertEqualsToFile(new File(getTestDataDirectory(), "output.txt"), normalizeOutput(output));
|
KotlinTestUtils.assertEqualsToFile(new File(getTestDataDirectory(), "output.txt"), normalizeOutput(output));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testWrongInlineTarget() throws Exception {
|
||||||
|
File library = compileLibrary("library", Arrays.asList("-jvm-target", "1.8"));
|
||||||
|
|
||||||
|
Pair<String, ExitCode> outputMain = compileKotlin("source.kt", tmpdir, library);
|
||||||
|
|
||||||
|
KotlinTestUtils.assertEqualsToFile(
|
||||||
|
new File(getTestDataDirectory(), "output.txt"), normalizeOutput(outputMain)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,17 +17,36 @@
|
|||||||
package org.jetbrains.kotlin.config
|
package org.jetbrains.kotlin.config
|
||||||
|
|
||||||
import org.jetbrains.kotlin.utils.DescriptionAware
|
import org.jetbrains.kotlin.utils.DescriptionAware
|
||||||
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
|
|
||||||
enum class JvmTarget(override val description: String) : DescriptionAware {
|
enum class JvmTarget(override val description: String) : DescriptionAware {
|
||||||
JVM_1_6("1.6"),
|
JVM_1_6("1.6"),
|
||||||
JVM_1_8("1.8"),
|
JVM_1_8("1.8"),
|
||||||
;
|
;
|
||||||
|
|
||||||
|
val bytecodeVersion: Int
|
||||||
|
get() = when(this) {
|
||||||
|
JVM_1_6 -> Opcodes.V1_6
|
||||||
|
JVM_1_8 -> Opcodes.V1_8
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField
|
@JvmField
|
||||||
val DEFAULT = JVM_1_6
|
val DEFAULT = JVM_1_6
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun fromString(string: String) = values().find { it.description == string }
|
fun fromString(string: String) = values().find { it.description == string }
|
||||||
|
|
||||||
|
fun getDescription(bytecodeVersion: Int): String {
|
||||||
|
val platformDescription = values().find { it.bytecodeVersion == bytecodeVersion }?.description ?:
|
||||||
|
when (bytecodeVersion) {
|
||||||
|
Opcodes.V1_7 -> "1.7"
|
||||||
|
Opcodes.V1_8 + 1 -> "1.9"
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (platformDescription != null) "JVM target $platformDescription"
|
||||||
|
else "JVM bytecode version $bytecodeVersion"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user