[FIR] Add NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER check
This commit is contained in:
+5
@@ -1150,6 +1150,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/methodOfAnyImplementedInInterface.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/methodOfAnyImplementedInInterface.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multipleBounds.kt")
|
||||||
|
public void testMultipleBounds() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/multipleBounds.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nonConstValInAnnotationArgument.kt")
|
@TestMetadata("nonConstValInAnnotationArgument.kt")
|
||||||
public void testNonConstValInAnnotationArgument() throws Exception {
|
public void testNonConstValInAnnotationArgument() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/nonConstValInAnnotationArgument.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/nonConstValInAnnotationArgument.kt");
|
||||||
|
|||||||
+109
@@ -0,0 +1,109 @@
|
|||||||
|
FILE: multipleBounds.kt
|
||||||
|
public open class A : R|kotlin/Any| {
|
||||||
|
public constructor(): R|Jet87/A| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final fun foo(): R|kotlin/Int| {
|
||||||
|
^foo Int(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public abstract interface B : R|kotlin/Any| {
|
||||||
|
public open fun bar(): R|kotlin/Double| {
|
||||||
|
^bar Double(1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public abstract interface G<X> : R|kotlin/Any| {
|
||||||
|
public abstract val <X : R|Jet87/A|, R|Jet87/B|> boo: R|kotlin/Double|
|
||||||
|
public get(): R|kotlin/Double|
|
||||||
|
|
||||||
|
public abstract val <A : R|Jet87/B|> bal: R|kotlin/Double|
|
||||||
|
public get(): R|kotlin/Double|
|
||||||
|
|
||||||
|
public abstract val <Y : R|Jet87/B|> bas: R|kotlin/Double|
|
||||||
|
public get(): R|kotlin/Double|
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class C : R|Jet87/A|, R|Jet87/B| {
|
||||||
|
public constructor(): R|Jet87/C| {
|
||||||
|
super<R|Jet87/A|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class D : R|kotlin/Any| {
|
||||||
|
public constructor(): R|Jet87/D| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final companion object Companion : R|Jet87/A|, R|Jet87/B| {
|
||||||
|
private constructor(): R|Jet87/D.Companion| {
|
||||||
|
super<R|Jet87/A|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Test1<T : R|Jet87/A|, R|Jet87/B|> : R|kotlin/Any| {
|
||||||
|
public constructor<T : R|Jet87/A|, R|Jet87/B|>(): R|Jet87/Test1<T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final fun test(t: R|T|): R|kotlin/Unit| {
|
||||||
|
R|?|.<Unresolved name: foo>#()
|
||||||
|
R|?|.<Unresolved name: bar>#()
|
||||||
|
R|<local>/t|.R|Jet87/A.foo|()
|
||||||
|
R|<local>/t|.R|Jet87/B.bar|()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun test(): R|kotlin/Unit| {
|
||||||
|
R|Jet87/Test1.Test1|<R|Jet87/B|>()
|
||||||
|
R|Jet87/Test1.Test1|<R|Jet87/A|>()
|
||||||
|
R|Jet87/Test1.Test1|<R|Jet87/C|>()
|
||||||
|
}
|
||||||
|
public final class Foo : R|kotlin/Any| {
|
||||||
|
public constructor(): R|Jet87/Foo| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Bar<T : R|Jet87/Foo|> : R|kotlin/Any| {
|
||||||
|
public constructor<T : R|Jet87/Foo|>(): R|Jet87/Bar<T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Buzz<T : R|Jet87/Bar<kotlin/Int>|, <ERROR TYPE REF: Symbol not found for nioho>> : R|kotlin/Any| {
|
||||||
|
public constructor<T : R|Jet87/Bar<kotlin/Int>|, <ERROR TYPE REF: Symbol not found for nioho>>(): R|Jet87/Buzz<T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class X<T : R|Jet87/Foo|> : R|kotlin/Any| {
|
||||||
|
public constructor<T : R|Jet87/Foo|>(): R|Jet87/X<T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Y<T : R|Jet87/Foo|, R|Jet87/Bar<Jet87/Foo>|> : R|kotlin/Any| {
|
||||||
|
public constructor<T : R|Jet87/Foo|, R|Jet87/Bar<Jet87/Foo>|>(): R|Jet87/Y<T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun <T : R|Jet87/A|, R|Jet87/B|> test2(t: R|T|): R|kotlin/Unit| {
|
||||||
|
R|?|.<Unresolved name: foo>#()
|
||||||
|
R|?|.<Unresolved name: bar>#()
|
||||||
|
R|<local>/t|.R|Jet87/A.foo|()
|
||||||
|
R|<local>/t|.R|Jet87/B.bar|()
|
||||||
|
}
|
||||||
|
public final val t1: R|kotlin/Unit| = <Inapplicable(INAPPLICABLE): Jet87/test2>#<R|Jet87/A|>(R|Jet87/A.A|())
|
||||||
|
public get(): R|kotlin/Unit|
|
||||||
|
public final val t2: R|kotlin/Unit| = <Inapplicable(INAPPLICABLE): Jet87/test2>#<R|Jet87/B|>(R|Jet87/C.C|())
|
||||||
|
public get(): R|kotlin/Unit|
|
||||||
|
public final val t3: R|kotlin/Unit| = R|Jet87/test2|<R|Jet87/C|>(R|Jet87/C.C|())
|
||||||
|
public get(): R|kotlin/Unit|
|
||||||
|
public final val <T, B : R|T|> x: R|kotlin/Int| = Int(0)
|
||||||
|
public get(): R|kotlin/Int|
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package Jet87
|
||||||
|
|
||||||
|
open class A() {
|
||||||
|
fun foo() : Int = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B {
|
||||||
|
fun bar() : Double = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface G<X> {
|
||||||
|
val <X> boo: Double where X : A, X : B
|
||||||
|
val <A> bal: Double where A : B
|
||||||
|
val <Y> bas: Double where Y : B, <!NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER!>X<!> : B
|
||||||
|
}
|
||||||
|
|
||||||
|
class C() : A(), B
|
||||||
|
|
||||||
|
class D() {
|
||||||
|
companion object : A(), B {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Test1<T>()
|
||||||
|
where
|
||||||
|
T : A,
|
||||||
|
T : B,
|
||||||
|
<!NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER!>B<!> : T // error
|
||||||
|
{
|
||||||
|
|
||||||
|
fun test(t : T) {
|
||||||
|
<!TYPE_PARAMETER_ON_LHS_OF_DOT!>T<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||||
|
<!TYPE_PARAMETER_ON_LHS_OF_DOT!>T<!>.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||||
|
t.foo()
|
||||||
|
t.bar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
Test1<<!UPPER_BOUND_VIOLATED!>B<!>>()
|
||||||
|
Test1<<!UPPER_BOUND_VIOLATED!>A<!>>()
|
||||||
|
Test1<C>()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo() {}
|
||||||
|
|
||||||
|
class Bar<T : <!FINAL_UPPER_BOUND!>Foo<!>>
|
||||||
|
|
||||||
|
class Buzz<T> where T : <!FINAL_UPPER_BOUND!>Bar<Int><!>, T : <!UNRESOLVED_REFERENCE!>nioho<!>
|
||||||
|
|
||||||
|
class X<T : <!FINAL_UPPER_BOUND!>Foo<!>>
|
||||||
|
class Y<<!CONFLICTING_UPPER_BOUNDS!>T<!>> where T : <!FINAL_UPPER_BOUND!>Foo<!>, T : <!FINAL_UPPER_BOUND, ONLY_ONE_CLASS_BOUND_ALLOWED!>Bar<Foo><!>
|
||||||
|
|
||||||
|
fun <T> test2(t : T)
|
||||||
|
where
|
||||||
|
T : A,
|
||||||
|
T : B,
|
||||||
|
<!NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER!>B<!> : T
|
||||||
|
{
|
||||||
|
<!TYPE_PARAMETER_ON_LHS_OF_DOT!>T<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||||
|
<!TYPE_PARAMETER_ON_LHS_OF_DOT!>T<!>.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||||
|
t.foo()
|
||||||
|
t.bar()
|
||||||
|
}
|
||||||
|
|
||||||
|
val t1 = <!INAPPLICABLE_CANDIDATE!>test2<!><A>(A())
|
||||||
|
val t2 = <!INAPPLICABLE_CANDIDATE!>test2<!><B>(C())
|
||||||
|
val t3 = test2<C>(C())
|
||||||
|
|
||||||
|
val <T, B : T> x : Int = 0
|
||||||
+6
@@ -1321,6 +1321,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/methodOfAnyImplementedInInterface.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/methodOfAnyImplementedInInterface.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("multipleBounds.kt")
|
||||||
|
public void testMultipleBounds() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/multipleBounds.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("nonConstValInAnnotationArgument.kt")
|
@TestMetadata("nonConstValInAnnotationArgument.kt")
|
||||||
public void testNonConstValInAnnotationArgument() throws Exception {
|
public void testNonConstValInAnnotationArgument() throws Exception {
|
||||||
|
|||||||
+6
@@ -1333,6 +1333,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/methodOfAnyImplementedInInterface.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/methodOfAnyImplementedInInterface.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("multipleBounds.kt")
|
||||||
|
public void testMultipleBounds() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/multipleBounds.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("nonConstValInAnnotationArgument.kt")
|
@TestMetadata("nonConstValInAnnotationArgument.kt")
|
||||||
public void testNonConstValInAnnotationArgument() throws Exception {
|
public void testNonConstValInAnnotationArgument() throws Exception {
|
||||||
|
|||||||
+6
-4
@@ -16,10 +16,7 @@ import org.jetbrains.kotlin.descriptors.Visibility
|
|||||||
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
@@ -309,6 +306,11 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
|||||||
val CONFLICTING_UPPER_BOUNDS by error<FirSourceElement, KtNamedDeclaration> {
|
val CONFLICTING_UPPER_BOUNDS by error<FirSourceElement, KtNamedDeclaration> {
|
||||||
parameter<FirTypeParameterSymbol>("typeParameter")
|
parameter<FirTypeParameterSymbol>("typeParameter")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER by error<FirSourceElement, KtSimpleNameExpression> {
|
||||||
|
parameter<Name>("typeParameterName")
|
||||||
|
parameter<FirDeclaration>("typeParametersOwner")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val REFLECTION by object : DiagnosticGroup("Reflection") {
|
val REFLECTION by object : DiagnosticGroup("Reflection") {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.SourceElementPositioningStrategies
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.SourceElementPositioningStrategies
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
@@ -226,6 +227,7 @@ object FirErrors {
|
|||||||
val ONLY_ONE_CLASS_BOUND_ALLOWED by error0<FirSourceElement, KtTypeReference>()
|
val ONLY_ONE_CLASS_BOUND_ALLOWED by error0<FirSourceElement, KtTypeReference>()
|
||||||
val REPEATED_BOUND by error0<FirSourceElement, KtTypeReference>()
|
val REPEATED_BOUND by error0<FirSourceElement, KtTypeReference>()
|
||||||
val CONFLICTING_UPPER_BOUNDS by error1<FirSourceElement, KtNamedDeclaration, FirTypeParameterSymbol>()
|
val CONFLICTING_UPPER_BOUNDS by error1<FirSourceElement, KtNamedDeclaration, FirTypeParameterSymbol>()
|
||||||
|
val NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER by error2<FirSourceElement, KtSimpleNameExpression, Name, FirDeclaration>()
|
||||||
|
|
||||||
// Reflection
|
// Reflection
|
||||||
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<FirSourceElement, KtExpression, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<FirSourceElement, KtExpression, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
|
|||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.declaration
|
||||||
|
|
||||||
|
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.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRefsOwner
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.getDanglingTypeConstraintsOrEmpty
|
||||||
|
|
||||||
|
object FirTypeConstraintsChecker : FirBasicDeclarationChecker() {
|
||||||
|
|
||||||
|
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration !is FirTypeParameterRefsOwner) return
|
||||||
|
|
||||||
|
//basically we transfer errors, which were discovered in ast parsers
|
||||||
|
declaration.getDanglingTypeConstraintsOrEmpty().forEach { constraint ->
|
||||||
|
reporter.reportOn(
|
||||||
|
constraint.source,
|
||||||
|
FirErrors.NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER,
|
||||||
|
constraint.name,
|
||||||
|
declaration,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+8
@@ -136,6 +136,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZ
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAMED_ARGUMENTS_NOT_ALLOWED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAMED_ARGUMENTS_NOT_ALLOWED
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAMED_PARAMETER_NOT_FOUND
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAMED_PARAMETER_NOT_FOUND
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NESTED_CLASS_NOT_ALLOWED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NESTED_CLASS_NOT_ALLOWED
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY
|
||||||
@@ -474,6 +475,13 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
|||||||
SYMBOL
|
SYMBOL
|
||||||
)
|
)
|
||||||
|
|
||||||
|
map.put(
|
||||||
|
NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER,
|
||||||
|
"{0} does not refer to a type parameter of {1}",
|
||||||
|
TO_STRING,
|
||||||
|
NAME
|
||||||
|
)
|
||||||
|
|
||||||
// Reflection
|
// Reflection
|
||||||
map.put(
|
map.put(
|
||||||
EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED,
|
EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED,
|
||||||
|
|||||||
+1
@@ -18,6 +18,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirModifierChecker,
|
FirModifierChecker,
|
||||||
FirConflictsChecker,
|
FirConflictsChecker,
|
||||||
FirConflictingProjectionChecker,
|
FirConflictingProjectionChecker,
|
||||||
|
FirTypeConstraintsChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val memberDeclarationCheckers: Set<FirMemberDeclarationChecker> = setOf(
|
override val memberDeclarationCheckers: Set<FirMemberDeclarationChecker> = setOf(
|
||||||
|
|||||||
+32
-2
@@ -526,6 +526,7 @@ class DeclarationsConverter(
|
|||||||
}
|
}
|
||||||
}.also {
|
}.also {
|
||||||
it.initContainingClassForLocalAttr()
|
it.initContainingClassForLocalAttr()
|
||||||
|
fillDanglingConstraintsTo(firTypeParameters, typeConstraints, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1083,6 +1084,8 @@ class DeclarationsConverter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
annotations += modifiers.annotations
|
annotations += modifiers.annotations
|
||||||
|
}.also {
|
||||||
|
fillDanglingConstraintsTo(firTypeParameters, typeConstraints, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1394,6 +1397,9 @@ class DeclarationsConverter(
|
|||||||
context.firFunctionTargets.removeLast()
|
context.firFunctionTargets.removeLast()
|
||||||
}.build().also {
|
}.build().also {
|
||||||
target.bind(it)
|
target.bind(it)
|
||||||
|
if (it is FirSimpleFunction) {
|
||||||
|
fillDanglingConstraintsTo(firTypeParameters, typeConstraints, it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1573,17 +1579,21 @@ class DeclarationsConverter(
|
|||||||
private fun convertTypeConstraint(typeConstraint: LighterASTNode): TypeConstraint {
|
private fun convertTypeConstraint(typeConstraint: LighterASTNode): TypeConstraint {
|
||||||
lateinit var identifier: String
|
lateinit var identifier: String
|
||||||
lateinit var firType: FirTypeRef
|
lateinit var firType: FirTypeRef
|
||||||
|
lateinit var referenceExpression: LighterASTNode
|
||||||
val annotations = mutableListOf<FirAnnotationCall>()
|
val annotations = mutableListOf<FirAnnotationCall>()
|
||||||
typeConstraint.forEachChildren {
|
typeConstraint.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
//annotations will be saved later, on mapping stage with type parameters
|
//annotations will be saved later, on mapping stage with type parameters
|
||||||
ANNOTATION, ANNOTATION_ENTRY -> annotations += convertAnnotation(it)
|
ANNOTATION, ANNOTATION_ENTRY -> annotations += convertAnnotation(it)
|
||||||
REFERENCE_EXPRESSION -> identifier = it.asText
|
REFERENCE_EXPRESSION -> {
|
||||||
|
identifier = it.asText
|
||||||
|
referenceExpression = it
|
||||||
|
}
|
||||||
TYPE_REFERENCE -> firType = convertType(it)
|
TYPE_REFERENCE -> firType = convertType(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypeConstraint(annotations, identifier, firType)
|
return TypeConstraint(annotations, identifier, firType, referenceExpression.toFirSourceElement())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1867,4 +1877,24 @@ class DeclarationsConverter(
|
|||||||
}
|
}
|
||||||
calleeReference = FirReferencePlaceholderForResolvedAnnotations
|
calleeReference = FirReferencePlaceholderForResolvedAnnotations
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <T> fillDanglingConstraintsTo(
|
||||||
|
typeParameters: List<FirTypeParameter>,
|
||||||
|
typeConstraints: List<TypeConstraint>,
|
||||||
|
to: T
|
||||||
|
) where T : FirDeclaration, T : FirTypeParameterRefsOwner {
|
||||||
|
val typeParamNames = typeParameters.map { it.name }.toSet()
|
||||||
|
val result = typeConstraints.mapNotNull { constraint ->
|
||||||
|
val name = constraint.identifier.nameAsSafeName()
|
||||||
|
if (!typeParamNames.contains(name)) {
|
||||||
|
DanglingTypeConstraint(name, constraint.source)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (result.isNotEmpty()) {
|
||||||
|
to.danglingTypeConstraints = result
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -5,7 +5,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.lightTree.fir
|
package org.jetbrains.kotlin.fir.lightTree.fir
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
|
|
||||||
class TypeConstraint(val annotations: List<FirAnnotationCall>, val identifier: String, val firTypeRef: FirTypeRef)
|
class TypeConstraint(
|
||||||
|
val annotations: List<FirAnnotationCall>,
|
||||||
|
val identifier: String,
|
||||||
|
val firTypeRef: FirTypeRef,
|
||||||
|
val source: FirSourceElement
|
||||||
|
)
|
||||||
|
|||||||
@@ -500,6 +500,23 @@ open class RawFirBuilder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <T> KtTypeParameterListOwner.fillDanglingConstraintsTo(to: T) where T : FirDeclaration, T : FirTypeParameterRefsOwner {
|
||||||
|
val typeParamNames = typeParameters.mapNotNull { it.nameAsName }.toSet()
|
||||||
|
val result = typeConstraints.mapNotNull { constraint ->
|
||||||
|
constraint.subjectTypeParameterName?.getReferencedNameAsName()?.let { name ->
|
||||||
|
if (!typeParamNames.contains(name)) {
|
||||||
|
DanglingTypeConstraint(name, constraint.subjectTypeParameterName!!.toFirSourceElement())
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (result.isNotEmpty()) {
|
||||||
|
to.danglingTypeConstraints = result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun KtDeclarationWithBody.extractValueParametersTo(
|
private fun KtDeclarationWithBody.extractValueParametersTo(
|
||||||
container: FirFunctionBuilder,
|
container: FirFunctionBuilder,
|
||||||
defaultTypeRef: FirTypeRef? = null,
|
defaultTypeRef: FirTypeRef? = null,
|
||||||
@@ -898,6 +915,7 @@ open class RawFirBuilder(
|
|||||||
}
|
}
|
||||||
}.also {
|
}.also {
|
||||||
it.initContainingClassForLocalAttr()
|
it.initContainingClassForLocalAttr()
|
||||||
|
classOrObject.fillDanglingConstraintsTo(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1030,6 +1048,9 @@ open class RawFirBuilder(
|
|||||||
context.firFunctionTargets.removeLast()
|
context.firFunctionTargets.removeLast()
|
||||||
}.build().also {
|
}.build().also {
|
||||||
target.bind(it)
|
target.bind(it)
|
||||||
|
if (it is FirSimpleFunction) {
|
||||||
|
function.fillDanglingConstraintsTo(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1308,6 +1329,10 @@ open class RawFirBuilder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
extractAnnotationsTo(this)
|
extractAnnotationsTo(this)
|
||||||
|
}.also {
|
||||||
|
if (!isLocal) {
|
||||||
|
fillDanglingConstraintsTo(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.declarations
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constraint without corresponding type argiment
|
||||||
|
*/
|
||||||
|
data class DanglingTypeConstraint(val name: Name, val source: FirSourceElement)
|
||||||
|
|
||||||
|
private object DanglingTypeConstraintsKey : FirDeclarationDataKey()
|
||||||
|
|
||||||
|
var <T> T.danglingTypeConstraints: List<DanglingTypeConstraint>?
|
||||||
|
where T : FirDeclaration, T : FirTypeParameterRefsOwner
|
||||||
|
by FirDeclarationDataRegistry.data(DanglingTypeConstraintsKey)
|
||||||
|
|
||||||
|
fun FirDeclaration.getDanglingTypeConstraintsOrEmpty(): List<DanglingTypeConstraint> {
|
||||||
|
val res = when (this) {
|
||||||
|
is FirRegularClass -> danglingTypeConstraints
|
||||||
|
is FirSimpleFunction -> danglingTypeConstraints
|
||||||
|
is FirProperty -> danglingTypeConstraints
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
return res ?: emptyList()
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ interface B {
|
|||||||
interface G<X> {
|
interface G<X> {
|
||||||
val <X> boo: Double where X : A, X : B
|
val <X> boo: Double where X : A, X : B
|
||||||
val <A> bal: Double where A : B
|
val <A> bal: Double where A : B
|
||||||
val <Y> bas: Double where Y : B, X : B
|
val <Y> bas: Double where Y : B, <!NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER!>X<!> : B
|
||||||
}
|
}
|
||||||
|
|
||||||
class C() : A(), B
|
class C() : A(), B
|
||||||
@@ -24,7 +24,7 @@ class Test1<T>()
|
|||||||
where
|
where
|
||||||
T : A,
|
T : A,
|
||||||
T : B,
|
T : B,
|
||||||
B : T // error
|
<!NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER!>B<!> : T // error
|
||||||
{
|
{
|
||||||
|
|
||||||
fun test(t : T) {
|
fun test(t : T) {
|
||||||
@@ -54,7 +54,7 @@ fun <T> test2(t : T)
|
|||||||
where
|
where
|
||||||
T : A,
|
T : A,
|
||||||
T : B,
|
T : B,
|
||||||
B : T
|
<!NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER!>B<!> : T
|
||||||
{
|
{
|
||||||
<!TYPE_PARAMETER_ON_LHS_OF_DOT!>T<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
<!TYPE_PARAMETER_ON_LHS_OF_DOT!>T<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||||
<!TYPE_PARAMETER_ON_LHS_OF_DOT!>T<!>.<!UNRESOLVED_REFERENCE!>bar<!>()
|
<!TYPE_PARAMETER_ON_LHS_OF_DOT!>T<!>.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||||
|
|||||||
+6
-4
@@ -15,10 +15,7 @@ import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
|||||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.DiagnosticData
|
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.DiagnosticData
|
||||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.DiagnosticList
|
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.DiagnosticList
|
||||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.DiagnosticParameter
|
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.DiagnosticParameter
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
@@ -183,6 +180,11 @@ private object FirToKtConversionCreator {
|
|||||||
KtVariableLikeSymbol::class.createType(),
|
KtVariableLikeSymbol::class.createType(),
|
||||||
importsToAdd = listOf("org.jetbrains.kotlin.fir.declarations.FirVariable")
|
importsToAdd = listOf("org.jetbrains.kotlin.fir.declarations.FirVariable")
|
||||||
),
|
),
|
||||||
|
FirDeclaration::class to HLFunctionCallConversion(
|
||||||
|
"firSymbolBuilder.buildSymbol({0})",
|
||||||
|
KtSymbol::class.createType(),
|
||||||
|
importsToAdd = listOf("org.jetbrains.kotlin.fir.declarations.FirDeclaration")
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
private val allowedTypesWithoutTypeParams = setOf(
|
private val allowedTypesWithoutTypeParams = setOf(
|
||||||
|
|||||||
+8
@@ -945,6 +945,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER) { firDiagnostic ->
|
||||||
|
NameInConstraintIsNotATypeParameterImpl(
|
||||||
|
firDiagnostic.a,
|
||||||
|
firSymbolBuilder.buildSymbol(firDiagnostic.b),
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED) { firDiagnostic ->
|
add(FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED) { firDiagnostic ->
|
||||||
ExtensionInClassReferenceNotAllowedImpl(
|
ExtensionInClassReferenceNotAllowedImpl(
|
||||||
firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a as FirCallableDeclaration),
|
firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a as FirCallableDeclaration),
|
||||||
|
|||||||
+6
@@ -673,6 +673,12 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
abstract val typeParameter: KtTypeParameterSymbol
|
abstract val typeParameter: KtTypeParameterSymbol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class NameInConstraintIsNotATypeParameter : KtFirDiagnostic<KtSimpleNameExpression>() {
|
||||||
|
override val diagnosticClass get() = NameInConstraintIsNotATypeParameter::class
|
||||||
|
abstract val typeParameterName: Name
|
||||||
|
abstract val typeParametersOwner: KtSymbol
|
||||||
|
}
|
||||||
|
|
||||||
abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic<KtExpression>() {
|
abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic<KtExpression>() {
|
||||||
override val diagnosticClass get() = ExtensionInClassReferenceNotAllowed::class
|
override val diagnosticClass get() = ExtensionInClassReferenceNotAllowed::class
|
||||||
abstract val referencedDeclaration: KtCallableSymbol
|
abstract val referencedDeclaration: KtCallableSymbol
|
||||||
|
|||||||
+9
@@ -1085,6 +1085,15 @@ internal class ConflictingUpperBoundsImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class NameInConstraintIsNotATypeParameterImpl(
|
||||||
|
override val typeParameterName: Name,
|
||||||
|
override val typeParametersOwner: KtSymbol,
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.NameInConstraintIsNotATypeParameter(), KtAbstractFirDiagnostic<KtSimpleNameExpression> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class ExtensionInClassReferenceNotAllowedImpl(
|
internal class ExtensionInClassReferenceNotAllowedImpl(
|
||||||
override val referencedDeclaration: KtCallableSymbol,
|
override val referencedDeclaration: KtCallableSymbol,
|
||||||
firDiagnostic: FirPsiDiagnostic<*>,
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
|||||||
+2
-2
@@ -18,7 +18,7 @@ class Test1<T>()
|
|||||||
where
|
where
|
||||||
T : A,
|
T : A,
|
||||||
T : B,
|
T : B,
|
||||||
B : T // error
|
<error descr="[NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER] B does not refer to a type parameter of Test1">B</error> : T // error
|
||||||
{
|
{
|
||||||
|
|
||||||
fun test(t : T) {
|
fun test(t : T) {
|
||||||
@@ -48,7 +48,7 @@ fun <T> test2(t : T)
|
|||||||
where
|
where
|
||||||
T : A,
|
T : A,
|
||||||
T : B,
|
T : B,
|
||||||
B : T
|
<error descr="[NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER] B does not refer to a type parameter of test2">B</error> : T
|
||||||
{
|
{
|
||||||
<error descr="[TYPE_PARAMETER_ON_LHS_OF_DOT] Type parameter 'T' cannot have or inherit a companion object, so it cannot be on the left hand side of dot">T</error>.<error descr="[UNRESOLVED_REFERENCE] Unresolved reference: foo">foo</error>()
|
<error descr="[TYPE_PARAMETER_ON_LHS_OF_DOT] Type parameter 'T' cannot have or inherit a companion object, so it cannot be on the left hand side of dot">T</error>.<error descr="[UNRESOLVED_REFERENCE] Unresolved reference: foo">foo</error>()
|
||||||
<error descr="[TYPE_PARAMETER_ON_LHS_OF_DOT] Type parameter 'T' cannot have or inherit a companion object, so it cannot be on the left hand side of dot">T</error>.<error descr="[UNRESOLVED_REFERENCE] Unresolved reference: bar">bar</error>()
|
<error descr="[TYPE_PARAMETER_ON_LHS_OF_DOT] Type parameter 'T' cannot have or inherit a companion object, so it cannot be on the left hand side of dot">T</error>.<error descr="[UNRESOLVED_REFERENCE] Unresolved reference: bar">bar</error>()
|
||||||
|
|||||||
Reference in New Issue
Block a user