From a5f34a880cbe1694207643ff1e13b8da91cec14f Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 7 Jul 2020 12:10:19 +0300 Subject: [PATCH] [FIR] Fix computeTypeArguments() & add diagnostic for type args --- .../projectionsOnNonClassTypeArguments.kt | 8 +++++ .../projectionsOnNonClassTypeArguments.txt | 18 ++++++++++ .../fir/FirDiagnosticsTestGenerated.java | 5 +++ ...DiagnosticsWithLightTreeTestGenerated.java | 5 +++ .../expression/DefaultExpressionCheckers.kt | 1 + ...rojectionsOnNonClassTypeArgumentChecker.kt | 36 +++++++++++++++++++ .../fir/analysis/diagnostics/FirErrors.kt | 3 ++ ...rCallCompletionResultsWriterTransformer.kt | 8 ++++- .../ProjectionOnFunctionArgumentErrror.fir.kt | 2 +- .../tests/StarsInFunctionCalls.fir.kt | 10 +++--- .../incompatibleVarianceModifiers.fir.kt | 2 +- .../nullCalleeExpression.fir.kt | 2 +- .../projectionsInTypeAliasConstructor.fir.kt | 4 +-- .../typeAliasConstructorForProjection.fir.kt | 2 +- 14 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/projectionsOnNonClassTypeArguments.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/projectionsOnNonClassTypeArguments.txt create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirProjectionsOnNonClassTypeArgumentChecker.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/projectionsOnNonClassTypeArguments.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/projectionsOnNonClassTypeArguments.kt new file mode 100644 index 00000000000..b4af0c1ef1b --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/projectionsOnNonClassTypeArguments.kt @@ -0,0 +1,8 @@ +class A +class B + +fun test() { + val a1 = A<in Int, out B>() + val a2 = A() + val a3 = A<*, *>() +} diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/projectionsOnNonClassTypeArguments.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/projectionsOnNonClassTypeArguments.txt new file mode 100644 index 00000000000..54f2c29fd25 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/projectionsOnNonClassTypeArguments.txt @@ -0,0 +1,18 @@ +FILE: projectionsOnNonClassTypeArguments.kt + public final class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + } + public final class B : R|kotlin/Any| { + public constructor(): R|B| { + super() + } + + } + public final fun test(): R|kotlin/Unit| { + lval a1: R|A| = R|/A.A|() + lval a2: R|A| = R|/A.A|() + lval a3: R|A| = R|/A.A|<*, *>() + } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 84eefc0e428..c36753d477f 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -901,6 +901,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/notASupertype.kt"); } + @TestMetadata("projectionsOnNonClassTypeArguments.kt") + public void testProjectionsOnNonClassTypeArguments() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/projectionsOnNonClassTypeArguments.kt"); + } + @TestMetadata("qualifiedSupertypeExtendedByOtherSupertype.kt") public void testQualifiedSupertypeExtendedByOtherSupertype() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/qualifiedSupertypeExtendedByOtherSupertype.kt"); diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 0e72ce8b510..65d8304c462 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -901,6 +901,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/notASupertype.kt"); } + @TestMetadata("projectionsOnNonClassTypeArguments.kt") + public void testProjectionsOnNonClassTypeArguments() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/projectionsOnNonClassTypeArguments.kt"); + } + @TestMetadata("qualifiedSupertypeExtendedByOtherSupertype.kt") public void testQualifiedSupertypeExtendedByOtherSupertype() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/qualifiedSupertypeExtendedByOtherSupertype.kt"); diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/DefaultExpressionCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/DefaultExpressionCheckers.kt index bef3bb04538..34e3ed7f3fc 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/DefaultExpressionCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/DefaultExpressionCheckers.kt @@ -13,6 +13,7 @@ object CommonExpressionCheckers : ExpressionCheckers() { FirSuperclassNotAccessibleFromInterfaceChecker, FirAbstractSuperCallChecker, FirQualifiedSupertypeExtendedByOtherSupertypeChecker, + FirProjectionsOnNonClassTypeArgumentChecker ) override val functionCallCheckers: List = listOf() } \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirProjectionsOnNonClassTypeArgumentChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirProjectionsOnNonClassTypeArgumentChecker.kt new file mode 100644 index 00000000000..8d6671347e5 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirProjectionsOnNonClassTypeArgumentChecker.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.analysis.checkers.expression + +import org.jetbrains.kotlin.fir.FirSourceElement +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression +import org.jetbrains.kotlin.fir.types.FirStarProjection +import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance +import org.jetbrains.kotlin.types.Variance + +object FirProjectionsOnNonClassTypeArgumentChecker : FirQualifiedAccessChecker() { + override fun check(functionCall: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) { + for (it in functionCall.typeArguments) { + when (it) { + is FirStarProjection -> reporter.report(it.source) + is FirTypeProjectionWithVariance -> { + if (it.variance != Variance.INVARIANT) { + reporter.report(it.source) + } + } + } + } + } + + private fun DiagnosticReporter.report(source: FirSourceElement?) { + source?.let { + report(FirErrors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(it)) + } + } +} \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 2125a617411..4bb3c5754d1 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -78,6 +78,9 @@ object FirErrors { val DEPRECATED_MODIFIER_PAIR by error2() val INCOMPATIBLE_MODIFIERS by error2() + // projection + val PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT by error0() + // Control flow diagnostics val UNINITIALIZED_VARIABLE by error1() } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index b1c70a05b13..f87b3df5347 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef +import org.jetbrains.kotlin.fir.types.builder.buildStarProjection import org.jetbrains.kotlin.fir.types.builder.buildTypeProjectionWithVariance import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.fir.visitors.* @@ -331,7 +332,7 @@ class FirCallCompletionResultsWriterTransformer( private fun computeTypeArguments( access: FirQualifiedAccess, candidate: Candidate - ): List { + ): List { return computeTypeArgumentTypes(candidate) .mapIndexed { index, type -> when (val argument = access.typeArguments.getOrNull(index)) { @@ -343,6 +344,11 @@ class FirCallCompletionResultsWriterTransformer( variance = argument.variance } } + is FirStarProjection -> { + buildStarProjection { + source = argument.source + } + } else -> { buildTypeProjectionWithVariance { source = argument?.source diff --git a/compiler/testData/diagnostics/tests/ProjectionOnFunctionArgumentErrror.fir.kt b/compiler/testData/diagnostics/tests/ProjectionOnFunctionArgumentErrror.fir.kt index 43c935eb9b4..e8b80c8f4ca 100644 --- a/compiler/testData/diagnostics/tests/ProjectionOnFunctionArgumentErrror.fir.kt +++ b/compiler/testData/diagnostics/tests/ProjectionOnFunctionArgumentErrror.fir.kt @@ -1,4 +1,4 @@ fun test() { fun foo(){} - foo() + foo<in Int>() } diff --git a/compiler/testData/diagnostics/tests/StarsInFunctionCalls.fir.kt b/compiler/testData/diagnostics/tests/StarsInFunctionCalls.fir.kt index bd8811ea0c1..d3fff3880a5 100644 --- a/compiler/testData/diagnostics/tests/StarsInFunctionCalls.fir.kt +++ b/compiler/testData/diagnostics/tests/StarsInFunctionCalls.fir.kt @@ -6,10 +6,10 @@ fun getTTT(x : Any) {} fun foo(a : Any?) {} public fun main() { - getT<*>() + getT<*>() ggetT<*>() - getTT<*, *>() - getTT<*, Int>() - getTT() - foo(getTTT(1)) + getTT<*, *>() + getTT<*, Int>() + getTT*>() + foo(getTTT*, Int>(1)) } diff --git a/compiler/testData/diagnostics/tests/modifiers/incompatibleVarianceModifiers.fir.kt b/compiler/testData/diagnostics/tests/modifiers/incompatibleVarianceModifiers.fir.kt index 28ea9b366b4..f28ff1dc4f4 100644 --- a/compiler/testData/diagnostics/tests/modifiers/incompatibleVarianceModifiers.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/incompatibleVarianceModifiers.fir.kt @@ -19,5 +19,5 @@ class A { } fun test4(a: A) { - a.bar() + a.bar<out out Int>() } diff --git a/compiler/testData/diagnostics/tests/qualifiedExpression/nullCalleeExpression.fir.kt b/compiler/testData/diagnostics/tests/qualifiedExpression/nullCalleeExpression.fir.kt index 72e653963d6..73d33cd86cb 100644 --- a/compiler/testData/diagnostics/tests/qualifiedExpression/nullCalleeExpression.fir.kt +++ b/compiler/testData/diagnostics/tests/qualifiedExpression/nullCalleeExpression.fir.kt @@ -1,4 +1,4 @@ // !WITH_NEW_INFERENCE // NI_EXPECTED_FILE -val unwrapped = some.<cabc$Wrapper::unwrap \ No newline at end of file +val unwrapped = some.<cabc$Wrapper<out Any>::unwrap \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/typealias/projectionsInTypeAliasConstructor.fir.kt b/compiler/testData/diagnostics/tests/typealias/projectionsInTypeAliasConstructor.fir.kt index 3be68c3e5dc..fc0a333602b 100644 --- a/compiler/testData/diagnostics/tests/typealias/projectionsInTypeAliasConstructor.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/projectionsInTypeAliasConstructor.fir.kt @@ -2,5 +2,5 @@ class In(val x: Any) typealias InAlias = In -val test1 = In("") -val test2 = InAlias("") +val test1 = In<out String>("") +val test2 = InAlias<out String>("") diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorForProjection.fir.kt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorForProjection.fir.kt index 5c6582cd83e..a163bc1498c 100644 --- a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorForProjection.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorForProjection.fir.kt @@ -11,5 +11,5 @@ typealias CT = C val test1 = CStar() val test2 = CIn() val test3 = COut() -val test4 = CT<*>() +val test4 = CT<*>() val test5 = CT>() \ No newline at end of file