[FIR] Disallow operators not on functions
Introduce `NOT_FUNCTION_AS_OPERATOR` and use it instead of `PROPERTY_AS_OPERATOR` ^KT-65881 Fixed Merge-request: KT-MR-14547
This commit is contained in:
committed by
Space Team
parent
df9d59851d
commit
2d4f4b9bb5
+4
-3
@@ -4529,9 +4529,10 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
add(FirErrors.PROPERTY_AS_OPERATOR) { firDiagnostic ->
|
add(FirErrors.NOT_FUNCTION_AS_OPERATOR) { firDiagnostic ->
|
||||||
PropertyAsOperatorImpl(
|
NotFunctionAsOperatorImpl(
|
||||||
firSymbolBuilder.variableLikeBuilder.buildVariableSymbol(firDiagnostic.a),
|
firDiagnostic.a,
|
||||||
|
firSymbolBuilder.buildSymbol(firDiagnostic.b),
|
||||||
firDiagnostic as KtPsiDiagnostic,
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
|
|||||||
+4
-3
@@ -3156,9 +3156,10 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
val operator: String
|
val operator: String
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PropertyAsOperator : KtFirDiagnostic<PsiElement> {
|
interface NotFunctionAsOperator : KtFirDiagnostic<PsiElement> {
|
||||||
override val diagnosticClass get() = PropertyAsOperator::class
|
override val diagnosticClass get() = NotFunctionAsOperator::class
|
||||||
val property: KtVariableSymbol
|
val elementName: String
|
||||||
|
val elementSymbol: KtSymbol
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DslScopeViolation : KtFirDiagnostic<PsiElement> {
|
interface DslScopeViolation : KtFirDiagnostic<PsiElement> {
|
||||||
|
|||||||
+4
-3
@@ -3800,11 +3800,12 @@ internal class AssignmentOperatorShouldReturnUnitImpl(
|
|||||||
token: KtLifetimeToken,
|
token: KtLifetimeToken,
|
||||||
) : KtAbstractFirDiagnostic<KtExpression>(firDiagnostic, token), KtFirDiagnostic.AssignmentOperatorShouldReturnUnit
|
) : KtAbstractFirDiagnostic<KtExpression>(firDiagnostic, token), KtFirDiagnostic.AssignmentOperatorShouldReturnUnit
|
||||||
|
|
||||||
internal class PropertyAsOperatorImpl(
|
internal class NotFunctionAsOperatorImpl(
|
||||||
override val property: KtVariableSymbol,
|
override val elementName: String,
|
||||||
|
override val elementSymbol: KtSymbol,
|
||||||
firDiagnostic: KtPsiDiagnostic,
|
firDiagnostic: KtPsiDiagnostic,
|
||||||
token: KtLifetimeToken,
|
token: KtLifetimeToken,
|
||||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.PropertyAsOperator
|
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.NotFunctionAsOperator
|
||||||
|
|
||||||
internal class DslScopeViolationImpl(
|
internal class DslScopeViolationImpl(
|
||||||
override val calleeSymbol: KtSymbol,
|
override val calleeSymbol: KtSymbol,
|
||||||
|
|||||||
+6
@@ -1023,6 +1023,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
|
|||||||
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OperatorConventions.kt")
|
||||||
|
public void testOperatorConventions() {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/OperatorConventions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("Operators.kt")
|
@TestMetadata("Operators.kt")
|
||||||
public void testOperators() {
|
public void testOperators() {
|
||||||
|
|||||||
+6
@@ -1023,6 +1023,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
|
|||||||
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OperatorConventions.kt")
|
||||||
|
public void testOperatorConventions() {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/OperatorConventions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("Operators.kt")
|
@TestMetadata("Operators.kt")
|
||||||
public void testOperators() {
|
public void testOperators() {
|
||||||
|
|||||||
+6
@@ -1023,6 +1023,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
|
|||||||
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OperatorConventions.kt")
|
||||||
|
public void testOperatorConventions() {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/OperatorConventions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("Operators.kt")
|
@TestMetadata("Operators.kt")
|
||||||
public void testOperators() {
|
public void testOperators() {
|
||||||
|
|||||||
+6
@@ -1023,6 +1023,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
|
|||||||
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OperatorConventions.kt")
|
||||||
|
public void testOperatorConventions() {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/OperatorConventions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("Operators.kt")
|
@TestMetadata("Operators.kt")
|
||||||
public void testOperators() {
|
public void testOperators() {
|
||||||
|
|||||||
+3
-2
@@ -1585,8 +1585,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
parameter<FirNamedFunctionSymbol>("functionSymbol")
|
parameter<FirNamedFunctionSymbol>("functionSymbol")
|
||||||
parameter<String>("operator")
|
parameter<String>("operator")
|
||||||
}
|
}
|
||||||
val PROPERTY_AS_OPERATOR by error<PsiElement>(PositioningStrategy.OPERATOR) {
|
val NOT_FUNCTION_AS_OPERATOR by error<PsiElement>(PositioningStrategy.OPERATOR) {
|
||||||
parameter<FirPropertySymbol>("property")
|
parameter<String>("elementName")
|
||||||
|
parameter<FirBasedSymbol<*>>("elementSymbol")
|
||||||
}
|
}
|
||||||
val DSL_SCOPE_VIOLATION by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) {
|
val DSL_SCOPE_VIOLATION by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) {
|
||||||
parameter<FirBasedSymbol<*>>("calleeSymbol")
|
parameter<FirBasedSymbol<*>>("calleeSymbol")
|
||||||
|
|||||||
+1
-1
@@ -796,7 +796,7 @@ object FirErrors {
|
|||||||
val IMPLICIT_BOXING_IN_IDENTITY_EQUALS: KtDiagnosticFactory2<ConeKotlinType, ConeKotlinType> by warning2<KtElement, ConeKotlinType, ConeKotlinType>()
|
val IMPLICIT_BOXING_IN_IDENTITY_EQUALS: KtDiagnosticFactory2<ConeKotlinType, ConeKotlinType> by warning2<KtElement, ConeKotlinType, ConeKotlinType>()
|
||||||
val INC_DEC_SHOULD_NOT_RETURN_UNIT: KtDiagnosticFactory0 by error0<KtExpression>(SourceElementPositioningStrategies.OPERATOR)
|
val INC_DEC_SHOULD_NOT_RETURN_UNIT: KtDiagnosticFactory0 by error0<KtExpression>(SourceElementPositioningStrategies.OPERATOR)
|
||||||
val ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT: KtDiagnosticFactory2<FirNamedFunctionSymbol, String> by error2<KtExpression, FirNamedFunctionSymbol, String>(SourceElementPositioningStrategies.OPERATOR)
|
val ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT: KtDiagnosticFactory2<FirNamedFunctionSymbol, String> by error2<KtExpression, FirNamedFunctionSymbol, String>(SourceElementPositioningStrategies.OPERATOR)
|
||||||
val PROPERTY_AS_OPERATOR: KtDiagnosticFactory1<FirPropertySymbol> by error1<PsiElement, FirPropertySymbol>(SourceElementPositioningStrategies.OPERATOR)
|
val NOT_FUNCTION_AS_OPERATOR: KtDiagnosticFactory2<String, FirBasedSymbol<*>> by error2<PsiElement, String, FirBasedSymbol<*>>(SourceElementPositioningStrategies.OPERATOR)
|
||||||
val DSL_SCOPE_VIOLATION: KtDiagnosticFactory1<FirBasedSymbol<*>> by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
val DSL_SCOPE_VIOLATION: KtDiagnosticFactory1<FirBasedSymbol<*>> by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
|
|
||||||
// Type alias
|
// Type alias
|
||||||
|
|||||||
+1
-1
@@ -533,7 +533,7 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set<String> = setOf(
|
|||||||
"FORBIDDEN_IDENTITY_EQUALS",
|
"FORBIDDEN_IDENTITY_EQUALS",
|
||||||
"INC_DEC_SHOULD_NOT_RETURN_UNIT",
|
"INC_DEC_SHOULD_NOT_RETURN_UNIT",
|
||||||
"ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT",
|
"ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT",
|
||||||
"PROPERTY_AS_OPERATOR",
|
"NOT_FUNCTION_AS_OPERATOR",
|
||||||
"DSL_SCOPE_VIOLATION",
|
"DSL_SCOPE_VIOLATION",
|
||||||
"TOPLEVEL_TYPEALIASES_ONLY",
|
"TOPLEVEL_TYPEALIASES_ONLY",
|
||||||
"RECURSIVE_TYPEALIAS_EXPANSION",
|
"RECURSIVE_TYPEALIAS_EXPANSION",
|
||||||
|
|||||||
+29
-13
@@ -11,23 +11,21 @@ import org.jetbrains.kotlin.diagnostics.reportOn
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
|
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.unwrapSmartcastExpression
|
|
||||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConePropertyAsOperator
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeNotFunctionAsOperator
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeDynamicType
|
import org.jetbrains.kotlin.fir.types.ConeDynamicType
|
||||||
|
import org.jetbrains.kotlin.fir.types.classId
|
||||||
import org.jetbrains.kotlin.fir.types.resolvedType
|
import org.jetbrains.kotlin.fir.types.resolvedType
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
|
|
||||||
object FirConventionFunctionCallChecker : FirFunctionCallChecker(MppCheckerKind.Common) {
|
object FirConventionFunctionCallChecker : FirFunctionCallChecker(MppCheckerKind.Common) {
|
||||||
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
// PROPERTY_AS_OPERATOR can only happen for function calls and it's reported on the receiver expression.
|
checkNotFunctionAsOperator(expression, expression.dispatchReceiver, context, reporter)
|
||||||
checkPropertyAsOperator(expression, expression.dispatchReceiver, context, reporter)
|
checkNotFunctionAsOperator(expression, expression.extensionReceiver, context, reporter)
|
||||||
checkPropertyAsOperator(expression, expression.extensionReceiver, context, reporter)
|
|
||||||
val calleeReference = expression.calleeReference as? FirErrorNamedReference ?: return
|
val calleeReference = expression.calleeReference as? FirErrorNamedReference ?: return
|
||||||
val diagnostic = calleeReference.diagnostic as? ConeUnresolvedNameError ?: return
|
val diagnostic = calleeReference.diagnostic as? ConeUnresolvedNameError ?: return
|
||||||
|
|
||||||
@@ -39,7 +37,7 @@ object FirConventionFunctionCallChecker : FirFunctionCallChecker(MppCheckerKind.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkPropertyAsOperator(
|
private fun checkNotFunctionAsOperator(
|
||||||
callExpression: FirFunctionCall,
|
callExpression: FirFunctionCall,
|
||||||
receiver: FirExpression?,
|
receiver: FirExpression?,
|
||||||
context: CheckerContext,
|
context: CheckerContext,
|
||||||
@@ -47,9 +45,27 @@ object FirConventionFunctionCallChecker : FirFunctionCallChecker(MppCheckerKind.
|
|||||||
) {
|
) {
|
||||||
if (callExpression.dispatchReceiver?.resolvedType is ConeDynamicType) return
|
if (callExpression.dispatchReceiver?.resolvedType is ConeDynamicType) return
|
||||||
// KT-61905: TODO: Return also in case of error type.
|
// KT-61905: TODO: Return also in case of error type.
|
||||||
val unwrapped = receiver?.unwrapSmartcastExpression()
|
val unwrapped = receiver?.unwrapSmartcastExpression() ?: return
|
||||||
if (unwrapped !is FirPropertyAccessExpression) return
|
val nonFatalDiagnostics = when (unwrapped) {
|
||||||
val diagnostic = unwrapped.nonFatalDiagnostics.firstIsInstanceOrNull<ConePropertyAsOperator>() ?: return
|
is FirQualifiedAccessExpression -> unwrapped.nonFatalDiagnostics
|
||||||
reporter.reportOn(callExpression.calleeReference.source, FirErrors.PROPERTY_AS_OPERATOR, diagnostic.symbol, context)
|
is FirResolvedQualifier -> unwrapped.nonFatalDiagnostics
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
val diagnosticSymbol = nonFatalDiagnostics.firstIsInstanceOrNull<ConeNotFunctionAsOperator>()?.symbol ?: return
|
||||||
|
when {
|
||||||
|
unwrapped.resolvedType.classId!!.shortClassName == OperatorNameConventions.ITERATOR -> {
|
||||||
|
reporter.reportOn(unwrapped.source, FirErrors.ITERATOR_MISSING, context)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// NOT_FUNCTION_AS_OPERATOR can only happen for function calls and it's reported on the receiver expression.
|
||||||
|
reporter.reportOn(
|
||||||
|
callExpression.calleeReference.source,
|
||||||
|
FirErrors.NOT_FUNCTION_AS_OPERATOR,
|
||||||
|
if (diagnosticSymbol is FirPropertySymbol) "Property" else "Object",
|
||||||
|
diagnosticSymbol,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.fir.resolve.calls.UnsafeCall
|
|||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
object FirForLoopChecker : FirBlockChecker(MppCheckerKind.Common) {
|
object FirForLoopChecker : FirBlockChecker(MppCheckerKind.Common) {
|
||||||
|
|||||||
+4
-3
@@ -451,6 +451,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_FUNCTION_LA
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_LOOP_LABEL
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_LOOP_LABEL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_MULTIPLATFORM_COMPILATION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_MULTIPLATFORM_COMPILATION
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_SUPERTYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_SUPERTYPE
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_FUNCTION_AS_OPERATOR
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_SUPPORTED_INLINE_PARAMETER_IN_INLINE_PARAMETER_DEFAULT_VALUE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_SUPPORTED_INLINE_PARAMETER_IN_INLINE_PARAMETER_DEFAULT_VALUE
|
||||||
@@ -521,7 +522,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_SETTER_FO
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_SETTER_FOR_OPEN_PROPERTY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_SETTER_FOR_OPEN_PROPERTY
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_AS_OPERATOR
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_FIELD_DECLARATION_MISSING_INITIALIZER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_FIELD_DECLARATION_MISSING_INITIALIZER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALIZER_IN_INTERFACE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALIZER_IN_INTERFACE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALIZER_NO_BACKING_FIELD
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALIZER_NO_BACKING_FIELD
|
||||||
@@ -2410,8 +2410,9 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
|||||||
TO_STRING
|
TO_STRING
|
||||||
)
|
)
|
||||||
map.put(
|
map.put(
|
||||||
PROPERTY_AS_OPERATOR,
|
NOT_FUNCTION_AS_OPERATOR,
|
||||||
"Property ''{0}'' cannot be used as operator.",
|
"{0} ''{1}'' cannot be used as operator.",
|
||||||
|
STRING,
|
||||||
SYMBOL
|
SYMBOL
|
||||||
)
|
)
|
||||||
map.put(
|
map.put(
|
||||||
|
|||||||
@@ -124,15 +124,12 @@ class CandidateFactory private constructor(
|
|||||||
result.addDiagnostic(NoCompanionObject)
|
result.addDiagnostic(NoCompanionObject)
|
||||||
}
|
}
|
||||||
if (callInfo.origin == FirFunctionCallOrigin.Operator) {
|
if (callInfo.origin == FirFunctionCallOrigin.Operator) {
|
||||||
val propertySymbol = when {
|
val normalizedSymbol = when (symbol) {
|
||||||
symbol is FirPropertySymbol -> symbol
|
!is FirFunctionSymbol -> symbol
|
||||||
callInfo.candidateForCommonInvokeReceiver != null -> callInfo.candidateForCommonInvokeReceiver.symbol as? FirPropertySymbol
|
else -> callInfo.candidateForCommonInvokeReceiver?.symbol?.takeIf { it !is FirFunctionSymbol }
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
if (propertySymbol != null) {
|
|
||||||
// Flag all property references that are resolved from an convention operator call.
|
|
||||||
result.addDiagnostic(PropertyAsOperator(propertySymbol))
|
|
||||||
}
|
}
|
||||||
|
// Flag all references that are resolved from an convention operator call.
|
||||||
|
normalizedSymbol?.let { result.addDiagnostic(NotFunctionAsOperator(normalizedSymbol)) }
|
||||||
}
|
}
|
||||||
if (symbol is FirPropertySymbol &&
|
if (symbol is FirPropertySymbol &&
|
||||||
!context.session.languageVersionSettings.supportsFeature(LanguageFeature.PrioritizedEnumEntries)
|
!context.session.languageVersionSettings.supportsFeature(LanguageFeature.PrioritizedEnumEntries)
|
||||||
|
|||||||
+16
-8
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
|||||||
import org.jetbrains.kotlin.fir.expressions.builder.FirPropertyAccessExpressionBuilder
|
import org.jetbrains.kotlin.fir.expressions.builder.FirPropertyAccessExpressionBuilder
|
||||||
import org.jetbrains.kotlin.fir.resolve.*
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConePropertyAsOperator
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeNotFunctionAsOperator
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
|||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||||
|
|
||||||
internal class FirInvokeResolveTowerExtension(
|
internal class FirInvokeResolveTowerExtension(
|
||||||
private val context: ResolutionContext,
|
private val context: ResolutionContext,
|
||||||
@@ -288,18 +289,26 @@ private fun BodyResolveComponents.createExplicitReceiverForInvoke(
|
|||||||
invokeBuiltinExtensionMode: Boolean,
|
invokeBuiltinExtensionMode: Boolean,
|
||||||
extensionReceiverExpression: FirExpression?
|
extensionReceiverExpression: FirExpression?
|
||||||
): FirExpression? {
|
): FirExpression? {
|
||||||
|
val notFunctionAsOperatorDiagnostics = runIf (candidate.currentApplicability == CandidateApplicability.K2_NOT_FUNCTION_AS_OPERATOR) {
|
||||||
|
candidate.diagnostics.filterIsInstance<NotFunctionAsOperator>().map { ConeNotFunctionAsOperator(it.symbol) }
|
||||||
|
} ?: emptyList()
|
||||||
return when (val symbol = candidate.symbol) {
|
return when (val symbol = candidate.symbol) {
|
||||||
is FirCallableSymbol<*> -> createExplicitReceiverForInvokeByCallable(
|
is FirCallableSymbol<*> -> createExplicitReceiverForInvokeByCallable(
|
||||||
candidate, info, invokeBuiltinExtensionMode, extensionReceiverExpression, symbol
|
candidate, info, invokeBuiltinExtensionMode, extensionReceiverExpression, symbol, notFunctionAsOperatorDiagnostics
|
||||||
)
|
)
|
||||||
is FirRegularClassSymbol -> buildResolvedQualifierForClass(
|
is FirRegularClassSymbol -> buildResolvedQualifierForClass(
|
||||||
symbol,
|
symbol,
|
||||||
sourceElement = info.fakeSourceForImplicitInvokeCallReceiver
|
sourceElement = info.fakeSourceForImplicitInvokeCallReceiver,
|
||||||
|
nonFatalDiagnostics = notFunctionAsOperatorDiagnostics,
|
||||||
)
|
)
|
||||||
is FirTypeAliasSymbol -> {
|
is FirTypeAliasSymbol -> {
|
||||||
val type = symbol.fir.expandedTypeRef.coneTypeUnsafe<ConeClassLikeType>().fullyExpandedType(session)
|
val type = symbol.fir.expandedTypeRef.coneTypeUnsafe<ConeClassLikeType>().fullyExpandedType(session)
|
||||||
val expansionRegularClassSymbol = type.lookupTag.toSymbol(session) ?: return null
|
val expansionRegularClassSymbol = type.lookupTag.toSymbol(session) ?: return null
|
||||||
buildResolvedQualifierForClass(expansionRegularClassSymbol, sourceElement = symbol.fir.source)
|
buildResolvedQualifierForClass(
|
||||||
|
expansionRegularClassSymbol,
|
||||||
|
sourceElement = symbol.fir.source,
|
||||||
|
nonFatalDiagnostics = notFunctionAsOperatorDiagnostics,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
else -> throw AssertionError()
|
else -> throw AssertionError()
|
||||||
}
|
}
|
||||||
@@ -310,7 +319,8 @@ private fun BodyResolveComponents.createExplicitReceiverForInvokeByCallable(
|
|||||||
info: CallInfo,
|
info: CallInfo,
|
||||||
invokeBuiltinExtensionMode: Boolean,
|
invokeBuiltinExtensionMode: Boolean,
|
||||||
extensionReceiverExpression: FirExpression?,
|
extensionReceiverExpression: FirExpression?,
|
||||||
symbol: FirCallableSymbol<*>
|
symbol: FirCallableSymbol<*>,
|
||||||
|
nonFatalDiagnostics: List<ConeNotFunctionAsOperator>,
|
||||||
): FirExpression {
|
): FirExpression {
|
||||||
return FirPropertyAccessExpressionBuilder().apply {
|
return FirPropertyAccessExpressionBuilder().apply {
|
||||||
val fakeSource = info.fakeSourceForImplicitInvokeCallReceiver
|
val fakeSource = info.fakeSourceForImplicitInvokeCallReceiver
|
||||||
@@ -337,9 +347,7 @@ private fun BodyResolveComponents.createExplicitReceiverForInvokeByCallable(
|
|||||||
explicitReceiver = info.explicitReceiver
|
explicitReceiver = info.explicitReceiver
|
||||||
}
|
}
|
||||||
|
|
||||||
if (candidate.currentApplicability == CandidateApplicability.K2_PROPERTY_AS_OPERATOR) {
|
this.nonFatalDiagnostics.addAll(nonFatalDiagnostics)
|
||||||
nonFatalDiagnostics.add(ConePropertyAsOperator(candidate.symbol as FirPropertySymbol))
|
|
||||||
}
|
|
||||||
|
|
||||||
candidate.updateSourcesOfReceivers()
|
candidate.updateSourcesOfReceivers()
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -170,11 +170,11 @@ class FirCallCompletionResultsWriterTransformer(
|
|||||||
|
|
||||||
qualifiedAccessExpression.replaceContextReceiverArguments(subCandidate.contextReceiverArguments())
|
qualifiedAccessExpression.replaceContextReceiverArguments(subCandidate.contextReceiverArguments())
|
||||||
|
|
||||||
subCandidate.diagnostics.firstIsInstanceOrNull<PropertyAsOperator>()?.let { propertyAsOperator ->
|
subCandidate.diagnostics.firstIsInstanceOrNull<NotFunctionAsOperator>()?.let { propertyAsOperator ->
|
||||||
val conePropertyAsOperator = ConePropertyAsOperator(propertyAsOperator.propertySymbol)
|
val coneNotFunctionAsOperator = ConeNotFunctionAsOperator(propertyAsOperator.symbol)
|
||||||
val nonFatalDiagnostics: List<ConeDiagnostic> = buildList {
|
val nonFatalDiagnostics: List<ConeDiagnostic> = buildList {
|
||||||
addAll(qualifiedAccessExpression.nonFatalDiagnostics)
|
addAll(qualifiedAccessExpression.nonFatalDiagnostics)
|
||||||
add(conePropertyAsOperator)
|
add(coneNotFunctionAsOperator)
|
||||||
}
|
}
|
||||||
qualifiedAccessExpression.replaceNonFatalDiagnostics(nonFatalDiagnostics)
|
qualifiedAccessExpression.replaceNonFatalDiagnostics(nonFatalDiagnostics)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
|
|||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.ConeTypeVariable
|
import org.jetbrains.kotlin.fir.types.ConeTypeVariable
|
||||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||||
@@ -136,7 +135,7 @@ class OperatorCallOfConstructor(val constructor: FirConstructorSymbol) : Resolut
|
|||||||
class InferenceError(val constraintError: ConstraintSystemError) : ResolutionDiagnostic(constraintError.applicability)
|
class InferenceError(val constraintError: ConstraintSystemError) : ResolutionDiagnostic(constraintError.applicability)
|
||||||
class Unsupported(val message: String, val source: KtSourceElement?) : ResolutionDiagnostic(K2_UNSUPPORTED)
|
class Unsupported(val message: String, val source: KtSourceElement?) : ResolutionDiagnostic(K2_UNSUPPORTED)
|
||||||
|
|
||||||
class PropertyAsOperator(val propertySymbol: FirPropertySymbol) : ResolutionDiagnostic(K2_PROPERTY_AS_OPERATOR)
|
class NotFunctionAsOperator(val symbol: FirBasedSymbol<*>) : ResolutionDiagnostic(K2_NOT_FUNCTION_AS_OPERATOR)
|
||||||
|
|
||||||
class DslScopeViolation(val calleeSymbol: FirBasedSymbol<*>) : ResolutionDiagnostic(RESOLVED_WITH_ERROR)
|
class DslScopeViolation(val calleeSymbol: FirBasedSymbol<*>) : ResolutionDiagnostic(RESOLVED_WITH_ERROR)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -350,8 +350,8 @@ class ConeLocalVariableNoTypeOrInitializer(val variable: FirVariable) : ConeDiag
|
|||||||
override val reason: String get() = "Cannot infer variable type without initializer / getter / delegate"
|
override val reason: String get() = "Cannot infer variable type without initializer / getter / delegate"
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConePropertyAsOperator(val symbol: FirPropertySymbol) : ConeDiagnostic {
|
class ConeNotFunctionAsOperator(val symbol: FirBasedSymbol<*>) : ConeDiagnostic {
|
||||||
override val reason: String get() = "Cannot use a property as an operator"
|
override val reason: String get() = "Cannot use not function as an operator"
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConeUnknownLambdaParameterTypeDiagnostic : ConeDiagnostic {
|
class ConeUnknownLambdaParameterTypeDiagnostic : ConeDiagnostic {
|
||||||
|
|||||||
+2
-2
@@ -89,10 +89,10 @@ enum class CandidateApplicability {
|
|||||||
RESOLVED_LOW_PRIORITY,
|
RESOLVED_LOW_PRIORITY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Candidate is successful but uses property of functional type as an operator.
|
* Candidate is successful but uses property or object of functional type as an operator.
|
||||||
* Tower resolve proceeds to next levels.
|
* Tower resolve proceeds to next levels.
|
||||||
*/
|
*/
|
||||||
K2_PROPERTY_AS_OPERATOR,
|
K2_NOT_FUNCTION_AS_OPERATOR,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Candidate is successful but uses new features that change resolve.
|
* Candidate is successful but uses new features that change resolve.
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
// ISSUE: KT-65881, KT-65760
|
||||||
|
|
||||||
|
class I: Iterator<Int> {
|
||||||
|
override fun hasNext(): Boolean = false
|
||||||
|
override fun next(): Int = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
object A {
|
||||||
|
object plusAssign {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object minusAssign {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object timesAssign {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object divAssign {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object remAssign {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object unaryPlus {
|
||||||
|
operator fun invoke(): A = A
|
||||||
|
}
|
||||||
|
object unaryMinus {
|
||||||
|
operator fun invoke(): A = A
|
||||||
|
}
|
||||||
|
object not {
|
||||||
|
operator fun invoke(): A = A
|
||||||
|
}
|
||||||
|
object plus {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object minus {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object times {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object div {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object rem {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object get {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object set {
|
||||||
|
operator fun invoke(x: Int, y: Int): A = A
|
||||||
|
}
|
||||||
|
object contains {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object invoke {
|
||||||
|
operator fun invoke(): A = A
|
||||||
|
}
|
||||||
|
object rangeTo {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object rangeUntil {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object compareTo {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object iterator {
|
||||||
|
operator fun invoke(): I = I()
|
||||||
|
}
|
||||||
|
object component1 {
|
||||||
|
operator fun invoke(): A = A
|
||||||
|
}
|
||||||
|
object component2 {
|
||||||
|
operator fun invoke(): A = A
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun usePlusAssign() { A <!NOT_FUNCTION_AS_OPERATOR!>+=<!> 1 }
|
||||||
|
fun useMinusAssign() { A <!NOT_FUNCTION_AS_OPERATOR!>-=<!> 1 }
|
||||||
|
fun useTimesAssign() { A <!NOT_FUNCTION_AS_OPERATOR!>*=<!> 1 }
|
||||||
|
fun useDivAssign() { A <!NOT_FUNCTION_AS_OPERATOR!>/=<!> 1 }
|
||||||
|
fun useRemAssign() { A <!NOT_FUNCTION_AS_OPERATOR!>%=<!> 1 }
|
||||||
|
val useUnaryPlus = <!NOT_FUNCTION_AS_OPERATOR!>+<!>A
|
||||||
|
val useUnaryMinus = <!NOT_FUNCTION_AS_OPERATOR!>-<!>A
|
||||||
|
val useNot = <!NOT_FUNCTION_AS_OPERATOR!>!<!>A
|
||||||
|
val usePlus = A <!NOT_FUNCTION_AS_OPERATOR!>+<!> 1
|
||||||
|
val useMinus = A <!NOT_FUNCTION_AS_OPERATOR!>-<!> 1
|
||||||
|
val useTimes = A <!NOT_FUNCTION_AS_OPERATOR!>*<!> 1
|
||||||
|
val useDiv = A <!NOT_FUNCTION_AS_OPERATOR!>/<!> 1
|
||||||
|
val useRem = A <!NOT_FUNCTION_AS_OPERATOR!>%<!> 1
|
||||||
|
val useGet = <!NOT_FUNCTION_AS_OPERATOR!>A[1]<!>
|
||||||
|
fun useSet() { <!NOT_FUNCTION_AS_OPERATOR!>A[1]<!> = 3 }
|
||||||
|
val useContains = 1 <!NOT_FUNCTION_AS_OPERATOR!>in<!> A
|
||||||
|
val useNotContains = 1 <!NOT_FUNCTION_AS_OPERATOR, UNRESOLVED_REFERENCE!>!in<!> A
|
||||||
|
val useInvoke = <!UNRESOLVED_REFERENCE!>A<!>()
|
||||||
|
val useRangeTo = A <!NOT_FUNCTION_AS_OPERATOR!>..<!> 3
|
||||||
|
val useRangeUntil = A <!NOT_FUNCTION_AS_OPERATOR!>..<<!> 3
|
||||||
|
val useCompareTo = A <!NOT_FUNCTION_AS_OPERATOR!>><!> 2
|
||||||
|
fun useIterator() {
|
||||||
|
for (x in <!ITERATOR_MISSING!>A<!>) { }
|
||||||
|
}
|
||||||
|
fun useComponentN() {
|
||||||
|
val (x, y) = <!COMPONENT_FUNCTION_MISSING, COMPONENT_FUNCTION_MISSING!>A<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
object D {
|
||||||
|
object getValue {
|
||||||
|
operator fun invoke(thisRef: Any?, property: Any?): Int = 0
|
||||||
|
}
|
||||||
|
object setValue {
|
||||||
|
operator fun invoke(thisRef: Any?, property: Any?, newValue: Int) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X {
|
||||||
|
val component1 = { "UwU" }
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun X.component1(): String = "Not UwU"
|
||||||
|
|
||||||
|
fun useDelegate() {
|
||||||
|
val m by <!DELEGATE_SPECIAL_FUNCTION_MISSING!>D<!>
|
||||||
|
var n by <!DELEGATE_SPECIAL_FUNCTION_MISSING, DELEGATE_SPECIAL_FUNCTION_MISSING!>D<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resolveToExtension() {
|
||||||
|
val (uwu) = X() // KT-65760
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
// ISSUE: KT-65881, KT-65760
|
||||||
|
|
||||||
|
class I: Iterator<Int> {
|
||||||
|
override fun hasNext(): Boolean = false
|
||||||
|
override fun next(): Int = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
object A {
|
||||||
|
object plusAssign {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object minusAssign {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object timesAssign {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object divAssign {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object remAssign {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object unaryPlus {
|
||||||
|
operator fun invoke(): A = A
|
||||||
|
}
|
||||||
|
object unaryMinus {
|
||||||
|
operator fun invoke(): A = A
|
||||||
|
}
|
||||||
|
object not {
|
||||||
|
operator fun invoke(): A = A
|
||||||
|
}
|
||||||
|
object plus {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object minus {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object times {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object div {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object rem {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object get {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object set {
|
||||||
|
operator fun invoke(x: Int, y: Int): A = A
|
||||||
|
}
|
||||||
|
object contains {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object invoke {
|
||||||
|
operator fun invoke(): A = A
|
||||||
|
}
|
||||||
|
object rangeTo {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object rangeUntil {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object compareTo {
|
||||||
|
operator fun invoke(x: Int): A = A
|
||||||
|
}
|
||||||
|
object iterator {
|
||||||
|
operator fun invoke(): I = I()
|
||||||
|
}
|
||||||
|
object component1 {
|
||||||
|
operator fun invoke(): A = A
|
||||||
|
}
|
||||||
|
object component2 {
|
||||||
|
operator fun invoke(): A = A
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun usePlusAssign() { A <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>+=<!> 1 }
|
||||||
|
fun useMinusAssign() { A <!RESOLUTION_TO_CLASSIFIER!>-=<!> 1 }
|
||||||
|
fun useTimesAssign() { A <!RESOLUTION_TO_CLASSIFIER!>*=<!> 1 }
|
||||||
|
fun useDivAssign() { A <!RESOLUTION_TO_CLASSIFIER!>/=<!> 1 }
|
||||||
|
fun useRemAssign() { A <!RESOLUTION_TO_CLASSIFIER!>%=<!> 1 }
|
||||||
|
val useUnaryPlus = <!RESOLUTION_TO_CLASSIFIER!>+<!>A
|
||||||
|
val useUnaryMinus = <!RESOLUTION_TO_CLASSIFIER!>-<!>A
|
||||||
|
val useNot = <!RESOLUTION_TO_CLASSIFIER!>!<!>A
|
||||||
|
val usePlus = A <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>+<!> 1
|
||||||
|
val useMinus = A <!RESOLUTION_TO_CLASSIFIER!>-<!> 1
|
||||||
|
val useTimes = A <!RESOLUTION_TO_CLASSIFIER!>*<!> 1
|
||||||
|
val useDiv = A <!RESOLUTION_TO_CLASSIFIER!>/<!> 1
|
||||||
|
val useRem = A <!RESOLUTION_TO_CLASSIFIER!>%<!> 1
|
||||||
|
val useGet = <!RESOLUTION_TO_CLASSIFIER!>A<!NO_GET_METHOD!>[1]<!><!>
|
||||||
|
fun useSet() { <!RESOLUTION_TO_CLASSIFIER!>A<!NO_SET_METHOD!>[1]<!><!> = 3 }
|
||||||
|
val useContains = 1 <!RESOLUTION_TO_CLASSIFIER!>in<!> A
|
||||||
|
val useNotContains = 1 <!RESOLUTION_TO_CLASSIFIER!>!in<!> A
|
||||||
|
val useInvoke = <!FUNCTION_EXPECTED!>A<!>()
|
||||||
|
val useRangeTo = A <!RESOLUTION_TO_CLASSIFIER!>..<!> 3
|
||||||
|
val useRangeUntil = A <!RESOLUTION_TO_CLASSIFIER!>..<<!> 3
|
||||||
|
val useCompareTo = A <!RESOLUTION_TO_CLASSIFIER!>><!> 2
|
||||||
|
fun useIterator() {
|
||||||
|
for (x in <!ITERATOR_MISSING!>A<!>) { }
|
||||||
|
}
|
||||||
|
fun useComponentN() {
|
||||||
|
val (x, y) = <!COMPONENT_FUNCTION_MISSING, COMPONENT_FUNCTION_MISSING!>A<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
object D {
|
||||||
|
object getValue {
|
||||||
|
operator fun invoke(thisRef: Any?, property: Any?): Int = 0
|
||||||
|
}
|
||||||
|
object setValue {
|
||||||
|
operator fun invoke(thisRef: Any?, property: Any?, newValue: Int) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X {
|
||||||
|
val component1 = { "UwU" }
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun X.<!EXTENSION_FUNCTION_SHADOWED_BY_MEMBER_PROPERTY_WITH_INVOKE!>component1<!>(): String = "Not UwU"
|
||||||
|
|
||||||
|
fun useDelegate() {
|
||||||
|
val m by D
|
||||||
|
var n by <!DELEGATE_SPECIAL_FUNCTION_MISSING!>D<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resolveToExtension() {
|
||||||
|
val (<!PROPERTY_AS_OPERATOR!>uwu<!>) = X() // KT-65760
|
||||||
|
}
|
||||||
@@ -12,11 +12,11 @@ val <X3> C<X3>.getValue: D<X3> get() = TODO()
|
|||||||
operator fun <X4> D<X4>.invoke(x: Any?, y: Any?): X4 = TODO()
|
operator fun <X4> D<X4>.invoke(x: Any?, y: Any?): X4 = TODO()
|
||||||
|
|
||||||
fun foo(a: A<String>, c: C<String>) {
|
fun foo(a: A<String>, c: C<String>) {
|
||||||
val x1 by <!PROPERTY_AS_OPERATOR!>a<!>
|
val x1 by <!NOT_FUNCTION_AS_OPERATOR!>a<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>x1<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>x1<!>
|
||||||
x1.length
|
x1.length
|
||||||
|
|
||||||
val y1 by <!PROPERTY_AS_OPERATOR!>c<!>
|
val y1 by <!NOT_FUNCTION_AS_OPERATOR!>c<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>y1<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>y1<!>
|
||||||
y1.length
|
y1.length
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
val Int.plusAssign: (Int) -> Unit
|
||||||
|
get() = {}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
1 <!NOT_FUNCTION_AS_OPERATOR!>+=<!> 2
|
||||||
|
}
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
|
|
||||||
val Int.plusAssign: (Int) -> Unit
|
val Int.plusAssign: (Int) -> Unit
|
||||||
get() = {}
|
get() = {}
|
||||||
|
|
||||||
|
|||||||
+22
-22
@@ -10,25 +10,25 @@ class A { }
|
|||||||
var a = A()
|
var a = A()
|
||||||
|
|
||||||
val A.inc: I get() = I()
|
val A.inc: I get() = I()
|
||||||
fun useInc() { a<!PROPERTY_AS_OPERATOR, RESULT_TYPE_MISMATCH!>++<!> }
|
fun useInc() { a<!NOT_FUNCTION_AS_OPERATOR, RESULT_TYPE_MISMATCH!>++<!> }
|
||||||
|
|
||||||
val A.dec: I get() = I()
|
val A.dec: I get() = I()
|
||||||
fun useDec() { a<!PROPERTY_AS_OPERATOR, RESULT_TYPE_MISMATCH!>--<!> }
|
fun useDec() { a<!NOT_FUNCTION_AS_OPERATOR, RESULT_TYPE_MISMATCH!>--<!> }
|
||||||
|
|
||||||
val A.plusAssign: I get() = I()
|
val A.plusAssign: I get() = I()
|
||||||
fun usePlusAssign() { a <!PROPERTY_AS_OPERATOR!>+=<!> 1 }
|
fun usePlusAssign() { a <!NOT_FUNCTION_AS_OPERATOR!>+=<!> 1 }
|
||||||
|
|
||||||
val A.minusAssign: I get() = I()
|
val A.minusAssign: I get() = I()
|
||||||
fun useMinusAssign() { a <!PROPERTY_AS_OPERATOR!>-=<!> 1 }
|
fun useMinusAssign() { a <!NOT_FUNCTION_AS_OPERATOR!>-=<!> 1 }
|
||||||
|
|
||||||
val A.timesAssign: I get() = I()
|
val A.timesAssign: I get() = I()
|
||||||
fun useTimesAssign() { a <!PROPERTY_AS_OPERATOR!>*=<!> 1 }
|
fun useTimesAssign() { a <!NOT_FUNCTION_AS_OPERATOR!>*=<!> 1 }
|
||||||
|
|
||||||
val A.divAssign: I get() = I()
|
val A.divAssign: I get() = I()
|
||||||
fun useDivAssign() { a <!PROPERTY_AS_OPERATOR!>/=<!> 1 }
|
fun useDivAssign() { a <!NOT_FUNCTION_AS_OPERATOR!>/=<!> 1 }
|
||||||
|
|
||||||
val A.remAssign: I get() = I()
|
val A.remAssign: I get() = I()
|
||||||
fun useRemAssign() { a <!PROPERTY_AS_OPERATOR!>%=<!> 1 }
|
fun useRemAssign() { a <!NOT_FUNCTION_AS_OPERATOR!>%=<!> 1 }
|
||||||
|
|
||||||
// operators over values
|
// operators over values
|
||||||
|
|
||||||
@@ -36,47 +36,47 @@ class E { }
|
|||||||
val e = E()
|
val e = E()
|
||||||
|
|
||||||
val E.unaryPlus: I get() = I()
|
val E.unaryPlus: I get() = I()
|
||||||
val useUnaryPlus = <!PROPERTY_AS_OPERATOR!>+<!>e
|
val useUnaryPlus = <!NOT_FUNCTION_AS_OPERATOR!>+<!>e
|
||||||
|
|
||||||
val E.unaryMinus: I get() = I()
|
val E.unaryMinus: I get() = I()
|
||||||
val useUnaryMinus = <!PROPERTY_AS_OPERATOR!>-<!>e
|
val useUnaryMinus = <!NOT_FUNCTION_AS_OPERATOR!>-<!>e
|
||||||
|
|
||||||
val E.not: I get() = I()
|
val E.not: I get() = I()
|
||||||
val useNot = <!PROPERTY_AS_OPERATOR!>!<!>e
|
val useNot = <!NOT_FUNCTION_AS_OPERATOR!>!<!>e
|
||||||
|
|
||||||
val E.plus: I get() = I()
|
val E.plus: I get() = I()
|
||||||
val usePlus = e <!PROPERTY_AS_OPERATOR!>+<!> 1
|
val usePlus = e <!NOT_FUNCTION_AS_OPERATOR!>+<!> 1
|
||||||
|
|
||||||
val E.minus: I get() = I()
|
val E.minus: I get() = I()
|
||||||
val useMinus = e <!PROPERTY_AS_OPERATOR!>-<!> 1
|
val useMinus = e <!NOT_FUNCTION_AS_OPERATOR!>-<!> 1
|
||||||
|
|
||||||
val E.times: I get() = I()
|
val E.times: I get() = I()
|
||||||
val useTimes = e <!PROPERTY_AS_OPERATOR!>*<!> 1
|
val useTimes = e <!NOT_FUNCTION_AS_OPERATOR!>*<!> 1
|
||||||
|
|
||||||
val E.div: I get() = I()
|
val E.div: I get() = I()
|
||||||
val useDiv = e <!PROPERTY_AS_OPERATOR!>/<!> 1
|
val useDiv = e <!NOT_FUNCTION_AS_OPERATOR!>/<!> 1
|
||||||
|
|
||||||
val E.rem: I get() = I()
|
val E.rem: I get() = I()
|
||||||
val useRem = e <!PROPERTY_AS_OPERATOR!>%<!> 1
|
val useRem = e <!NOT_FUNCTION_AS_OPERATOR!>%<!> 1
|
||||||
|
|
||||||
val E.get: I get() = I()
|
val E.get: I get() = I()
|
||||||
val useGet = <!PROPERTY_AS_OPERATOR!>e[1]<!>
|
val useGet = <!NOT_FUNCTION_AS_OPERATOR!>e[1]<!>
|
||||||
|
|
||||||
val E.set: I get() = I()
|
val E.set: I get() = I()
|
||||||
fun useSet() { <!PROPERTY_AS_OPERATOR!>e[1]<!> = 3 }
|
fun useSet() { <!NOT_FUNCTION_AS_OPERATOR!>e[1]<!> = 3 }
|
||||||
|
|
||||||
val E.contains: I get() = I()
|
val E.contains: I get() = I()
|
||||||
val useContains = 1 <!PROPERTY_AS_OPERATOR!>in<!> e
|
val useContains = 1 <!NOT_FUNCTION_AS_OPERATOR!>in<!> e
|
||||||
val useNotContains = 1 <!PROPERTY_AS_OPERATOR, PROPERTY_AS_OPERATOR!>!in<!> e
|
val useNotContains = 1 <!NOT_FUNCTION_AS_OPERATOR, NOT_FUNCTION_AS_OPERATOR!>!in<!> e
|
||||||
|
|
||||||
val E.invoke: I get() = I()
|
val E.invoke: I get() = I()
|
||||||
val useInvoke = <!NONE_APPLICABLE!>e<!>()
|
val useInvoke = <!NONE_APPLICABLE!>e<!>()
|
||||||
|
|
||||||
val E.rangeTo: I get() = I()
|
val E.rangeTo: I get() = I()
|
||||||
val useRangeTo = e <!PROPERTY_AS_OPERATOR!>..<!> 3
|
val useRangeTo = e <!NOT_FUNCTION_AS_OPERATOR!>..<!> 3
|
||||||
|
|
||||||
val E.rangeUntil: I get() = I()
|
val E.rangeUntil: I get() = I()
|
||||||
val useRangeUntil = e <!PROPERTY_AS_OPERATOR!>..<<!> 3
|
val useRangeUntil = e <!NOT_FUNCTION_AS_OPERATOR!>..<<!> 3
|
||||||
|
|
||||||
val E.compareTo: I get() = I()
|
val E.compareTo: I get() = I()
|
||||||
val useCompareTo = e <!PROPERTY_AS_OPERATOR!>><!> 2
|
val useCompareTo = e <!NOT_FUNCTION_AS_OPERATOR!>><!> 2
|
||||||
|
|||||||
Vendored
+23
@@ -0,0 +1,23 @@
|
|||||||
|
// ISSUE: KT-59715
|
||||||
|
|
||||||
|
class FunctionComponent {
|
||||||
|
val component1: () -> String = { "hello" }
|
||||||
|
}
|
||||||
|
|
||||||
|
class I {
|
||||||
|
operator fun invoke(): String = "hello"
|
||||||
|
}
|
||||||
|
|
||||||
|
class InvokeComponent {
|
||||||
|
val component1: I = I()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test_1(c: FunctionComponent) {
|
||||||
|
val (<!NOT_FUNCTION_AS_OPERATOR!>x<!>) = FunctionComponent()
|
||||||
|
val (<!NOT_FUNCTION_AS_OPERATOR!>y<!>) = c
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test_2(c: InvokeComponent) {
|
||||||
|
val (<!NOT_FUNCTION_AS_OPERATOR!>x<!>) = FunctionComponent()
|
||||||
|
val (<!NOT_FUNCTION_AS_OPERATOR!>y<!>) = c
|
||||||
|
}
|
||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// ISSUE: KT-59715
|
// ISSUE: KT-59715
|
||||||
|
|
||||||
class FunctionComponent {
|
class FunctionComponent {
|
||||||
|
|||||||
Generated
+6
@@ -1023,6 +1023,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OperatorConventions.kt")
|
||||||
|
public void testOperatorConventions() {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/OperatorConventions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("Operators.kt")
|
@TestMetadata("Operators.kt")
|
||||||
public void testOperators() {
|
public void testOperators() {
|
||||||
|
|||||||
+15
-15
@@ -25,7 +25,7 @@ fun case1() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class B() {
|
class B() {
|
||||||
val p: String by <!DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, PROPERTY_AS_OPERATOR!>Delegate()<!> // DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE expected
|
val p: String by <!DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, NOT_FUNCTION_AS_OPERATOR!>Delegate()<!> // DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE expected
|
||||||
}
|
}
|
||||||
|
|
||||||
class Delegate {
|
class Delegate {
|
||||||
@@ -50,7 +50,7 @@ fun case2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class B() {
|
class B() {
|
||||||
var p: String by <!DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, PROPERTY_AS_OPERATOR, PROPERTY_AS_OPERATOR!>Delegate()<!> // DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE expected
|
var p: String by <!DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, NOT_FUNCTION_AS_OPERATOR, NOT_FUNCTION_AS_OPERATOR!>Delegate()<!> // DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE expected
|
||||||
}
|
}
|
||||||
|
|
||||||
class Delegate {
|
class Delegate {
|
||||||
@@ -109,14 +109,14 @@ class B() {
|
|||||||
|
|
||||||
fun case3() {
|
fun case3() {
|
||||||
var b = B()
|
var b = B()
|
||||||
b <!PROPERTY_AS_OPERATOR!>+<!> 5
|
b <!NOT_FUNCTION_AS_OPERATOR!>+<!> 5
|
||||||
b <!PROPERTY_AS_OPERATOR!>-<!> 5
|
b <!NOT_FUNCTION_AS_OPERATOR!>-<!> 5
|
||||||
b <!PROPERTY_AS_OPERATOR!><<!> 5
|
b <!NOT_FUNCTION_AS_OPERATOR!><<!> 5
|
||||||
b <!PROPERTY_AS_OPERATOR!>>=<!> 5
|
b <!NOT_FUNCTION_AS_OPERATOR!>>=<!> 5
|
||||||
1 <!PROPERTY_AS_OPERATOR!>in<!> b
|
1 <!NOT_FUNCTION_AS_OPERATOR!>in<!> b
|
||||||
<!PROPERTY_AS_OPERATOR!>b[2]<!>
|
<!NOT_FUNCTION_AS_OPERATOR!>b[2]<!>
|
||||||
<!PROPERTY_AS_OPERATOR!>b[3]<!> = 4
|
<!NOT_FUNCTION_AS_OPERATOR!>b[3]<!> = 4
|
||||||
<!PROPERTY_AS_OPERATOR!>+<!>b
|
<!NOT_FUNCTION_AS_OPERATOR!>+<!>b
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE: TestCase4.kt
|
// FILE: TestCase4.kt
|
||||||
@@ -135,8 +135,8 @@ class B(val minusAssign: Assign = Assign()) {
|
|||||||
|
|
||||||
fun case3() {
|
fun case3() {
|
||||||
var b = B()
|
var b = B()
|
||||||
b <!PROPERTY_AS_OPERATOR!>+=<!> 2
|
b <!NOT_FUNCTION_AS_OPERATOR!>+=<!> 2
|
||||||
b <!PROPERTY_AS_OPERATOR!>-=<!> 3
|
b <!NOT_FUNCTION_AS_OPERATOR!>-=<!> 3
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE: TestCase5.kt
|
// FILE: TestCase5.kt
|
||||||
@@ -175,7 +175,7 @@ class B(var a: Int = 0) {
|
|||||||
val plus :E =TODO()
|
val plus :E =TODO()
|
||||||
|
|
||||||
fun foo(b: B){
|
fun foo(b: B){
|
||||||
this <!PROPERTY_AS_OPERATOR!>+<!> 1
|
this <!NOT_FUNCTION_AS_OPERATOR!>+<!> 1
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun invoke(value: Int) = B()
|
operator fun invoke(value: Int) = B()
|
||||||
@@ -193,7 +193,7 @@ package testPackCase7
|
|||||||
|
|
||||||
fun case7 () {
|
fun case7 () {
|
||||||
val iterable: Iterable = Iterable(Inv('s'))
|
val iterable: Iterable = Iterable(Inv('s'))
|
||||||
for (i in <!PROPERTY_AS_OPERATOR!>iterable<!>) {
|
for (i in <!NOT_FUNCTION_AS_OPERATOR!>iterable<!>) {
|
||||||
println(i)
|
println(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,7 +226,7 @@ package testPackCase8
|
|||||||
|
|
||||||
fun case8 () {
|
fun case8 () {
|
||||||
val iterable: Iterable = Iterable()
|
val iterable: Iterable = Iterable()
|
||||||
for (i in <!PROPERTY_AS_OPERATOR!>iterable<!>) {
|
for (i in <!NOT_FUNCTION_AS_OPERATOR!>iterable<!>) {
|
||||||
println(i)
|
println(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ class B() {
|
|||||||
fun case7(){
|
fun case7(){
|
||||||
var b =B()
|
var b =B()
|
||||||
b<!ASSIGN_OPERATOR_AMBIGUITY!>+=<!>1 //ASSIGN_OPERATOR_AMBIGUITY
|
b<!ASSIGN_OPERATOR_AMBIGUITY!>+=<!>1 //ASSIGN_OPERATOR_AMBIGUITY
|
||||||
this <!PROPERTY_AS_OPERATOR!>+=<!> 1 //ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT, PROPERTY_AS_OPERATOR
|
this <!NOT_FUNCTION_AS_OPERATOR!>+=<!> 1 //ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT, PROPERTY_AS_OPERATOR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -25,7 +25,7 @@ class Case1() {
|
|||||||
fun foo(e: E) {
|
fun foo(e: E) {
|
||||||
|
|
||||||
if (e.plus != null) {
|
if (e.plus != null) {
|
||||||
run { e <!PROPERTY_AS_OPERATOR!>+<!> 1 }
|
run { e <!NOT_FUNCTION_AS_OPERATOR!>+<!> 1 }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[PROPERTY_AS_OPERATOR] (ok)
|
[PROPERTY_AS_OPERATOR] (ok)
|
||||||
@@ -33,7 +33,7 @@ class Case1() {
|
|||||||
[UNSAFE_OPERATOR_CALL] (nok)
|
[UNSAFE_OPERATOR_CALL] (nok)
|
||||||
Operator call corresponds to a dot-qualified call 'e.plus(1)' which is not allowed on a nullable receiver 'e'.
|
Operator call corresponds to a dot-qualified call 'e.plus(1)' which is not allowed on a nullable receiver 'e'.
|
||||||
*/
|
*/
|
||||||
e <!PROPERTY_AS_OPERATOR!>+<!> 1
|
e <!NOT_FUNCTION_AS_OPERATOR!>+<!> 1
|
||||||
|
|
||||||
e.plus.invoke(1) //ok
|
e.plus.invoke(1) //ok
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user