Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIR: Self types draft #4796

Draft
wants to merge 24 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c71098e
Self types: implementation of Self types using `@Self` as annotation.
maxim092001 Apr 16, 2022
3c4ce65
Self types: Add Self type for class annotated with @Self into all
maxim092001 Nov 19, 2022
8f4d527
Self types: rewritten implementation of ControlFlowInfo from Kotlin
maxim092001 Dec 10, 2022
210d584
rebase and fix conflicts
maxim092001 Jan 7, 2023
1391397
Self types: Add enum class checker.
maxim092001 Jan 11, 2023
9cdec30
Self types: Fix double <Self> in super type parameters
maxim092001 Jan 11, 2023
ec1ca0f
Self types: diagnostics for annotation classes
maxim092001 Jan 14, 2023
d2848c5
Self types: multiple tests added.
maxim092001 Jan 16, 2023
7942529
Self types: add test for object, refactor diagnostic tests
maxim092001 Jan 20, 2023
0cd7520
Self types: refactor box tests structure.
maxim092001 Jan 22, 2023
6ad8c6c
Self types: fix annotation find inside FirTypeResolverImpl
maxim092001 Jan 27, 2023
07fd7cc
Self types: refactor cfg tests
maxim092001 Jan 27, 2023
7780e18
Self types: add self type parameter only for FirRegularClass
maxim092001 Jan 27, 2023
8649129
Self types: test with self class as return type with implicit self ty…
maxim092001 Jan 27, 2023
279889b
Self types: test with self class as return type with implicit self ty…
maxim092001 Jan 27, 2023
42b129f
Self types: test with self abstract class and manual self type parameter
maxim092001 Jan 27, 2023
0a26bb4
Self types: more tests for nested classes
maxim092001 Jan 27, 2023
a17bc3e
Self types: add transformation chain test
maxim092001 Feb 1, 2023
896f2ad
Self types: add observer pattern test
maxim092001 Feb 11, 2023
4eb4edc
Self types: use this without explicit cast to Self
maxim092001 Mar 5, 2023
6c03792
Self types: remove unchecked cast check for Self types
maxim092001 Mar 5, 2023
c8abb59
Self types: add outer and nested self classes
maxim092001 Mar 16, 2023
8eea494
Self types: fix fir
maxim092001 Mar 16, 2023
3ab3b57
Self types: change symbol name check to standard name in SelfTypeChecker
maxim092001 Mar 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.SELF_TYPE_INAPPLICABLE_TARGET) { firDiagnostic ->
SelfTypeInapplicableTargetImpl(
firDiagnostic.a,
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.OPT_IN_USAGE) { firDiagnostic ->
OptInUsageImpl(
firDiagnostic.a,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,11 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val typeFromTypesPhase: KtType
}

abstract class SelfTypeInapplicableTarget : KtFirDiagnostic<KtAnnotationEntry>() {
override val diagnosticClass get() = SelfTypeInapplicableTarget::class
abstract val actualTarget: String
}

abstract class OptInUsage : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = OptInUsage::class
abstract val optInMarkerFqName: FqName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,12 @@ internal class PluginAnnotationAmbiguityImpl(
override val token: KtLifetimeToken,
) : KtFirDiagnostic.PluginAnnotationAmbiguity(), KtAbstractFirDiagnostic<PsiElement>

internal class SelfTypeInapplicableTargetImpl(
override val actualTarget: String,
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.SelfTypeInapplicableTarget(), KtAbstractFirDiagnostic<KtAnnotationEntry>

internal class OptInUsageImpl(
override val optInMarkerFqName: FqName,
override val message: String,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

166 changes: 166 additions & 0 deletions compiler/fir/analysis-tests/testData/resolve/cfg/selfTypes.fir.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
FILE: selfTypes.kt
@R|kotlin/Self|() public final class JustSelfAnnotation<out <Self> : R|JustSelfAnnotation<<Self>>|> : R|kotlin/Any| {
public constructor<out <Self> : R|JustSelfAnnotation<<Self>>|>(): R|JustSelfAnnotation<<Self>>| {
super<R|kotlin/Any|>()
}

public final fun anyFun(): R|kotlin/String| {
^anyFun String(string)
}

}
@R|kotlin/Self|() public final class ReturnType<out <Self> : R|ReturnType<<Self>>|> : R|kotlin/Any| {
public constructor<out <Self> : R|ReturnType<<Self>>|>(): R|ReturnType<<Self>>| {
super<R|kotlin/Any|>()
}

public final fun returnTypeWithVal(): R|<Self>| {
lval res: R|<Self>| = (this@R|/ReturnType| as R|<Self>|)
^returnTypeWithVal R|<local>/res|
}

}
@R|kotlin/Self|() public final class ReturnTypeWithTypeParameter<T, out <Self> : R|ReturnTypeWithTypeParameter<T, <Self>>|> : R|kotlin/Any| {
public constructor<T, out <Self> : R|ReturnTypeWithTypeParameter<T, <Self>>|>(): R|ReturnTypeWithTypeParameter<T, <Self>>| {
super<R|kotlin/Any|>()
}

public final fun returnType(): R|<Self>| {
^returnType (this@R|/ReturnTypeWithTypeParameter| as R|<Self>|)
}

public final fun functionWithConstruct(): R|<Self>| {
lval s: R|ReturnTypeWithTypeParameter<kotlin/Int, ReturnTypeWithTypeParameter<kotlin/Int, *>>| = R|/ReturnTypeWithTypeParameter.ReturnTypeWithTypeParameter|<R|kotlin/Int|, R|ReturnTypeWithTypeParameter<kotlin/Int, *>|>()
^functionWithConstruct (this@R|/ReturnTypeWithTypeParameter| as R|<Self>|)
}

}
@R|kotlin/Self|() public final class ReturnTypeWithTypeParameters<T, A, F, out <Self> : R|ReturnTypeWithTypeParameters<T, A, F, <Self>>|> : R|kotlin/Any| {
public constructor<T, A, F, out <Self> : R|ReturnTypeWithTypeParameters<T, A, F, <Self>>|>(): R|ReturnTypeWithTypeParameters<T, A, F, <Self>>| {
super<R|kotlin/Any|>()
}

public final fun returnType(): R|<Self>| {
^returnType (this@R|/ReturnTypeWithTypeParameters| as R|<Self>|)
}

}
public final class InnerClass : R|kotlin/Any| {
public constructor(): R|InnerClass| {
super<R|kotlin/Any|>()
}

@R|kotlin/Self|() public final inner class Inner<out <Self> : R|InnerClass.Inner<<Self>>|> : R|kotlin/Any| {
public InnerClass.constructor<out <Self> : R|InnerClass.Inner<<Self>>|>(): R|InnerClass.Inner<<Self>>| {
super<R|kotlin/Any|>()
}

public final fun returnType(): R|<Self>| {
^returnType (this@R|/InnerClass.Inner| as R|<Self>|)
}

}

}
public final class NestedClass : R|kotlin/Any| {
public constructor(): R|NestedClass| {
super<R|kotlin/Any|>()
}

@R|kotlin/Self|() public final class Nested<out <Self> : R|NestedClass.Nested<<Self>>|> : R|kotlin/Any| {
public constructor<out <Self> : R|NestedClass.Nested<<Self>>|>(): R|NestedClass.Nested<<Self>>| {
super<R|kotlin/Any|>()
}

public final fun returnType(): R|<Self>| {
^returnType (this@R|/NestedClass.Nested| as R|<Self>|)
}

}

}
@R|kotlin/Self|() public final class InnerSelfClass<out <Self> : R|InnerSelfClass<<Self>>|> : R|kotlin/Any| {
public constructor<out <Self> : R|InnerSelfClass<<Self>>|>(): R|InnerSelfClass<<Self>>| {
super<R|kotlin/Any|>()
}

public final inner class Self : R|kotlin/Any| {
public InnerSelfClass.constructor(): R|InnerSelfClass.Self| {
super<R|kotlin/Any|>()
}

public final fun returnSelf(): R|InnerSelfClass.Self| {
^returnSelf this@R|/InnerSelfClass.Self|
}

}

public final fun returnType(): R|<Self>| {
^returnType (this@R|/InnerSelfClass| as R|<Self>|)
}

public final fun returnSelfClassType(): R|InnerSelfClass.Self| {
^returnSelfClassType R|/InnerSelfClass.InnerSelfClass|<R|InnerSelfClass<*>|>().R|/InnerSelfClass.Self.Self|()
}

}
@R|kotlin/Self|() public final class TypeAliasSelf<out <Self> : R|TypeAliasSelf<<Self>>|> : R|kotlin/Any| {
public constructor<out <Self> : R|TypeAliasSelf<<Self>>|>(): R|TypeAliasSelf<<Self>>| {
super<R|kotlin/Any|>()
}

@R|kotlin/Suppress|(names = vararg(String(TOPLEVEL_TYPEALIASES_ONLY))) public final typealias Self = R|kotlin/String|

public final fun returnType(): R|<Self>| {
^returnType (this@R|/TypeAliasSelf| as R|<Self>|)
}

public final fun returnTypealias(): R|TypeAliasSelf.Self| {
^returnTypealias String(typealias)
}

}
@R|kotlin/Self|() public final class SelfWithSelfVariable<out <Self> : R|SelfWithSelfVariable<<Self>>|> : R|kotlin/Any| {
public constructor<out <Self> : R|SelfWithSelfVariable<<Self>>|>(): R|SelfWithSelfVariable<<Self>>| {
super<R|kotlin/Any|>()
}

public final fun returnType(): R|<Self>| {
lval Self: R|<Self>| = (this@R|/SelfWithSelfVariable| as R|<Self>|)
^returnType R|<local>/Self|
}

}
public final class InnerClassWithSelfAnnotation<S : R|InnerClassWithSelfAnnotation<S>|> : R|kotlin/Any| {
public constructor<S : R|InnerClassWithSelfAnnotation<S>|>(): R|InnerClassWithSelfAnnotation<S>| {
super<R|kotlin/Any|>()
}

@R|kotlin/Self|() public final inner class SelfAnnotated<S : R|InnerClassWithSelfAnnotation<S>|, out <Self> : R|InnerClassWithSelfAnnotation.SelfAnnotated<S, <Self>>|> : R|kotlin/Any| {
public InnerClassWithSelfAnnotation<S>.constructor<out <Self> : R|InnerClassWithSelfAnnotation.SelfAnnotated<S, <Self>>|>(): R|InnerClassWithSelfAnnotation.SelfAnnotated<S, <Self>>| {
super<R|kotlin/Any|>()
}

public final fun returnType(): R|<Self>| {
^returnType (this@R|/InnerClassWithSelfAnnotation.SelfAnnotated| as R|<Self>|)
}

}

@R|kotlin/Suppress|(names = vararg(String(UNCHECKED_CAST))) public final fun returnType(): R|S| {
^returnType (this@R|/InnerClassWithSelfAnnotation| as R|S|)
}

}
@R|kotlin/Self|() public abstract interface SelfTypeParameterInterface<out <Self> : R|SelfTypeParameterInterface<<Self>>|> : R|kotlin/Any| {
}
@R|kotlin/Self|() public final class SelfTypeAsTypeParameterInExtends<out <Self> : R|SelfTypeAsTypeParameterInExtends<<Self>>|> : R|SelfTypeParameterInterface<<Self>>| {
public constructor<out <Self> : R|SelfTypeAsTypeParameterInExtends<<Self>>|>(): R|SelfTypeAsTypeParameterInExtends<<Self>>| {
super<R|kotlin/Any|>()
}

public final fun returnType(): R|<Self>| {
^returnType (this@R|/SelfTypeAsTypeParameterInExtends| as R|<Self>|)
}

}
118 changes: 118 additions & 0 deletions compiler/fir/analysis-tests/testData/resolve/cfg/selfTypes.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// FIR_DISABLE_LAZY_RESOLVE_CHECKS
import kotlin.Self

@Self
class JustSelfAnnotation {
fun anyFun(): String = "string"
}

@Self
class ReturnType {
fun returnTypeWithVal(): Self {
val res: Self = this as Self
return res
}
}

@Self
class ReturnTypeWithTypeParameter<T> {
fun returnType(): Self {
return this as Self
}

fun functionWithConstruct(): Self {
val s = ReturnTypeWithTypeParameter<Int, ReturnTypeWithTypeParameter<Int, *>>()
return this as Self
}
}

@Self
class ReturnTypeWithTypeParameters<T, A, F> {
fun returnType(): Self {
return this as Self
}
}

class InnerClass {
@Self
inner class Inner {
fun returnType(): Self {
return this as Self
}
}
}

class NestedClass {
@Self
class Nested {
fun returnType(): Self {
return this as Self
}
}
}

@Self
class InnerSelfClass {
inner class Self {
fun returnSelf(): InnerSelfClass.Self {
return this
}
}

fun returnType(): Self {
return this as Self
}

fun returnSelfClassType(): InnerSelfClass.Self {
return InnerSelfClass<InnerSelfClass<*>>().Self()
}
}

@Self
class TypeAliasSelf {
@Suppress("TOPLEVEL_TYPEALIASES_ONLY")
typealias Self = String

fun returnType(): Self {
return this as Self
}

fun returnTypealias(): TypeAliasSelf.Self {
return "typealias"
}
}

@Self
class SelfWithSelfVariable {
fun returnType(): Self {
val Self: Self = this as Self
return Self
}
}

class InnerClassWithSelfAnnotation<S: InnerClassWithSelfAnnotation<S>> {

@Self
inner class SelfAnnotated {
fun returnType(): Self {
return this as Self
}
}

@Suppress("UNCHECKED_CAST")
fun returnType(): S {
return this as S
}

}

@Self
interface SelfTypeParameterInterface

@Self
class SelfTypeAsTypeParameterInExtends : SelfTypeParameterInterface<Self> {

fun returnType(): Self {
return this as Self
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FILE: selfTypeForEnumClass.kt
@R|kotlin/Self|() public final enum class EnumClass<out <Self> : R|EnumClass<<Self>>|> : R|kotlin/Enum<EnumClass>| {
private constructor<out <Self> : R|EnumClass<<Self>>|>(): R|EnumClass<<Self>>| {
super<R|kotlin/Enum<EnumClass>|>()
}

public final static fun values(): R|kotlin/Array<EnumClass>| {
}

public final static fun valueOf(value: R|kotlin/String|): R|EnumClass| {
}

public final static val entries: R|kotlin/enums/EnumEntries<EnumClass>|
public get(): R|kotlin/enums/EnumEntries<EnumClass>|

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// FIR_DISABLE_LAZY_RESOLVE_CHECKS
import kotlin.Self
<!TYPE_PARAMETERS_IN_ENUM!><!SELF_TYPE_INAPPLICABLE_TARGET!>@Self<!>
enum class EnumClass {

}<!>
Loading