FIR: Implement cycle avoidance in implicit type resolution
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.fir.symbols.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
|
||||
sealed class ConeKotlinTypeProjection : TypeArgumentMarker {
|
||||
@@ -69,21 +70,11 @@ val ConeKotlinType.isNullable: Boolean get() = nullability != ConeNullability.NO
|
||||
|
||||
val ConeKotlinType.isMarkedNullable: Boolean get() = nullability == ConeNullability.NULLABLE
|
||||
|
||||
class ConeKotlinErrorType(val reason: String) : ConeKotlinType() {
|
||||
override val typeArguments: Array<out ConeKotlinTypeProjection>
|
||||
get() = EMPTY_ARRAY
|
||||
|
||||
override val nullability: ConeNullability
|
||||
get() = ConeNullability.UNKNOWN
|
||||
|
||||
override fun toString(): String {
|
||||
return "<ERROR TYPE: $reason>"
|
||||
}
|
||||
}
|
||||
typealias ConeKotlinErrorType = ConeClassErrorType
|
||||
|
||||
class ConeClassErrorType(val reason: String) : ConeClassLikeType() {
|
||||
override val lookupTag: ConeClassLikeLookupTag
|
||||
get() = error("!")
|
||||
get() = ConeClassLikeLookupTagImpl(ClassId.fromString("<error>"))
|
||||
|
||||
override val typeArguments: Array<out ConeKotlinTypeProjection>
|
||||
get() = EMPTY_ARRAY
|
||||
|
||||
@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
|
||||
fun ConeKotlinType.scope(useSiteSession: FirSession): FirScope? {
|
||||
return when (this) {
|
||||
@@ -32,3 +34,16 @@ fun ConeKotlinType.scope(useSiteSession: FirSession): FirScope? {
|
||||
|
||||
|
||||
|
||||
|
||||
fun FirRegularClass.defaultType(): ConeClassTypeImpl {
|
||||
return ConeClassTypeImpl(
|
||||
symbol.toLookupTag(),
|
||||
typeParameters.map {
|
||||
ConeTypeParameterTypeImpl(
|
||||
it.symbol.toLookupTag(),
|
||||
isNullable = false
|
||||
)
|
||||
}.toTypedArray(),
|
||||
isNullable = false
|
||||
)
|
||||
}
|
||||
@@ -9,6 +9,9 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirNamedFunction
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
|
||||
@@ -16,9 +19,15 @@ import org.jetbrains.kotlin.fir.scopes.FirPosition
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.scopes.processClassifiersByNameWithAction
|
||||
import org.jetbrains.kotlin.fir.service
|
||||
import org.jetbrains.kotlin.fir.symbols.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import java.util.*
|
||||
import kotlin.collections.LinkedHashSet
|
||||
|
||||
@@ -72,7 +81,9 @@ class CallResolver(val typeCalculator: ReturnTypeCalculator) {
|
||||
|
||||
enum class CandidateApplicability {
|
||||
HIDDEN,
|
||||
WRONG_RECEIVER,
|
||||
PARAMETER_MAPPING_ERROR,
|
||||
INAPPLICABLE,
|
||||
SYNTHETIC_RESOLVED,
|
||||
RESOLVED
|
||||
}
|
||||
@@ -98,15 +109,11 @@ abstract class ApplicabilityChecker {
|
||||
currentApplicability = CandidateApplicability.HIDDEN
|
||||
}
|
||||
|
||||
|
||||
fun isSubtypeOf(superType: FirTypeRef?, subType: FirTypeRef?): Boolean {
|
||||
if (superType == null && subType == null) return true
|
||||
if (superType != null && subType != null) return true
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
protected open fun getApplicability(group: Int, symbol: ConeSymbol): CandidateApplicability {
|
||||
protected open fun getApplicability(
|
||||
group: Int,
|
||||
symbol: ConeSymbol,
|
||||
resolver: CallResolver
|
||||
): CandidateApplicability {
|
||||
val declaration = (symbol as? FirBasedSymbol<*>)?.fir
|
||||
?: return CandidateApplicability.HIDDEN
|
||||
declaration as FirDeclaration
|
||||
@@ -119,7 +126,7 @@ abstract class ApplicabilityChecker {
|
||||
}
|
||||
|
||||
open fun consumeCandidate(group: Int, symbol: ConeSymbol, resolver: CallResolver) {
|
||||
val applicability = getApplicability(group, symbol)
|
||||
val applicability = getApplicability(group, symbol, resolver)
|
||||
|
||||
if (applicability > currentApplicability) {
|
||||
groupNumbers.clear()
|
||||
@@ -192,7 +199,11 @@ class VariableInvokeApplicabilityChecker(val variableName: Name) : FunctionAppli
|
||||
return true //TODO: Actual type-check here
|
||||
}
|
||||
|
||||
override fun getApplicability(group: Int, symbol: ConeSymbol): CandidateApplicability {
|
||||
override fun getApplicability(
|
||||
group: Int,
|
||||
symbol: ConeSymbol,
|
||||
resolver: CallResolver
|
||||
): CandidateApplicability {
|
||||
|
||||
symbol as ConeCallableSymbol
|
||||
val declaration = (symbol as? FirBasedSymbol<*>)?.fir
|
||||
@@ -239,9 +250,10 @@ class VariableInvokeApplicabilityChecker(val variableName: Name) : FunctionAppli
|
||||
|
||||
val lastCandidate = variableChecker.candidates.lastOrNull()
|
||||
if (variableChecker.currentApplicability == CandidateApplicability.RESOLVED && lastCandidate == symbol) {
|
||||
|
||||
val receiverScope =
|
||||
resolver.typeCalculator.tryCalculateReturnType(lastCandidate.firUnsafe())?.type
|
||||
?.scope(resolver.session)
|
||||
resolver.typeCalculator.tryCalculateReturnType(lastCandidate.firUnsafe()).type
|
||||
.scope(resolver.session)
|
||||
|
||||
|
||||
lookupInvoke = true
|
||||
@@ -294,18 +306,51 @@ open class FunctionApplicabilityChecker(val name: Name) : ApplicabilityChecker()
|
||||
names.add(name)
|
||||
}
|
||||
|
||||
override fun getApplicability(group: Int, symbol: ConeSymbol): CandidateApplicability {
|
||||
val declaration = (symbol as FirBasedSymbol<*>).fir
|
||||
lateinit var session: FirSession
|
||||
|
||||
if (declaration is FirFunction) {
|
||||
if (declaration.valueParameters.size != parameterCount) return CandidateApplicability.PARAMETER_MAPPING_ERROR
|
||||
override fun getApplicability(
|
||||
group: Int,
|
||||
symbol: ConeSymbol,
|
||||
resolver: CallResolver
|
||||
): CandidateApplicability {
|
||||
val declaration = symbol.firUnsafe<FirCallableDeclaration>()
|
||||
|
||||
if (declaration is FirFunction && declaration.valueParameters.size != parameterCount) return CandidateApplicability.PARAMETER_MAPPING_ERROR
|
||||
|
||||
|
||||
var extensionReceiver = declaration.receiverTypeRef?.coneTypeUnsafe()
|
||||
var dispatchReceiver = declaration.dispatchReceiverType(session)
|
||||
|
||||
val explicitReceiverType = explicitReceiverType?.coneTypeUnsafe()
|
||||
|
||||
|
||||
if (explicitReceiverType != null) {
|
||||
if (dispatchReceiver != null && explicitReceiverType.isSubtypeOf(dispatchReceiver, session)) {
|
||||
dispatchReceiver = null
|
||||
}
|
||||
if (extensionReceiver != null && explicitReceiverType.isSubtypeOf(extensionReceiver, session)) {
|
||||
extensionReceiver = null
|
||||
}
|
||||
if (extensionReceiver != null || dispatchReceiver != null) return CandidateApplicability.WRONG_RECEIVER
|
||||
}
|
||||
return super.getApplicability(group, symbol)
|
||||
|
||||
return CandidateApplicability.RESOLVED
|
||||
}
|
||||
|
||||
fun ConeKotlinType.isSubtypeOf(type: ConeKotlinType, session: FirSession): Boolean {
|
||||
return AbstractTypeChecker.isSubtypeOf(ConeTypeCheckerContext(true, session), this, type)
|
||||
}
|
||||
|
||||
override fun consumeCandidate(group: Int, symbol: ConeSymbol, resolver: CallResolver) {
|
||||
if (symbol !is ConeFunctionSymbol) return
|
||||
if (symbol.callableId.callableName != name) return
|
||||
session = resolver.session
|
||||
super.consumeCandidate(group, symbol, resolver)
|
||||
}
|
||||
}
|
||||
|
||||
fun FirCallableDeclaration.dispatchReceiverType(session: FirSession): ConeKotlinType? {
|
||||
val id = (this.symbol as ConeCallableSymbol).callableId.classId ?: return null
|
||||
val symbol = session.service<FirSymbolProvider>().getClassLikeSymbolByFqName(id) as? FirClassSymbol ?: return null
|
||||
return symbol.fir.defaultType()
|
||||
}
|
||||
+70
-49
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.transformers
|
||||
import com.google.common.collect.LinkedHashMultimap
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultSetterValueParameter
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
|
||||
@@ -17,6 +18,7 @@ import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
import org.jetbrains.kotlin.fir.scopes.*
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||
@@ -26,10 +28,7 @@ import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.compose
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
@@ -67,6 +66,7 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
|
||||
|
||||
override fun transformValueParameter(valueParameter: FirValueParameter, data: Any?): CompositeTransformResult<FirDeclaration> {
|
||||
localScopes.lastOrNull()?.storeDeclaration(valueParameter)
|
||||
if (valueParameter.returnTypeRef is FirImplicitTypeRef) return valueParameter.compose() // TODO
|
||||
return super.transformValueParameter(valueParameter, data)
|
||||
}
|
||||
|
||||
@@ -88,19 +88,6 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirRegularClass.defaultType(): ConeClassTypeImpl {
|
||||
return ConeClassTypeImpl(
|
||||
symbol.toLookupTag(),
|
||||
typeParameters.map {
|
||||
ConeTypeParameterTypeImpl(
|
||||
it.symbol.toLookupTag(),
|
||||
isNullable = false
|
||||
)
|
||||
}.toTypedArray(),
|
||||
isNullable = false
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
protected inline fun <T> withScopeCleanup(scopes: MutableList<*>, crossinline l: () -> T): T {
|
||||
val sizeBefore = scopes.size
|
||||
@@ -119,7 +106,7 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
|
||||
val labels = LinkedHashMultimap.create<Name, ConeKotlinType>()
|
||||
|
||||
|
||||
val jump = ReturnTypeCalculatorWithJump()
|
||||
val jump = ReturnTypeCalculatorWithJump(session)
|
||||
|
||||
private fun runTowerResolver(
|
||||
checkers: List<ApplicabilityChecker>
|
||||
@@ -138,7 +125,7 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
|
||||
is FirErrorNamedReference ->
|
||||
FirErrorTypeRefImpl(session, access.psi, newCallee.errorReason)
|
||||
is FirResolvedCallableReference ->
|
||||
jump.tryCalculateReturnType(newCallee.callableSymbol.firUnsafe())!!
|
||||
jump.tryCalculateReturnType(newCallee.callableSymbol.firUnsafe())
|
||||
else -> return
|
||||
}
|
||||
}
|
||||
@@ -369,40 +356,74 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
|
||||
require(result.single === this)
|
||||
}
|
||||
|
||||
inner class ReturnTypeCalculatorWithJump : ReturnTypeCalculator {
|
||||
override fun tryCalculateReturnType(declaration: FirTypedDeclaration): FirResolvedTypeRef? {
|
||||
val returnTypeRef = declaration.returnTypeRef
|
||||
if (returnTypeRef is FirResolvedTypeRef) return returnTypeRef
|
||||
require(declaration is FirCallableMemberDeclaration)
|
||||
}
|
||||
|
||||
|
||||
val id = (declaration.symbol as ConeCallableSymbol).callableId
|
||||
|
||||
val provider = session.service<FirProvider>()
|
||||
|
||||
val file = provider.getFirCallableContainerFile(id) ?: FirErrorTypeRefImpl(
|
||||
session,
|
||||
null,
|
||||
"I don't know what todo"
|
||||
)
|
||||
|
||||
val outerClasses = generateSequence(id.classId) { classId ->
|
||||
classId.outerClassId
|
||||
}.mapTo(mutableListOf()) { provider.getFirClassifierByFqName(it)!! }
|
||||
class ReturnTypeCalculatorWithJump(val session: FirSession) : ReturnTypeCalculator {
|
||||
|
||||
|
||||
val transformer = FirDesignatedBodyResolveTransformer(
|
||||
(listOf(file) + outerClasses.asReversed() + listOf(declaration)).iterator(),
|
||||
file.session
|
||||
)
|
||||
|
||||
transformer.transformElement(file, null)
|
||||
|
||||
val newReturnTypeRef = declaration.returnTypeRef
|
||||
require(newReturnTypeRef is FirResolvedTypeRef) { declaration.render() }
|
||||
return newReturnTypeRef
|
||||
val storeType = object : FirTransformer<FirTypeRef>() {
|
||||
override fun <E : FirElement> transformElement(element: E, data: FirTypeRef): CompositeTransformResult<E> {
|
||||
return element.compose()
|
||||
}
|
||||
|
||||
override fun transformImplicitTypeRef(
|
||||
implicitTypeRef: FirImplicitTypeRef,
|
||||
data: FirTypeRef
|
||||
): CompositeTransformResult<FirTypeRef> {
|
||||
return data.compose()
|
||||
}
|
||||
}
|
||||
|
||||
private fun cycleErrorType(declaration: FirTypedDeclaration): FirResolvedTypeRef? {
|
||||
if (declaration.returnTypeRef is FirComputingImplicitTypeRef) {
|
||||
declaration.transformReturnTypeRef(storeType, FirErrorTypeRefImpl(session, null, "cycle"))
|
||||
return declaration.returnTypeRef as FirResolvedTypeRef
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun tryCalculateReturnType(declaration: FirTypedDeclaration): FirResolvedTypeRef {
|
||||
|
||||
if (declaration is FirValueParameter && declaration.returnTypeRef is FirImplicitTypeRef) {
|
||||
// TODO?
|
||||
declaration.transformReturnTypeRef(storeType, FirErrorTypeRefImpl(session, null, "Unsupported: implicit VP type"))
|
||||
}
|
||||
val returnTypeRef = declaration.returnTypeRef
|
||||
if (returnTypeRef is FirResolvedTypeRef) return returnTypeRef
|
||||
cycleErrorType(declaration)?.let { return it }
|
||||
require(declaration is FirCallableMemberDeclaration) { "${declaration::class}: ${declaration.render()}" }
|
||||
|
||||
|
||||
val id = (declaration.symbol as ConeCallableSymbol).callableId
|
||||
|
||||
val provider = session.service<FirProvider>()
|
||||
|
||||
val file = provider.getFirCallableContainerFile(id) ?: FirErrorTypeRefImpl(
|
||||
session,
|
||||
null,
|
||||
"I don't know what todo"
|
||||
)
|
||||
|
||||
val outerClasses = generateSequence(id.classId) { classId ->
|
||||
classId.outerClassId
|
||||
}.mapTo(mutableListOf()) { provider.getFirClassifierByFqName(it)!! }
|
||||
|
||||
|
||||
declaration.transformReturnTypeRef(storeType, FirComputingImplicitTypeRef)
|
||||
|
||||
val transformer = FirDesignatedBodyResolveTransformer(
|
||||
(listOf(file) + outerClasses.asReversed() + listOf(declaration)).iterator(),
|
||||
file.session
|
||||
)
|
||||
|
||||
file.transform(transformer, null)
|
||||
|
||||
|
||||
val newReturnTypeRef = declaration.returnTypeRef
|
||||
cycleErrorType(declaration)?.let { return it }
|
||||
require(newReturnTypeRef is FirResolvedTypeRef) { declaration.render() }
|
||||
return newReturnTypeRef
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,12 +467,12 @@ class FirBodyResolveTransformerAdapter : FirTransformer<Nothing?>() {
|
||||
}
|
||||
|
||||
|
||||
inline fun <reified T> ConeSymbol.firUnsafe(): T {
|
||||
inline fun <reified T : FirElement> ConeSymbol.firUnsafe(): T {
|
||||
this as FirBasedSymbol<*>
|
||||
return this.fir as T
|
||||
}
|
||||
|
||||
|
||||
interface ReturnTypeCalculator {
|
||||
fun tryCalculateReturnType(declaration: FirTypedDeclaration): FirResolvedTypeRef?
|
||||
fun tryCalculateReturnType(declaration: FirTypedDeclaration): FirResolvedTypeRef
|
||||
}
|
||||
+4
-1
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.FirNamedFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirMemberFunctionImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorWithJump
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.symbols.*
|
||||
@@ -97,6 +98,8 @@ class FirClassSubstitutionScope(
|
||||
return useSiteScope.processPropertiesByName(name, processor)
|
||||
}
|
||||
|
||||
private val typeCalculator by lazy { ReturnTypeCalculatorWithJump(session) }
|
||||
|
||||
private fun createFakeOverride(
|
||||
original: ConeFunctionSymbol,
|
||||
name: Name
|
||||
@@ -105,7 +108,7 @@ class FirClassSubstitutionScope(
|
||||
val receiverType = member.receiverTypeRef?.coneTypeUnsafe()
|
||||
val newReceiverType = receiverType?.substitute()
|
||||
|
||||
val returnType = member.returnTypeRef.coneTypeUnsafe()
|
||||
val returnType = typeCalculator.tryCalculateReturnType(member).type
|
||||
val newReturnType = returnType.substitute()
|
||||
|
||||
val newParameterTypes = member.valueParameters.map {
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.expandedConeType
|
||||
import org.jetbrains.kotlin.fir.declarations.superConeTypes
|
||||
@@ -22,7 +23,13 @@ import org.jetbrains.kotlin.fir.types.impl.ConeAbbreviatedTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeFunctionTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType
|
||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||
import org.jetbrains.kotlin.types.DefinitelyNotNullType
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedType
|
||||
import org.jetbrains.kotlin.types.checker.convertVariance
|
||||
import org.jetbrains.kotlin.types.isError
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
|
||||
|
||||
@@ -176,6 +183,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext {
|
||||
}
|
||||
|
||||
override fun TypeConstructorMarker.supertypes(): Collection<KotlinTypeMarker> {
|
||||
if (this is ErrorTypeConstructor) return emptyList()
|
||||
require(this is ConeSymbol)
|
||||
return when (this) {
|
||||
is ConeTypeParameterSymbol -> emptyList()
|
||||
@@ -235,7 +243,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext {
|
||||
}
|
||||
|
||||
override fun captureFromArguments(type: SimpleTypeMarker, status: CaptureStatus): SimpleTypeMarker? {
|
||||
TODO("not implemented")
|
||||
return type //TODO
|
||||
}
|
||||
|
||||
override fun SimpleTypeMarker.asArgumentList(): TypeArgumentListMarker {
|
||||
@@ -264,7 +272,39 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext {
|
||||
return typeConstructor().isNothingConstructor() && !this.nullability.isNullable
|
||||
}
|
||||
|
||||
|
||||
|
||||
override fun SimpleTypeMarker.isSingleClassifierType(): Boolean {
|
||||
TODO("not implemented")
|
||||
require(this is ConeLookupTagBasedType)
|
||||
val symbol = this.lookupTag.toSymbol(session)
|
||||
return !isError() &&
|
||||
(symbol is FirClassSymbol ||
|
||||
symbol is FirTypeParameterSymbol)
|
||||
// || TODO: (this is CapturedType || this is NewCapturedType || this is DefinitelyNotNullType)
|
||||
}
|
||||
}
|
||||
|
||||
class ConeTypeCheckerContext(override val isErrorTypeEqualsToAnything: Boolean, override val session: FirSession) :
|
||||
AbstractTypeCheckerContext(), ConeTypeContext {
|
||||
override fun substitutionSupertypePolicy(type: SimpleTypeMarker): SupertypesPolicy.DoCustomTransform {
|
||||
return object : SupertypesPolicy.DoCustomTransform() {
|
||||
override fun transformType(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): SimpleTypeMarker {
|
||||
return type.lowerBoundIfFlexible() //TODO
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun areEqualTypeConstructors(a: TypeConstructorMarker, b: TypeConstructorMarker): Boolean {
|
||||
return a == b
|
||||
}
|
||||
|
||||
override fun intersectTypes(types: List<KotlinTypeMarker>): KotlinTypeMarker {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override val KotlinTypeMarker.isAllowedTypeVariable: Boolean
|
||||
get() = false
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
interface Base {
|
||||
fun check()
|
||||
}
|
||||
|
||||
|
||||
class My {
|
||||
lateinit var delegate: Base
|
||||
|
||||
fun check() = delegate.check() // Should not resolve
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
FILE: dispatchReceiver.kt
|
||||
public abstract interface Base {
|
||||
public abstract fun check(): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public final class My {
|
||||
public constructor(): super<R|kotlin/Any|>()
|
||||
|
||||
public final lateinit var delegate: R|Base|
|
||||
public get(): R|Base|
|
||||
public set(value: R|Base|): R|kotlin/Unit|
|
||||
|
||||
public final fun check(): <ERROR TYPE: cycle> {
|
||||
^check R|/My.delegate|.R|/My.check|()
|
||||
}
|
||||
|
||||
}
|
||||
+5
@@ -159,6 +159,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/resolve/testData/resolve/expresssions"), Pattern.compile("^([^.]+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("dispatchReceiver.kt")
|
||||
public void testDispatchReceiver() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/dispatchReceiver.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localImplicitBodies.kt")
|
||||
public void testLocalImplicitBodies() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/localImplicitBodies.kt");
|
||||
|
||||
@@ -16,4 +16,14 @@ class FirImplicitTypeRefImpl(
|
||||
) : FirImplicitTypeRef {
|
||||
override val annotations: List<FirAnnotationCall>
|
||||
get() = emptyList()
|
||||
}
|
||||
|
||||
object FirComputingImplicitTypeRef : FirImplicitTypeRef {
|
||||
override val psi: PsiElement?
|
||||
get() = null
|
||||
override val session: FirSession
|
||||
get() = error("Session independent")
|
||||
override val annotations: List<FirAnnotationCall>
|
||||
get() = emptyList()
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user