AA FIR: refactor KtFirType hierarchy
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/FirKtType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/FirKtType.kt
deleted file mode 100644
index 21fd4a0..0000000
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/FirKtType.kt
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * 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.analysis.api.fir.types
-
-import org.jetbrains.kotlin.analysis.api.KtTypeArgument
-import org.jetbrains.kotlin.analysis.api.KtTypeArgumentWithVariance
-import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeOwner
-import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
-import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
-import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
-import org.jetbrains.kotlin.analysis.api.fir.getCandidateSymbols
-import org.jetbrains.kotlin.analysis.api.fir.utils.cached
-import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
-import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol
-import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
-import org.jetbrains.kotlin.analysis.api.types.*
-import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
-import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
-import org.jetbrains.kotlin.fir.types.*
-import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
-import org.jetbrains.kotlin.name.ClassId
-import org.jetbrains.kotlin.name.Name
-
-internal interface KtFirType : KtLifetimeOwner {
-    val coneType: ConeKotlinType
-}
-
-private fun KtFirType.typeEquals(other: Any?): Boolean {
-    if (other !is KtFirType) return false
-    return this.coneType == other.coneType
-}
-
-private fun KtFirType.typeHashcode(): Int = coneType.hashCode()
-
-internal class KtFirUsualClassType(
-    override val coneType: ConeClassLikeTypeImpl,
-    override val token: KtLifetimeToken,
-    private val builder: KtSymbolByFirBuilder,
-) : KtUsualClassType(), KtFirType {
-    override val classId: ClassId get() = withValidityAssertion { coneType.lookupTag.classId }
-    override val classSymbol: KtClassLikeSymbol by cached {
-        builder.classifierBuilder.buildClassLikeSymbolByLookupTag(coneType.lookupTag)
-            ?: error("Class ${coneType.lookupTag} was not found")
-    }
-    override val typeArguments: List<KtTypeArgument> by cached {
-        coneType.typeArguments.map { typeArgument ->
-            builder.typeBuilder.buildTypeArgument(typeArgument)
-        }
-    }
-
-    override val annotationsList: KtAnnotationsList by cached {
-        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
-    }
-
-    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
-    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
-    override fun equals(other: Any?) = typeEquals(other)
-    override fun hashCode() = typeHashcode()
-}
-
-internal class KtFirFunctionalType(
-    override val coneType: ConeClassLikeTypeImpl,
-    override val token: KtLifetimeToken,
-    private val builder: KtSymbolByFirBuilder,
-) : KtFunctionalType(), KtFirType {
-    override val classId: ClassId get() = withValidityAssertion { coneType.lookupTag.classId }
-    override val classSymbol: KtClassLikeSymbol by cached {
-        builder.classifierBuilder.buildClassLikeSymbolByLookupTag(coneType.lookupTag)
-            ?: error("Class ${coneType.lookupTag} was not found")
-    }
-    override val typeArguments: List<KtTypeArgument> by cached {
-        coneType.typeArguments.map { typeArgument ->
-            builder.typeBuilder.buildTypeArgument(typeArgument)
-        }
-    }
-
-    override val annotationsList: KtAnnotationsList by cached {
-        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
-    }
-
-    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
-
-    override val isSuspend: Boolean get() = withValidityAssertion { coneType.isSuspendFunctionType(builder.rootSession) }
-    override val arity: Int
-        get() = withValidityAssertion {
-            if (coneType.isExtensionFunctionType) coneType.typeArguments.size - 2
-            else coneType.typeArguments.size - 1
-        }
-
-    override val receiverType: KtType?
-        get() = withValidityAssertion {
-            if (coneType.isExtensionFunctionType) (typeArguments.first() as KtTypeArgumentWithVariance).type
-            else null
-        }
-
-    override val hasReceiver: Boolean
-        get() = withValidityAssertion {
-            coneType.receiverType(builder.rootSession) != null
-        }
-
-    override val parameterTypes: List<KtType> by cached {
-        val parameterTypeArgs = if (coneType.isExtensionFunctionType) typeArguments.subList(1, typeArguments.lastIndex)
-        else typeArguments.subList(0, typeArguments.lastIndex)
-        parameterTypeArgs.map { (it as KtTypeArgumentWithVariance).type }
-    }
-
-    override val returnType: KtType
-        get() = withValidityAssertion { (typeArguments.last() as KtTypeArgumentWithVariance).type }
-
-    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
-    override fun equals(other: Any?) = typeEquals(other)
-    override fun hashCode() = typeHashcode()
-}
-
-internal class KtFirClassErrorType(
-    override val coneType: ConeErrorType,
-    override val token: KtLifetimeToken,
-    private val builder: KtSymbolByFirBuilder,
-) : KtClassErrorType(), KtFirType {
-
-    override val error: String get() = withValidityAssertion { coneType.diagnostic.reason }
-    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
-
-    override val annotationsList: KtAnnotationsList by cached {
-        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
-    }
-
-    override val candidateClassSymbols: Collection<KtClassLikeSymbol> by cached {
-        val symbols = coneType.diagnostic.getCandidateSymbols().filterIsInstance<FirClassLikeSymbol<*>>()
-        symbols.map { builder.classifierBuilder.buildClassLikeSymbol(it) }
-    }
-
-    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
-    override fun equals(other: Any?) = typeEquals(other)
-    override fun hashCode() = typeHashcode()
-}
-
-internal class KtFirCapturedType(
-    override val coneType: ConeCapturedType,
-    override val token: KtLifetimeToken,
-    private val builder: KtSymbolByFirBuilder,
-) : KtCapturedType(), KtFirType {
-    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
-
-    override val annotationsList: KtAnnotationsList by cached {
-        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
-    }
-
-    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
-
-
-    override fun equals(other: Any?) = typeEquals(other)
-    override fun hashCode() = typeHashcode()
-}
-
-internal class KtFirDefinitelyNotNullType(
-    override val coneType: ConeDefinitelyNotNullType,
-    override val token: KtLifetimeToken,
-    private val builder: KtSymbolByFirBuilder,
-) : KtDefinitelyNotNullType(), KtFirType {
-    override val original: KtType by cached { builder.typeBuilder.buildKtType(this.coneType.original) }
-    override val annotationsList: KtAnnotationsList by cached {
-        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
-    }
-
-    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
-    override fun equals(other: Any?) = typeEquals(other)
-    override fun hashCode() = typeHashcode()
-}
-
-internal class KtFirTypeParameterType(
-    override val coneType: ConeTypeParameterType,
-    override val token: KtLifetimeToken,
-    private val builder: KtSymbolByFirBuilder,
-) : KtTypeParameterType(), KtFirType {
-    override val name: Name get() = withValidityAssertion { coneType.lookupTag.name }
-    override val symbol: KtTypeParameterSymbol by cached {
-        builder.classifierBuilder.buildTypeParameterSymbolByLookupTag(coneType.lookupTag)
-            ?: error("Type parameter ${coneType.lookupTag} was not found")
-    }
-
-    override val annotationsList: KtAnnotationsList by cached {
-        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
-    }
-
-    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
-
-    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
-    override fun equals(other: Any?) = typeEquals(other)
-    override fun hashCode() = typeHashcode()
-}
-
-internal class KtFirFlexibleType(
-    override val coneType: ConeFlexibleType,
-    override val token: KtLifetimeToken,
-    private val builder: KtSymbolByFirBuilder,
-) : KtFlexibleType(), KtFirType {
-
-    override val lowerBound: KtType by cached { builder.typeBuilder.buildKtType(coneType.lowerBound) }
-    override val upperBound: KtType by cached { builder.typeBuilder.buildKtType(coneType.upperBound) }
-    override val annotationsList: KtAnnotationsList by cached {
-        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
-    }
-    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
-
-    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
-    override fun equals(other: Any?) = typeEquals(other)
-    override fun hashCode() = typeHashcode()
-}
-
-internal class KtFirIntersectionType(
-    override val coneType: ConeIntersectionType,
-    override val token: KtLifetimeToken,
-    private val builder: KtSymbolByFirBuilder,
-) : KtIntersectionType(), KtFirType {
-    override val conjuncts: List<KtType> by cached {
-        coneType.intersectedTypes.map { conjunct -> builder.typeBuilder.buildKtType(conjunct) }
-    }
-    override val annotationsList: KtAnnotationsList by cached {
-        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
-    }
-    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
-
-    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
-    override fun equals(other: Any?) = typeEquals(other)
-    override fun hashCode() = typeHashcode()
-}
-
-internal class KtFirIntegerLiteralType(
-    override val coneType: ConeIntegerLiteralConstantType,
-    override val token: KtLifetimeToken,
-    private val builder: KtSymbolByFirBuilder,
-) : KtIntegerLiteralType(), KtFirType {
-    override val isUnsigned: Boolean get() = withValidityAssertion { coneType.isUnsigned }
-
-    override val value: Long get() = withValidityAssertion { coneType.value }
-
-    override val possibleTypes: List<KtClassType> by cached {
-        coneType.possibleTypes.map { possibleType ->
-            builder.typeBuilder.buildKtType(possibleType) as KtClassType
-        }
-    }
-
-    override val annotationsList: KtAnnotationsList by cached {
-        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
-    }
-
-    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
-
-    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
-    override fun equals(other: Any?) = typeEquals(other)
-    override fun hashCode() = typeHashcode()
-}
-
-private fun ConeNullability.asKtNullability(): KtTypeNullability = when (this) {
-    ConeNullability.NULLABLE -> KtTypeNullability.NULLABLE
-    ConeNullability.UNKNOWN -> KtTypeNullability.UNKNOWN
-    ConeNullability.NOT_NULL -> KtTypeNullability.NON_NULLABLE
-}
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirCapturedType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirCapturedType.kt
new file mode 100644
index 0000000..3c4f206
--- /dev/null
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirCapturedType.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010-2022 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.analysis.api.fir.types
+
+import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
+import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
+import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
+import org.jetbrains.kotlin.analysis.api.fir.utils.cached
+import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
+import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
+import org.jetbrains.kotlin.analysis.api.types.KtCapturedType
+import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
+import org.jetbrains.kotlin.fir.types.ConeCapturedType
+import org.jetbrains.kotlin.fir.types.render
+
+internal class KtFirCapturedType(
+    override val coneType: ConeCapturedType,
+    override val token: KtLifetimeToken,
+    private val builder: KtSymbolByFirBuilder,
+) : KtCapturedType(), KtFirType {
+    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
+
+    override val annotationsList: KtAnnotationsList by cached {
+        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
+    }
+
+    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
+
+
+    override fun equals(other: Any?) = typeEquals(other)
+    override fun hashCode() = typeHashcode()
+}
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirClassErrorType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirClassErrorType.kt
new file mode 100644
index 0000000..e488881
--- /dev/null
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirClassErrorType.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2010-2022 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.analysis.api.fir.types
+
+import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
+import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
+import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
+import org.jetbrains.kotlin.analysis.api.fir.getCandidateSymbols
+import org.jetbrains.kotlin.analysis.api.fir.utils.cached
+import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
+import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
+import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
+import org.jetbrains.kotlin.analysis.api.types.KtClassErrorType
+import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
+import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
+import org.jetbrains.kotlin.fir.types.ConeErrorType
+import org.jetbrains.kotlin.fir.types.render
+
+internal class KtFirClassErrorType(
+    override val coneType: ConeErrorType,
+    override val token: KtLifetimeToken,
+    private val builder: KtSymbolByFirBuilder,
+) : KtClassErrorType(), KtFirType {
+
+    override val error: String get() = withValidityAssertion { coneType.diagnostic.reason }
+    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
+
+    override val annotationsList: KtAnnotationsList by cached {
+        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
+    }
+
+    override val candidateClassSymbols: Collection<KtClassLikeSymbol> by cached {
+        val symbols = coneType.diagnostic.getCandidateSymbols().filterIsInstance<FirClassLikeSymbol<*>>()
+        symbols.map { builder.classifierBuilder.buildClassLikeSymbol(it) }
+    }
+
+    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
+    override fun equals(other: Any?) = typeEquals(other)
+    override fun hashCode() = typeHashcode()
+}
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirDefinitelyNotNullType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirDefinitelyNotNullType.kt
new file mode 100644
index 0000000..903da23
--- /dev/null
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirDefinitelyNotNullType.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010-2022 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.analysis.api.fir.types
+
+import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
+import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
+import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
+import org.jetbrains.kotlin.analysis.api.fir.utils.cached
+import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
+import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
+import org.jetbrains.kotlin.analysis.api.types.KtDefinitelyNotNullType
+import org.jetbrains.kotlin.analysis.api.types.KtType
+import org.jetbrains.kotlin.fir.types.ConeDefinitelyNotNullType
+import org.jetbrains.kotlin.fir.types.render
+
+internal class KtFirDefinitelyNotNullType(
+    override val coneType: ConeDefinitelyNotNullType,
+    override val token: KtLifetimeToken,
+    private val builder: KtSymbolByFirBuilder,
+) : KtDefinitelyNotNullType(), KtFirType {
+    override val original: KtType by cached { builder.typeBuilder.buildKtType(this.coneType.original) }
+    override val annotationsList: KtAnnotationsList by cached {
+        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
+    }
+
+    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
+    override fun equals(other: Any?) = typeEquals(other)
+    override fun hashCode() = typeHashcode()
+}
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirFlexibleType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirFlexibleType.kt
new file mode 100644
index 0000000..79db272
--- /dev/null
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirFlexibleType.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010-2022 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.analysis.api.fir.types
+
+import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
+import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
+import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
+import org.jetbrains.kotlin.analysis.api.fir.utils.cached
+import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
+import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
+import org.jetbrains.kotlin.analysis.api.types.KtFlexibleType
+import org.jetbrains.kotlin.analysis.api.types.KtType
+import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
+import org.jetbrains.kotlin.fir.types.ConeFlexibleType
+import org.jetbrains.kotlin.fir.types.render
+
+internal class KtFirFlexibleType(
+    override val coneType: ConeFlexibleType,
+    override val token: KtLifetimeToken,
+    private val builder: KtSymbolByFirBuilder,
+) : KtFlexibleType(), KtFirType {
+
+    override val lowerBound: KtType by cached { builder.typeBuilder.buildKtType(coneType.lowerBound) }
+    override val upperBound: KtType by cached { builder.typeBuilder.buildKtType(coneType.upperBound) }
+    override val annotationsList: KtAnnotationsList by cached {
+        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
+    }
+    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
+
+    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
+    override fun equals(other: Any?) = typeEquals(other)
+    override fun hashCode() = typeHashcode()
+}
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirFunctionalType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirFunctionalType.kt
new file mode 100644
index 0000000..4026ec2
--- /dev/null
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirFunctionalType.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2010-2022 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.analysis.api.fir.types
+
+import org.jetbrains.kotlin.analysis.api.KtTypeArgument
+import org.jetbrains.kotlin.analysis.api.KtTypeArgumentWithVariance
+import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
+import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
+import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
+import org.jetbrains.kotlin.analysis.api.fir.utils.cached
+import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
+import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
+import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
+import org.jetbrains.kotlin.analysis.api.types.KtFunctionalType
+import org.jetbrains.kotlin.analysis.api.types.KtType
+import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
+import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
+import org.jetbrains.kotlin.fir.types.isExtensionFunctionType
+import org.jetbrains.kotlin.fir.types.isSuspendFunctionType
+import org.jetbrains.kotlin.fir.types.receiverType
+import org.jetbrains.kotlin.fir.types.render
+import org.jetbrains.kotlin.name.ClassId
+
+internal class KtFirFunctionalType(
+    override val coneType: ConeClassLikeTypeImpl,
+    override val token: KtLifetimeToken,
+    private val builder: KtSymbolByFirBuilder,
+) : KtFunctionalType(), KtFirType {
+    override val classId: ClassId get() = withValidityAssertion { coneType.lookupTag.classId }
+    override val classSymbol: KtClassLikeSymbol by cached {
+        builder.classifierBuilder.buildClassLikeSymbolByLookupTag(coneType.lookupTag)
+            ?: error("Class ${coneType.lookupTag} was not found")
+    }
+    override val typeArguments: List<KtTypeArgument> by cached {
+        coneType.typeArguments.map { typeArgument ->
+            builder.typeBuilder.buildTypeArgument(typeArgument)
+        }
+    }
+
+    override val annotationsList: KtAnnotationsList by cached {
+        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
+    }
+
+    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
+
+    override val isSuspend: Boolean get() = withValidityAssertion { coneType.isSuspendFunctionType(builder.rootSession) }
+    override val arity: Int
+        get() = withValidityAssertion {
+            if (coneType.isExtensionFunctionType) coneType.typeArguments.size - 2
+            else coneType.typeArguments.size - 1
+        }
+
+    override val receiverType: KtType?
+        get() = withValidityAssertion {
+            if (coneType.isExtensionFunctionType) (typeArguments.first() as KtTypeArgumentWithVariance).type
+            else null
+        }
+
+    override val hasReceiver: Boolean
+        get() = withValidityAssertion {
+            coneType.receiverType(builder.rootSession) != null
+        }
+
+    override val parameterTypes: List<KtType> by cached {
+        val parameterTypeArgs = if (coneType.isExtensionFunctionType) typeArguments.subList(1, typeArguments.lastIndex)
+        else typeArguments.subList(0, typeArguments.lastIndex)
+        parameterTypeArgs.map { (it as KtTypeArgumentWithVariance).type }
+    }
+
+    override val returnType: KtType
+        get() = withValidityAssertion { (typeArguments.last() as KtTypeArgumentWithVariance).type }
+
+    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
+    override fun equals(other: Any?) = typeEquals(other)
+    override fun hashCode() = typeHashcode()
+}
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirIntegerLiteralType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirIntegerLiteralType.kt
new file mode 100644
index 0000000..2faf80b
--- /dev/null
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirIntegerLiteralType.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2010-2022 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.analysis.api.fir.types
+
+import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
+import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
+import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
+import org.jetbrains.kotlin.analysis.api.fir.utils.cached
+import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
+import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
+import org.jetbrains.kotlin.analysis.api.types.KtClassType
+import org.jetbrains.kotlin.analysis.api.types.KtIntegerLiteralType
+import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
+import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralConstantType
+import org.jetbrains.kotlin.fir.types.render
+
+internal class KtFirIntegerLiteralType(
+    override val coneType: ConeIntegerLiteralConstantType,
+    override val token: KtLifetimeToken,
+    private val builder: KtSymbolByFirBuilder,
+) : KtIntegerLiteralType(), KtFirType {
+    override val isUnsigned: Boolean get() = withValidityAssertion { coneType.isUnsigned }
+
+    override val value: Long get() = withValidityAssertion { coneType.value }
+
+    override val possibleTypes: List<KtClassType> by cached {
+        coneType.possibleTypes.map { possibleType ->
+            builder.typeBuilder.buildKtType(possibleType) as KtClassType
+        }
+    }
+
+    override val annotationsList: KtAnnotationsList by cached {
+        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
+    }
+
+    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
+
+    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
+    override fun equals(other: Any?) = typeEquals(other)
+    override fun hashCode() = typeHashcode()
+}
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirIntersectionType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirIntersectionType.kt
new file mode 100644
index 0000000..abc8fc9
--- /dev/null
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirIntersectionType.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010-2022 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.analysis.api.fir.types
+
+import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
+import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
+import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
+import org.jetbrains.kotlin.analysis.api.fir.utils.cached
+import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
+import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
+import org.jetbrains.kotlin.analysis.api.types.KtIntersectionType
+import org.jetbrains.kotlin.analysis.api.types.KtType
+import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
+import org.jetbrains.kotlin.fir.types.ConeIntersectionType
+import org.jetbrains.kotlin.fir.types.render
+
+internal class KtFirIntersectionType(
+    override val coneType: ConeIntersectionType,
+    override val token: KtLifetimeToken,
+    private val builder: KtSymbolByFirBuilder,
+) : KtIntersectionType(), KtFirType {
+    override val conjuncts: List<KtType> by cached {
+        coneType.intersectedTypes.map { conjunct -> builder.typeBuilder.buildKtType(conjunct) }
+    }
+    override val annotationsList: KtAnnotationsList by cached {
+        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
+    }
+    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
+
+    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
+    override fun equals(other: Any?) = typeEquals(other)
+    override fun hashCode() = typeHashcode()
+}
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirType.kt
new file mode 100644
index 0000000..82c2916
--- /dev/null
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirType.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2010-2022 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.analysis.api.fir.types
+
+import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeOwner
+import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
+import org.jetbrains.kotlin.fir.types.ConeKotlinType
+import org.jetbrains.kotlin.fir.types.ConeNullability
+
+internal interface KtFirType : KtLifetimeOwner {
+    val coneType: ConeKotlinType
+}
+
+internal fun KtFirType.typeEquals(other: Any?): Boolean {
+    if (other !is KtFirType) return false
+    return this.coneType == other.coneType
+}
+
+internal fun KtFirType.typeHashcode(): Int = coneType.hashCode()
+
+internal fun ConeNullability.asKtNullability(): KtTypeNullability = when (this) {
+    ConeNullability.NULLABLE -> KtTypeNullability.NULLABLE
+    ConeNullability.UNKNOWN -> KtTypeNullability.UNKNOWN
+    ConeNullability.NOT_NULL -> KtTypeNullability.NON_NULLABLE
+}
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirTypeParameterType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirTypeParameterType.kt
new file mode 100644
index 0000000..6956874
--- /dev/null
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirTypeParameterType.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2010-2022 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.analysis.api.fir.types
+
+import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
+import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
+import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
+import org.jetbrains.kotlin.analysis.api.fir.utils.cached
+import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
+import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
+import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol
+import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
+import org.jetbrains.kotlin.analysis.api.types.KtTypeParameterType
+import org.jetbrains.kotlin.fir.types.ConeTypeParameterType
+import org.jetbrains.kotlin.fir.types.render
+import org.jetbrains.kotlin.name.Name
+
+internal class KtFirTypeParameterType(
+    override val coneType: ConeTypeParameterType,
+    override val token: KtLifetimeToken,
+    private val builder: KtSymbolByFirBuilder,
+) : KtTypeParameterType(), KtFirType {
+    override val name: Name get() = withValidityAssertion { coneType.lookupTag.name }
+    override val symbol: KtTypeParameterSymbol by cached {
+        builder.classifierBuilder.buildTypeParameterSymbolByLookupTag(coneType.lookupTag)
+            ?: error("Type parameter ${coneType.lookupTag} was not found")
+    }
+
+    override val annotationsList: KtAnnotationsList by cached {
+        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
+    }
+
+    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
+
+    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
+    override fun equals(other: Any?) = typeEquals(other)
+    override fun hashCode() = typeHashcode()
+}
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirUsualClassType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirUsualClassType.kt
new file mode 100644
index 0000000..7acbff6
--- /dev/null
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirUsualClassType.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010-2022 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.analysis.api.fir.types
+
+import org.jetbrains.kotlin.analysis.api.KtTypeArgument
+import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
+import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
+import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
+import org.jetbrains.kotlin.analysis.api.fir.utils.cached
+import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
+import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
+import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
+import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
+import org.jetbrains.kotlin.analysis.api.types.KtUsualClassType
+import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
+import org.jetbrains.kotlin.fir.types.render
+import org.jetbrains.kotlin.name.ClassId
+
+internal class KtFirUsualClassType(
+    override val coneType: ConeClassLikeTypeImpl,
+    override val token: KtLifetimeToken,
+    private val builder: KtSymbolByFirBuilder,
+) : KtUsualClassType(), KtFirType {
+    override val classId: ClassId get() = withValidityAssertion { coneType.lookupTag.classId }
+    override val classSymbol: KtClassLikeSymbol by cached {
+        builder.classifierBuilder.buildClassLikeSymbolByLookupTag(coneType.lookupTag)
+            ?: error("Class ${coneType.lookupTag} was not found")
+    }
+    override val typeArguments: List<KtTypeArgument> by cached {
+        coneType.typeArguments.map { typeArgument ->
+            builder.typeBuilder.buildTypeArgument(typeArgument)
+        }
+    }
+
+    override val annotationsList: KtAnnotationsList by cached {
+        KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
+    }
+
+    override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
+    override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
+    override fun equals(other: Any?) = typeEquals(other)
+    override fun hashCode() = typeHashcode()
+}