FIR: Select most specific members from supertypes scope
This commit is contained in:
+1
-1
@@ -25,7 +25,7 @@ abstract class AbstractFirOverrideScope(val session: FirSession, protected val o
|
|||||||
return overrideChecker.isOverriddenProperty(overrideCandidate, baseDeclaration)
|
return overrideChecker.isOverriddenProperty(overrideCandidate, baseDeclaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun similarFunctionsOrBothProperties(
|
protected fun similarFunctionsOrBothProperties(
|
||||||
overrideCandidate: FirCallableMemberDeclaration<*>,
|
overrideCandidate: FirCallableMemberDeclaration<*>,
|
||||||
baseDeclaration: FirCallableMemberDeclaration<*>
|
baseDeclaration: FirCallableMemberDeclaration<*>
|
||||||
): Boolean {
|
): Boolean {
|
||||||
|
|||||||
+15
-7
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.scopes.impl
|
package org.jetbrains.kotlin.fir.scopes.impl
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||||
@@ -20,12 +21,7 @@ abstract class FirAbstractOverrideChecker : FirOverrideChecker {
|
|||||||
overrideCandidate: FirSimpleFunction,
|
overrideCandidate: FirSimpleFunction,
|
||||||
baseDeclaration: FirSimpleFunction
|
baseDeclaration: FirSimpleFunction
|
||||||
): ConeSubstitutor? {
|
): ConeSubstitutor? {
|
||||||
if (overrideCandidate.typeParameters.size != baseDeclaration.typeParameters.size) return null
|
val substitutor = buildSubstitutorForOverridesCheck(overrideCandidate, baseDeclaration) ?: return null
|
||||||
|
|
||||||
val types = baseDeclaration.typeParameters.map {
|
|
||||||
ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
|
|
||||||
}
|
|
||||||
val substitutor = substitutorByMap(overrideCandidate.typeParameters.map { it.symbol }.zip(types).toMap())
|
|
||||||
if (!overrideCandidate.typeParameters.zip(baseDeclaration.typeParameters).all { (a, b) ->
|
if (!overrideCandidate.typeParameters.zip(baseDeclaration.typeParameters).all { (a, b) ->
|
||||||
a.bounds.size == b.bounds.size && a.bounds.zip(b.bounds).all { (aBound, bBound) ->
|
a.bounds.size == b.bounds.size && a.bounds.zip(b.bounds).all { (aBound, bBound) ->
|
||||||
isEqualTypes(aBound, bBound, substitutor)
|
isEqualTypes(aBound, bBound, substitutor)
|
||||||
@@ -34,4 +30,16 @@ abstract class FirAbstractOverrideChecker : FirOverrideChecker {
|
|||||||
) return null
|
) return null
|
||||||
return substitutor
|
return substitutor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun buildSubstitutorForOverridesCheck(
|
||||||
|
overrideCandidate: FirCallableMemberDeclaration<*>,
|
||||||
|
baseDeclaration: FirCallableMemberDeclaration<*>
|
||||||
|
): ConeSubstitutor? {
|
||||||
|
if (overrideCandidate.typeParameters.size != baseDeclaration.typeParameters.size) return null
|
||||||
|
|
||||||
|
val types = baseDeclaration.typeParameters.map {
|
||||||
|
ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
|
||||||
|
}
|
||||||
|
return substitutorByMap(overrideCandidate.typeParameters.map { it.symbol }.zip(types).toMap())
|
||||||
|
}
|
||||||
|
|||||||
+164
-19
@@ -5,14 +5,28 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.scopes.impl
|
package org.jetbrains.kotlin.fir.scopes.impl
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
|
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeFlexibleType
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
|
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.flattenTo
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.HashSet
|
||||||
|
|
||||||
class FirSuperTypeScope private constructor(
|
class FirSuperTypeScope private constructor(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
@@ -26,6 +40,8 @@ class FirSuperTypeScope private constructor(
|
|||||||
|
|
||||||
private val absentClassifiers = mutableSetOf<Name>()
|
private val absentClassifiers = mutableSetOf<Name>()
|
||||||
|
|
||||||
|
private val typeContext = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = false, isStubTypeEqualsToAnything = false, session)
|
||||||
|
|
||||||
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
|
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||||
processCallablesByName(name, processor, absentFunctions, FirScope::processFunctionsByName)?.let { return it }
|
processCallablesByName(name, processor, absentFunctions, FirScope::processFunctionsByName)?.let { return it }
|
||||||
return super.processFunctionsByName(name, processor)
|
return super.processFunctionsByName(name, processor)
|
||||||
@@ -46,32 +62,161 @@ class FirSuperTypeScope private constructor(
|
|||||||
return ProcessorAction.NEXT
|
return ProcessorAction.NEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
val accepted = HashSet<FirCallableSymbol<*>>()
|
val membersByScope = scopes.mapNotNull { scope ->
|
||||||
val pending = mutableListOf<FirCallableSymbol<*>>()
|
val resultForScope = mutableListOf<D>()
|
||||||
var empty = true
|
scope.processCallables(name) {
|
||||||
for (scope in scopes) {
|
if (it !is FirConstructorSymbol) {
|
||||||
if (scope.processCallables(name) {
|
resultForScope.add(it)
|
||||||
empty = false
|
}
|
||||||
if (it !in accepted && it.getOverridden(accepted) == null) {
|
ProcessorAction.NEXT
|
||||||
pending += it
|
|
||||||
processor(it)
|
|
||||||
} else {
|
|
||||||
ProcessorAction.NEXT
|
|
||||||
}
|
|
||||||
}.stop()
|
|
||||||
) {
|
|
||||||
return ProcessorAction.STOP
|
|
||||||
}
|
}
|
||||||
accepted += pending
|
|
||||||
pending.clear()
|
resultForScope.takeIf { it.isNotEmpty() }
|
||||||
}
|
}
|
||||||
if (empty) {
|
|
||||||
absentNames += name
|
if (membersByScope.isEmpty()) {
|
||||||
|
absentNames.add(name)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
membersByScope.singleOrNull()?.let { members ->
|
||||||
|
for (member in members) {
|
||||||
|
if (processor(member).stop()) return ProcessorAction.STOP
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessorAction.NEXT
|
||||||
|
}
|
||||||
|
|
||||||
|
val allMembers = membersByScope.flattenTo(LinkedList())
|
||||||
|
|
||||||
|
while (allMembers.isNotEmpty()) {
|
||||||
|
val maxByVisibility = findMemberWithMaxVisibility(allMembers)
|
||||||
|
val extractedOverrides = extractBothWaysOverridable(maxByVisibility, allMembers)
|
||||||
|
|
||||||
|
val mostSpecific = selectMostSpecificMember(extractedOverrides)
|
||||||
|
|
||||||
|
if (processor(mostSpecific).stop()) return ProcessorAction.STOP
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <D : FirCallableSymbol<*>> selectMostSpecificMember(
|
||||||
|
overridables: Collection<D>
|
||||||
|
): D {
|
||||||
|
require(overridables.isNotEmpty()) { "Should have at least one overridable descriptor" }
|
||||||
|
if (overridables.size == 1) {
|
||||||
|
return overridables.first()
|
||||||
|
}
|
||||||
|
|
||||||
|
val candidates: MutableCollection<D> = ArrayList(2)
|
||||||
|
var transitivelyMostSpecific: D = overridables.first()
|
||||||
|
|
||||||
|
for (candidate in overridables) {
|
||||||
|
if (overridables.all { isMoreSpecific(candidate, it) }) {
|
||||||
|
candidates.add(candidate)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMoreSpecific(candidate, transitivelyMostSpecific) && !isMoreSpecific(transitivelyMostSpecific, candidate)) {
|
||||||
|
transitivelyMostSpecific = candidate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when {
|
||||||
|
candidates.isEmpty() -> {
|
||||||
|
return transitivelyMostSpecific
|
||||||
|
}
|
||||||
|
candidates.size == 1 -> {
|
||||||
|
return candidates.first()
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
candidates.firstOrNull {
|
||||||
|
val type = it.fir.returnTypeRef.coneTypeSafe<ConeKotlinType>()
|
||||||
|
type != null && type !is ConeFlexibleType
|
||||||
|
}?.let { return it }
|
||||||
|
return candidates.first()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isMoreSpecific(
|
||||||
|
a: FirCallableSymbol<*>,
|
||||||
|
b: FirCallableSymbol<*>
|
||||||
|
): Boolean {
|
||||||
|
val aFir = a.fir
|
||||||
|
val bFir = b.fir
|
||||||
|
if (aFir !is FirCallableMemberDeclaration<*> || bFir !is FirCallableMemberDeclaration<*>) return false
|
||||||
|
|
||||||
|
val substitutor = buildSubstitutorForOverridesCheck(aFir, bFir) ?: return false
|
||||||
|
|
||||||
|
val aReturnType = a.fir.returnTypeRef.coneTypeSafe<ConeKotlinType>()?.let(substitutor::substituteOrSelf) ?: return false
|
||||||
|
val bReturnType = b.fir.returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: return false
|
||||||
|
|
||||||
|
if (aFir is FirSimpleFunction) {
|
||||||
|
require(bFir is FirSimpleFunction) { "b is " + b.javaClass }
|
||||||
|
return isTypeMoreSpecific(aReturnType, bReturnType)
|
||||||
|
}
|
||||||
|
if (aFir is FirProperty) {
|
||||||
|
require(bFir is FirProperty) { "b is " + b.javaClass }
|
||||||
|
// TODO: if (!OverridingUtil.isAccessorMoreSpecific(pa.getSetter(), pb.getSetter())) return false
|
||||||
|
return if (aFir.isVar && bFir.isVar) {
|
||||||
|
AbstractTypeChecker.equalTypes(typeContext as AbstractTypeCheckerContext, aReturnType, bReturnType)
|
||||||
|
} else { // both vals or var vs val: val can't be more specific then var
|
||||||
|
!(!aFir.isVar && bFir.isVar) && isTypeMoreSpecific(aReturnType, bReturnType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw IllegalArgumentException("Unexpected callable: " + a.javaClass)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isTypeMoreSpecific(a: ConeKotlinType, b: ConeKotlinType): Boolean =
|
||||||
|
AbstractTypeChecker.isSubtypeOf(typeContext as AbstractTypeCheckerContext, a, b)
|
||||||
|
|
||||||
|
private fun <D : FirCallableSymbol<*>> findMemberWithMaxVisibility(members: Collection<D>): D {
|
||||||
|
assert(members.isNotEmpty())
|
||||||
|
|
||||||
|
var member: D? = null
|
||||||
|
for (candidate in members) {
|
||||||
|
if (member == null) {
|
||||||
|
member = candidate
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = Visibilities.compare(
|
||||||
|
(member.fir as FirCallableMemberDeclaration<*>).status.visibility,
|
||||||
|
(candidate.fir as FirCallableMemberDeclaration<*>).status.visibility
|
||||||
|
)
|
||||||
|
if (result != null && result < 0) {
|
||||||
|
member = candidate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return member!!
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <D : FirCallableSymbol<*>> extractBothWaysOverridable(
|
||||||
|
overrider: D,
|
||||||
|
members: MutableCollection<D>
|
||||||
|
): Collection<D> {
|
||||||
|
val result = mutableListOf<D>().apply { add(overrider) }
|
||||||
|
|
||||||
|
val iterator = members.iterator()
|
||||||
|
|
||||||
|
val overrideCandidate = overrider.fir as FirCallableMemberDeclaration<*>
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
val next = iterator.next()
|
||||||
|
if (next == overrider) {
|
||||||
|
iterator.remove()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (similarFunctionsOrBothProperties(overrideCandidate, next.fir as FirCallableMemberDeclaration<*>)) {
|
||||||
|
result.add(next)
|
||||||
|
iterator.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
override fun processClassifiersByName(name: Name, processor: (FirClassifierSymbol<*>) -> ProcessorAction): ProcessorAction {
|
override fun processClassifiersByName(name: Name, processor: (FirClassifierSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||||
if (name in absentClassifiers) {
|
if (name in absentClassifiers) {
|
||||||
return ProcessorAction.NEXT
|
return ProcessorAction.NEXT
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// !CHECK_TYPE
|
||||||
|
interface A {
|
||||||
|
val x: CharSequence
|
||||||
|
|
||||||
|
fun foo(): String?
|
||||||
|
|
||||||
|
fun <T, F> bar(x: T, y: F): F?
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B {
|
||||||
|
var x: String
|
||||||
|
|
||||||
|
fun foo(): String
|
||||||
|
|
||||||
|
fun <X, Y> bar(x: X, y: Y): Y
|
||||||
|
}
|
||||||
|
|
||||||
|
interface C {
|
||||||
|
val x: String
|
||||||
|
}
|
||||||
|
|
||||||
|
interface D1 : A, B
|
||||||
|
interface D2 : B, A
|
||||||
|
interface D3 : A, C
|
||||||
|
|
||||||
|
fun main(d1: D1, d2: D2, d3: D3) {
|
||||||
|
d1.x.checkType { _<String>() }
|
||||||
|
d1.x = ""
|
||||||
|
d1.foo().checkType { _<String>() }
|
||||||
|
d1.bar(1, "").checkType { _<String>() }
|
||||||
|
|
||||||
|
d2.x.checkType { _<String>() }
|
||||||
|
d2.x = ""
|
||||||
|
d2.foo().checkType { _<String>() }
|
||||||
|
d2.bar(1, "").checkType { _<String>() }
|
||||||
|
|
||||||
|
d3.x.checkType { _<String>() }
|
||||||
|
d3.x = ""
|
||||||
|
d3.foo().checkType { _<String?>() }
|
||||||
|
d3.bar(1, "").checkType { _<String?>() }
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
FILE: simpleMostSpecific.kt
|
||||||
|
public abstract interface A : R|kotlin/Any| {
|
||||||
|
public abstract val x: R|kotlin/CharSequence|
|
||||||
|
public get(): R|kotlin/CharSequence|
|
||||||
|
|
||||||
|
public abstract fun foo(): R|kotlin/String?|
|
||||||
|
|
||||||
|
public abstract fun <T, F> bar(x: R|T|, y: R|F|): R|F?|
|
||||||
|
|
||||||
|
}
|
||||||
|
public abstract interface B : R|kotlin/Any| {
|
||||||
|
public abstract var x: R|kotlin/String|
|
||||||
|
public get(): R|kotlin/String|
|
||||||
|
public set(value: R|kotlin/String|): R|kotlin/Unit|
|
||||||
|
|
||||||
|
public abstract fun foo(): R|kotlin/String|
|
||||||
|
|
||||||
|
public abstract fun <X, Y> bar(x: R|X|, y: R|Y|): R|Y|
|
||||||
|
|
||||||
|
}
|
||||||
|
public abstract interface C : R|kotlin/Any| {
|
||||||
|
public abstract val x: R|kotlin/String|
|
||||||
|
public get(): R|kotlin/String|
|
||||||
|
|
||||||
|
}
|
||||||
|
public abstract interface D1 : R|A|, R|B| {
|
||||||
|
}
|
||||||
|
public abstract interface D2 : R|B|, R|A| {
|
||||||
|
}
|
||||||
|
public abstract interface D3 : R|A|, R|C| {
|
||||||
|
}
|
||||||
|
public final fun main(d1: R|D1|, d2: R|D2|, d3: R|D3|): R|kotlin/Unit| {
|
||||||
|
R|<local>/d1|.R|/B.x|.R|tests/_checkType/checkType|<R|kotlin/String|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/String>|.<anonymous>(): R|kotlin/Unit| {
|
||||||
|
this@R|special/anonymous|.R|tests/_checkType/_|<R|kotlin/String|>()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
R|<local>/d1|.R|/B.x| = String()
|
||||||
|
R|<local>/d1|.R|/B.foo|().R|tests/_checkType/checkType|<R|kotlin/String|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/String>|.<anonymous>(): R|kotlin/Unit| {
|
||||||
|
this@R|special/anonymous|.R|tests/_checkType/_|<R|kotlin/String|>()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
R|<local>/d1|.R|/B.bar|<R|kotlin/Int|, R|kotlin/String|>(Int(1), String()).R|tests/_checkType/checkType|<R|kotlin/String|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/String>|.<anonymous>(): R|kotlin/Unit| {
|
||||||
|
this@R|special/anonymous|.R|tests/_checkType/_|<R|kotlin/String|>()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
R|<local>/d2|.R|/B.x|.R|tests/_checkType/checkType|<R|kotlin/String|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/String>|.<anonymous>(): R|kotlin/Unit| {
|
||||||
|
this@R|special/anonymous|.R|tests/_checkType/_|<R|kotlin/String|>()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
R|<local>/d2|.R|/B.x| = String()
|
||||||
|
R|<local>/d2|.R|/B.foo|().R|tests/_checkType/checkType|<R|kotlin/String|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/String>|.<anonymous>(): R|kotlin/Unit| {
|
||||||
|
this@R|special/anonymous|.R|tests/_checkType/_|<R|kotlin/String|>()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
R|<local>/d2|.R|/B.bar|<R|kotlin/Int|, R|kotlin/String|>(Int(1), String()).R|tests/_checkType/checkType|<R|kotlin/String|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/String>|.<anonymous>(): R|kotlin/Unit| {
|
||||||
|
this@R|special/anonymous|.R|tests/_checkType/_|<R|kotlin/String|>()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
R|<local>/d3|.R|/C.x|.R|tests/_checkType/checkType|<R|kotlin/String|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/String>|.<anonymous>(): R|kotlin/Unit| {
|
||||||
|
this@R|special/anonymous|.R|tests/_checkType/_|<R|kotlin/String|>()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
R|<local>/d3|.R|/C.x| = String()
|
||||||
|
R|<local>/d3|.R|/A.foo|().R|tests/_checkType/checkType|<R|kotlin/String?|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/String?>|.<anonymous>(): R|kotlin/Unit| {
|
||||||
|
this@R|special/anonymous|.R|tests/_checkType/_|<R|kotlin/String?|>()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
R|<local>/d3|.R|/A.bar|<R|kotlin/Int|, R|kotlin/String|>(Int(1), String()).R|tests/_checkType/checkType|<R|kotlin/String?|>(<L> = checkType@fun R|tests/_checkType/Inv<kotlin/String?>|.<anonymous>(): R|kotlin/Unit| {
|
||||||
|
this@R|special/anonymous|.R|tests/_checkType/_|<R|kotlin/String?|>()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
FILE: CHECK_TYPE.kt
|
||||||
|
public final fun <T> checkSubtype(t: R|T|): R|T| {
|
||||||
|
^checkSubtype R|<local>/t|
|
||||||
|
}
|
||||||
|
public final class Inv<T> : R|kotlin/Any| {
|
||||||
|
public constructor<T>(): R|tests/_checkType/Inv<T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun <E> R|tests/_checkType/Inv<E>|._(): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
|
public final infix fun <T> R|T|.checkType(f: R|tests/_checkType/Inv<T>.() -> kotlin/Unit|): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
+5
@@ -873,6 +873,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
|||||||
runTest("compiler/fir/resolve/testData/resolve/overrides/simpleFakeOverride.kt");
|
runTest("compiler/fir/resolve/testData/resolve/overrides/simpleFakeOverride.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleMostSpecific.kt")
|
||||||
|
public void testSimpleMostSpecific() throws Exception {
|
||||||
|
runTest("compiler/fir/resolve/testData/resolve/overrides/simpleMostSpecific.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("supertypeGenerics.kt")
|
@TestMetadata("supertypeGenerics.kt")
|
||||||
public void testSupertypeGenerics() throws Exception {
|
public void testSupertypeGenerics() throws Exception {
|
||||||
runTest("compiler/fir/resolve/testData/resolve/overrides/supertypeGenerics.kt");
|
runTest("compiler/fir/resolve/testData/resolve/overrides/supertypeGenerics.kt");
|
||||||
|
|||||||
+3
-3
@@ -201,10 +201,10 @@ FILE fqName:<root> fileName:/kt30020.kt
|
|||||||
overridden:
|
overridden:
|
||||||
public abstract fun isEmpty (): kotlin.Boolean declared in kotlin.collections.List
|
public abstract fun isEmpty (): kotlin.Boolean declared in kotlin.collections.List
|
||||||
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.List
|
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.List
|
||||||
FUN FAKE_OVERRIDE name:iterator visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List) returnType:kotlin.collections.Iterator<kotlin.Int> [fake_override,operator]
|
FUN FAKE_OVERRIDE name:iterator visibility:public modality:ABSTRACT <> ($this:kotlin.collections.MutableCollection) returnType:kotlin.collections.MutableIterator<kotlin.Int> [fake_override,operator]
|
||||||
overridden:
|
overridden:
|
||||||
public abstract fun iterator (): kotlin.collections.Iterator<E of kotlin.collections.MutableList> [operator] declared in kotlin.collections.List
|
public abstract fun iterator (): kotlin.collections.MutableIterator<E of kotlin.collections.MutableList> [operator] declared in kotlin.collections.MutableCollection
|
||||||
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.List
|
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.MutableCollection
|
||||||
FUN FAKE_OVERRIDE name:lastIndexOf visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List, element:kotlin.Int) returnType:kotlin.Int [fake_override]
|
FUN FAKE_OVERRIDE name:lastIndexOf visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List, element:kotlin.Int) returnType:kotlin.Int [fake_override]
|
||||||
overridden:
|
overridden:
|
||||||
public abstract fun lastIndexOf (element: E of kotlin.collections.MutableList): kotlin.Int declared in kotlin.collections.List
|
public abstract fun lastIndexOf (element: E of kotlin.collections.MutableList): kotlin.Int declared in kotlin.collections.List
|
||||||
|
|||||||
Reference in New Issue
Block a user