Report error on generating calls to binary incompatible classes

This commit is contained in:
Alexander Udalov
2016-01-13 22:11:23 +03:00
parent 4bd1d064bb
commit e17cd12c3c
15 changed files with 315 additions and 49 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.codegen.signature
import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker
import org.jetbrains.kotlin.codegen.state.JetTypeMapper
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
@@ -26,7 +27,8 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.KotlinToJvmSignatureMapper
class KotlinToJvmSignatureMapperImpl : KotlinToJvmSignatureMapper {
// We use empty BindingContext, because it is only used by JetTypeMapper for purposes irrelevant to the needs of this class
private val typeMapper: JetTypeMapper = JetTypeMapper(BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES, NoResolveFileClassesProvider, null, JvmAbi.DEFAULT_MODULE_NAME)
private val typeMapper = JetTypeMapper(BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES, NoResolveFileClassesProvider, null,
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME)
override fun mapToJvmMethodSignature(function: FunctionDescriptor) = typeMapper.mapSignature(function)
}
@@ -51,7 +51,8 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
) : SignatureCollectingClassBuilderFactory(builderFactory) {
// Avoid errors when some classes are not loaded for some reason
private val typeMapper = JetTypeMapper(bindingContext, ClassBuilderMode.LIGHT_CLASSES, fileClassesProvider, incrementalCache, moduleName)
private val typeMapper = JetTypeMapper(bindingContext, ClassBuilderMode.LIGHT_CLASSES, fileClassesProvider, incrementalCache,
IncompatibleClassTracker.DoNothing, moduleName)
private val reportDiagnosticsTasks = ArrayList<() -> Unit>()
fun reportDiagnostics() {
@@ -95,7 +95,7 @@ class GenerationState @JvmOverloads constructor(
incrementalCompilationComponents.getIncrementalCache(targetId)
else null
private val extraJvmDiagnosticsTrace: BindingTrace = DelegatingBindingTrace(bindingContext, false, "For extra diagnostics in ${this.javaClass}")
val extraJvmDiagnosticsTrace: BindingTrace = DelegatingBindingTrace(bindingContext, false, "For extra diagnostics in ${this.javaClass}")
private val interceptedBuilderFactory: ClassBuilderFactory
private var used = false
@@ -109,7 +109,10 @@ class GenerationState @JvmOverloads constructor(
val classBuilderMode: ClassBuilderMode = builderFactory.classBuilderMode
val bindingTrace: BindingTrace = DelegatingBindingTrace(bindingContext, "trace in GenerationState")
val bindingContext: BindingContext = bindingTrace.bindingContext
val typeMapper: JetTypeMapper = JetTypeMapper(this.bindingContext, classBuilderMode, fileClassesProvider, getIncrementalCacheForThisTarget(), this.moduleName)
val typeMapper: JetTypeMapper = JetTypeMapper(
this.bindingContext, classBuilderMode, fileClassesProvider, getIncrementalCacheForThisTarget(),
IncompatibleClassTrackerImpl(extraJvmDiagnosticsTrace), this.moduleName
)
val intrinsics: IntrinsicMethods = IntrinsicMethods()
val samWrapperClasses: SamWrapperClasses = SamWrapperClasses(this)
val inlineCycleReporter: InlineCycleReporter = InlineCycleReporter(diagnostics)
@@ -0,0 +1,48 @@
/*
* 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.state
import org.jetbrains.kotlin.load.java.components.IncompatibleVersionErrorData
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.util.slicedMap.Slices
import org.jetbrains.kotlin.util.slicedMap.WritableSlice
interface IncompatibleClassTracker {
fun record(binaryClass: KotlinJvmBinaryClass)
object DoNothing : IncompatibleClassTracker {
override fun record(binaryClass: KotlinJvmBinaryClass) {
}
}
}
class IncompatibleClassTrackerImpl(val trace: BindingTrace) : IncompatibleClassTracker {
private val classes = linkedSetOf<String>()
override fun record(binaryClass: KotlinJvmBinaryClass) {
if (classes.add(binaryClass.location)) {
val errorData = IncompatibleVersionErrorData(binaryClass.classHeader.bytecodeVersion, binaryClass.location, binaryClass.classId)
trace.record(BYTECODE_VERSION_ERRORS, binaryClass.location, errorData)
}
}
companion object {
@JvmField
val BYTECODE_VERSION_ERRORS: WritableSlice<String, IncompatibleVersionErrorData> = Slices.createCollectiveSlice()
}
}
@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.codegen.state;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import kotlin.collections.CollectionsKt;
import kotlin.Pair;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.BuiltinsPackageFragment;
@@ -38,10 +38,15 @@ import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature;
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion;
import org.jetbrains.kotlin.load.java.SpecialBuiltinMembers;
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment;
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageScope;
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass;
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryPackageSourceElement;
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement;
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider;
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache;
import org.jetbrains.kotlin.name.*;
@@ -66,6 +71,7 @@ import org.jetbrains.kotlin.resolve.scopes.AbstractScopeAdapter;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.serialization.deserialization.DeserializedType;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor;
import org.jetbrains.kotlin.types.*;
import org.jetbrains.kotlin.util.OperatorNameConventions;
import org.jetbrains.org.objectweb.asm.Type;
@@ -90,6 +96,7 @@ public class JetTypeMapper {
private final ClassBuilderMode classBuilderMode;
private final JvmFileClassesProvider fileClassesProvider;
private final IncrementalCache incrementalCache;
private final IncompatibleClassTracker incompatibleClassTracker;
private final String moduleName;
public JetTypeMapper(
@@ -97,12 +104,14 @@ public class JetTypeMapper {
@NotNull ClassBuilderMode classBuilderMode,
@NotNull JvmFileClassesProvider fileClassesProvider,
@Nullable IncrementalCache incrementalCache,
@NotNull IncompatibleClassTracker incompatibleClassTracker,
@NotNull String moduleName
) {
this.bindingContext = bindingContext;
this.classBuilderMode = classBuilderMode;
this.fileClassesProvider = fileClassesProvider;
this.incrementalCache = incrementalCache;
this.incompatibleClassTracker = incompatibleClassTracker;
this.moduleName = moduleName;
}
@@ -978,12 +987,17 @@ public class JetTypeMapper {
}
@NotNull
public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind,
List<ValueParameterDescriptor> valueParameters) {
public JvmMethodSignature mapSignature(
@NotNull FunctionDescriptor f,
@NotNull OwnerKind kind,
@NotNull List<ValueParameterDescriptor> valueParameters
) {
if (f instanceof FunctionImportedFromObject) {
return mapSignature(((FunctionImportedFromObject) f).getCallableFromObject());
}
checkOwnerCompatibility(f);
BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
if (f instanceof ConstructorDescriptor) {
@@ -1036,6 +1050,33 @@ public class JetTypeMapper {
return signature;
}
private void checkOwnerCompatibility(@NotNull FunctionDescriptor descriptor) {
if (!(descriptor instanceof DeserializedCallableMemberDescriptor)) return;
KotlinJvmBinaryClass ownerClass = null;
DeclarationDescriptor container = descriptor.getContainingDeclaration();
if (container instanceof DeserializedClassDescriptor) {
SourceElement source = ((DeserializedClassDescriptor) container).getSource();
if (source instanceof KotlinJvmBinarySourceElement) {
ownerClass = ((KotlinJvmBinarySourceElement) source).getBinaryClass();
}
}
else if (container instanceof LazyJavaPackageFragment) {
SourceElement source = ((LazyJavaPackageFragment) container).getSource();
if (source instanceof KotlinJvmBinaryPackageSourceElement) {
ownerClass = ((KotlinJvmBinaryPackageSourceElement) source).getRepresentativeBinaryClass();
}
}
if (ownerClass != null) {
JvmBytecodeBinaryVersion version = ownerClass.getClassHeader().getBytecodeVersion();
if (!version.isCompatible()) {
incompatibleClassTracker.record(ownerClass);
}
}
}
private boolean writeCustomParameter(
@NotNull FunctionDescriptor f,
@NotNull ValueParameterDescriptor parameter,