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
This commit is contained in:
Denis Zharkov
2017-02-07 18:59:25 +03:00
parent d84c303029
commit 1bb40afada
7 changed files with 58 additions and 120 deletions
@@ -1,67 +0,0 @@
/*
* 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.resolve.jvm.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
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.checkers.DeclarationChecker
object AdditionalBuiltInsMembersCallChecker : CallChecker {
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
if (context.languageVersionSettings.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)) return
val resultingDescriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return
if (resultingDescriptor.isAdditionalBuiltInMember()) {
context.trace.report(Errors.UNSUPPORTED_FEATURE.on(reportOn, LanguageFeature.AdditionalBuiltInsMembers))
}
}
}
object AdditionalBuiltInsMemberOverrideDeclarationChecker : DeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext,
languageVersionSettings: LanguageVersionSettings
) {
if (languageVersionSettings.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)) return
val resultingDescriptor = descriptor as? CallableMemberDescriptor ?: return
val overrideKeyword = declaration.modifierList?.getModifier(KtTokens.OVERRIDE_KEYWORD) ?: return
val overriddenDescriptors = resultingDescriptor.original.overriddenDescriptors
if (overriddenDescriptors.isNotEmpty() && overriddenDescriptors.all { it.isAdditionalBuiltInMember() }) {
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(overrideKeyword, LanguageFeature.AdditionalBuiltInsMembers))
}
}
}
private fun CallableMemberDescriptor.isAdditionalBuiltInMember() =
KotlinBuiltIns.isBuiltIn(this) && this is JavaCallableMemberDescriptor
@@ -44,7 +44,6 @@ object JvmPlatformConfigurator : PlatformConfigurator(
TypeParameterBoundIsNotArrayChecker(),
JvmSyntheticApplicabilityChecker(),
StrictfpApplicabilityChecker(),
AdditionalBuiltInsMemberOverrideDeclarationChecker,
HeaderImplDeclarationChecker()
),
@@ -57,8 +56,7 @@ object JvmPlatformConfigurator : PlatformConfigurator(
SuperCallWithDefaultArgumentsChecker(),
MissingDependencyClassChecker,
ProtectedSyntheticExtensionCallChecker,
ReifiedTypeParameterSubstitutionChecker(),
AdditionalBuiltInsMembersCallChecker
ReifiedTypeParameterSubstitutionChecker()
),
additionalTypeCheckers = listOf(
@@ -0,0 +1,8 @@
// LANGUAGE_VERSION: 1.0
// WITH_RUNTIME
// FULL_JDK
class A(val x: List<String>) : List<String> by x
fun box(): String {
return A(listOf("OK"))[0]
}
@@ -3,24 +3,44 @@
// SKIP_TXT
class A : java.util.ArrayList<String>() {
override fun stream(): java.util.stream.Stream<String> = super.stream()
// `stream` is defined in ArrayList, so it was impossible to override it in 1.0
<!NOTHING_TO_OVERRIDE!>override<!> fun stream(): java.util.stream.Stream<String> = super.<!UNRESOLVED_REFERENCE!>stream<!>()
// `sort` is defined in ArrayList, so it was possible to override it in 1.0
override fun sort(c: Comparator<in String>?) {
super.sort(c)
}
}
class A1 : java.util.ArrayList<String>() {
fun stream(): java.util.stream.Stream<String> = super.stream()
// `stream` is defined in ArrayList, so it was possible to declare it in 1.0 without an 'override' keyword
fun stream(): java.util.stream.Stream<String> = super.<!UNRESOLVED_REFERENCE!>stream<!>()
// `sort` is defined in ArrayList, so it was impossible to declare it in 1.0 without an 'override' keyword
<!VIRTUAL_MEMBER_HIDDEN!>fun sort(c: Comparator<in String>?)<!> {
super.sort(c)
}
}
interface A2 : List<String> {
<!UNSUPPORTED_FEATURE!>override<!> fun stream(): java.util.stream.Stream<String> = null!!
<!NOTHING_TO_OVERRIDE!>override<!> fun stream(): java.util.stream.Stream<String> = null!!
}
class B : <!UNSUPPORTED_FEATURE!>Throwable<!>("", null, false, false)
class B : <!NONE_APPLICABLE!>Throwable<!>("", null, false, false)
fun Throwable.<!EXTENSION_SHADOWED_BY_MEMBER!>fillInStackTrace<!>() = 1
class B1 : RuntimeException() {
<!NOTHING_TO_OVERRIDE!>override<!> fun fillInStackTrace(): Throwable { // 'override' keyword must be prohibited, as it was in 1.0.x
return this
}
}
fun foo(x: List<String>, y: Throwable) {
x.<!UNSUPPORTED_FEATURE!>stream<!>()
java.util.ArrayList<String>().stream()
class A3(val x: List<String>) : List<String> by x
fun Throwable.fillInStackTrace() = 1
fun foo(x: List<String>, y: Throwable, z: A3) {
x.<!UNRESOLVED_REFERENCE!>stream<!>()
java.util.ArrayList<String>().<!UNRESOLVED_REFERENCE!>stream<!>()
y.fillInStackTrace() checkType { _<Int>() }
@@ -28,6 +48,8 @@ fun foo(x: List<String>, y: Throwable) {
// Falls back to extension in stdlib
y.printStackTrace()
z.<!UNRESOLVED_REFERENCE!>stream<!>()
}
interface X {
@@ -120,6 +120,12 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg
doTest(fileName);
}
@TestMetadata("streamBackwardCompatibility.kt")
public void testStreamBackwardCompatibility() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/streamBackwardCompatibility.kt");
doTest(fileName);
}
@TestMetadata("useStream.kt")
public void testUseStream() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/useStream.kt");