Skip to content

Commit 1bb40af

Browse files
committed
Simplify compatibility mode with ll=1.0 on JDK dependent built-ins
A lot of problem arise with current solution (loading them with lowpriority annotation + additional call checkers): - We errorneously treated ArrayList.stream as an existing method, while it's just a fake override from List - The same problem arises when creating a class delegating to List. Also the latter case is failing with codegen internal error (see issue KT-16171) The negative side of this solution is that instead of reporting meaningful diagnostic, there will be UNRESOLVED_REFERENCE. But it seems to be better than having strange problems like ones described above. #KT-16073 Fixed #KT-16171 Fixed
1 parent d84c303 commit 1bb40af

File tree

7 files changed

+58
-120
lines changed

7 files changed

+58
-120
lines changed

compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/AdditionalBuiltInsMembersChecker.kt

Lines changed: 0 additions & 67 deletions
This file was deleted.

compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ object JvmPlatformConfigurator : PlatformConfigurator(
4444
TypeParameterBoundIsNotArrayChecker(),
4545
JvmSyntheticApplicabilityChecker(),
4646
StrictfpApplicabilityChecker(),
47-
AdditionalBuiltInsMemberOverrideDeclarationChecker,
4847
HeaderImplDeclarationChecker()
4948
),
5049

@@ -57,8 +56,7 @@ object JvmPlatformConfigurator : PlatformConfigurator(
5756
SuperCallWithDefaultArgumentsChecker(),
5857
MissingDependencyClassChecker,
5958
ProtectedSyntheticExtensionCallChecker,
60-
ReifiedTypeParameterSubstitutionChecker(),
61-
AdditionalBuiltInsMembersCallChecker
59+
ReifiedTypeParameterSubstitutionChecker()
6260
),
6361

6462
additionalTypeCheckers = listOf(
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// LANGUAGE_VERSION: 1.0
2+
// WITH_RUNTIME
3+
// FULL_JDK
4+
class A(val x: List<String>) : List<String> by x
5+
6+
fun box(): String {
7+
return A(listOf("OK"))[0]
8+
}

compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/unsupportedFeature.kt

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,53 @@
33
// SKIP_TXT
44

55
class A : java.util.ArrayList<String>() {
6-
override fun stream(): java.util.stream.Stream<String> = super.stream()
6+
// `stream` is defined in ArrayList, so it was impossible to override it in 1.0
7+
<!NOTHING_TO_OVERRIDE!>override<!> fun stream(): java.util.stream.Stream<String> = super.<!UNRESOLVED_REFERENCE!>stream<!>()
8+
9+
// `sort` is defined in ArrayList, so it was possible to override it in 1.0
10+
override fun sort(c: Comparator<in String>?) {
11+
super.sort(c)
12+
}
713
}
814

915
class A1 : java.util.ArrayList<String>() {
10-
fun stream(): java.util.stream.Stream<String> = super.stream()
16+
// `stream` is defined in ArrayList, so it was possible to declare it in 1.0 without an 'override' keyword
17+
fun stream(): java.util.stream.Stream<String> = super.<!UNRESOLVED_REFERENCE!>stream<!>()
18+
19+
// `sort` is defined in ArrayList, so it was impossible to declare it in 1.0 without an 'override' keyword
20+
<!VIRTUAL_MEMBER_HIDDEN!>fun sort(c: Comparator<in String>?)<!> {
21+
super.sort(c)
22+
}
1123
}
1224

1325
interface A2 : List<String> {
14-
<!UNSUPPORTED_FEATURE!>override<!> fun stream(): java.util.stream.Stream<String> = null!!
26+
<!NOTHING_TO_OVERRIDE!>override<!> fun stream(): java.util.stream.Stream<String> = null!!
27+
}
28+
29+
class B : <!NONE_APPLICABLE!>Throwable<!>("", null, false, false)
30+
31+
class B1 : RuntimeException() {
32+
<!NOTHING_TO_OVERRIDE!>override<!> fun fillInStackTrace(): Throwable { // 'override' keyword must be prohibited, as it was in 1.0.x
33+
return this
34+
}
1535
}
1636

17-
class B : <!UNSUPPORTED_FEATURE!>Throwable<!>("", null, false, false)
37+
class A3(val x: List<String>) : List<String> by x
1838

19-
fun Throwable.<!EXTENSION_SHADOWED_BY_MEMBER!>fillInStackTrace<!>() = 1
39+
fun Throwable.fillInStackTrace() = 1
2040

21-
fun foo(x: List<String>, y: Throwable) {
22-
x.<!UNSUPPORTED_FEATURE!>stream<!>()
23-
java.util.ArrayList<String>().stream()
41+
fun foo(x: List<String>, y: Throwable, z: A3) {
42+
x.<!UNRESOLVED_REFERENCE!>stream<!>()
43+
java.util.ArrayList<String>().<!UNRESOLVED_REFERENCE!>stream<!>()
2444

2545
y.fillInStackTrace() checkType { _<Int>() }
2646

2747
HashMap<String, Int>().getOrDefault(Any(), null)
2848

2949
// Falls back to extension in stdlib
3050
y.printStackTrace()
51+
52+
z.<!UNRESOLVED_REFERENCE!>stream<!>()
3153
}
3254

3355
interface X {

compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ public void testStream() throws Exception {
120120
doTest(fileName);
121121
}
122122

123+
@TestMetadata("streamBackwardCompatibility.kt")
124+
public void testStreamBackwardCompatibility() throws Exception {
125+
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/streamBackwardCompatibility.kt");
126+
doTest(fileName);
127+
}
128+
123129
@TestMetadata("useStream.kt")
124130
public void testUseStream() throws Exception {
125131
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/useStream.kt");

core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsSettings.kt

Lines changed: 12 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ import org.jetbrains.kotlin.builtins.CloneableClassScope
2121
import org.jetbrains.kotlin.builtins.JvmBuiltInClassDescriptorFactory
2222
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
2323
import org.jetbrains.kotlin.descriptors.*
24-
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
25-
import org.jetbrains.kotlin.descriptors.annotations.Annotations
2624
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
2725
import org.jetbrains.kotlin.descriptors.annotations.createDeprecatedAnnotation
2826
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
@@ -36,7 +34,6 @@ import org.jetbrains.kotlin.name.Name
3634
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
3735
import org.jetbrains.kotlin.platform.createMappedTypeParametersSubstitution
3836
import org.jetbrains.kotlin.resolve.OverridingUtil
39-
import org.jetbrains.kotlin.resolve.descriptorUtil.LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_FQ_NAME
4037
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
4138
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
4239
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
@@ -53,7 +50,6 @@ import org.jetbrains.kotlin.types.LazyWrappedType
5350
import org.jetbrains.kotlin.utils.DFS
5451
import org.jetbrains.kotlin.utils.SmartSet
5552
import org.jetbrains.kotlin.utils.addToStdlib.check
56-
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
5753
import java.io.Serializable
5854
import java.util.*
5955

@@ -82,22 +78,6 @@ open class JvmBuiltInsSettings(
8278
).let { AnnotationsImpl(listOf(it)) }
8379
}
8480

85-
private val lowPriorityAnnotation: Annotations by storageManager.createLazyValue {
86-
// We use both LowPriorityInOverloadResolution to achieve the following goal:
87-
// If there is something to resolve to beside an additional built-in member, it's *almost* always will win
88-
val lowPriorityAnnotation =
89-
ClassDescriptorImpl(
90-
moduleDescriptor.getPackage(LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_FQ_NAME.parent()), LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_FQ_NAME.shortName(),
91-
Modality.FINAL, ClassKind.ANNOTATION_CLASS, moduleDescriptor.builtIns.anyType.singletonList(),
92-
SourceElement.NO_SOURCE, /* isExternal = */ false
93-
).run {
94-
initialize(MemberScope.Empty, emptySet(), null)
95-
AnnotationDescriptorImpl(defaultType, emptyMap(), SourceElement.NO_SOURCE)
96-
}
97-
98-
AnnotationsImpl(listOf(lowPriorityAnnotation))
99-
}
100-
10181
private fun StorageManager.createMockJavaIoSerializableType(): KotlinType {
10282
val mockJavaIoPackageFragment = object : PackageFragmentDescriptorImpl(moduleDescriptor, FqName("java.io")) {
10383
override fun getMemberScope() = MemberScope.Empty
@@ -131,6 +111,8 @@ open class JvmBuiltInsSettings(
131111
))
132112
}
133113

114+
if (!isAdditionalBuiltInsFeatureSupported) return emptyList()
115+
134116
return getAdditionalFunctions(classDescriptor) {
135117
it.getContributedFunctions(name, NoLookupLocation.FROM_BUILTINS)
136118
}.mapNotNull {
@@ -156,31 +138,24 @@ open class JvmBuiltInsSettings(
156138
}
157139

158140
JDKMemberStatus.NOT_CONSIDERED -> {
159-
if (!isAdditionalBuiltInsFeatureSupported) {
160-
setAdditionalAnnotations(lowPriorityAnnotation)
161-
}
162-
else {
163-
setAdditionalAnnotations(notConsideredDeprecation)
164-
}
141+
setAdditionalAnnotations(notConsideredDeprecation)
165142
}
166143

167144
JDKMemberStatus.DROP -> return@mapNotNull null
168145

169-
JDKMemberStatus.WHITE_LIST -> {
170-
if (!isAdditionalBuiltInsFeatureSupported) {
171-
setAdditionalAnnotations(lowPriorityAnnotation)
172-
}
173-
}
146+
JDKMemberStatus.WHITE_LIST -> Unit // Do nothing
174147
}
175148

176149
}.build()!!
177150
}
178151
}
179152

180-
override fun getFunctionsNames(classDescriptor: DeserializedClassDescriptor): Set<Name> =
181-
// NB: It's just an approximation that could be calculated relatively fast
182-
// More precise computation would look like `getAdditionalFunctions` (and the measurements show that it would be rather slow)
183-
classDescriptor.getJavaAnalogue()?.unsubstitutedMemberScope?.getFunctionNames() ?: emptySet()
153+
override fun getFunctionsNames(classDescriptor: DeserializedClassDescriptor): Set<Name> {
154+
if (!isAdditionalBuiltInsFeatureSupported) return emptySet()
155+
// NB: It's just an approximation that could be calculated relatively fast
156+
// More precise computation would look like `getAdditionalFunctions` (and the measurements show that it would be rather slow)
157+
return classDescriptor.getJavaAnalogue()?.unsubstitutedMemberScope?.getFunctionNames() ?: emptySet()
158+
}
184159

185160
private fun getAdditionalFunctions(
186161
classDescriptor: DeserializedClassDescriptor,
@@ -287,7 +262,7 @@ open class JvmBuiltInsSettings(
287262
}
288263

289264
override fun getConstructors(classDescriptor: DeserializedClassDescriptor): Collection<ClassConstructorDescriptor> {
290-
if (classDescriptor.kind != ClassKind.CLASS) return emptyList()
265+
if (classDescriptor.kind != ClassKind.CLASS || !isAdditionalBuiltInsFeatureSupported) return emptyList()
291266

292267
val javaAnalogueDescriptor = classDescriptor.getJavaAnalogue() ?: return emptyList()
293268

@@ -314,11 +289,7 @@ open class JvmBuiltInsSettings(
314289
setReturnType(classDescriptor.defaultType)
315290
setPreserveSourceElement()
316291
setSubstitution(substitutor.substitution)
317-
318-
if (!isAdditionalBuiltInsFeatureSupported) {
319-
setAdditionalAnnotations(lowPriorityAnnotation)
320-
}
321-
else if (SignatureBuildingComponents.signature(javaAnalogueDescriptor, javaConstructor.computeJvmDescriptor()) !in WHITE_LIST_CONSTRUCTOR_SIGNATURES) {
292+
if (SignatureBuildingComponents.signature(javaAnalogueDescriptor, javaConstructor.computeJvmDescriptor()) !in WHITE_LIST_CONSTRUCTOR_SIGNATURES) {
322293
setAdditionalAnnotations(notConsideredDeprecation)
323294
}
324295

core/descriptors/src/org/jetbrains/kotlin/resolve/annotationsForResolve.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.types.KotlinType
2929

3030
private val NO_INFER_ANNOTATION_FQ_NAME = FqName("kotlin.internal.NoInfer")
3131
private val EXACT_ANNOTATION_FQ_NAME = FqName("kotlin.internal.Exact")
32-
val LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_FQ_NAME = FqName("kotlin.internal.LowPriorityInOverloadResolution")
32+
private val LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_FQ_NAME = FqName("kotlin.internal.LowPriorityInOverloadResolution")
3333
private val HIDES_MEMBERS_ANNOTATION_FQ_NAME = FqName("kotlin.internal.HidesMembers")
3434
private val ONLY_INPUT_TYPES_FQ_NAME = FqName("kotlin.internal.OnlyInputTypes")
3535
private val DYNAMIC_EXTENSION_FQ_NAME = FqName("kotlin.internal.DynamicExtension")

0 commit comments

Comments
 (0)