[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,
|
||||
)
|
||||
}
|
||||
add(FirErrors.PROPERTY_AS_OPERATOR) { firDiagnostic ->
|
||||
PropertyAsOperatorImpl(
|
||||
firSymbolBuilder.variableLikeBuilder.buildVariableSymbol(firDiagnostic.a),
|
||||
add(FirErrors.NOT_FUNCTION_AS_OPERATOR) { firDiagnostic ->
|
||||
NotFunctionAsOperatorImpl(
|
||||
firDiagnostic.a,
|
||||
firSymbolBuilder.buildSymbol(firDiagnostic.b),
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
|
||||
+4
-3
@@ -3156,9 +3156,10 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
val operator: String
|
||||
}
|
||||
|
||||
interface PropertyAsOperator : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = PropertyAsOperator::class
|
||||
val property: KtVariableSymbol
|
||||
interface NotFunctionAsOperator : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = NotFunctionAsOperator::class
|
||||
val elementName: String
|
||||
val elementSymbol: KtSymbol
|
||||
}
|
||||
|
||||
interface DslScopeViolation : KtFirDiagnostic<PsiElement> {
|
||||
|
||||
+4
-3
@@ -3800,11 +3800,12 @@ internal class AssignmentOperatorShouldReturnUnitImpl(
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<KtExpression>(firDiagnostic, token), KtFirDiagnostic.AssignmentOperatorShouldReturnUnit
|
||||
|
||||
internal class PropertyAsOperatorImpl(
|
||||
override val property: KtVariableSymbol,
|
||||
internal class NotFunctionAsOperatorImpl(
|
||||
override val elementName: String,
|
||||
override val elementSymbol: KtSymbol,
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.PropertyAsOperator
|
||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.NotFunctionAsOperator
|
||||
|
||||
internal class DslScopeViolationImpl(
|
||||
override val calleeSymbol: KtSymbol,
|
||||
|
||||
+6
@@ -1023,6 +1023,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
|
||||
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("OperatorConventions.kt")
|
||||
public void testOperatorConventions() {
|
||||
runTest("compiler/testData/diagnostics/tests/OperatorConventions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("Operators.kt")
|
||||
public void testOperators() {
|
||||
|
||||
+6
@@ -1023,6 +1023,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
|
||||
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("OperatorConventions.kt")
|
||||
public void testOperatorConventions() {
|
||||
runTest("compiler/testData/diagnostics/tests/OperatorConventions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("Operators.kt")
|
||||
public void testOperators() {
|
||||
|
||||
+6
@@ -1023,6 +1023,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
|
||||
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("OperatorConventions.kt")
|
||||
public void testOperatorConventions() {
|
||||
runTest("compiler/testData/diagnostics/tests/OperatorConventions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("Operators.kt")
|
||||
public void testOperators() {
|
||||
|
||||
+6
@@ -1023,6 +1023,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
|
||||
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("OperatorConventions.kt")
|
||||
public void testOperatorConventions() {
|
||||
runTest("compiler/testData/diagnostics/tests/OperatorConventions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("Operators.kt")
|
||||
public void testOperators() {
|
||||
|
||||
+3
-2
@@ -1585,8 +1585,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<FirNamedFunctionSymbol>("functionSymbol")
|
||||
parameter<String>("operator")
|
||||
}
|
||||
val PROPERTY_AS_OPERATOR by error<PsiElement>(PositioningStrategy.OPERATOR) {
|
||||
parameter<FirPropertySymbol>("property")
|
||||
val NOT_FUNCTION_AS_OPERATOR by error<PsiElement>(PositioningStrategy.OPERATOR) {
|
||||
parameter<String>("elementName")
|
||||
parameter<FirBasedSymbol<*>>("elementSymbol")
|
||||
}
|
||||
val DSL_SCOPE_VIOLATION by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) {
|
||||
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 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 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)
|
||||
|
||||
// Type alias
|
||||
|
||||
+1
-1
@@ -533,7 +533,7 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set<String> = setOf(
|
||||
"FORBIDDEN_IDENTITY_EQUALS",
|
||||
"INC_DEC_SHOULD_NOT_RETURN_UNIT",
|
||||
"ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT",
|
||||
"PROPERTY_AS_OPERATOR",
|
||||
"NOT_FUNCTION_AS_OPERATOR",
|
||||
"DSL_SCOPE_VIOLATION",
|
||||
"TOPLEVEL_TYPEALIASES_ONLY",
|
||||
"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.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
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.expressions.*
|
||||
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.symbols.impl.FirPropertySymbol
|
||||
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.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
|
||||
object FirConventionFunctionCallChecker : FirFunctionCallChecker(MppCheckerKind.Common) {
|
||||
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.
|
||||
checkPropertyAsOperator(expression, expression.dispatchReceiver, context, reporter)
|
||||
checkPropertyAsOperator(expression, expression.extensionReceiver, context, reporter)
|
||||
checkNotFunctionAsOperator(expression, expression.dispatchReceiver, context, reporter)
|
||||
checkNotFunctionAsOperator(expression, expression.extensionReceiver, context, reporter)
|
||||
val calleeReference = expression.calleeReference as? FirErrorNamedReference ?: return
|
||||
val diagnostic = calleeReference.diagnostic as? ConeUnresolvedNameError ?: return
|
||||
|
||||
@@ -39,7 +37,7 @@ object FirConventionFunctionCallChecker : FirFunctionCallChecker(MppCheckerKind.
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPropertyAsOperator(
|
||||
private fun checkNotFunctionAsOperator(
|
||||
callExpression: FirFunctionCall,
|
||||
receiver: FirExpression?,
|
||||
context: CheckerContext,
|
||||
@@ -47,9 +45,27 @@ object FirConventionFunctionCallChecker : FirFunctionCallChecker(MppCheckerKind.
|
||||
) {
|
||||
if (callExpression.dispatchReceiver?.resolvedType is ConeDynamicType) return
|
||||
// KT-61905: TODO: Return also in case of error type.
|
||||
val unwrapped = receiver?.unwrapSmartcastExpression()
|
||||
if (unwrapped !is FirPropertyAccessExpression) return
|
||||
val diagnostic = unwrapped.nonFatalDiagnostics.firstIsInstanceOrNull<ConePropertyAsOperator>() ?: return
|
||||
reporter.reportOn(callExpression.calleeReference.source, FirErrors.PROPERTY_AS_OPERATOR, diagnostic.symbol, context)
|
||||
val unwrapped = receiver?.unwrapSmartcastExpression() ?: return
|
||||
val nonFatalDiagnostics = when (unwrapped) {
|
||||
is FirQualifiedAccessExpression -> unwrapped.nonFatalDiagnostics
|
||||
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.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
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_MULTIPLATFORM_COMPILATION
|
||||
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_LAMBDA_EXPRESSION
|
||||
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.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.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_INITIALIZER_IN_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALIZER_NO_BACKING_FIELD
|
||||
@@ -2410,8 +2410,9 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
TO_STRING
|
||||
)
|
||||
map.put(
|
||||
PROPERTY_AS_OPERATOR,
|
||||
"Property ''{0}'' cannot be used as operator.",
|
||||
NOT_FUNCTION_AS_OPERATOR,
|
||||
"{0} ''{1}'' cannot be used as operator.",
|
||||
STRING,
|
||||
SYMBOL
|
||||
)
|
||||
map.put(
|
||||
|
||||
@@ -124,15 +124,12 @@ class CandidateFactory private constructor(
|
||||
result.addDiagnostic(NoCompanionObject)
|
||||
}
|
||||
if (callInfo.origin == FirFunctionCallOrigin.Operator) {
|
||||
val propertySymbol = when {
|
||||
symbol is FirPropertySymbol -> symbol
|
||||
callInfo.candidateForCommonInvokeReceiver != null -> callInfo.candidateForCommonInvokeReceiver.symbol as? FirPropertySymbol
|
||||
else -> null
|
||||
}
|
||||
if (propertySymbol != null) {
|
||||
// Flag all property references that are resolved from an convention operator call.
|
||||
result.addDiagnostic(PropertyAsOperator(propertySymbol))
|
||||
val normalizedSymbol = when (symbol) {
|
||||
!is FirFunctionSymbol -> symbol
|
||||
else -> callInfo.candidateForCommonInvokeReceiver?.symbol?.takeIf { it !is FirFunctionSymbol }
|
||||
}
|
||||
// Flag all references that are resolved from an convention operator call.
|
||||
normalizedSymbol?.let { result.addDiagnostic(NotFunctionAsOperator(normalizedSymbol)) }
|
||||
}
|
||||
if (symbol is FirPropertySymbol &&
|
||||
!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.resolve.*
|
||||
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.types.*
|
||||
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.TypeApproximatorConfiguration
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
|
||||
internal class FirInvokeResolveTowerExtension(
|
||||
private val context: ResolutionContext,
|
||||
@@ -288,18 +289,26 @@ private fun BodyResolveComponents.createExplicitReceiverForInvoke(
|
||||
invokeBuiltinExtensionMode: Boolean,
|
||||
extensionReceiverExpression: 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) {
|
||||
is FirCallableSymbol<*> -> createExplicitReceiverForInvokeByCallable(
|
||||
candidate, info, invokeBuiltinExtensionMode, extensionReceiverExpression, symbol
|
||||
candidate, info, invokeBuiltinExtensionMode, extensionReceiverExpression, symbol, notFunctionAsOperatorDiagnostics
|
||||
)
|
||||
is FirRegularClassSymbol -> buildResolvedQualifierForClass(
|
||||
symbol,
|
||||
sourceElement = info.fakeSourceForImplicitInvokeCallReceiver
|
||||
sourceElement = info.fakeSourceForImplicitInvokeCallReceiver,
|
||||
nonFatalDiagnostics = notFunctionAsOperatorDiagnostics,
|
||||
)
|
||||
is FirTypeAliasSymbol -> {
|
||||
val type = symbol.fir.expandedTypeRef.coneTypeUnsafe<ConeClassLikeType>().fullyExpandedType(session)
|
||||
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()
|
||||
}
|
||||
@@ -310,7 +319,8 @@ private fun BodyResolveComponents.createExplicitReceiverForInvokeByCallable(
|
||||
info: CallInfo,
|
||||
invokeBuiltinExtensionMode: Boolean,
|
||||
extensionReceiverExpression: FirExpression?,
|
||||
symbol: FirCallableSymbol<*>
|
||||
symbol: FirCallableSymbol<*>,
|
||||
nonFatalDiagnostics: List<ConeNotFunctionAsOperator>,
|
||||
): FirExpression {
|
||||
return FirPropertyAccessExpressionBuilder().apply {
|
||||
val fakeSource = info.fakeSourceForImplicitInvokeCallReceiver
|
||||
@@ -337,9 +347,7 @@ private fun BodyResolveComponents.createExplicitReceiverForInvokeByCallable(
|
||||
explicitReceiver = info.explicitReceiver
|
||||
}
|
||||
|
||||
if (candidate.currentApplicability == CandidateApplicability.K2_PROPERTY_AS_OPERATOR) {
|
||||
nonFatalDiagnostics.add(ConePropertyAsOperator(candidate.symbol as FirPropertySymbol))
|
||||
}
|
||||
this.nonFatalDiagnostics.addAll(nonFatalDiagnostics)
|
||||
|
||||
candidate.updateSourcesOfReceivers()
|
||||
|
||||
|
||||
+3
-3
@@ -170,11 +170,11 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
|
||||
qualifiedAccessExpression.replaceContextReceiverArguments(subCandidate.contextReceiverArguments())
|
||||
|
||||
subCandidate.diagnostics.firstIsInstanceOrNull<PropertyAsOperator>()?.let { propertyAsOperator ->
|
||||
val conePropertyAsOperator = ConePropertyAsOperator(propertyAsOperator.propertySymbol)
|
||||
subCandidate.diagnostics.firstIsInstanceOrNull<NotFunctionAsOperator>()?.let { propertyAsOperator ->
|
||||
val coneNotFunctionAsOperator = ConeNotFunctionAsOperator(propertyAsOperator.symbol)
|
||||
val nonFatalDiagnostics: List<ConeDiagnostic> = buildList {
|
||||
addAll(qualifiedAccessExpression.nonFatalDiagnostics)
|
||||
add(conePropertyAsOperator)
|
||||
add(coneNotFunctionAsOperator)
|
||||
}
|
||||
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.impl.FirConstructorSymbol
|
||||
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.ConeTypeVariable
|
||||
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 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)
|
||||
|
||||
|
||||
+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"
|
||||
}
|
||||
|
||||
class ConePropertyAsOperator(val symbol: FirPropertySymbol) : ConeDiagnostic {
|
||||
override val reason: String get() = "Cannot use a property as an operator"
|
||||
class ConeNotFunctionAsOperator(val symbol: FirBasedSymbol<*>) : ConeDiagnostic {
|
||||
override val reason: String get() = "Cannot use not function as an operator"
|
||||
}
|
||||
|
||||
class ConeUnknownLambdaParameterTypeDiagnostic : ConeDiagnostic {
|
||||
|
||||
+2
-2
@@ -89,10 +89,10 @@ enum class CandidateApplicability {
|
||||
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.
|
||||
*/
|
||||
K2_PROPERTY_AS_OPERATOR,
|
||||
K2_NOT_FUNCTION_AS_OPERATOR,
|
||||
|
||||
/**
|
||||
* 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()
|
||||
|
||||
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<!>
|
||||
x1.length
|
||||
|
||||
val y1 by <!PROPERTY_AS_OPERATOR!>c<!>
|
||||
val y1 by <!NOT_FUNCTION_AS_OPERATOR!>c<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>y1<!>
|
||||
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
|
||||
get() = {}
|
||||
|
||||
|
||||
+22
-22
@@ -10,25 +10,25 @@ class A { }
|
||||
var a = A()
|
||||
|
||||
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()
|
||||
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()
|
||||
fun usePlusAssign() { a <!PROPERTY_AS_OPERATOR!>+=<!> 1 }
|
||||
fun usePlusAssign() { a <!NOT_FUNCTION_AS_OPERATOR!>+=<!> 1 }
|
||||
|
||||
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()
|
||||
fun useTimesAssign() { a <!PROPERTY_AS_OPERATOR!>*=<!> 1 }
|
||||
fun useTimesAssign() { a <!NOT_FUNCTION_AS_OPERATOR!>*=<!> 1 }
|
||||
|
||||
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()
|
||||
fun useRemAssign() { a <!PROPERTY_AS_OPERATOR!>%=<!> 1 }
|
||||
fun useRemAssign() { a <!NOT_FUNCTION_AS_OPERATOR!>%=<!> 1 }
|
||||
|
||||
// operators over values
|
||||
|
||||
@@ -36,47 +36,47 @@ class E { }
|
||||
val e = E()
|
||||
|
||||
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 useUnaryMinus = <!PROPERTY_AS_OPERATOR!>-<!>e
|
||||
val useUnaryMinus = <!NOT_FUNCTION_AS_OPERATOR!>-<!>e
|
||||
|
||||
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 usePlus = e <!PROPERTY_AS_OPERATOR!>+<!> 1
|
||||
val usePlus = e <!NOT_FUNCTION_AS_OPERATOR!>+<!> 1
|
||||
|
||||
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 useTimes = e <!PROPERTY_AS_OPERATOR!>*<!> 1
|
||||
val useTimes = e <!NOT_FUNCTION_AS_OPERATOR!>*<!> 1
|
||||
|
||||
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 useRem = e <!PROPERTY_AS_OPERATOR!>%<!> 1
|
||||
val useRem = e <!NOT_FUNCTION_AS_OPERATOR!>%<!> 1
|
||||
|
||||
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()
|
||||
fun useSet() { <!PROPERTY_AS_OPERATOR!>e[1]<!> = 3 }
|
||||
fun useSet() { <!NOT_FUNCTION_AS_OPERATOR!>e[1]<!> = 3 }
|
||||
|
||||
val E.contains: I get() = I()
|
||||
val useContains = 1 <!PROPERTY_AS_OPERATOR!>in<!> e
|
||||
val useNotContains = 1 <!PROPERTY_AS_OPERATOR, PROPERTY_AS_OPERATOR!>!in<!> e
|
||||
val useContains = 1 <!NOT_FUNCTION_AS_OPERATOR!>in<!> e
|
||||
val useNotContains = 1 <!NOT_FUNCTION_AS_OPERATOR, NOT_FUNCTION_AS_OPERATOR!>!in<!> e
|
||||
|
||||
val E.invoke: I get() = I()
|
||||
val useInvoke = <!NONE_APPLICABLE!>e<!>()
|
||||
|
||||
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 useRangeUntil = e <!PROPERTY_AS_OPERATOR!>..<<!> 3
|
||||
val useRangeUntil = e <!NOT_FUNCTION_AS_OPERATOR!>..<<!> 3
|
||||
|
||||
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
|
||||
|
||||
class FunctionComponent {
|
||||
|
||||
Generated
+6
@@ -1023,6 +1023,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/OperatorChecks.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("OperatorConventions.kt")
|
||||
public void testOperatorConventions() {
|
||||
runTest("compiler/testData/diagnostics/tests/OperatorConventions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("Operators.kt")
|
||||
public void testOperators() {
|
||||
|
||||
+15
-15
@@ -25,7 +25,7 @@ fun case1() {
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -50,7 +50,7 @@ fun case2() {
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -109,14 +109,14 @@ class B() {
|
||||
|
||||
fun case3() {
|
||||
var b = B()
|
||||
b <!PROPERTY_AS_OPERATOR!>+<!> 5
|
||||
b <!PROPERTY_AS_OPERATOR!>-<!> 5
|
||||
b <!PROPERTY_AS_OPERATOR!><<!> 5
|
||||
b <!PROPERTY_AS_OPERATOR!>>=<!> 5
|
||||
1 <!PROPERTY_AS_OPERATOR!>in<!> b
|
||||
<!PROPERTY_AS_OPERATOR!>b[2]<!>
|
||||
<!PROPERTY_AS_OPERATOR!>b[3]<!> = 4
|
||||
<!PROPERTY_AS_OPERATOR!>+<!>b
|
||||
b <!NOT_FUNCTION_AS_OPERATOR!>+<!> 5
|
||||
b <!NOT_FUNCTION_AS_OPERATOR!>-<!> 5
|
||||
b <!NOT_FUNCTION_AS_OPERATOR!><<!> 5
|
||||
b <!NOT_FUNCTION_AS_OPERATOR!>>=<!> 5
|
||||
1 <!NOT_FUNCTION_AS_OPERATOR!>in<!> b
|
||||
<!NOT_FUNCTION_AS_OPERATOR!>b[2]<!>
|
||||
<!NOT_FUNCTION_AS_OPERATOR!>b[3]<!> = 4
|
||||
<!NOT_FUNCTION_AS_OPERATOR!>+<!>b
|
||||
}
|
||||
|
||||
// FILE: TestCase4.kt
|
||||
@@ -135,8 +135,8 @@ class B(val minusAssign: Assign = Assign()) {
|
||||
|
||||
fun case3() {
|
||||
var b = B()
|
||||
b <!PROPERTY_AS_OPERATOR!>+=<!> 2
|
||||
b <!PROPERTY_AS_OPERATOR!>-=<!> 3
|
||||
b <!NOT_FUNCTION_AS_OPERATOR!>+=<!> 2
|
||||
b <!NOT_FUNCTION_AS_OPERATOR!>-=<!> 3
|
||||
}
|
||||
|
||||
// FILE: TestCase5.kt
|
||||
@@ -175,7 +175,7 @@ class B(var a: Int = 0) {
|
||||
val plus :E =TODO()
|
||||
|
||||
fun foo(b: B){
|
||||
this <!PROPERTY_AS_OPERATOR!>+<!> 1
|
||||
this <!NOT_FUNCTION_AS_OPERATOR!>+<!> 1
|
||||
}
|
||||
|
||||
operator fun invoke(value: Int) = B()
|
||||
@@ -193,7 +193,7 @@ package testPackCase7
|
||||
|
||||
fun case7 () {
|
||||
val iterable: Iterable = Iterable(Inv('s'))
|
||||
for (i in <!PROPERTY_AS_OPERATOR!>iterable<!>) {
|
||||
for (i in <!NOT_FUNCTION_AS_OPERATOR!>iterable<!>) {
|
||||
println(i)
|
||||
}
|
||||
}
|
||||
@@ -226,7 +226,7 @@ package testPackCase8
|
||||
|
||||
fun case8 () {
|
||||
val iterable: Iterable = Iterable()
|
||||
for (i in <!PROPERTY_AS_OPERATOR!>iterable<!>) {
|
||||
for (i in <!NOT_FUNCTION_AS_OPERATOR!>iterable<!>) {
|
||||
println(i)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ class B() {
|
||||
fun case7(){
|
||||
var b =B()
|
||||
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) {
|
||||
|
||||
if (e.plus != null) {
|
||||
run { e <!PROPERTY_AS_OPERATOR!>+<!> 1 }
|
||||
run { e <!NOT_FUNCTION_AS_OPERATOR!>+<!> 1 }
|
||||
|
||||
/*
|
||||
[PROPERTY_AS_OPERATOR] (ok)
|
||||
@@ -33,7 +33,7 @@ class Case1() {
|
||||
[UNSAFE_OPERATOR_CALL] (nok)
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user