[FIR] Properly set isOperator flag for java functions
^KT-56875 Fixed
This commit is contained in:
committed by
Space Team
parent
df47581c5a
commit
244dbb37cf
+6
@@ -1083,6 +1083,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/extensionInvokeAfterSafeCall.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incorrectPlusOperatorFromJava.kt")
|
||||
public void testIncorrectPlusOperatorFromJava() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/incorrectPlusOperatorFromJava.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invokeAmbiguity.kt")
|
||||
public void testInvokeAmbiguity() throws Exception {
|
||||
|
||||
+5
@@ -933,6 +933,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/extensionInvokeAfterSafeCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("incorrectPlusOperatorFromJava.kt")
|
||||
public void testIncorrectPlusOperatorFromJava() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/incorrectPlusOperatorFromJava.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invokeAmbiguity.kt")
|
||||
public void testInvokeAmbiguity() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/invokeAmbiguity.kt");
|
||||
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
FILE: main.kt
|
||||
public final operator fun R|Base|.plus(s: R|kotlin/String|): R|kotlin/Int| {
|
||||
^plus Int(0)
|
||||
}
|
||||
public final class Derived : R|Base| {
|
||||
public constructor(): R|Derived| {
|
||||
super<R|Base|>()
|
||||
}
|
||||
|
||||
public final fun test_1(x: R|Base|): R|kotlin/Unit| {
|
||||
lval y: R|kotlin/Int| = R|<local>/x|.R|/plus|(String())
|
||||
R|<local>/y|.R|kotlin/Int.inc|()
|
||||
}
|
||||
|
||||
public final fun test_2(x: R|Base|): R|kotlin/Unit| {
|
||||
lval y: R|kotlin/String!| = R|<local>/x|.R|/Base.plus|(vararg(String()))
|
||||
R|<local>/y|.R|kotlin/String.length|
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
// ISSUE: KT-56875
|
||||
// FILE: Base.java
|
||||
public class Base {
|
||||
public String plus(String... strings) { // (1)
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
operator fun Base.plus(s: String): Int = 0 // (2)
|
||||
|
||||
class Derived : Base() {
|
||||
fun test_1(x: Base) {
|
||||
val y = x + "" // should resolve to (2)
|
||||
y.inc() // should be ok
|
||||
}
|
||||
|
||||
fun test_2(x: Base) {
|
||||
val y = x.plus("") // should resolve to (1)
|
||||
y.length // should be ok
|
||||
}
|
||||
}
|
||||
+6
@@ -1083,6 +1083,12 @@ public class FirLightTreeDiagnosticsTestGenerated extends AbstractFirLightTreeDi
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/extensionInvokeAfterSafeCall.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incorrectPlusOperatorFromJava.kt")
|
||||
public void testIncorrectPlusOperatorFromJava() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/incorrectPlusOperatorFromJava.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invokeAmbiguity.kt")
|
||||
public void testInvokeAmbiguity() throws Exception {
|
||||
|
||||
+6
@@ -1083,6 +1083,12 @@ public class FirPsiDiagnosticTestGenerated extends AbstractFirPsiDiagnosticTest
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/extensionInvokeAfterSafeCall.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incorrectPlusOperatorFromJava.kt")
|
||||
public void testIncorrectPlusOperatorFromJava() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/callResolution/incorrectPlusOperatorFromJava.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invokeAmbiguity.kt")
|
||||
public void testInvokeAmbiguity() throws Exception {
|
||||
|
||||
@@ -189,20 +189,7 @@ fun FirNamedFunctionSymbol.overriddenFunctions(
|
||||
containingClass: FirClassSymbol<*>,
|
||||
context: CheckerContext
|
||||
): List<FirFunctionSymbol<*>> {
|
||||
val firTypeScope = containingClass.unsubstitutedScope(
|
||||
context.sessionHolder.session,
|
||||
context.sessionHolder.scopeSession,
|
||||
withForcedTypeCalculator = true
|
||||
)
|
||||
|
||||
val overriddenFunctions = mutableListOf<FirFunctionSymbol<*>>()
|
||||
firTypeScope.processFunctionsByName(callableId.callableName) { }
|
||||
firTypeScope.processOverriddenFunctions(this) {
|
||||
overriddenFunctions.add(it)
|
||||
ProcessorAction.NEXT
|
||||
}
|
||||
|
||||
return overriddenFunctions
|
||||
return overriddenFunctions(containingClass, context.session, context.scopeSession)
|
||||
}
|
||||
|
||||
fun FirClass.collectSupertypesWithDelegates(): Map<FirTypeRef, FirFieldSymbol?> {
|
||||
|
||||
+4
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.resolve.ImplicitReceiverStack
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.SessionHolder
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||
|
||||
@@ -47,6 +48,9 @@ abstract class CheckerContext : DiagnosticContext {
|
||||
val session: FirSession
|
||||
get() = sessionHolder.session
|
||||
|
||||
val scopeSession: ScopeSession
|
||||
get() = sessionHolder.scopeSession
|
||||
|
||||
override fun isDiagnosticSuppressed(diagnostic: KtDiagnostic): Boolean {
|
||||
val factory = diagnostic.factory
|
||||
val name = factory.name
|
||||
|
||||
+10
-203
@@ -9,49 +9,16 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.Checks.Returns
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.Checks.ValueParametersCount
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.Checks.isKProperty
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.Checks.member
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.Checks.memberOrExtension
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.Checks.noDefaultAndVarargs
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.hasModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isSupertypeOf
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.overriddenFunctions
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||
import org.jetbrains.kotlin.fir.declarations.CheckResult
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInline
|
||||
import org.jetbrains.kotlin.fir.declarations.OperatorFunctionChecks
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.name.isSubpackageOf
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.ASSIGNMENT_OPERATIONS
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.BINARY_OPERATION_NAMES
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.COMPARE_TO
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.COMPONENT_REGEX
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.CONTAINS
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.DEC
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.EQUALS
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.GET
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.GET_VALUE
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.HAS_NEXT
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.INC
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.INVOKE
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.ITERATOR
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.NEXT
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.PROVIDE_DELEGATE
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.RANGE_TO
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.RANGE_UNTIL
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.SET
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.SET_VALUE
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions.SIMPLE_UNARY_OPERATION_NAMES
|
||||
|
||||
|
||||
object FirOperatorModifierChecker : FirSimpleFunctionChecker() {
|
||||
@@ -61,18 +28,14 @@ object FirOperatorModifierChecker : FirSimpleFunctionChecker() {
|
||||
//we are not interested in implicit operators from override
|
||||
if (!declaration.hasModifier(KtTokens.OPERATOR_KEYWORD)) return
|
||||
|
||||
val checks = OperatorFunctionChecks.checksByName.getOrElse(declaration.name) {
|
||||
OperatorFunctionChecks.regexChecks.find { it.first.matches(declaration.name.asString()) }?.second
|
||||
}
|
||||
|
||||
if (checks == null) {
|
||||
reporter.reportOn(declaration.source, FirErrors.INAPPLICABLE_OPERATOR_MODIFIER, "illegal function name", context)
|
||||
return
|
||||
}
|
||||
|
||||
for (check in checks) {
|
||||
check.check(context, declaration)?.let { error ->
|
||||
reporter.reportOn(declaration.source, FirErrors.INAPPLICABLE_OPERATOR_MODIFIER, error, context)
|
||||
when (val checkResult = OperatorFunctionChecks.isOperator(declaration, context.session, context.scopeSession)) {
|
||||
CheckResult.SuccessCheck -> {}
|
||||
CheckResult.IllegalFunctionName -> {
|
||||
reporter.reportOn(declaration.source, FirErrors.INAPPLICABLE_OPERATOR_MODIFIER, "illegal function name", context)
|
||||
return
|
||||
}
|
||||
is CheckResult.IllegalSignature -> {
|
||||
reporter.reportOn(declaration.source, FirErrors.INAPPLICABLE_OPERATOR_MODIFIER, checkResult.error, context)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -95,159 +58,3 @@ object FirOperatorModifierChecker : FirSimpleFunctionChecker() {
|
||||
reporter.reportOn(declaration.source, diagnostic, declaration.symbol, replacement.asString(), context)
|
||||
}
|
||||
}
|
||||
|
||||
private interface Check : (CheckerContext, FirSimpleFunction) -> String? {
|
||||
override fun invoke(p1: CheckerContext, p2: FirSimpleFunction): String? {
|
||||
return check(p1, p2)
|
||||
}
|
||||
|
||||
fun check(context: CheckerContext, function: FirSimpleFunction): String?
|
||||
}
|
||||
|
||||
private object Checks {
|
||||
fun simple(message: String, predicate: (FirSimpleFunction) -> Boolean) = object : Check {
|
||||
override fun check(context: CheckerContext, function: FirSimpleFunction): String? = message.takeIf { !predicate(function) }
|
||||
}
|
||||
|
||||
fun full(message: String, predicate: (CheckerContext, FirSimpleFunction) -> Boolean) = object : Check {
|
||||
override fun check(context: CheckerContext, function: FirSimpleFunction): String? = message.takeIf { !predicate(context, function) }
|
||||
}
|
||||
|
||||
val memberOrExtension = simple("must be a member or an extension function") {
|
||||
it.dispatchReceiverType != null || it.receiverParameter != null
|
||||
}
|
||||
|
||||
val member = simple("must be a member function") {
|
||||
it.dispatchReceiverType != null
|
||||
}
|
||||
|
||||
object ValueParametersCount {
|
||||
fun atLeast(n: Int) = simple("must have at least $n value parameter" + (if (n > 1) "s" else "")) {
|
||||
it.valueParameters.size >= n
|
||||
}
|
||||
|
||||
fun exactly(n: Int) = simple("must have exactly $n value parameters") {
|
||||
it.valueParameters.size == n
|
||||
}
|
||||
|
||||
val single = simple("must have a single value parameter") {
|
||||
it.valueParameters.size == 1
|
||||
}
|
||||
val none = simple("must have no value parameters") {
|
||||
it.valueParameters.isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
object Returns {
|
||||
val boolean = simple("must return Boolean") {
|
||||
it.returnTypeRef.isBoolean
|
||||
}
|
||||
|
||||
val int = simple("must return Int") {
|
||||
it.returnTypeRef.isInt
|
||||
}
|
||||
|
||||
val unit = simple("must return Unit") {
|
||||
it.returnTypeRef.isUnit
|
||||
}
|
||||
}
|
||||
|
||||
val noDefaultAndVarargs = simple("should not have varargs or parameters with default values") {
|
||||
it.valueParameters.all { param ->
|
||||
param.defaultValue == null && !param.isVararg
|
||||
}
|
||||
}
|
||||
|
||||
val isKProperty = full("second parameter must be of type KProperty<*> or its supertype") { ctx, function ->
|
||||
val paramType = function.valueParameters[1].returnTypeRef.coneType
|
||||
paramType.isSupertypeOf(
|
||||
ctx.session.typeContext,
|
||||
ConeClassLikeTypeImpl(
|
||||
StandardClassIds.KProperty.toLookupTag(),
|
||||
arrayOf(ConeStarProjection),
|
||||
isNullable = false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private object OperatorFunctionChecks {
|
||||
|
||||
//reimplementation of org.jetbrains.kotlin.util.OperatorChecks for FIR
|
||||
val checksByName: Map<Name, List<Check>> = buildMap {
|
||||
checkFor(GET, memberOrExtension, ValueParametersCount.atLeast(1))
|
||||
checkFor(
|
||||
SET,
|
||||
memberOrExtension, ValueParametersCount.atLeast(2),
|
||||
Checks.simple("last parameter should not have a default value or be a vararg") {
|
||||
it.valueParameters.lastOrNull()?.let { param ->
|
||||
param.defaultValue == null && !param.isVararg
|
||||
} == true
|
||||
}
|
||||
)
|
||||
checkFor(GET_VALUE, memberOrExtension, noDefaultAndVarargs, ValueParametersCount.atLeast(2), isKProperty)
|
||||
checkFor(SET_VALUE, memberOrExtension, noDefaultAndVarargs, ValueParametersCount.atLeast(3), isKProperty)
|
||||
checkFor(PROVIDE_DELEGATE, memberOrExtension, noDefaultAndVarargs, ValueParametersCount.exactly(2), isKProperty)
|
||||
checkFor(INVOKE, memberOrExtension)
|
||||
checkFor(CONTAINS, memberOrExtension, ValueParametersCount.single, noDefaultAndVarargs, Returns.boolean)
|
||||
checkFor(ITERATOR, memberOrExtension, ValueParametersCount.none)
|
||||
checkFor(NEXT, memberOrExtension, ValueParametersCount.none)
|
||||
checkFor(HAS_NEXT, memberOrExtension, ValueParametersCount.none, Returns.boolean)
|
||||
checkFor(RANGE_TO, memberOrExtension, ValueParametersCount.single, noDefaultAndVarargs)
|
||||
checkFor(RANGE_UNTIL, memberOrExtension, ValueParametersCount.single, noDefaultAndVarargs)
|
||||
checkFor(
|
||||
EQUALS,
|
||||
member,
|
||||
object : Check {
|
||||
override fun check(context: CheckerContext, function: FirSimpleFunction): String? {
|
||||
val containingClassSymbol = function.containingClassLookupTag()?.toFirRegularClassSymbol(context.session) ?: return null
|
||||
val customEqualsSupported = context.languageVersionSettings.supportsFeature(LanguageFeature.CustomEqualsInValueClasses)
|
||||
|
||||
if (function.overriddenFunctions(containingClassSymbol, context)
|
||||
.any { it.containingClassLookupTag()?.classId == StandardClassIds.Any }
|
||||
|| (customEqualsSupported && function.isTypedEqualsInValueClass(context.session))
|
||||
) {
|
||||
return null
|
||||
}
|
||||
return buildString {
|
||||
append("must override ''equals()'' in Any")
|
||||
if (customEqualsSupported && containingClassSymbol.isInline) {
|
||||
val expectedParameterTypeRendered =
|
||||
containingClassSymbol.defaultType().replaceArgumentsWithStarProjections().renderReadable();
|
||||
append(" or define ''equals(other: ${expectedParameterTypeRendered}): Boolean''")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
checkFor(COMPARE_TO, memberOrExtension, Returns.int, ValueParametersCount.single, noDefaultAndVarargs)
|
||||
checkFor(BINARY_OPERATION_NAMES, memberOrExtension, ValueParametersCount.single, noDefaultAndVarargs)
|
||||
checkFor(SIMPLE_UNARY_OPERATION_NAMES, memberOrExtension, ValueParametersCount.none)
|
||||
checkFor(
|
||||
setOf(INC, DEC),
|
||||
memberOrExtension,
|
||||
Checks.full("receiver must be a supertype of the return type") { ctx, function ->
|
||||
val receiver = function.dispatchReceiverType ?: function.receiverParameter?.typeRef?.coneType ?: return@full false
|
||||
function.returnTypeRef.coneType.isSubtypeOf(ctx.session.typeContext, receiver)
|
||||
}
|
||||
)
|
||||
checkFor(ASSIGNMENT_OPERATIONS, memberOrExtension, Returns.unit, ValueParametersCount.single, noDefaultAndVarargs)
|
||||
}
|
||||
|
||||
val regexChecks: List<Pair<Regex, List<Check>>> = buildList {
|
||||
checkFor(COMPONENT_REGEX, memberOrExtension, ValueParametersCount.none)
|
||||
}
|
||||
|
||||
private fun MutableMap<Name, List<Check>>.checkFor(name: Name, vararg checks: Check) {
|
||||
put(name, checks.asList())
|
||||
}
|
||||
|
||||
private fun MutableMap<Name, List<Check>>.checkFor(names: Set<Name>, vararg checks: Check) {
|
||||
names.forEach { put(it, checks.asList()) }
|
||||
}
|
||||
|
||||
private fun MutableList<Pair<Regex, List<Check>>>.checkFor(regex: Regex, vararg checks: Check) {
|
||||
add(regex to checks.asList())
|
||||
}
|
||||
}
|
||||
|
||||
-17
@@ -10,17 +10,12 @@ import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.modality
|
||||
import org.jetbrains.kotlin.fir.containingClassForStaticMemberAttr
|
||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
internal fun isInsideExpectClass(containingClass: FirClass, context: CheckerContext): Boolean {
|
||||
return isInsideSpecificClass(containingClass, context) { klass -> klass is FirRegularClass && klass.isExpect }
|
||||
@@ -110,18 +105,6 @@ fun FirClassSymbol<*>.primaryConstructorSymbol(): FirConstructorSymbol? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun FirSimpleFunction.isTypedEqualsInValueClass(session: FirSession): Boolean =
|
||||
containingClassLookupTag()?.toFirRegularClassSymbol(session)?.run {
|
||||
val valueClassStarProjection = this@run.defaultType().replaceArgumentsWithStarProjections()
|
||||
with(this@isTypedEqualsInValueClass) {
|
||||
contextReceivers.isEmpty() && receiverParameter == null
|
||||
&& name == OperatorNameConventions.EQUALS
|
||||
&& this@run.isInline && valueParameters.size == 1
|
||||
&& (returnTypeRef.isBoolean || returnTypeRef.isNothing)
|
||||
&& valueParameters[0].returnTypeRef.coneType.let { it is ConeClassLikeType && it.replaceArgumentsWithStarProjections() == valueClassStarProjection }
|
||||
}
|
||||
} ?: false
|
||||
|
||||
fun FirTypeRef.needsMultiFieldValueClassFlattening(session: FirSession) = with(session.typeContext) {
|
||||
coneType.typeConstructor().isMultiFieldValueClass() && !coneType.isNullable
|
||||
}
|
||||
|
||||
@@ -569,9 +569,6 @@ abstract class FirJavaFacade(
|
||||
javaMethod.visibility.toEffectiveVisibility(dispatchReceiver.lookupTag)
|
||||
).apply {
|
||||
isStatic = javaMethod.isStatic
|
||||
// Approximation: all Java methods with name that allows to use it in operator form are considered operators
|
||||
// We need here more detailed checks (see modifierChecks.kt)
|
||||
isOperator = name in ALL_JAVA_OPERATION_NAMES || OperatorNameConventions.COMPONENT_REGEX.matches(name.asString())
|
||||
hasStableParameterNames = false
|
||||
}
|
||||
|
||||
|
||||
+10
-1
@@ -25,8 +25,8 @@ import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.unexpandedClassId
|
||||
import org.jetbrains.kotlin.fir.java.*
|
||||
import org.jetbrains.kotlin.fir.java.FirJavaTypeConversionMode
|
||||
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
|
||||
import org.jetbrains.kotlin.fir.java.declarations.*
|
||||
import org.jetbrains.kotlin.fir.java.resolveIfJavaType
|
||||
import org.jetbrains.kotlin.fir.java.symbols.FirJavaOverriddenSyntheticPropertySymbol
|
||||
@@ -339,11 +339,20 @@ class FirSignatureEnhancement(
|
||||
if (isJavaRecordComponent) {
|
||||
this.isJavaRecordComponent = true
|
||||
}
|
||||
updateIsOperatorFlagIfNeeded(this)
|
||||
}
|
||||
|
||||
return function.symbol
|
||||
}
|
||||
|
||||
private fun updateIsOperatorFlagIfNeeded(function: FirFunction) {
|
||||
if (function !is FirSimpleFunction) return
|
||||
val isOperator = OperatorFunctionChecks.isOperator(function, session, scopeSession = null).isSuccess
|
||||
if (!isOperator) return
|
||||
val newStatus = function.status.copy(isOperator = true)
|
||||
function.replaceStatus(newStatus)
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform first time initialization of bounds with FirResolvedTypeRef instances
|
||||
* But after that bounds are still not enhanced and more over might have not totally correct raw types bounds
|
||||
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.declarations
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInline
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.scopes.overriddenFunctions
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
sealed class CheckResult(val isSuccess: Boolean) {
|
||||
class IllegalSignature(val error: String) : CheckResult(false)
|
||||
object IllegalFunctionName : CheckResult(false)
|
||||
object SuccessCheck : CheckResult(true)
|
||||
}
|
||||
|
||||
object OperatorFunctionChecks {
|
||||
fun isOperator(function: FirSimpleFunction, session: FirSession, scopeSession: ScopeSession?): CheckResult {
|
||||
val checks = checksByName.getOrElse(function.name) {
|
||||
regexChecks.find { it.first.matches(function.name.asString()) }?.second
|
||||
} ?: return CheckResult.IllegalFunctionName
|
||||
|
||||
for (check in checks) {
|
||||
check.check(function, session, scopeSession)?.let { return CheckResult.IllegalSignature(it) }
|
||||
}
|
||||
return CheckResult.SuccessCheck
|
||||
}
|
||||
|
||||
//reimplementation of org.jetbrains.kotlin.util.OperatorChecks for FIR
|
||||
private val checksByName: Map<Name, List<Check>> = buildMap {
|
||||
checkFor(OperatorNameConventions.GET, Checks.memberOrExtension, Checks.ValueParametersCount.atLeast(1))
|
||||
checkFor(
|
||||
OperatorNameConventions.SET,
|
||||
Checks.memberOrExtension, Checks.ValueParametersCount.atLeast(2),
|
||||
Checks.simple("last parameter should not have a default value or be a vararg") {
|
||||
it.valueParameters.lastOrNull()?.let { param ->
|
||||
param.defaultValue == null && !param.isVararg
|
||||
} == true
|
||||
}
|
||||
)
|
||||
checkFor(
|
||||
OperatorNameConventions.GET_VALUE,
|
||||
Checks.memberOrExtension,
|
||||
Checks.noDefaultAndVarargs, Checks.ValueParametersCount.atLeast(2),
|
||||
Checks.isKProperty
|
||||
)
|
||||
checkFor(
|
||||
OperatorNameConventions.SET_VALUE,
|
||||
Checks.memberOrExtension,
|
||||
Checks.noDefaultAndVarargs, Checks.ValueParametersCount.atLeast(3),
|
||||
Checks.isKProperty
|
||||
)
|
||||
checkFor(
|
||||
OperatorNameConventions.PROVIDE_DELEGATE,
|
||||
Checks.memberOrExtension,
|
||||
Checks.noDefaultAndVarargs, Checks.ValueParametersCount.exactly(2),
|
||||
Checks.isKProperty
|
||||
)
|
||||
checkFor(OperatorNameConventions.INVOKE, Checks.memberOrExtension)
|
||||
checkFor(
|
||||
OperatorNameConventions.CONTAINS,
|
||||
Checks.memberOrExtension, Checks.ValueParametersCount.single,
|
||||
Checks.noDefaultAndVarargs, Checks.Returns.boolean
|
||||
)
|
||||
checkFor(OperatorNameConventions.ITERATOR, Checks.memberOrExtension, Checks.ValueParametersCount.none)
|
||||
checkFor(OperatorNameConventions.NEXT, Checks.memberOrExtension, Checks.ValueParametersCount.none)
|
||||
checkFor(OperatorNameConventions.HAS_NEXT, Checks.memberOrExtension, Checks.ValueParametersCount.none, Checks.Returns.boolean)
|
||||
checkFor(OperatorNameConventions.RANGE_TO, Checks.memberOrExtension, Checks.ValueParametersCount.single, Checks.noDefaultAndVarargs)
|
||||
checkFor(
|
||||
OperatorNameConventions.RANGE_UNTIL,
|
||||
Checks.memberOrExtension, Checks.ValueParametersCount.single,
|
||||
Checks.noDefaultAndVarargs
|
||||
)
|
||||
checkFor(
|
||||
OperatorNameConventions.EQUALS,
|
||||
Checks.member,
|
||||
object : Check() {
|
||||
override fun check(function: FirSimpleFunction, session: FirSession, scopeSession: ScopeSession?): String? {
|
||||
if (scopeSession == null) return null
|
||||
val containingClassSymbol = function.containingClassLookupTag()?.toFirRegularClassSymbol(session) ?: return null
|
||||
val customEqualsSupported = session.languageVersionSettings.supportsFeature(LanguageFeature.CustomEqualsInValueClasses)
|
||||
|
||||
if (function.symbol.overriddenFunctions(containingClassSymbol, session, scopeSession)
|
||||
.any { it.containingClassLookupTag()?.classId == StandardClassIds.Any }
|
||||
|| (customEqualsSupported && function.isTypedEqualsInValueClass(session))
|
||||
) {
|
||||
return null
|
||||
}
|
||||
return buildString {
|
||||
append("must override ''equals()'' in Any")
|
||||
if (customEqualsSupported && containingClassSymbol.isInline) {
|
||||
val expectedParameterTypeRendered =
|
||||
containingClassSymbol.defaultType().replaceArgumentsWithStarProjections().renderReadable()
|
||||
append(" or define ''equals(other: ${expectedParameterTypeRendered}): Boolean''")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
checkFor(
|
||||
OperatorNameConventions.COMPARE_TO,
|
||||
Checks.memberOrExtension, Checks.Returns.int, Checks.ValueParametersCount.single,
|
||||
Checks.noDefaultAndVarargs
|
||||
)
|
||||
checkFor(
|
||||
OperatorNameConventions.BINARY_OPERATION_NAMES,
|
||||
Checks.memberOrExtension, Checks.ValueParametersCount.single,
|
||||
Checks.noDefaultAndVarargs
|
||||
)
|
||||
checkFor(OperatorNameConventions.SIMPLE_UNARY_OPERATION_NAMES, Checks.memberOrExtension, Checks.ValueParametersCount.none)
|
||||
checkFor(
|
||||
setOf(OperatorNameConventions.INC, OperatorNameConventions.DEC),
|
||||
Checks.memberOrExtension,
|
||||
Checks.full("receiver must be a supertype of the return type") { session, function ->
|
||||
val receiver = function.dispatchReceiverType ?: function.receiverParameter?.typeRef?.coneType ?: return@full false
|
||||
function.returnTypeRef.coneType.isSubtypeOf(session.typeContext, receiver)
|
||||
}
|
||||
)
|
||||
checkFor(
|
||||
OperatorNameConventions.ASSIGNMENT_OPERATIONS,
|
||||
Checks.memberOrExtension, Checks.Returns.unit, Checks.ValueParametersCount.single,
|
||||
Checks.noDefaultAndVarargs
|
||||
)
|
||||
}
|
||||
|
||||
private val regexChecks: List<Pair<Regex, List<Check>>> = buildList {
|
||||
checkFor(OperatorNameConventions.COMPONENT_REGEX, Checks.memberOrExtension, Checks.ValueParametersCount.none)
|
||||
}
|
||||
|
||||
private fun MutableMap<Name, List<Check>>.checkFor(name: Name, vararg checks: Check) {
|
||||
put(name, checks.asList())
|
||||
}
|
||||
|
||||
private fun MutableMap<Name, List<Check>>.checkFor(names: Set<Name>, vararg checks: Check) {
|
||||
names.forEach { put(it, checks.asList()) }
|
||||
}
|
||||
|
||||
private fun MutableList<Pair<Regex, List<Check>>>.checkFor(regex: Regex, vararg checks: Check) {
|
||||
add(regex to checks.asList())
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class Check {
|
||||
abstract fun check(function: FirSimpleFunction, session: FirSession, scopeSession: ScopeSession?): String?
|
||||
}
|
||||
|
||||
private object Checks {
|
||||
fun simple(message: String, predicate: (FirSimpleFunction) -> Boolean) = object : Check() {
|
||||
override fun check(function: FirSimpleFunction, session: FirSession, scopeSession: ScopeSession?): String? =
|
||||
message.takeIf { !predicate(function) }
|
||||
}
|
||||
|
||||
fun full(message: String, predicate: (FirSession, FirSimpleFunction) -> Boolean) = object : Check() {
|
||||
override fun check(function: FirSimpleFunction, session: FirSession, scopeSession: ScopeSession?): String? =
|
||||
message.takeIf { !predicate(session, function) }
|
||||
}
|
||||
|
||||
val memberOrExtension = simple("must be a member or an extension function") {
|
||||
it.dispatchReceiverType != null || it.receiverParameter != null
|
||||
}
|
||||
|
||||
val member = simple("must be a member function") {
|
||||
it.dispatchReceiverType != null
|
||||
}
|
||||
|
||||
object ValueParametersCount {
|
||||
fun atLeast(n: Int) = simple("must have at least $n value parameter" + (if (n > 1) "s" else "")) {
|
||||
it.valueParameters.size >= n
|
||||
}
|
||||
|
||||
fun exactly(n: Int) = simple("must have exactly $n value parameters") {
|
||||
it.valueParameters.size == n
|
||||
}
|
||||
|
||||
val single = simple("must have a single value parameter") {
|
||||
it.valueParameters.size == 1
|
||||
}
|
||||
|
||||
val none = simple("must have no value parameters") {
|
||||
it.valueParameters.isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
object Returns {
|
||||
val boolean = simple("must return Boolean") {
|
||||
it.returnTypeRef.isBoolean
|
||||
}
|
||||
|
||||
val int = simple("must return Int") {
|
||||
it.returnTypeRef.isInt
|
||||
}
|
||||
|
||||
val unit = simple("must return Unit") {
|
||||
it.returnTypeRef.isUnit
|
||||
}
|
||||
}
|
||||
|
||||
val noDefaultAndVarargs = simple("should not have varargs or parameters with default values") {
|
||||
it.valueParameters.all { param ->
|
||||
param.defaultValue == null && !param.isVararg
|
||||
}
|
||||
}
|
||||
|
||||
private val kPropertyType = ConeClassLikeTypeImpl(
|
||||
StandardClassIds.KProperty.toLookupTag(),
|
||||
arrayOf(ConeStarProjection),
|
||||
isNullable = false
|
||||
)
|
||||
|
||||
val isKProperty = full("second parameter must be of type KProperty<*> or its supertype") { session, function ->
|
||||
val paramType = function.valueParameters.getOrNull(1)?.returnTypeRef?.coneType ?: return@full false
|
||||
kPropertyType.isSubtypeOf(paramType, session, errorTypesEqualToAnything = true)
|
||||
}
|
||||
}
|
||||
+16
-1
@@ -9,16 +9,19 @@ import org.jetbrains.kotlin.descriptors.InlineClassRepresentation
|
||||
import org.jetbrains.kotlin.descriptors.ValueClassRepresentation
|
||||
import org.jetbrains.kotlin.descriptors.createValueClassRepresentation
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInline
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.model.typeConstructor
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
internal fun ConeKotlinType.substitutedUnderlyingTypeForInlineClass(session: FirSession, context: ConeTypeContext): ConeKotlinType? {
|
||||
val unsubstitutedType = unsubstitutedUnderlyingTypeForInlineClass(session) ?: return null
|
||||
@@ -77,3 +80,15 @@ private fun ConeSimpleKotlinType.valueClassRepresentationTypeMarkersList(session
|
||||
.onEach { it.lazyResolveToPhase(FirResolvePhase.TYPES) }
|
||||
.map { it.name to it.resolvedReturnType as ConeSimpleKotlinType }
|
||||
}
|
||||
|
||||
fun FirSimpleFunction.isTypedEqualsInValueClass(session: FirSession): Boolean =
|
||||
containingClassLookupTag()?.toFirRegularClassSymbol(session)?.run {
|
||||
val valueClassStarProjection = this@run.defaultType().replaceArgumentsWithStarProjections()
|
||||
with(this@isTypedEqualsInValueClass) {
|
||||
contextReceivers.isEmpty() && receiverParameter == null
|
||||
&& name == OperatorNameConventions.EQUALS
|
||||
&& this@run.isInline && valueParameters.size == 1
|
||||
&& (returnTypeRef.isBoolean || returnTypeRef.isNothing)
|
||||
&& valueParameters[0].returnTypeRef.coneType.let { it is ConeClassLikeType && it.replaceArgumentsWithStarProjections() == valueClassStarProjection }
|
||||
}
|
||||
} ?: false
|
||||
|
||||
@@ -13,9 +13,7 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
|
||||
fun ConeClassLikeLookupTag.getNestedClassifierScope(session: FirSession, scopeSession: ScopeSession): FirContainingNamesAwareScope? {
|
||||
val klass = toSymbol(session)?.fir as? FirRegularClass ?: return null
|
||||
@@ -56,3 +54,24 @@ fun debugCollectOverrides(symbol: FirCallableSymbol<*>, scope: FirTypeScope): Ma
|
||||
}
|
||||
return process(scope, symbol)
|
||||
}
|
||||
|
||||
fun FirNamedFunctionSymbol.overriddenFunctions(
|
||||
containingClass: FirClassSymbol<*>,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession
|
||||
): List<FirFunctionSymbol<*>> {
|
||||
val firTypeScope = containingClass.unsubstitutedScope(
|
||||
session,
|
||||
scopeSession,
|
||||
withForcedTypeCalculator = true
|
||||
)
|
||||
|
||||
val overriddenFunctions = mutableListOf<FirFunctionSymbol<*>>()
|
||||
firTypeScope.processFunctionsByName(callableId.callableName) { }
|
||||
firTypeScope.processOverriddenFunctions(this) {
|
||||
overriddenFunctions.add(it)
|
||||
ProcessorAction.NEXT
|
||||
}
|
||||
|
||||
return overriddenFunctions
|
||||
}
|
||||
|
||||
@@ -516,9 +516,9 @@ private class CapturedArguments(val capturedArguments: Array<out ConeTypeProject
|
||||
}
|
||||
}
|
||||
|
||||
fun ConeKotlinType.isSubtypeOf(superType: ConeKotlinType, session: FirSession): Boolean =
|
||||
fun ConeKotlinType.isSubtypeOf(superType: ConeKotlinType, session: FirSession, errorTypesEqualToAnything: Boolean = false): Boolean =
|
||||
AbstractTypeChecker.isSubtypeOf(
|
||||
session.typeContext.newTypeCheckerState(errorTypesEqualToAnything = false, stubTypesEqualToAnything = false),
|
||||
session.typeContext.newTypeCheckerState(errorTypesEqualToAnything, stubTypesEqualToAnything = false),
|
||||
this, superType,
|
||||
)
|
||||
|
||||
|
||||
+6
-6
@@ -15,12 +15,12 @@ FILE fqName:<root> fileName:/kt43217.kt
|
||||
BLOCK_BODY
|
||||
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.DoubleExpression'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:<no name provided> modality:FINAL visibility:local superTypes:[<root>.DoubleExpression]'
|
||||
FUN name:get visibility:public modality:OPEN <> ($this:<root>.A.b.<no name provided>) returnType:kotlin.Double [operator]
|
||||
FUN name:get visibility:public modality:OPEN <> ($this:<root>.A.b.<no name provided>) returnType:kotlin.Double
|
||||
overridden:
|
||||
public abstract fun get (): @[EnhancedNullability] kotlin.Double [fake_override,operator] declared in <root>.DoubleExpression
|
||||
public abstract fun get (): @[EnhancedNullability] kotlin.Double [fake_override] declared in <root>.DoubleExpression
|
||||
$this: VALUE_PARAMETER name:<this> type:<root>.A.b.<no name provided>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public open fun get (): kotlin.Double [operator] declared in <root>.A.b.<no name provided>'
|
||||
RETURN type=kotlin.Nothing from='public open fun get (): kotlin.Double declared in <root>.A.b.<no name provided>'
|
||||
CONST Double type=kotlin.Double value=0.0
|
||||
FUN FAKE_OVERRIDE name:isEqualTo visibility:public modality:OPEN <> ($this:<root>.DoubleExpression, value:kotlin.Double) returnType:@[EnhancedNullability] kotlin.Any [fake_override]
|
||||
annotations:
|
||||
@@ -79,12 +79,12 @@ FILE fqName:<root> fileName:/kt43217.kt
|
||||
BLOCK_BODY
|
||||
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.DoubleExpression'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:C modality:FINAL visibility:public superTypes:[<root>.DoubleExpression]'
|
||||
FUN name:get visibility:public modality:OPEN <> ($this:<root>.C) returnType:kotlin.Double [operator]
|
||||
FUN name:get visibility:public modality:OPEN <> ($this:<root>.C) returnType:kotlin.Double
|
||||
overridden:
|
||||
public abstract fun get (): @[EnhancedNullability] kotlin.Double [fake_override,operator] declared in <root>.DoubleExpression
|
||||
public abstract fun get (): @[EnhancedNullability] kotlin.Double [fake_override] declared in <root>.DoubleExpression
|
||||
$this: VALUE_PARAMETER name:<this> type:<root>.C
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public open fun get (): kotlin.Double [operator] declared in <root>.C'
|
||||
RETURN type=kotlin.Nothing from='public open fun get (): kotlin.Double declared in <root>.C'
|
||||
CONST Double type=kotlin.Double value=0.0
|
||||
FUN FAKE_OVERRIDE name:isEqualTo visibility:public modality:OPEN <> ($this:<root>.DoubleExpression, value:kotlin.Double) returnType:@[EnhancedNullability] kotlin.Any [fake_override]
|
||||
annotations:
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ class A {
|
||||
|
||||
}
|
||||
|
||||
override operator fun get(): Double {
|
||||
override fun get(): Double {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class C : DoubleExpression {
|
||||
|
||||
}
|
||||
|
||||
override operator fun get(): Double {
|
||||
override fun get(): Double {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ FILE fqName:<root> fileName:/exclExclOnPlatformType.kt
|
||||
CALL 'public final fun use (a: kotlin.Any): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||
a: CALL 'public final fun CHECK_NOT_NULL <T0> (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): {T0 of kotlin.internal.ir.CHECK_NOT_NULL & Any} declared in kotlin.internal.ir' type=kotlin.String origin=EXCLEXCL
|
||||
<T0>: kotlin.String
|
||||
arg0: CALL 'public open fun get (): T of java.lang.ref.WeakReference? [fake_override,operator] declared in java.lang.ref.WeakReference' type=kotlin.String? origin=null
|
||||
arg0: CALL 'public open fun get (): T of java.lang.ref.WeakReference? [fake_override] declared in java.lang.ref.WeakReference' type=kotlin.String? origin=null
|
||||
$this: CONSTRUCTOR_CALL 'public constructor <init> (p0: @[FlexibleNullability] T of java.lang.ref.WeakReference?) declared in java.lang.ref.WeakReference' type=java.lang.ref.WeakReference<@[FlexibleNullability] kotlin.String?> origin=null
|
||||
<class: T>: @[FlexibleNullability] kotlin.String?
|
||||
p0: CONST String type=kotlin.String value=""
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
public abstract interface SubclassOfMapEntry<K : R|kotlin/Any!|, V : R|kotlin/Any!|> : R|kotlin/collections/MutableMap.MutableEntry<ft<K & Any, K?>, ft<V & Any, V?>>| {
|
||||
public abstract operator fun setValue(value: R|ft<V & Any, V?>|): R|ft<V & Any, V?>|
|
||||
public abstract fun setValue(value: R|ft<V & Any, V?>|): R|ft<V & Any, V?>|
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@ public abstract interface ReturnInnerSubclassOfSupersInner : R|kotlin/Any| {
|
||||
public constructor<B : R|kotlin/Any!|>(): R|test/ReturnInnerSubclassOfSupersInner.Sub<B>|
|
||||
|
||||
public/*package*/ open inner class Inner<B : R|kotlin/Any!|> : R|test/ReturnInnerSubclassOfSupersInner.Super.Inner<ft<B & Any, B?>>| {
|
||||
public/*package*/ open operator fun get(): R|ft<test/ReturnInnerSubclassOfSupersInner.Sub<ft<B & Any, B?>>, test/ReturnInnerSubclassOfSupersInner.Sub<ft<B & Any, B?>>?>|
|
||||
public/*package*/ open fun get(): R|ft<test/ReturnInnerSubclassOfSupersInner.Sub<ft<B & Any, B?>>, test/ReturnInnerSubclassOfSupersInner.Sub<ft<B & Any, B?>>?>|
|
||||
|
||||
public/*package*/ test/ReturnInnerSubclassOfSupersInner.Sub<B>.constructor(): R|test/ReturnInnerSubclassOfSupersInner.Sub.Inner<B>|
|
||||
|
||||
@@ -13,7 +13,7 @@ public abstract interface ReturnInnerSubclassOfSupersInner : R|kotlin/Any| {
|
||||
public constructor<A : R|kotlin/Any!|>(): R|test/ReturnInnerSubclassOfSupersInner.Super<A>|
|
||||
|
||||
public/*package*/ open inner class Inner<A : R|kotlin/Any!|> : R|kotlin/Any| {
|
||||
public/*package*/ open operator fun get(): R|ft<test/ReturnInnerSubclassOfSupersInner.Super<ft<A & Any, A?>>, test/ReturnInnerSubclassOfSupersInner.Super<ft<A & Any, A?>>?>|
|
||||
public/*package*/ open fun get(): R|ft<test/ReturnInnerSubclassOfSupersInner.Super<ft<A & Any, A?>>, test/ReturnInnerSubclassOfSupersInner.Super<ft<A & Any, A?>>?>|
|
||||
|
||||
public/*package*/ test/ReturnInnerSubclassOfSupersInner.Super<A>.constructor(): R|test/ReturnInnerSubclassOfSupersInner.Super.Inner<A>|
|
||||
|
||||
|
||||
Reference in New Issue
Block a user