[FIR] Initialize outer type parameters for local classes

This commit is contained in:
Ivan Kochurkin
2021-09-15 19:28:02 +03:00
committed by TeamCityServer
parent 38820d3e41
commit e52a410599
39 changed files with 293 additions and 193 deletions
@@ -34,9 +34,7 @@ internal class FirDesignatedAnnotationArgumentsResolveTransformerForIDE(
} }
} }
is FirRegularClass -> { is FirRegularClass -> {
context.withContainingClass(nextElement) { moveNextDeclaration(designationIterator)
moveNextDeclaration(designationIterator)
}
} }
is FirEnumEntry -> { is FirEnumEntry -> {
context.forEnumEntry { context.forEnumEntry {
@@ -11345,6 +11345,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/generics/kt9985.kt"); runTest("compiler/testData/diagnostics/tests/generics/kt9985.kt");
} }
@Test
@TestMetadata("localClassWithTypeArgumentFromFunction.kt")
public void testLocalClassWithTypeArgumentFromFunction() throws Exception {
runTest("compiler/testData/diagnostics/tests/generics/localClassWithTypeArgumentFromFunction.kt");
}
@Test @Test
@TestMetadata("Projections.kt") @TestMetadata("Projections.kt")
public void testProjections() throws Exception { public void testProjections() throws Exception {
@@ -39,8 +39,8 @@ FILE: throwableSubclass.kt
} }
public final fun foo(): R|kotlin/Unit| { public final fun foo(): R|kotlin/Unit| {
local final class Test7 : R|kotlin/Throwable| { local final class Test7<T, B> : R|kotlin/Throwable| {
public constructor(): R|Test5.Test7| { public constructor(): R|Test5.Test7<T, B>| {
super<R|kotlin/Throwable|>() super<R|kotlin/Throwable|>()
} }
@@ -50,8 +50,8 @@ FILE: throwableSubclass.kt
} }
public final fun <Z> topLevelFun(): R|kotlin/Unit| { public final fun <Z> topLevelFun(): R|kotlin/Unit| {
local final class Test8 : R|kotlin/Error| { local final class Test8<Z> : R|kotlin/Error| {
public constructor(): R|Test8| { public constructor(): R|Test8<Z>| {
super<R|kotlin/Error|>() super<R|kotlin/Error|>()
} }
@@ -11345,6 +11345,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/generics/kt9985.kt"); runTest("compiler/testData/diagnostics/tests/generics/kt9985.kt");
} }
@Test
@TestMetadata("localClassWithTypeArgumentFromFunction.kt")
public void testLocalClassWithTypeArgumentFromFunction() throws Exception {
runTest("compiler/testData/diagnostics/tests/generics/localClassWithTypeArgumentFromFunction.kt");
}
@Test @Test
@TestMetadata("Projections.kt") @TestMetadata("Projections.kt")
public void testProjections() throws Exception { public void testProjections() throws Exception {
@@ -11345,6 +11345,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/generics/kt9985.kt"); runTest("compiler/testData/diagnostics/tests/generics/kt9985.kt");
} }
@Test
@TestMetadata("localClassWithTypeArgumentFromFunction.kt")
public void testLocalClassWithTypeArgumentFromFunction() throws Exception {
runTest("compiler/testData/diagnostics/tests/generics/localClassWithTypeArgumentFromFunction.kt");
}
@Test @Test
@TestMetadata("Projections.kt") @TestMetadata("Projections.kt")
public void testProjections() throws Exception { public void testProjections() throws Exception {
@@ -1102,6 +1102,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
} }
val CASTS_AND_IS_CHECKS by object : DiagnosticGroup("Casts and is-checks") { val CASTS_AND_IS_CHECKS by object : DiagnosticGroup("Casts and is-checks") {
val CANNOT_CHECK_FOR_ERASED by error<PsiElement> {
parameter<ConeKotlinType>("type")
}
val USELESS_CAST by warning<KtBinaryExpressionWithTypeRHS>(PositioningStrategy.AS_TYPE) val USELESS_CAST by warning<KtBinaryExpressionWithTypeRHS>(PositioningStrategy.AS_TYPE)
val USELESS_IS_CHECK by warning<KtElement> { val USELESS_IS_CHECK by warning<KtElement> {
parameter<Boolean>("compileTimeCheckResult") parameter<Boolean>("compileTimeCheckResult")
@@ -590,6 +590,7 @@ object FirErrors {
val USELESS_ELVIS_RIGHT_IS_NULL by warning0<KtBinaryExpression>(SourceElementPositioningStrategies.USELESS_ELVIS) val USELESS_ELVIS_RIGHT_IS_NULL by warning0<KtBinaryExpression>(SourceElementPositioningStrategies.USELESS_ELVIS)
// Casts and is-checks // Casts and is-checks
val CANNOT_CHECK_FOR_ERASED by error1<PsiElement, ConeKotlinType>()
val USELESS_CAST by warning0<KtBinaryExpressionWithTypeRHS>(SourceElementPositioningStrategies.AS_TYPE) val USELESS_CAST by warning0<KtBinaryExpressionWithTypeRHS>(SourceElementPositioningStrategies.AS_TYPE)
val USELESS_IS_CHECK by warning1<KtElement, Boolean>() val USELESS_IS_CHECK by warning1<KtElement, Boolean>()
val IS_ENUM_ENTRY by error0<KtTypeReference>() val IS_ENUM_ENTRY by error0<KtTypeReference>()
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.resolve.isValidTypeParameterFromOuterClass import org.jetbrains.kotlin.fir.resolve.isValidTypeParameterFromOuterDeclaration
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.toTypeProjections import org.jetbrains.kotlin.fir.resolve.toTypeProjections
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
@@ -47,7 +47,7 @@ object FirOuterClassArgumentsRequiredChecker : FirRegularClassChecker() {
for (index in typeArguments.size until typeParameters.size) { for (index in typeArguments.size until typeParameters.size) {
val typeParameter = typeParameters[index] val typeParameter = typeParameters[index]
if (!isValidTypeParameterFromOuterClass(typeParameter, declaration, context.session)) { if (!isValidTypeParameterFromOuterDeclaration(typeParameter, declaration, context.session)) {
val outerClass = typeParameter.containingDeclarationSymbol as? FirRegularClassSymbol ?: break val outerClass = typeParameter.containingDeclarationSymbol as? FirRegularClassSymbol ?: break
reporter.reportOn(typeRef.source, FirErrors.OUTER_CLASS_ARGUMENTS_REQUIRED, outerClass, context) reporter.reportOn(typeRef.source, FirErrors.OUTER_CLASS_ARGUMENTS_REQUIRED, outerClass, context)
break break
@@ -26,7 +26,7 @@ object FirThrowableSubclassChecker : FirClassChecker() {
reporter.reportOn(declaration.typeParameters.firstOrNull()?.source, FirErrors.GENERIC_THROWABLE_SUBCLASS, context) reporter.reportOn(declaration.typeParameters.firstOrNull()?.source, FirErrors.GENERIC_THROWABLE_SUBCLASS, context)
val source = when { val source = when {
(declaration as? FirRegularClass)?.isInner == true -> declaration.source (declaration as? FirRegularClass)?.let { it.isInner || it.isLocal } == true -> declaration.source
declaration is FirAnonymousObject -> (declaration.declarations.firstOrNull())?.source declaration is FirAnonymousObject -> (declaration.declarations.firstOrNull())?.source
else -> null else -> null
} }
@@ -8,11 +8,13 @@ package org.jetbrains.kotlin.fir.scopes.impl
import kotlinx.collections.immutable.PersistentMap import kotlinx.collections.immutable.PersistentMap
import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.persistentMapOf
import org.jetbrains.kotlin.builtins.StandardNames.BACKING_FIELD import org.jetbrains.kotlin.builtins.StandardNames.BACKING_FIELD
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.FirVariable import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
@@ -24,29 +26,30 @@ import org.jetbrains.kotlin.name.Name
class FirLocalScope private constructor( class FirLocalScope private constructor(
val properties: PersistentMap<Name, FirVariableSymbol<*>>, val properties: PersistentMap<Name, FirVariableSymbol<*>>,
val functions: PersistentMultimap<Name, FirNamedFunctionSymbol>, val functions: PersistentMultimap<Name, FirNamedFunctionSymbol>,
val classes: PersistentMap<Name, FirRegularClassSymbol> val classes: PersistentMap<Name, FirRegularClassSymbol>,
val useSiteSession: FirSession
) : FirContainingNamesAwareScope() { ) : FirContainingNamesAwareScope() {
constructor() : this(persistentMapOf(), PersistentMultimap(), persistentMapOf()) constructor(session: FirSession) : this(persistentMapOf(), PersistentMultimap(), persistentMapOf(), session)
fun storeClass(klass: FirRegularClass): FirLocalScope { fun storeClass(klass: FirRegularClass, session: FirSession): FirLocalScope {
return FirLocalScope( return FirLocalScope(
properties, functions, classes.put(klass.name, klass.symbol) properties, functions, classes.put(klass.name, klass.symbol), session
) )
} }
fun storeFunction(function: FirSimpleFunction): FirLocalScope { fun storeFunction(function: FirSimpleFunction, session: FirSession): FirLocalScope {
return FirLocalScope( return FirLocalScope(
properties, functions.put(function.name, function.symbol), classes properties, functions.put(function.name, function.symbol), classes, session
) )
} }
fun storeVariable(variable: FirVariable): FirLocalScope { fun storeVariable(variable: FirVariable, session: FirSession): FirLocalScope {
return FirLocalScope( return FirLocalScope(
properties.put(variable.name, variable.symbol), functions, classes properties.put(variable.name, variable.symbol), functions, classes, session
) )
} }
fun storeBackingField(property: FirProperty): FirLocalScope { fun storeBackingField(property: FirProperty, session: FirSession): FirLocalScope {
val enhancedProperties = property.backingField?.symbol?.let { val enhancedProperties = property.backingField?.symbol?.let {
properties.put(BACKING_FIELD, it) properties.put(BACKING_FIELD, it)
} }
@@ -54,7 +57,8 @@ class FirLocalScope private constructor(
return FirLocalScope( return FirLocalScope(
enhancedProperties ?: properties, enhancedProperties ?: properties,
functions, functions,
classes classes,
session
) )
} }
@@ -74,7 +78,8 @@ class FirLocalScope private constructor(
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) { override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
val klass = classes[name] val klass = classes[name]
if (klass != null) { if (klass != null) {
processor(klass, ConeSubstitutor.Empty) val substitution = klass.typeParameterSymbols.associateWith { it.toConeType() }
processor(klass, ConeSubstitutorByMap(substitution, useSiteSession))
} }
} }
@@ -436,7 +436,7 @@ class DeclarationsConverter(
typeParameterList?.let { firTypeParameters += convertTypeParameters(it, typeConstraints, classSymbol) } typeParameterList?.let { firTypeParameters += convertTypeParameters(it, typeConstraints, classSymbol) }
withCapturedTypeParameters(status.isInner, firTypeParameters) { withCapturedTypeParameters(status.isInner || isLocal, firTypeParameters) {
buildRegularClass { buildRegularClass {
source = classNode.toFirSourceElement() source = classNode.toFirSourceElement()
moduleData = baseModuleData moduleData = baseModuleData
@@ -1044,7 +1044,7 @@ open class RawFirBuilder(
isExternal = classOrObject.hasModifier(EXTERNAL_KEYWORD) isExternal = classOrObject.hasModifier(EXTERNAL_KEYWORD)
} }
withCapturedTypeParameters(status.isInner, listOf()) { withCapturedTypeParameters(status.isInner || isLocal, listOf()) {
buildRegularClass { buildRegularClass {
source = classOrObject.toFirSourceElement() source = classOrObject.toFirSourceElement()
moduleData = baseModuleData moduleData = baseModuleData
@@ -1060,7 +1060,7 @@ open class RawFirBuilder(
context.appendOuterTypeParameters(ignoreLastLevel = true, typeParameters) context.appendOuterTypeParameters(ignoreLastLevel = true, typeParameters)
context.pushFirTypeParameters( context.pushFirTypeParameters(
status.isInner, status.isInner || isLocal,
typeParameters.subList(0, classOrObject.typeParameters.size) typeParameters.subList(0, classOrObject.typeParameters.size)
) )
@@ -49,8 +49,8 @@ class Context<T> {
val dispatchReceiverTypesStack = mutableListOf<ConeClassLikeType>() val dispatchReceiverTypesStack = mutableListOf<ConeClassLikeType>()
var containerIsExpect: Boolean = false var containerIsExpect: Boolean = false
fun pushFirTypeParameters(notNested: Boolean, parameters: List<FirTypeParameterRef>) { fun pushFirTypeParameters(isInnerOrLocal: Boolean, parameters: List<FirTypeParameterRef>) {
capturedTypeParameters.add(StatusFirTypeParameterSymbolList(notNested, parameters.map { it.symbol })) capturedTypeParameters.add(StatusFirTypeParameterSymbolList(isInnerOrLocal, parameters.map { it.symbol }))
} }
fun popFirTypeParameters() { fun popFirTypeParameters() {
@@ -68,7 +68,7 @@ class Context<T> {
} }
} }
if (!element.notNested) { if (!element.isInnerOrLocal) {
break break
} }
} }
@@ -119,5 +119,5 @@ class Context<T> {
} }
} }
data class StatusFirTypeParameterSymbolList(val notNested: Boolean, val list: List<FirTypeParameterSymbol> = listOf()) data class StatusFirTypeParameterSymbolList(val isInnerOrLocal: Boolean, val list: List<FirTypeParameterSymbol> = listOf())
} }
@@ -466,20 +466,3 @@ fun FirFunction.getAsForbiddenNamedArgumentsTarget(session: FirSession): Forbidd
// org.jetbrains.kotlin.fir.serialization.FirElementSerializer.functionProto // org.jetbrains.kotlin.fir.serialization.FirElementSerializer.functionProto
// org.jetbrains.kotlin.fir.serialization.FirElementSerializer.constructorProto // org.jetbrains.kotlin.fir.serialization.FirElementSerializer.constructorProto
fun FirFunction.getHasStableParameterNames(session: FirSession): Boolean = getAsForbiddenNamedArgumentsTarget(session) == null fun FirFunction.getHasStableParameterNames(session: FirSession): Boolean = getAsForbiddenNamedArgumentsTarget(session) == null
fun FirClassLikeDeclaration.getActualTypeParametersCount(session: FirSession): Int {
var result = (if (this is FirTypeAlias) this.typeParameters else (this as FirClass).typeParameters).size
if (this is FirRegularClass && !isInner) {
return result
}
val containingClass = getContainingDeclaration(session) as? FirRegularClass
if (containingClass != null) {
result -= containingClass.typeParameters.size
}
return result
}
@@ -197,7 +197,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
symbol: FirBasedSymbol<*>?, symbol: FirBasedSymbol<*>?,
substitutor: ConeSubstitutor?, substitutor: ConeSubstitutor?,
areBareTypesAllowed: Boolean, areBareTypesAllowed: Boolean,
topDeclaration: FirRegularClass?, topContainer: FirDeclaration?,
isOperandOfIsOperator: Boolean isOperandOfIsOperator: Boolean
): ConeKotlinType { ): ConeKotlinType {
if (symbol == null || symbol !is FirClassifierSymbol<*>) { if (symbol == null || symbol !is FirClassifierSymbol<*>) {
@@ -240,14 +240,25 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
if (!isPossibleBareType) { if (!isPossibleBareType) {
val actualSubstitutor = substitutor ?: ConeSubstitutor.Empty val actualSubstitutor = substitutor ?: ConeSubstitutor.Empty
val typeParameters = calculateTypeParameters(symbol) val originalTypeParameters = collectTypeParameters(symbol)
val (typeParametersAlignedToQualifierParts, outerClasses) = getClassesAlignedToQualifierParts(symbol, qualifier, session) val (typeParametersAlignedToQualifierParts, outerDeclarations) = getClassesAlignedToQualifierParts(
symbol,
qualifier,
session
)
for ((index, typeParameter) in typeParameters.withIndex()) { val actualTypeParametersCount =
when (symbol) {
is FirTypeAliasSymbol ->
outerDeclarations.sumOf { it?.let { d -> getActualTypeParametersCount(d) } ?: 0 }
else -> (symbol as FirClassSymbol<*>).typeParameterSymbols.size
}
for ((typeParameterIndex, typeParameter) in originalTypeParameters.withIndex()) {
val (parameterClass, qualifierPartIndex) = typeParametersAlignedToQualifierParts[typeParameter.symbol] ?: continue val (parameterClass, qualifierPartIndex) = typeParametersAlignedToQualifierParts[typeParameter.symbol] ?: continue
if (index < typeArgumentsCount) { if (typeParameterIndex < typeArgumentsCount) {
// Check if type argument matches type parameter in respective qualifier part // Check if type argument matches type parameter in respective qualifier part
val qualifierPartArgumentsCount = qualifier[qualifierPartIndex].typeArgumentList.typeArguments.size val qualifierPartArgumentsCount = qualifier[qualifierPartIndex].typeArgumentList.typeArguments.size
createDiagnosticsIfExists( createDiagnosticsIfExists(
@@ -261,12 +272,18 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
} }
if (typeParameter !is FirOuterClassTypeParameterRef || if (typeParameter !is FirOuterClassTypeParameterRef ||
isValidTypeParameterFromOuterClass(typeParameter.symbol, topDeclaration, session) isValidTypeParameterFromOuterDeclaration(typeParameter.symbol, topContainer, session)
) { ) {
val type = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(typeParameter.symbol), isNullable = false) val type = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(typeParameter.symbol), isNullable = false)
val substituted = actualSubstitutor.substituteOrNull(type) val substituted = actualSubstitutor.substituteOrNull(type)
if (substituted == null) { if (substituted == null) {
createDiagnosticsIfExists(parameterClass, qualifierPartIndex, symbol, typeRef)?.let { return it } createDiagnosticsIfExists(
parameterClass,
qualifierPartIndex,
symbol,
typeRef,
qualifierPartArgumentsCount = null
)?.let { return it }
} else { } else {
allTypeArguments.add(substituted) allTypeArguments.add(substituted)
} }
@@ -276,15 +293,16 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
} }
// Check rest type arguments // Check rest type arguments
if (typeArgumentsCount > typeParameters.size) { if (typeArgumentsCount > actualTypeParametersCount) {
for (index in qualifier.indices) { for (index in qualifier.indices) {
if (qualifier[index].typeArgumentList.typeArguments.isNotEmpty()) { if (qualifier[index].typeArgumentList.typeArguments.isNotEmpty()) {
val parameterClass = outerClasses.elementAtOrNull(index) val parameterClass = outerDeclarations.elementAtOrNull(index)
createDiagnosticsIfExists( createDiagnosticsIfExists(
parameterClass, parameterClass,
index, index,
symbol, symbol,
typeRef typeRef,
qualifierPartArgumentsCount = null
)?.let { return it } )?.let { return it }
} }
} }
@@ -304,43 +322,43 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
} }
} }
private fun calculateTypeParameters(symbol: FirClassLikeSymbol<*>): List<FirTypeParameterRef> { private fun collectTypeParameters(symbol: FirClassLikeSymbol<*>): List<FirTypeParameterRef> {
return if (symbol is FirTypeAliasSymbol) { if (symbol is FirClassSymbol<*>) {
val typeAliasFir = symbol.fir return symbol.fir.typeParameters
val typeAliasTypeParameters = typeAliasFir.typeParameters.toMutableList() }
val fullyExpandedClass = typeAliasFir.fullyExpandedClass(session)
val newTypeParameters: MutableList<FirTypeParameterRef>
if (fullyExpandedClass != null) { // TODO: Should not be null, move to resolver? require(symbol is FirTypeAliasSymbol)
val expandedTypeRef = typeAliasFir.expandedTypeRef
fun checkTypeArguments(typeArgument: ConeTypeProjection) { val typeAliasFir = symbol.fir
when (typeArgument) { val typeAliasTypeParameters = typeAliasFir.typeParameters.toMutableList()
is ConeTypeParameterType -> typeAliasTypeParameters.removeIf { it.symbol == typeArgument.lookupTag.symbol } val fullyExpandedClass = typeAliasFir.fullyExpandedClass(session)
is ConeClassLikeType -> { val newTypeParameters = if (fullyExpandedClass != null) { // TODO: Should not be null, move to resolver?
for (subTypeArgument in typeArgument.typeArguments) { val expandedTypeRef = typeAliasFir.expandedTypeRef
checkTypeArguments(subTypeArgument)
} fun checkTypeArguments(typeArgument: ConeTypeProjection) {
} when (typeArgument) {
is ConeKotlinTypeProjection -> checkTypeArguments(typeArgument.type) is ConeTypeParameterType -> typeAliasTypeParameters.removeIf { it.symbol == typeArgument.lookupTag.symbol }
else -> { is ConeClassLikeType -> {
for (subTypeArgument in typeArgument.typeArguments) {
checkTypeArguments(subTypeArgument)
} }
} }
is ConeKotlinTypeProjection -> checkTypeArguments(typeArgument.type)
else -> {
}
} }
checkTypeArguments(expandedTypeRef.coneType)
newTypeParameters = fullyExpandedClass.typeParameters.toMutableList()
} else {
newTypeParameters = mutableListOf()
} }
for (typeParameter in typeAliasTypeParameters) { checkTypeArguments(expandedTypeRef.coneType)
newTypeParameters.add(typeParameter) fullyExpandedClass.typeParameters.toMutableList()
}
newTypeParameters
} else { } else {
(symbol as FirClassSymbol<*>).fir.typeParameters mutableListOf()
} }
for (typeParameter in typeAliasTypeParameters) {
newTypeParameters.add(typeParameter)
}
return newTypeParameters
} }
@OptIn(SymbolInternals::class) @OptIn(SymbolInternals::class)
@@ -373,8 +391,10 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
for (index in reversedOuterClasses.indices) { for (index in reversedOuterClasses.indices) {
currentClassLikeDeclaration = reversedOuterClasses[index] currentClassLikeDeclaration = reversedOuterClasses[index]
val typeParameters = if (currentClassLikeDeclaration is FirTypeAlias) currentClassLikeDeclaration.typeParameters else val typeParameters = when (currentClassLikeDeclaration) {
(currentClassLikeDeclaration as? FirClass)?.typeParameters is FirTypeAlias -> currentClassLikeDeclaration.typeParameters
else -> (currentClassLikeDeclaration as? FirClass)?.typeParameters
}
if (currentClassLikeDeclaration != null && typeParameters != null) { if (currentClassLikeDeclaration != null && typeParameters != null) {
for (typeParameter in typeParameters) { for (typeParameter in typeParameters) {
val typeParameterSymbol = typeParameter.symbol val typeParameterSymbol = typeParameter.symbol
@@ -404,10 +424,10 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
qualifierPartIndex: Int, qualifierPartIndex: Int,
symbol: FirClassLikeSymbol<*>, symbol: FirClassLikeSymbol<*>,
userTypeRef: FirUserTypeRef, userTypeRef: FirUserTypeRef,
qualifierPartArgumentsCount: Int? = null qualifierPartArgumentsCount: Int?
): ConeClassErrorType? { ): ConeClassErrorType? {
// TODO: It should be TYPE_ARGUMENTS_NOT_ALLOWED diagnostics when parameterClass is null // TODO: It should be TYPE_ARGUMENTS_NOT_ALLOWED diagnostics when parameterClass is null
val actualTypeParametersCount = (parameterClass ?: symbol.fir).getActualTypeParametersCount(session) val actualTypeParametersCount = getActualTypeParametersCount(parameterClass ?: symbol.fir)
if (qualifierPartArgumentsCount == null || actualTypeParametersCount != qualifierPartArgumentsCount) { if (qualifierPartArgumentsCount == null || actualTypeParametersCount != qualifierPartArgumentsCount) {
val source = getTypeArgumentsOrNameSource(userTypeRef, qualifierPartIndex) val source = getTypeArgumentsOrNameSource(userTypeRef, qualifierPartIndex)
@@ -425,6 +445,11 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
return null return null
} }
private fun getActualTypeParametersCount(element: FirClassLikeDeclaration): Int {
return (element as FirTypeParameterRefsOwner).typeParameters
.count { it !is FirOuterClassTypeParameterRef }
}
private fun getTypeArgumentsOrNameSource(typeRef: FirUserTypeRef, qualifierIndex: Int?): KtSourceElement? { private fun getTypeArgumentsOrNameSource(typeRef: FirUserTypeRef, qualifierIndex: Int?): KtSourceElement? {
val qualifierPart = if (qualifierIndex != null) typeRef.qualifier.elementAtOrNull(qualifierIndex) else null val qualifierPart = if (qualifierIndex != null) typeRef.qualifier.elementAtOrNull(qualifierIndex) else null
val typeArgumentsList = qualifierPart?.typeArgumentList val typeArgumentsList = qualifierPart?.typeArgumentList
@@ -475,7 +500,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
symbol, symbol,
substitutor, substitutor,
areBareTypesAllowed, areBareTypesAllowed,
scopeClassDeclaration.containingDeclarations.lastOrNull(), scopeClassDeclaration.topContainer ?: scopeClassDeclaration.containingDeclarations.lastOrNull(),
isOperandOfIsOperator isOperandOfIsOperator
) )
} }
@@ -5,10 +5,11 @@
package org.jetbrains.kotlin.fir.resolve.transformers package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
data class ScopeClassDeclaration( data class ScopeClassDeclaration(
val scopes: List<FirScope>, val scopes: List<FirScope>,
val containingDeclarations: List<FirRegularClass> val containingDeclarations: List<FirDeclaration>,
val topContainer: FirDeclaration? = null
) )
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.PrivateForInline import org.jetbrains.kotlin.fir.PrivateForInline
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
@@ -211,8 +212,8 @@ class BodyResolveContext(
} }
@PrivateForInline @PrivateForInline
fun storeFunction(function: FirSimpleFunction) { fun storeFunction(function: FirSimpleFunction, session: FirSession) {
updateLastScope { storeFunction(function) } updateLastScope { storeFunction(function, session) }
} }
@PrivateForInline @PrivateForInline
@@ -251,8 +252,8 @@ class BodyResolveContext(
return FirMemberTypeParameterScope(this) return FirMemberTypeParameterScope(this)
} }
fun buildSecondaryConstructorParametersScope(constructor: FirConstructor): FirLocalScope = fun buildSecondaryConstructorParametersScope(constructor: FirConstructor, session: FirSession): FirLocalScope =
constructor.valueParameters.fold(FirLocalScope()) { acc, param -> acc.storeVariable(param) } constructor.valueParameters.fold(FirLocalScope(session)) { acc, param -> acc.storeVariable(param, session) }
@PrivateForInline @PrivateForInline
fun addInaccessibleImplicitReceiverValue( fun addInaccessibleImplicitReceiverValue(
@@ -272,8 +273,8 @@ class BodyResolveContext(
} }
@PrivateForInline @PrivateForInline
private fun storeBackingField(property: FirProperty) { private fun storeBackingField(property: FirProperty, session: FirSession) {
updateLastScope { storeBackingField(property) } updateLastScope { storeBackingField(property, session) }
} }
// ANALYSIS PUBLIC API // ANALYSIS PUBLIC API
@@ -285,14 +286,14 @@ class BodyResolveContext(
towerDataContextsForClassParts.primaryConstructorAllParametersScope towerDataContextsForClassParts.primaryConstructorAllParametersScope
@OptIn(PrivateForInline::class) @OptIn(PrivateForInline::class)
fun storeClassIfNotNested(klass: FirRegularClass) { fun storeClassIfNotNested(klass: FirRegularClass, session: FirSession) {
if (containerIfAny is FirClass) return if (containerIfAny is FirClass) return
updateLastScope { storeClass(klass) } updateLastScope { storeClass(klass, session) }
} }
@OptIn(PrivateForInline::class) @OptIn(PrivateForInline::class)
fun storeVariable(variable: FirVariable) { fun storeVariable(variable: FirVariable, session: FirSession) {
updateLastScope { storeVariable(variable) } updateLastScope { storeVariable(variable, session) }
} }
@OptIn(PrivateForInline::class) @OptIn(PrivateForInline::class)
@@ -368,7 +369,7 @@ class BodyResolveContext(
forContracts: Boolean = false, forContracts: Boolean = false,
f: () -> T f: () -> T
): T { ): T {
storeClassIfNotNested(regularClass) storeClassIfNotNested(regularClass, holder.session)
if (forContracts) { if (forContracts) {
return withTypeParametersOf(regularClass) { return withTypeParametersOf(regularClass) {
withContainerClass(regularClass, f) withContainerClass(regularClass, f)
@@ -452,7 +453,7 @@ class BodyResolveContext(
val constructor = (owner as? FirRegularClass)?.declarations?.firstOrNull { it is FirConstructor } as? FirConstructor val constructor = (owner as? FirRegularClass)?.declarations?.firstOrNull { it is FirConstructor } as? FirConstructor
val (primaryConstructorPureParametersScope, primaryConstructorAllParametersScope) = val (primaryConstructorPureParametersScope, primaryConstructorAllParametersScope) =
if (constructor?.isPrimary == true) { if (constructor?.isPrimary == true) {
constructor.scopesWithPrimaryConstructorParameters(owner) constructor.scopesWithPrimaryConstructorParameters(owner, holder.session)
} else { } else {
null to null null to null
} }
@@ -473,16 +474,17 @@ class BodyResolveContext(
} }
private fun FirConstructor.scopesWithPrimaryConstructorParameters( private fun FirConstructor.scopesWithPrimaryConstructorParameters(
ownerClass: FirClass ownerClass: FirClass,
session: FirSession
): Pair<FirLocalScope, FirLocalScope> { ): Pair<FirLocalScope, FirLocalScope> {
var parameterScope = FirLocalScope() var parameterScope = FirLocalScope(session)
var allScope = FirLocalScope() var allScope = FirLocalScope(session)
val properties = ownerClass.declarations.filterIsInstance<FirProperty>().associateBy { it.name } val properties = ownerClass.declarations.filterIsInstance<FirProperty>().associateBy { it.name }
for (parameter in valueParameters) { for (parameter in valueParameters) {
allScope = allScope.storeVariable(parameter) allScope = allScope.storeVariable(parameter, session)
val property = properties[parameter.name] val property = properties[parameter.name]
if (property?.source?.kind != KtFakeSourceElementKind.PropertyFromParameter) { if (property?.source?.kind != KtFakeSourceElementKind.PropertyFromParameter) {
parameterScope = parameterScope.storeVariable(parameter) parameterScope = parameterScope.storeVariable(parameter, session)
} }
} }
return parameterScope to allScope return parameterScope to allScope
@@ -491,10 +493,11 @@ class BodyResolveContext(
@OptIn(PrivateForInline::class) @OptIn(PrivateForInline::class)
inline fun <T> withSimpleFunction( inline fun <T> withSimpleFunction(
simpleFunction: FirSimpleFunction, simpleFunction: FirSimpleFunction,
session: FirSession,
f: () -> T f: () -> T
): T { ): T {
if (containerIfAny !is FirClass) { if (containerIfAny !is FirClass) {
storeFunction(simpleFunction) storeFunction(simpleFunction, session)
} }
return withTypeParametersOf(simpleFunction) { return withTypeParametersOf(simpleFunction) {
@@ -509,13 +512,13 @@ class BodyResolveContext(
f: () -> T f: () -> T
): T { ): T {
return withTowerDataCleanup { return withTowerDataCleanup {
addLocalScope(FirLocalScope()) addLocalScope(FirLocalScope(holder.session))
if (function is FirSimpleFunction) { if (function is FirSimpleFunction) {
// Make all value parameters available in the local scope so that even one parameter that refers to another parameter, // Make all value parameters available in the local scope so that even one parameter that refers to another parameter,
// which may not be initialized yet, can be resolved. [FirFunctionParameterChecker] will detect and report an error // which may not be initialized yet, can be resolved. [FirFunctionParameterChecker] will detect and report an error
// if an uninitialized parameter is accessed by a preceding parameter. // if an uninitialized parameter is accessed by a preceding parameter.
for (parameter in function.valueParameters) { for (parameter in function.valueParameters) {
storeVariable(parameter) storeVariable(parameter, holder.session)
} }
val receiverTypeRef = function.receiverTypeRef val receiverTypeRef = function.receiverTypeRef
withLabelAndReceiverType(function.name, function, receiverTypeRef?.coneType, holder, f) withLabelAndReceiverType(function.name, function, receiverTypeRef?.coneType, holder, f)
@@ -528,6 +531,7 @@ class BodyResolveContext(
@OptIn(PrivateForInline::class) @OptIn(PrivateForInline::class)
fun <T> forConstructorBody( fun <T> forConstructorBody(
constructor: FirConstructor, constructor: FirConstructor,
session: FirSession,
f: () -> T f: () -> T
): T { ): T {
return if (constructor.isPrimary) { return if (constructor.isPrimary) {
@@ -542,7 +546,7 @@ class BodyResolveContext(
} }
} else { } else {
withTowerDataCleanup { withTowerDataCleanup {
addLocalScope(buildSecondaryConstructorParametersScope(constructor)) addLocalScope(buildSecondaryConstructorParametersScope(constructor, session))
f() f()
} }
} }
@@ -562,7 +566,7 @@ class BodyResolveContext(
return f() return f()
} }
return withTowerDataCleanup { return withTowerDataCleanup {
addLocalScope(FirLocalScope()) addLocalScope(FirLocalScope(holder.session))
val receiverTypeRef = anonymousFunction.receiverTypeRef val receiverTypeRef = anonymousFunction.receiverTypeRef
val labelName = anonymousFunction.label?.name?.let { Name.identifier(it) } val labelName = anonymousFunction.label?.name?.let { Name.identifier(it) }
withContainer(anonymousFunction) { withContainer(anonymousFunction) {
@@ -600,11 +604,12 @@ class BodyResolveContext(
@OptIn(PrivateForInline::class) @OptIn(PrivateForInline::class)
inline fun <T> withAnonymousInitializer( inline fun <T> withAnonymousInitializer(
anonymousInitializer: FirAnonymousInitializer, anonymousInitializer: FirAnonymousInitializer,
session: FirSession,
f: () -> T f: () -> T
): T { ): T {
return withTowerDataCleanup { return withTowerDataCleanup {
getPrimaryConstructorPureParametersScope()?.let { addLocalScope(it) } getPrimaryConstructorPureParametersScope()?.let { addLocalScope(it) }
addLocalScope(FirLocalScope()) addLocalScope(FirLocalScope(session))
withContainer(anonymousInitializer, f) withContainer(anonymousInitializer, f)
} }
} }
@@ -612,10 +617,11 @@ class BodyResolveContext(
@OptIn(PrivateForInline::class) @OptIn(PrivateForInline::class)
inline fun <T> withValueParameter( inline fun <T> withValueParameter(
valueParameter: FirValueParameter, valueParameter: FirValueParameter,
session: FirSession,
f: () -> T f: () -> T
): T { ): T {
if (!valueParameter.name.isSpecial || valueParameter.name != UNDERSCORE_FOR_UNUSED_VAR) { if (!valueParameter.name.isSpecial || valueParameter.name != UNDERSCORE_FOR_UNUSED_VAR) {
storeVariable(valueParameter) storeVariable(valueParameter, session)
} }
return withContainer(valueParameter, f) return withContainer(valueParameter, f)
} }
@@ -641,17 +647,17 @@ class BodyResolveContext(
if (accessor is FirDefaultPropertyAccessor || accessor.body == null) { if (accessor is FirDefaultPropertyAccessor || accessor.body == null) {
return if (accessor.isGetter) withContainer(accessor, f) return if (accessor.isGetter) withContainer(accessor, f)
else withTowerDataCleanup { else withTowerDataCleanup {
addLocalScope(FirLocalScope()) addLocalScope(FirLocalScope(holder.session))
withContainer(accessor, f) withContainer(accessor, f)
} }
} }
return withTowerDataCleanup { return withTowerDataCleanup {
val receiverTypeRef = property.receiverTypeRef val receiverTypeRef = property.receiverTypeRef
addLocalScope(FirLocalScope()) addLocalScope(FirLocalScope(holder.session))
if (!forContracts && receiverTypeRef == null && property.returnTypeRef !is FirImplicitTypeRef && if (!forContracts && receiverTypeRef == null && property.returnTypeRef !is FirImplicitTypeRef &&
!property.isLocal && property.delegate == null !property.isLocal && property.delegate == null
) { ) {
storeBackingField(property) storeBackingField(property, holder.session)
} }
withContainer(accessor) { withContainer(accessor) {
withLabelAndReceiverType(property.name, property, receiverTypeRef?.coneType, holder, f) withLabelAndReceiverType(property.name, property, receiverTypeRef?.coneType, holder, f)
@@ -731,8 +737,8 @@ class BodyResolveContext(
} else { } else {
addInaccessibleImplicitReceiverValue(owningClass, holder) addInaccessibleImplicitReceiverValue(owningClass, holder)
withTowerDataCleanup { withTowerDataCleanup {
addLocalScope(buildSecondaryConstructorParametersScope(constructor)) addLocalScope(buildSecondaryConstructorParametersScope(constructor, holder.session))
constructor.valueParameters.forEach { storeVariable(it) } constructor.valueParameters.forEach { storeVariable(it, holder.session) }
f() f()
} }
} }
@@ -747,15 +753,15 @@ class BodyResolveContext(
towerDataContextForCallableReferences.remove(callableReferenceAccess) towerDataContextForCallableReferences.remove(callableReferenceAccess)
} }
fun <T> withWhenExpression(whenExpression: FirWhenExpression, f: () -> T): T { fun <T> withWhenExpression(whenExpression: FirWhenExpression, session: FirSession, f: () -> T): T {
if (whenExpression.subjectVariable == null) return f() if (whenExpression.subjectVariable == null) return f()
return forBlock(f) return forBlock(session, f)
} }
@OptIn(PrivateForInline::class) @OptIn(PrivateForInline::class)
inline fun <T> forBlock(f: () -> T): T { inline fun <T> forBlock(session: FirSession, f: () -> T): T {
return withTowerDataCleanup { return withTowerDataCleanup {
addLocalScope(FirLocalScope()) addLocalScope(FirLocalScope(session))
f() f()
} }
} }
@@ -70,7 +70,8 @@ open class FirBodyResolveTransformer(
typeRef, typeRef,
ScopeClassDeclaration( ScopeClassDeclaration(
components.createCurrentScopeList(), components.createCurrentScopeList(),
context.containingClassDeclarations context.containingClassDeclarations,
context.containers.lastOrNull { it is FirTypeParameterRefsOwner && it !is FirAnonymousFunction }
) )
) )
} }
@@ -41,7 +41,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
override fun transformDoWhileLoop(doWhileLoop: FirDoWhileLoop, data: ResolutionMode): FirStatement { override fun transformDoWhileLoop(doWhileLoop: FirDoWhileLoop, data: ResolutionMode): FirStatement {
// Do-while has a specific scope structure (its block and condition effectively share the scope) // Do-while has a specific scope structure (its block and condition effectively share the scope)
return context.forBlock { return context.forBlock(session) {
val context = ResolutionMode.ContextIndependent val context = ResolutionMode.ContextIndependent
doWhileLoop.also(dataFlowAnalyzer::enterDoWhileLoop) doWhileLoop.also(dataFlowAnalyzer::enterDoWhileLoop)
.also { .also {
@@ -61,7 +61,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
} }
whenExpression.annotations.forEach { it.accept(this, data) } whenExpression.annotations.forEach { it.accept(this, data) }
dataFlowAnalyzer.enterWhenExpression(whenExpression) dataFlowAnalyzer.enterWhenExpression(whenExpression)
return context.withWhenExpression(whenExpression) with@{ return context.withWhenExpression(whenExpression, session) with@{
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
var whenExpression = whenExpression.transformSubject(transformer, ResolutionMode.ContextIndependent) var whenExpression = whenExpression.transformSubject(transformer, ResolutionMode.ContextIndependent)
@@ -164,7 +164,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
override fun transformCatch(catch: FirCatch, data: ResolutionMode): FirCatch { override fun transformCatch(catch: FirCatch, data: ResolutionMode): FirCatch {
dataFlowAnalyzer.enterCatchClause(catch) dataFlowAnalyzer.enterCatchClause(catch)
catch.parameter.transformReturnTypeRef(transformer, ResolutionMode.ContextIndependent) catch.parameter.transformReturnTypeRef(transformer, ResolutionMode.ContextIndependent)
return context.forBlock { return context.forBlock(session) {
catch.transformParameter(transformer, ResolutionMode.ContextIndependent) catch.transformParameter(transformer, ResolutionMode.ContextIndependent)
catch.transformBlock(transformer, ResolutionMode.ContextDependent) catch.transformBlock(transformer, ResolutionMode.ContextDependent)
}.also { dataFlowAnalyzer.exitCatchClause(it) } }.also { dataFlowAnalyzer.exitCatchClause(it) }
@@ -330,7 +330,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
variable.transformAccessors() variable.transformAccessors()
} }
variable.transformOtherChildren(transformer, ResolutionMode.ContextIndependent) variable.transformOtherChildren(transformer, ResolutionMode.ContextIndependent)
context.storeVariable(variable) context.storeVariable(variable, session)
dataFlowAnalyzer.exitLocalVariableDeclaration(variable, hadExplicitType) dataFlowAnalyzer.exitLocalVariableDeclaration(variable, hadExplicitType)
return variable return variable
} }
@@ -540,7 +540,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
doTransformTypeParameters(simpleFunction) doTransformTypeParameters(simpleFunction)
val containingDeclaration = context.containerIfAny val containingDeclaration = context.containerIfAny
return context.withSimpleFunction(simpleFunction) { return context.withSimpleFunction(simpleFunction, session) {
// TODO: I think it worth creating something like runAllPhasesForLocalFunction // TODO: I think it worth creating something like runAllPhasesForLocalFunction
if (containingDeclaration != null && containingDeclaration !is FirClass) { if (containingDeclaration != null && containingDeclaration !is FirClass) {
// For class members everything should be already prepared // For class members everything should be already prepared
@@ -635,7 +635,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
constructor.transformValueParameters(transformer, data) constructor.transformValueParameters(transformer, data)
} }
constructor.transformDelegatedConstructor(transformer, data) constructor.transformDelegatedConstructor(transformer, data)
context.forConstructorBody(constructor) { context.forConstructorBody(constructor, session) {
constructor.transformBody(transformer, data) constructor.transformBody(transformer, data)
} }
} }
@@ -651,7 +651,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
): FirAnonymousInitializer { ): FirAnonymousInitializer {
if (implicitTypeOnly) return anonymousInitializer if (implicitTypeOnly) return anonymousInitializer
dataFlowAnalyzer.enterInitBlock(anonymousInitializer) dataFlowAnalyzer.enterInitBlock(anonymousInitializer)
return context.withAnonymousInitializer(anonymousInitializer) { return context.withAnonymousInitializer(anonymousInitializer, session) {
val result = val result =
transformDeclarationContent(anonymousInitializer, ResolutionMode.ContextIndependent) as FirAnonymousInitializer transformDeclarationContent(anonymousInitializer, ResolutionMode.ContextIndependent) as FirAnonymousInitializer
val graph = dataFlowAnalyzer.exitInitBlock(result) val graph = dataFlowAnalyzer.exitInitBlock(result)
@@ -671,7 +671,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
} }
dataFlowAnalyzer.enterValueParameter(valueParameter) dataFlowAnalyzer.enterValueParameter(valueParameter)
val result = context.withValueParameter(valueParameter) { val result = context.withValueParameter(valueParameter, session) {
transformDeclarationContent( transformDeclarationContent(
valueParameter, valueParameter,
withExpectedType(valueParameter.returnTypeRef) withExpectedType(valueParameter.returnTypeRef)
@@ -384,7 +384,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
} }
override fun transformBlock(block: FirBlock, data: ResolutionMode): FirStatement { override fun transformBlock(block: FirBlock, data: ResolutionMode): FirStatement {
context.forBlock { context.forBlock(session) {
transformBlockInCurrentScope(block, data) transformBlockInCurrentScope(block, data)
} }
return block return block
@@ -22,7 +22,7 @@ fun <F : FirClassLikeDeclaration> F.runAllPhasesForLocalClass(
): F { ): F {
if (status is FirResolvedDeclarationStatus) return this if (status is FirResolvedDeclarationStatus) return this
if (this is FirRegularClass) { if (this is FirRegularClass) {
components.context.storeClassIfNotNested(this) components.context.storeClassIfNotNested(this, components.session)
} }
this.transformAnnotations(transformer, ResolutionMode.ContextIndependent) this.transformAnnotations(transformer, ResolutionMode.ContextIndependent)
val localClassesNavigationInfo = collectLocalClassesNavigationInfo() val localClassesNavigationInfo = collectLocalClassesNavigationInfo()
@@ -71,7 +71,7 @@ open class FirContractResolveTransformer(
return simpleFunction return simpleFunction
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return context.withSimpleFunction(simpleFunction) { return context.withSimpleFunction(simpleFunction, session) {
context.forFunctionBody(simpleFunction, components) { context.forFunctionBody(simpleFunction, components) {
transformContractDescriptionOwner(simpleFunction) transformContractDescriptionOwner(simpleFunction)
} }
@@ -129,7 +129,7 @@ open class FirContractResolveTransformer(
): T { ): T {
val valueParameters = owner.valueParameters val valueParameters = owner.valueParameters
for (valueParameter in valueParameters) { for (valueParameter in valueParameters) {
context.storeVariable(valueParameter) context.storeVariable(valueParameter, session)
} }
val contractCall = contractDescription.contractCall.transformSingle(transformer, ResolutionMode.ContextIndependent) val contractCall = contractDescription.contractCall.transformSingle(transformer, ResolutionMode.ContextIndependent)
val resolvedId = contractCall.toResolvedCallableSymbol()?.callableId ?: return transformOwnerWithUnresolvedContract(owner) val resolvedId = contractCall.toResolvedCallableSymbol()?.callableId ?: return transformOwnerWithUnresolvedContract(owner)
@@ -32,31 +32,38 @@ fun FirClassLikeDeclaration.getContainingDeclaration(session: FirSession): FirCl
return null return null
} }
fun isValidTypeParameterFromOuterClass( fun isValidTypeParameterFromOuterDeclaration(
typeParameterSymbol: FirTypeParameterSymbol, typeParameterSymbol: FirTypeParameterSymbol,
classDeclaration: FirRegularClass?, declaration: FirDeclaration?,
session: FirSession session: FirSession
): Boolean { ): Boolean {
if (classDeclaration == null) { if (declaration == null) {
return true // Extra check is required because of classDeclaration will be resolved later return true // Extra check is required because of classDeclaration will be resolved later
} }
fun containsTypeParameter(currentClassDeclaration: FirRegularClass): Boolean { fun containsTypeParameter(currentDeclaration: FirDeclaration?): Boolean {
if (currentClassDeclaration.typeParameters.any { it.symbol == typeParameterSymbol }) { if (currentDeclaration is FirTypeParameterRefsOwner) {
return true if (currentDeclaration.typeParameters.any { it.symbol == typeParameterSymbol }) {
}
for (superTypeRef in currentClassDeclaration.superTypeRefs) {
val superClassFir = superTypeRef.firClassLike(session)
if (superClassFir == null || superClassFir is FirRegularClass && containsTypeParameter(superClassFir)) {
return true return true
} }
if (currentDeclaration is FirCallableDeclaration) {
val containingClassId = currentDeclaration.symbol.callableId.classId ?: return true
return containsTypeParameter(session.symbolProvider.getClassLikeSymbolByClassId(containingClassId)?.fir)
} else if (currentDeclaration is FirClass) {
for (superTypeRef in currentDeclaration.superTypeRefs) {
val superClassFir = superTypeRef.firClassLike(session)
if (superClassFir == null || superClassFir is FirRegularClass && containsTypeParameter(superClassFir)) {
return true
}
}
}
} }
return false return false
} }
return containsTypeParameter(classDeclaration) return containsTypeParameter(declaration)
} }
fun FirTypeRef.firClassLike(session: FirSession): FirClassLikeDeclaration? { fun FirTypeRef.firClassLike(session: FirSession): FirClassLikeDeclaration? {
@@ -19,14 +19,14 @@ private class Outer<E> {
private var doubleStringInt = Outer<Double>().Inner<String>().foo<Int>()() private var doubleStringInt = Outer<Double>().Inner<String>().foo<Int>()()
private fun bar() { private fun bar() {
doubleCharSequenceInt = doubleStringNumber doubleCharSequenceInt = <!ASSIGNMENT_TYPE_MISMATCH!>doubleStringNumber<!>
doubleCharSequenceInt = doubleStringInt doubleCharSequenceInt = doubleStringInt
doubleStringInt = Outer<Double>().Inner<String>().foo<Int>()() doubleStringInt = Outer<Double>().Inner<String>().foo<Int>()()
doubleStringInt.e.checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Double>() } doubleStringInt.e.checkType { _<Double>() }
doubleStringInt.f.checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><String>() } doubleStringInt.f.checkType { _<String>() }
doubleStringInt.g.checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Int>() } doubleStringInt.g.checkType { _<Int>() }
} }
} }
} }
@@ -14,11 +14,11 @@ class Q {
private var y = foo<String>()() private var y = foo<String>()()
fun bar() { fun bar() {
x = y x = <!ASSIGNMENT_TYPE_MISMATCH!>y<!>
x = foo<CharSequence>()() x = foo<CharSequence>()()
y = foo<String>()() y = foo<String>()()
x.prop.checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><CharSequence>() } x.prop.checkType { _<CharSequence>() }
y.prop.checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><String>() } y.prop.checkType { _<String>() }
} }
} }
@@ -15,8 +15,8 @@ class Q {
private var x = foo<CharSequence, Number>()() private var x = foo<CharSequence, Number>()()
fun bar() { fun bar() {
x.e.checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><CharSequence>() } x.e.checkType { _<CharSequence>() }
x.f.checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Number>() } x.f.checkType { _<Number>() }
x.g.checkType { _<Number>() } x.g.checkType { _<Number>() }
} }
} }
@@ -1,16 +1,16 @@
fun <E> foo(x: Any, y: Any) : Any { fun <E> foo(x: Any, y: Any) : Any {
class C class C
// without E? // without E?
if(x is C) { if(x is <!NO_TYPE_ARGUMENTS_ON_RHS!>C<!>) {
return x return x
} }
if (1 == 2) { if (1 == 2) {
x as C x as <!NO_TYPE_ARGUMENTS_ON_RHS!>C<!>
} }
if (2 == 3) { if (2 == 3) {
x as? C x as? <!NO_TYPE_ARGUMENTS_ON_RHS, NO_TYPE_ARGUMENTS_ON_RHS!>C<!>
} }
class Outer<F> { class Outer<F> {
@@ -41,10 +41,10 @@ fun test() {
var x = foobar<String>() var x = foobar<String>()
x = foobar<String>() x = foobar<String>()
x().foo().a() checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><A<String, Double, Short, Long>>() } x().foo().a() checkType { _<A<String, Double, Short, Long>>() }
x().bar() <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>checkType<!> { _<A<String, Double, Short, Char>>() } x().bar() <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>checkType<!> { _<A<String, Double, Short, Char>>() }
x = foobar<Int>() x = <!ASSIGNMENT_TYPE_MISMATCH!>foobar<Int>()<!>
var y = noParameters() var y = noParameters()
y = noParameters() y = noParameters()
@@ -42,11 +42,11 @@ class Outer<T> {
var x = foobar<String>() var x = foobar<String>()
x = foobar<String>() x = foobar<String>()
x().foo().a() checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><A<T, F, String, Double, Short, Long>>() } x().foo().a() checkType { _<A<T, F, String, Double, Short, Long>>() }
x().bar() <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>checkType<!> { _<A<T, F, String, Double, Short, Char>>() } x().bar() <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>checkType<!> { _<A<T, F, String, Double, Short, Char>>() }
x = foobar<Int>() x = <!ASSIGNMENT_TYPE_MISMATCH!>foobar<Int>()<!>
x = z.foobar<String>() x = <!ASSIGNMENT_TYPE_MISMATCH!>z.foobar<String>()<!>
var y = noParameters() var y = noParameters()
y = noParameters() y = noParameters()
@@ -0,0 +1,14 @@
// FIR_IDENTICAL
class C1<T1>
class C2<T3> {
fun <T2> test() {
class LocalClass
C1<LocalClass>()
}
}
class A<T> {
private inner class Inner
private val test = ArrayList<Inner>()
}
@@ -0,0 +1,31 @@
package
public final class A</*0*/ T> {
public constructor A</*0*/ T>()
private final val test: kotlin.collections.ArrayList<A<T>.Inner> /* = java.util.ArrayList<A<T>.Inner> */
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
private final inner class Inner /*captured type parameters: /*0*/ T*/ {
public constructor Inner()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
public final class C1</*0*/ T1> {
public constructor C1</*0*/ T1>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class C2</*0*/ T3> {
public constructor C2</*0*/ T3>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun </*0*/ T2> test(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -4,8 +4,8 @@ class A<T> {
class B { class B {
fun test() { fun test() {
class C<W>() : P<W, <!UNRESOLVED_REFERENCE!>T<!>> { class C<W>() : P<W, <!UNRESOLVED_REFERENCE!>T<!>> {
<!WRONG_MODIFIER_CONTAINING_DECLARATION!>companion<!> object : P<W, <!UNRESOLVED_REFERENCE!>T<!>> { <!TYPE_PARAMETERS_IN_OBJECT!><!WRONG_MODIFIER_CONTAINING_DECLARATION!>companion<!> object : P<W, <!UNRESOLVED_REFERENCE!>T<!>> {
} }<!>
inner class D : P<W, <!UNRESOLVED_REFERENCE!>T<!>> inner class D : P<W, <!UNRESOLVED_REFERENCE!>T<!>>
} }
@@ -18,12 +18,12 @@ class Outer<T> {
fun test5(x: <!UNRESOLVED_REFERENCE!>GenericInnerAlias<Int><!>) = x fun test5(x: <!UNRESOLVED_REFERENCE!>GenericInnerAlias<Int><!>) = x
fun <T> test6(x: <!UNRESOLVED_REFERENCE!>GenericInnerAlias<T><!>) = x fun <T> test6(x: <!UNRESOLVED_REFERENCE!>GenericInnerAlias<T><!>) = x
} }
fun test1(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>.NestedAlias) = x fun test1(x: Outer<Int>.NestedAlias) = x
fun <T> test2(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T><!>.NestedAlias) = x fun <T> test2(x: Outer<T>.NestedAlias) = x
fun test3(x: Outer.NestedAlias) = x fun test3(x: Outer.NestedAlias) = x
fun test4(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>.GenericNestedAlias<Int>) = x fun test4(x: Outer<Int>.GenericNestedAlias<Int>) = x
fun <T> test5(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T><!>.GenericNestedAlias<Int>) = x fun <T> test5(x: Outer<T>.GenericNestedAlias<Int>) = x
fun <T> test6(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>.GenericNestedAlias<T>) = x fun <T> test6(x: Outer<Int>.GenericNestedAlias<T>) = x
fun test7(x: Outer.GenericNestedAlias<Int>) = x fun test7(x: Outer.GenericNestedAlias<Int>) = x
fun <T> test8(x: Outer.GenericNestedAlias<T>) = x fun <T> test8(x: Outer.GenericNestedAlias<T>) = x
fun test9(x: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Outer<!>.InnerAlias) = x fun test9(x: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Outer<!>.InnerAlias) = x
@@ -6,5 +6,5 @@ class OuterClass<T1> {
} }
typealias ON1<T1, T2> = OuterClass<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T1><!>.NestedClass<T2> typealias ON1<T1, T2> = OuterClass<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T1><!>.NestedClass<T2>
typealias ON2<T1, T2> = OuterClass<T1>.NestedType<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T2><!> typealias ON2<T1, T2> = OuterClass<T1>.NestedType<T2>
typealias ON3<T2> = OuterClass.NestedType<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T2><!> typealias ON3<T2> = OuterClass.NestedType<T2>
@@ -30,6 +30,6 @@ fun testWrong4(x: List<Any>) = x is <!NO_TYPE_ARGUMENTS_ON_RHS!>ReadableList<!>
fun <T> testLocal(x: Any) { fun <T> testLocal(x: Any) {
class C class C
typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>CA<!> = C typealias <!EXPOSED_TYPEALIAS_EXPANDED_TYPE!>CA<!> = C
if (x is C) {} if (x is <!NO_TYPE_ARGUMENTS_ON_RHS!>C<!>) {}
if (x is <!UNRESOLVED_REFERENCE!>CA<!>) {} if (x is <!UNRESOLVED_REFERENCE!>CA<!>) {}
} }
@@ -70,9 +70,9 @@ FILE fqName:<root> fileName:/genericLocalClassConstructorReference.kt
$receiver: VALUE_PARAMETER name:<this> type:<root>.Rec<PT of <root>.<get-p>> $receiver: VALUE_PARAMETER name:<this> type:<root>.Rec<PT of <root>.<get-p>>
BLOCK_BODY BLOCK_BODY
CLASS CLASS name:PLocal modality:FINAL visibility:local superTypes:[<root>.L<LT of <root>.<get-p>.PLocal>] CLASS CLASS name:PLocal modality:FINAL visibility:local superTypes:[<root>.L<LT of <root>.<get-p>.PLocal>]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.<get-p>.PLocal<LT of <root>.<get-p>.PLocal> $this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.<get-p>.PLocal<LT of <root>.<get-p>.PLocal, PT of <root>.<get-p>>
TYPE_PARAMETER name:LT index:0 variance: superTypes:[kotlin.Any?] TYPE_PARAMETER name:LT index:0 variance: superTypes:[kotlin.Any?]
CONSTRUCTOR visibility:public <> (lt:LT of <root>.<get-p>.PLocal, pt:PT of <root>.<get-p>) returnType:<root>.<get-p>.PLocal<LT of <root>.<get-p>.PLocal> [primary] CONSTRUCTOR visibility:public <> (lt:LT of <root>.<get-p>.PLocal, pt:PT of <root>.<get-p>) returnType:<root>.<get-p>.PLocal<LT of <root>.<get-p>.PLocal, PT of <root>.<get-p>> [primary]
VALUE_PARAMETER name:lt index:0 type:LT of <root>.<get-p>.PLocal VALUE_PARAMETER name:lt index:0 type:LT of <root>.<get-p>.PLocal
VALUE_PARAMETER name:pt index:1 type:PT of <root>.<get-p> VALUE_PARAMETER name:pt index:1 type:PT of <root>.<get-p>
BLOCK_BODY BLOCK_BODY
@@ -84,13 +84,13 @@ FILE fqName:<root> fileName:/genericLocalClassConstructorReference.kt
FIELD PROPERTY_BACKING_FIELD name:pt type:PT of <root>.<get-p> visibility:private [final] FIELD PROPERTY_BACKING_FIELD name:pt type:PT of <root>.<get-p> visibility:private [final]
EXPRESSION_BODY EXPRESSION_BODY
GET_VAR 'pt: PT of <root>.<get-p> declared in <root>.<get-p>.PLocal.<init>' type=PT of <root>.<get-p> origin=INITIALIZE_PROPERTY_FROM_PARAMETER GET_VAR 'pt: PT of <root>.<get-p> declared in <root>.<get-p>.PLocal.<init>' type=PT of <root>.<get-p> origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-pt> visibility:public modality:FINAL <> ($this:<root>.<get-p>.PLocal<LT of <root>.<get-p>.PLocal>) returnType:PT of <root>.<get-p> FUN DEFAULT_PROPERTY_ACCESSOR name:<get-pt> visibility:public modality:FINAL <> ($this:<root>.<get-p>.PLocal<LT of <root>.<get-p>.PLocal, PT of <root>.<get-p>>) returnType:PT of <root>.<get-p>
correspondingProperty: PROPERTY name:pt visibility:public modality:FINAL [val] correspondingProperty: PROPERTY name:pt visibility:public modality:FINAL [val]
$this: VALUE_PARAMETER name:<this> type:<root>.<get-p>.PLocal<LT of <root>.<get-p>.PLocal> $this: VALUE_PARAMETER name:<this> type:<root>.<get-p>.PLocal<LT of <root>.<get-p>.PLocal, PT of <root>.<get-p>>
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-pt> (): PT of <root>.<get-p> declared in <root>.<get-p>.PLocal' RETURN type=kotlin.Nothing from='public final fun <get-pt> (): PT of <root>.<get-p> declared in <root>.<get-p>.PLocal'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:pt type:PT of <root>.<get-p> visibility:private [final]' type=PT of <root>.<get-p> origin=null GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:pt type:PT of <root>.<get-p> visibility:private [final]' type=PT of <root>.<get-p> origin=null
receiver: GET_VAR '<this>: <root>.<get-p>.PLocal<LT of <root>.<get-p>.PLocal> declared in <root>.<get-p>.PLocal.<get-pt>' type=<root>.<get-p>.PLocal<LT of <root>.<get-p>.PLocal> origin=null receiver: GET_VAR '<this>: <root>.<get-p>.PLocal<LT of <root>.<get-p>.PLocal, PT of <root>.<get-p>> declared in <root>.<get-p>.PLocal.<get-pt>' type=<root>.<get-p>.PLocal<LT of <root>.<get-p>.PLocal, PT of <root>.<get-p>> origin=null
PROPERTY FAKE_OVERRIDE name:ll visibility:public modality:FINAL [fake_override,val] PROPERTY FAKE_OVERRIDE name:ll visibility:public modality:FINAL [fake_override,val]
overridden: overridden:
public final ll: LL of <root>.L [val] public final ll: LL of <root>.L [val]
@@ -113,24 +113,24 @@ FILE fqName:<root> fileName:/genericLocalClassConstructorReference.kt
public open fun toString (): kotlin.String [fake_override] declared in <root>.L public open fun toString (): kotlin.String [fake_override] declared in <root>.L
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any
RETURN type=kotlin.Nothing from='public final fun <get-p> <PT> (): <root>.L<PT of <root>.<get-p>> declared in <root>' RETURN type=kotlin.Nothing from='public final fun <get-p> <PT> (): <root>.L<PT of <root>.<get-p>> declared in <root>'
CALL 'public final fun foo2 <T1, T2, R> (t1: T1 of <root>.foo2, t2: T2 of <root>.foo2, bb: kotlin.Function2<T1 of <root>.foo2, T2 of <root>.foo2, R of <root>.foo2>): R of <root>.foo2 declared in <root>' type=<root>.<get-p>.PLocal<PT of <root>.<get-p>> origin=null CALL 'public final fun foo2 <T1, T2, R> (t1: T1 of <root>.foo2, t2: T2 of <root>.foo2, bb: kotlin.Function2<T1 of <root>.foo2, T2 of <root>.foo2, R of <root>.foo2>): R of <root>.foo2 declared in <root>' type=<root>.<get-p>.PLocal<PT of <root>.<get-p>, PT of <root>.<get-p>> origin=null
<T1>: PT of <root>.<get-p> <T1>: PT of <root>.<get-p>
<T2>: PT of <root>.<get-p> <T2>: PT of <root>.<get-p>
<R>: <root>.<get-p>.PLocal<PT of <root>.<get-p>> <R>: <root>.<get-p>.PLocal<PT of <root>.<get-p>, PT of <root>.<get-p>>
t1: CALL 'public final fun <get-rt> (): T of <root>.Rec declared in <root>.Rec' type=PT of <root>.<get-p> origin=GET_PROPERTY t1: CALL 'public final fun <get-rt> (): T of <root>.Rec declared in <root>.Rec' type=PT of <root>.<get-p> origin=GET_PROPERTY
$this: GET_VAR '<this>: <root>.Rec<PT of <root>.<get-p>> declared in <root>.<get-p>' type=<root>.Rec<PT of <root>.<get-p>> origin=null $this: GET_VAR '<this>: <root>.Rec<PT of <root>.<get-p>> declared in <root>.<get-p>' type=<root>.Rec<PT of <root>.<get-p>> origin=null
t2: CALL 'public final fun <get-rt> (): T of <root>.Rec declared in <root>.Rec' type=PT of <root>.<get-p> origin=GET_PROPERTY t2: CALL 'public final fun <get-rt> (): T of <root>.Rec declared in <root>.Rec' type=PT of <root>.<get-p> origin=GET_PROPERTY
$this: GET_VAR '<this>: <root>.Rec<PT of <root>.<get-p>> declared in <root>.<get-p>' type=<root>.Rec<PT of <root>.<get-p>> origin=null $this: GET_VAR '<this>: <root>.Rec<PT of <root>.<get-p>> declared in <root>.<get-p>' type=<root>.Rec<PT of <root>.<get-p>> origin=null
bb: FUNCTION_REFERENCE 'public constructor <init> (lt: LT of <root>.<get-p>.PLocal, pt: PT of <root>.<get-p>) [primary] declared in <root>.<get-p>.PLocal' type=kotlin.reflect.KFunction2<PT of <root>.<get-p>, PT of <root>.<get-p>, <root>.<get-p>.PLocal<PT of <root>.<get-p>>> origin=null reflectionTarget=<same> bb: FUNCTION_REFERENCE 'public constructor <init> (lt: LT of <root>.<get-p>.PLocal, pt: PT of <root>.<get-p>) [primary] declared in <root>.<get-p>.PLocal' type=kotlin.reflect.KFunction2<PT of <root>.<get-p>, PT of <root>.<get-p>, <root>.<get-p>.PLocal<PT of <root>.<get-p>, PT of <root>.<get-p>>> origin=null reflectionTarget=<same>
<LT>: PT of <root>.<get-p> <LT>: PT of <root>.<get-p>
FUN name:fn visibility:public modality:FINAL <FT> ($receiver:<root>.Rec<FT of <root>.fn>) returnType:<root>.L<FT of <root>.fn> FUN name:fn visibility:public modality:FINAL <FT> ($receiver:<root>.Rec<FT of <root>.fn>) returnType:<root>.L<FT of <root>.fn>
TYPE_PARAMETER name:FT index:0 variance: superTypes:[kotlin.Any?] TYPE_PARAMETER name:FT index:0 variance: superTypes:[kotlin.Any?]
$receiver: VALUE_PARAMETER name:<this> type:<root>.Rec<FT of <root>.fn> $receiver: VALUE_PARAMETER name:<this> type:<root>.Rec<FT of <root>.fn>
BLOCK_BODY BLOCK_BODY
CLASS CLASS name:FLocal modality:FINAL visibility:local superTypes:[<root>.L<LT of <root>.fn.FLocal>] CLASS CLASS name:FLocal modality:FINAL visibility:local superTypes:[<root>.L<LT of <root>.fn.FLocal>]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.fn.FLocal<LT of <root>.fn.FLocal> $this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.fn.FLocal<LT of <root>.fn.FLocal, FT of <root>.fn>
TYPE_PARAMETER name:LT index:0 variance: superTypes:[kotlin.Any?] TYPE_PARAMETER name:LT index:0 variance: superTypes:[kotlin.Any?]
CONSTRUCTOR visibility:public <> (lt:LT of <root>.fn.FLocal, pt:FT of <root>.fn) returnType:<root>.fn.FLocal<LT of <root>.fn.FLocal> [primary] CONSTRUCTOR visibility:public <> (lt:LT of <root>.fn.FLocal, pt:FT of <root>.fn) returnType:<root>.fn.FLocal<LT of <root>.fn.FLocal, FT of <root>.fn> [primary]
VALUE_PARAMETER name:lt index:0 type:LT of <root>.fn.FLocal VALUE_PARAMETER name:lt index:0 type:LT of <root>.fn.FLocal
VALUE_PARAMETER name:pt index:1 type:FT of <root>.fn VALUE_PARAMETER name:pt index:1 type:FT of <root>.fn
BLOCK_BODY BLOCK_BODY
@@ -142,13 +142,13 @@ FILE fqName:<root> fileName:/genericLocalClassConstructorReference.kt
FIELD PROPERTY_BACKING_FIELD name:pt type:FT of <root>.fn visibility:private [final] FIELD PROPERTY_BACKING_FIELD name:pt type:FT of <root>.fn visibility:private [final]
EXPRESSION_BODY EXPRESSION_BODY
GET_VAR 'pt: FT of <root>.fn declared in <root>.fn.FLocal.<init>' type=FT of <root>.fn origin=INITIALIZE_PROPERTY_FROM_PARAMETER GET_VAR 'pt: FT of <root>.fn declared in <root>.fn.FLocal.<init>' type=FT of <root>.fn origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-pt> visibility:public modality:FINAL <> ($this:<root>.fn.FLocal<LT of <root>.fn.FLocal>) returnType:FT of <root>.fn FUN DEFAULT_PROPERTY_ACCESSOR name:<get-pt> visibility:public modality:FINAL <> ($this:<root>.fn.FLocal<LT of <root>.fn.FLocal, FT of <root>.fn>) returnType:FT of <root>.fn
correspondingProperty: PROPERTY name:pt visibility:public modality:FINAL [val] correspondingProperty: PROPERTY name:pt visibility:public modality:FINAL [val]
$this: VALUE_PARAMETER name:<this> type:<root>.fn.FLocal<LT of <root>.fn.FLocal> $this: VALUE_PARAMETER name:<this> type:<root>.fn.FLocal<LT of <root>.fn.FLocal, FT of <root>.fn>
BLOCK_BODY BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-pt> (): FT of <root>.fn declared in <root>.fn.FLocal' RETURN type=kotlin.Nothing from='public final fun <get-pt> (): FT of <root>.fn declared in <root>.fn.FLocal'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:pt type:FT of <root>.fn visibility:private [final]' type=FT of <root>.fn origin=null GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:pt type:FT of <root>.fn visibility:private [final]' type=FT of <root>.fn origin=null
receiver: GET_VAR '<this>: <root>.fn.FLocal<LT of <root>.fn.FLocal> declared in <root>.fn.FLocal.<get-pt>' type=<root>.fn.FLocal<LT of <root>.fn.FLocal> origin=null receiver: GET_VAR '<this>: <root>.fn.FLocal<LT of <root>.fn.FLocal, FT of <root>.fn> declared in <root>.fn.FLocal.<get-pt>' type=<root>.fn.FLocal<LT of <root>.fn.FLocal, FT of <root>.fn> origin=null
PROPERTY FAKE_OVERRIDE name:ll visibility:public modality:FINAL [fake_override,val] PROPERTY FAKE_OVERRIDE name:ll visibility:public modality:FINAL [fake_override,val]
overridden: overridden:
public final ll: LL of <root>.L [val] public final ll: LL of <root>.L [val]
@@ -171,15 +171,15 @@ FILE fqName:<root> fileName:/genericLocalClassConstructorReference.kt
public open fun toString (): kotlin.String [fake_override] declared in <root>.L public open fun toString (): kotlin.String [fake_override] declared in <root>.L
$this: VALUE_PARAMETER name:<this> type:kotlin.Any $this: VALUE_PARAMETER name:<this> type:kotlin.Any
RETURN type=kotlin.Nothing from='public final fun fn <FT> (): <root>.L<FT of <root>.fn> declared in <root>' RETURN type=kotlin.Nothing from='public final fun fn <FT> (): <root>.L<FT of <root>.fn> declared in <root>'
CALL 'public final fun foo2 <T1, T2, R> (t1: T1 of <root>.foo2, t2: T2 of <root>.foo2, bb: kotlin.Function2<T1 of <root>.foo2, T2 of <root>.foo2, R of <root>.foo2>): R of <root>.foo2 declared in <root>' type=<root>.fn.FLocal<FT of <root>.fn> origin=null CALL 'public final fun foo2 <T1, T2, R> (t1: T1 of <root>.foo2, t2: T2 of <root>.foo2, bb: kotlin.Function2<T1 of <root>.foo2, T2 of <root>.foo2, R of <root>.foo2>): R of <root>.foo2 declared in <root>' type=<root>.fn.FLocal<FT of <root>.fn, FT of <root>.fn> origin=null
<T1>: FT of <root>.fn <T1>: FT of <root>.fn
<T2>: FT of <root>.fn <T2>: FT of <root>.fn
<R>: <root>.fn.FLocal<FT of <root>.fn> <R>: <root>.fn.FLocal<FT of <root>.fn, FT of <root>.fn>
t1: CALL 'public final fun <get-rt> (): T of <root>.Rec declared in <root>.Rec' type=FT of <root>.fn origin=GET_PROPERTY t1: CALL 'public final fun <get-rt> (): T of <root>.Rec declared in <root>.Rec' type=FT of <root>.fn origin=GET_PROPERTY
$this: GET_VAR '<this>: <root>.Rec<FT of <root>.fn> declared in <root>.fn' type=<root>.Rec<FT of <root>.fn> origin=null $this: GET_VAR '<this>: <root>.Rec<FT of <root>.fn> declared in <root>.fn' type=<root>.Rec<FT of <root>.fn> origin=null
t2: CALL 'public final fun <get-rt> (): T of <root>.Rec declared in <root>.Rec' type=FT of <root>.fn origin=GET_PROPERTY t2: CALL 'public final fun <get-rt> (): T of <root>.Rec declared in <root>.Rec' type=FT of <root>.fn origin=GET_PROPERTY
$this: GET_VAR '<this>: <root>.Rec<FT of <root>.fn> declared in <root>.fn' type=<root>.Rec<FT of <root>.fn> origin=null $this: GET_VAR '<this>: <root>.Rec<FT of <root>.fn> declared in <root>.fn' type=<root>.Rec<FT of <root>.fn> origin=null
bb: FUNCTION_REFERENCE 'public constructor <init> (lt: LT of <root>.fn.FLocal, pt: FT of <root>.fn) [primary] declared in <root>.fn.FLocal' type=kotlin.reflect.KFunction2<FT of <root>.fn, FT of <root>.fn, <root>.fn.FLocal<FT of <root>.fn>> origin=null reflectionTarget=<same> bb: FUNCTION_REFERENCE 'public constructor <init> (lt: LT of <root>.fn.FLocal, pt: FT of <root>.fn) [primary] declared in <root>.fn.FLocal' type=kotlin.reflect.KFunction2<FT of <root>.fn, FT of <root>.fn, <root>.fn.FLocal<FT of <root>.fn, FT of <root>.fn>> origin=null reflectionTarget=<same>
<LT>: FT of <root>.fn <LT>: FT of <root>.fn
FUN name:foo2 visibility:public modality:FINAL <T1, T2, R> (t1:T1 of <root>.foo2, t2:T2 of <root>.foo2, bb:kotlin.Function2<T1 of <root>.foo2, T2 of <root>.foo2, R of <root>.foo2>) returnType:R of <root>.foo2 FUN name:foo2 visibility:public modality:FINAL <T1, T2, R> (t1:T1 of <root>.foo2, t2:T2 of <root>.foo2, bb:kotlin.Function2<T1 of <root>.foo2, T2 of <root>.foo2, R of <root>.foo2>) returnType:R of <root>.foo2
TYPE_PARAMETER name:T1 index:0 variance: superTypes:[kotlin.Any?] TYPE_PARAMETER name:T1 index:0 variance: superTypes:[kotlin.Any?]
@@ -39,7 +39,7 @@ val <PT : Any?> Rec<PT>.p: L<PT>
} }
return foo2<PT, PT, PLocal<PT>>(t1 = <this>.<get-rt>(), t2 = <this>.<get-rt>(), bb = PLocal::<init>/*<PT>()*/) return foo2<PT, PT, PLocal<PT, PT>>(t1 = <this>.<get-rt>(), t2 = <this>.<get-rt>(), bb = PLocal::<init>/*<PT>()*/)
} }
fun <FT : Any?> Rec<FT>.fn(): L<FT> { fun <FT : Any?> Rec<FT>.fn(): L<FT> {
@@ -56,9 +56,10 @@ fun <FT : Any?> Rec<FT>.fn(): L<FT> {
} }
return foo2<FT, FT, FLocal<FT>>(t1 = <this>.<get-rt>(), t2 = <this>.<get-rt>(), bb = FLocal::<init>/*<FT>()*/) return foo2<FT, FT, FLocal<FT, FT>>(t1 = <this>.<get-rt>(), t2 = <this>.<get-rt>(), bb = FLocal::<init>/*<FT>()*/)
} }
fun <T1 : Any?, T2 : Any?, R : Any?> foo2(t1: T1, t2: T2, bb: Function2<T1, T2, R>): R { fun <T1 : Any?, T2 : Any?, R : Any?> foo2(t1: T1, t2: T2, bb: Function2<T1, T2, R>): R {
return bb.invoke(p1 = t1, p2 = t2) return bb.invoke(p1 = t1, p2 = t2)
} }
@@ -11351,6 +11351,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/generics/kt9985.kt"); runTest("compiler/testData/diagnostics/tests/generics/kt9985.kt");
} }
@Test
@TestMetadata("localClassWithTypeArgumentFromFunction.kt")
public void testLocalClassWithTypeArgumentFromFunction() throws Exception {
runTest("compiler/testData/diagnostics/tests/generics/localClassWithTypeArgumentFromFunction.kt");
}
@Test @Test
@TestMetadata("Projections.kt") @TestMetadata("Projections.kt")
public void testProjections() throws Exception { public void testProjections() throws Exception {