[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 -> {
context.withContainingClass(nextElement) {
moveNextDeclaration(designationIterator)
}
moveNextDeclaration(designationIterator)
}
is FirEnumEntry -> {
context.forEnumEntry {
@@ -11345,6 +11345,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
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
@TestMetadata("Projections.kt")
public void testProjections() throws Exception {
@@ -39,8 +39,8 @@ FILE: throwableSubclass.kt
}
public final fun foo(): R|kotlin/Unit| {
local final class Test7 : R|kotlin/Throwable| {
public constructor(): R|Test5.Test7| {
local final class Test7<T, B> : R|kotlin/Throwable| {
public constructor(): R|Test5.Test7<T, B>| {
super<R|kotlin/Throwable|>()
}
@@ -50,8 +50,8 @@ FILE: throwableSubclass.kt
}
public final fun <Z> topLevelFun(): R|kotlin/Unit| {
local final class Test8 : R|kotlin/Error| {
public constructor(): R|Test8| {
local final class Test8<Z> : R|kotlin/Error| {
public constructor(): R|Test8<Z>| {
super<R|kotlin/Error|>()
}
@@ -11345,6 +11345,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
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
@TestMetadata("Projections.kt")
public void testProjections() throws Exception {
@@ -11345,6 +11345,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
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
@TestMetadata("Projections.kt")
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 CANNOT_CHECK_FOR_ERASED by error<PsiElement> {
parameter<ConeKotlinType>("type")
}
val USELESS_CAST by warning<KtBinaryExpressionWithTypeRHS>(PositioningStrategy.AS_TYPE)
val USELESS_IS_CHECK by warning<KtElement> {
parameter<Boolean>("compileTimeCheckResult")
@@ -590,6 +590,7 @@ object FirErrors {
val USELESS_ELVIS_RIGHT_IS_NULL by warning0<KtBinaryExpression>(SourceElementPositioningStrategies.USELESS_ELVIS)
// Casts and is-checks
val CANNOT_CHECK_FOR_ERASED by error1<PsiElement, ConeKotlinType>()
val USELESS_CAST by warning0<KtBinaryExpressionWithTypeRHS>(SourceElementPositioningStrategies.AS_TYPE)
val USELESS_IS_CHECK by warning1<KtElement, Boolean>()
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.diagnostics.reportOn
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.toTypeProjections
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
@@ -47,7 +47,7 @@ object FirOuterClassArgumentsRequiredChecker : FirRegularClassChecker() {
for (index in typeArguments.size until typeParameters.size) {
val typeParameter = typeParameters[index]
if (!isValidTypeParameterFromOuterClass(typeParameter, declaration, context.session)) {
if (!isValidTypeParameterFromOuterDeclaration(typeParameter, declaration, context.session)) {
val outerClass = typeParameter.containingDeclarationSymbol as? FirRegularClassSymbol ?: break
reporter.reportOn(typeRef.source, FirErrors.OUTER_CLASS_ARGUMENTS_REQUIRED, outerClass, context)
break
@@ -26,7 +26,7 @@ object FirThrowableSubclassChecker : FirClassChecker() {
reporter.reportOn(declaration.typeParameters.firstOrNull()?.source, FirErrors.GENERIC_THROWABLE_SUBCLASS, context)
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
else -> null
}
@@ -8,11 +8,13 @@ package org.jetbrains.kotlin.fir.scopes.impl
import kotlinx.collections.immutable.PersistentMap
import kotlinx.collections.immutable.persistentMapOf
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.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.FirVariable
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.symbols.impl.FirClassifierSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
@@ -24,29 +26,30 @@ import org.jetbrains.kotlin.name.Name
class FirLocalScope private constructor(
val properties: PersistentMap<Name, FirVariableSymbol<*>>,
val functions: PersistentMultimap<Name, FirNamedFunctionSymbol>,
val classes: PersistentMap<Name, FirRegularClassSymbol>
val classes: PersistentMap<Name, FirRegularClassSymbol>,
val useSiteSession: FirSession
) : 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(
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(
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(
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 {
properties.put(BACKING_FIELD, it)
}
@@ -54,7 +57,8 @@ class FirLocalScope private constructor(
return FirLocalScope(
enhancedProperties ?: properties,
functions,
classes
classes,
session
)
}
@@ -74,7 +78,8 @@ class FirLocalScope private constructor(
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
val klass = classes[name]
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) }
withCapturedTypeParameters(status.isInner, firTypeParameters) {
withCapturedTypeParameters(status.isInner || isLocal, firTypeParameters) {
buildRegularClass {
source = classNode.toFirSourceElement()
moduleData = baseModuleData
@@ -1044,7 +1044,7 @@ open class RawFirBuilder(
isExternal = classOrObject.hasModifier(EXTERNAL_KEYWORD)
}
withCapturedTypeParameters(status.isInner, listOf()) {
withCapturedTypeParameters(status.isInner || isLocal, listOf()) {
buildRegularClass {
source = classOrObject.toFirSourceElement()
moduleData = baseModuleData
@@ -1060,7 +1060,7 @@ open class RawFirBuilder(
context.appendOuterTypeParameters(ignoreLastLevel = true, typeParameters)
context.pushFirTypeParameters(
status.isInner,
status.isInner || isLocal,
typeParameters.subList(0, classOrObject.typeParameters.size)
)
@@ -49,8 +49,8 @@ class Context<T> {
val dispatchReceiverTypesStack = mutableListOf<ConeClassLikeType>()
var containerIsExpect: Boolean = false
fun pushFirTypeParameters(notNested: Boolean, parameters: List<FirTypeParameterRef>) {
capturedTypeParameters.add(StatusFirTypeParameterSymbolList(notNested, parameters.map { it.symbol }))
fun pushFirTypeParameters(isInnerOrLocal: Boolean, parameters: List<FirTypeParameterRef>) {
capturedTypeParameters.add(StatusFirTypeParameterSymbolList(isInnerOrLocal, parameters.map { it.symbol }))
}
fun popFirTypeParameters() {
@@ -68,7 +68,7 @@ class Context<T> {
}
}
if (!element.notNested) {
if (!element.isInnerOrLocal) {
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.constructorProto
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<*>?,
substitutor: ConeSubstitutor?,
areBareTypesAllowed: Boolean,
topDeclaration: FirRegularClass?,
topContainer: FirDeclaration?,
isOperandOfIsOperator: Boolean
): ConeKotlinType {
if (symbol == null || symbol !is FirClassifierSymbol<*>) {
@@ -240,14 +240,25 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
if (!isPossibleBareType) {
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
if (index < typeArgumentsCount) {
if (typeParameterIndex < typeArgumentsCount) {
// Check if type argument matches type parameter in respective qualifier part
val qualifierPartArgumentsCount = qualifier[qualifierPartIndex].typeArgumentList.typeArguments.size
createDiagnosticsIfExists(
@@ -261,12 +272,18 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
}
if (typeParameter !is FirOuterClassTypeParameterRef ||
isValidTypeParameterFromOuterClass(typeParameter.symbol, topDeclaration, session)
isValidTypeParameterFromOuterDeclaration(typeParameter.symbol, topContainer, session)
) {
val type = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(typeParameter.symbol), isNullable = false)
val substituted = actualSubstitutor.substituteOrNull(type)
if (substituted == null) {
createDiagnosticsIfExists(parameterClass, qualifierPartIndex, symbol, typeRef)?.let { return it }
createDiagnosticsIfExists(
parameterClass,
qualifierPartIndex,
symbol,
typeRef,
qualifierPartArgumentsCount = null
)?.let { return it }
} else {
allTypeArguments.add(substituted)
}
@@ -276,15 +293,16 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
}
// Check rest type arguments
if (typeArgumentsCount > typeParameters.size) {
if (typeArgumentsCount > actualTypeParametersCount) {
for (index in qualifier.indices) {
if (qualifier[index].typeArgumentList.typeArguments.isNotEmpty()) {
val parameterClass = outerClasses.elementAtOrNull(index)
val parameterClass = outerDeclarations.elementAtOrNull(index)
createDiagnosticsIfExists(
parameterClass,
index,
symbol,
typeRef
typeRef,
qualifierPartArgumentsCount = null
)?.let { return it }
}
}
@@ -304,43 +322,43 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
}
}
private fun calculateTypeParameters(symbol: FirClassLikeSymbol<*>): List<FirTypeParameterRef> {
return if (symbol is FirTypeAliasSymbol) {
val typeAliasFir = symbol.fir
val typeAliasTypeParameters = typeAliasFir.typeParameters.toMutableList()
val fullyExpandedClass = typeAliasFir.fullyExpandedClass(session)
val newTypeParameters: MutableList<FirTypeParameterRef>
private fun collectTypeParameters(symbol: FirClassLikeSymbol<*>): List<FirTypeParameterRef> {
if (symbol is FirClassSymbol<*>) {
return symbol.fir.typeParameters
}
if (fullyExpandedClass != null) { // TODO: Should not be null, move to resolver?
val expandedTypeRef = typeAliasFir.expandedTypeRef
require(symbol is FirTypeAliasSymbol)
fun checkTypeArguments(typeArgument: ConeTypeProjection) {
when (typeArgument) {
is ConeTypeParameterType -> typeAliasTypeParameters.removeIf { it.symbol == typeArgument.lookupTag.symbol }
is ConeClassLikeType -> {
for (subTypeArgument in typeArgument.typeArguments) {
checkTypeArguments(subTypeArgument)
}
}
is ConeKotlinTypeProjection -> checkTypeArguments(typeArgument.type)
else -> {
val typeAliasFir = symbol.fir
val typeAliasTypeParameters = typeAliasFir.typeParameters.toMutableList()
val fullyExpandedClass = typeAliasFir.fullyExpandedClass(session)
val newTypeParameters = if (fullyExpandedClass != null) { // TODO: Should not be null, move to resolver?
val expandedTypeRef = typeAliasFir.expandedTypeRef
fun checkTypeArguments(typeArgument: ConeTypeProjection) {
when (typeArgument) {
is ConeTypeParameterType -> typeAliasTypeParameters.removeIf { it.symbol == typeArgument.lookupTag.symbol }
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) {
newTypeParameters.add(typeParameter)
}
newTypeParameters
checkTypeArguments(expandedTypeRef.coneType)
fullyExpandedClass.typeParameters.toMutableList()
} else {
(symbol as FirClassSymbol<*>).fir.typeParameters
mutableListOf()
}
for (typeParameter in typeAliasTypeParameters) {
newTypeParameters.add(typeParameter)
}
return newTypeParameters
}
@OptIn(SymbolInternals::class)
@@ -373,8 +391,10 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
for (index in reversedOuterClasses.indices) {
currentClassLikeDeclaration = reversedOuterClasses[index]
val typeParameters = if (currentClassLikeDeclaration is FirTypeAlias) currentClassLikeDeclaration.typeParameters else
(currentClassLikeDeclaration as? FirClass)?.typeParameters
val typeParameters = when (currentClassLikeDeclaration) {
is FirTypeAlias -> currentClassLikeDeclaration.typeParameters
else -> (currentClassLikeDeclaration as? FirClass)?.typeParameters
}
if (currentClassLikeDeclaration != null && typeParameters != null) {
for (typeParameter in typeParameters) {
val typeParameterSymbol = typeParameter.symbol
@@ -404,10 +424,10 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
qualifierPartIndex: Int,
symbol: FirClassLikeSymbol<*>,
userTypeRef: FirUserTypeRef,
qualifierPartArgumentsCount: Int? = null
qualifierPartArgumentsCount: Int?
): ConeClassErrorType? {
// 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) {
val source = getTypeArgumentsOrNameSource(userTypeRef, qualifierPartIndex)
@@ -425,6 +445,11 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
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? {
val qualifierPart = if (qualifierIndex != null) typeRef.qualifier.elementAtOrNull(qualifierIndex) else null
val typeArgumentsList = qualifierPart?.typeArgumentList
@@ -475,7 +500,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
symbol,
substitutor,
areBareTypesAllowed,
scopeClassDeclaration.containingDeclarations.lastOrNull(),
scopeClassDeclaration.topContainer ?: scopeClassDeclaration.containingDeclarations.lastOrNull(),
isOperandOfIsOperator
)
}
@@ -5,10 +5,11 @@
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
data class ScopeClassDeclaration(
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.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.PrivateForInline
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
@@ -211,8 +212,8 @@ class BodyResolveContext(
}
@PrivateForInline
fun storeFunction(function: FirSimpleFunction) {
updateLastScope { storeFunction(function) }
fun storeFunction(function: FirSimpleFunction, session: FirSession) {
updateLastScope { storeFunction(function, session) }
}
@PrivateForInline
@@ -251,8 +252,8 @@ class BodyResolveContext(
return FirMemberTypeParameterScope(this)
}
fun buildSecondaryConstructorParametersScope(constructor: FirConstructor): FirLocalScope =
constructor.valueParameters.fold(FirLocalScope()) { acc, param -> acc.storeVariable(param) }
fun buildSecondaryConstructorParametersScope(constructor: FirConstructor, session: FirSession): FirLocalScope =
constructor.valueParameters.fold(FirLocalScope(session)) { acc, param -> acc.storeVariable(param, session) }
@PrivateForInline
fun addInaccessibleImplicitReceiverValue(
@@ -272,8 +273,8 @@ class BodyResolveContext(
}
@PrivateForInline
private fun storeBackingField(property: FirProperty) {
updateLastScope { storeBackingField(property) }
private fun storeBackingField(property: FirProperty, session: FirSession) {
updateLastScope { storeBackingField(property, session) }
}
// ANALYSIS PUBLIC API
@@ -285,14 +286,14 @@ class BodyResolveContext(
towerDataContextsForClassParts.primaryConstructorAllParametersScope
@OptIn(PrivateForInline::class)
fun storeClassIfNotNested(klass: FirRegularClass) {
fun storeClassIfNotNested(klass: FirRegularClass, session: FirSession) {
if (containerIfAny is FirClass) return
updateLastScope { storeClass(klass) }
updateLastScope { storeClass(klass, session) }
}
@OptIn(PrivateForInline::class)
fun storeVariable(variable: FirVariable) {
updateLastScope { storeVariable(variable) }
fun storeVariable(variable: FirVariable, session: FirSession) {
updateLastScope { storeVariable(variable, session) }
}
@OptIn(PrivateForInline::class)
@@ -368,7 +369,7 @@ class BodyResolveContext(
forContracts: Boolean = false,
f: () -> T
): T {
storeClassIfNotNested(regularClass)
storeClassIfNotNested(regularClass, holder.session)
if (forContracts) {
return withTypeParametersOf(regularClass) {
withContainerClass(regularClass, f)
@@ -452,7 +453,7 @@ class BodyResolveContext(
val constructor = (owner as? FirRegularClass)?.declarations?.firstOrNull { it is FirConstructor } as? FirConstructor
val (primaryConstructorPureParametersScope, primaryConstructorAllParametersScope) =
if (constructor?.isPrimary == true) {
constructor.scopesWithPrimaryConstructorParameters(owner)
constructor.scopesWithPrimaryConstructorParameters(owner, holder.session)
} else {
null to null
}
@@ -473,16 +474,17 @@ class BodyResolveContext(
}
private fun FirConstructor.scopesWithPrimaryConstructorParameters(
ownerClass: FirClass
ownerClass: FirClass,
session: FirSession
): Pair<FirLocalScope, FirLocalScope> {
var parameterScope = FirLocalScope()
var allScope = FirLocalScope()
var parameterScope = FirLocalScope(session)
var allScope = FirLocalScope(session)
val properties = ownerClass.declarations.filterIsInstance<FirProperty>().associateBy { it.name }
for (parameter in valueParameters) {
allScope = allScope.storeVariable(parameter)
allScope = allScope.storeVariable(parameter, session)
val property = properties[parameter.name]
if (property?.source?.kind != KtFakeSourceElementKind.PropertyFromParameter) {
parameterScope = parameterScope.storeVariable(parameter)
parameterScope = parameterScope.storeVariable(parameter, session)
}
}
return parameterScope to allScope
@@ -491,10 +493,11 @@ class BodyResolveContext(
@OptIn(PrivateForInline::class)
inline fun <T> withSimpleFunction(
simpleFunction: FirSimpleFunction,
session: FirSession,
f: () -> T
): T {
if (containerIfAny !is FirClass) {
storeFunction(simpleFunction)
storeFunction(simpleFunction, session)
}
return withTypeParametersOf(simpleFunction) {
@@ -509,13 +512,13 @@ class BodyResolveContext(
f: () -> T
): T {
return withTowerDataCleanup {
addLocalScope(FirLocalScope())
addLocalScope(FirLocalScope(holder.session))
if (function is FirSimpleFunction) {
// 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
// if an uninitialized parameter is accessed by a preceding parameter.
for (parameter in function.valueParameters) {
storeVariable(parameter)
storeVariable(parameter, holder.session)
}
val receiverTypeRef = function.receiverTypeRef
withLabelAndReceiverType(function.name, function, receiverTypeRef?.coneType, holder, f)
@@ -528,6 +531,7 @@ class BodyResolveContext(
@OptIn(PrivateForInline::class)
fun <T> forConstructorBody(
constructor: FirConstructor,
session: FirSession,
f: () -> T
): T {
return if (constructor.isPrimary) {
@@ -542,7 +546,7 @@ class BodyResolveContext(
}
} else {
withTowerDataCleanup {
addLocalScope(buildSecondaryConstructorParametersScope(constructor))
addLocalScope(buildSecondaryConstructorParametersScope(constructor, session))
f()
}
}
@@ -562,7 +566,7 @@ class BodyResolveContext(
return f()
}
return withTowerDataCleanup {
addLocalScope(FirLocalScope())
addLocalScope(FirLocalScope(holder.session))
val receiverTypeRef = anonymousFunction.receiverTypeRef
val labelName = anonymousFunction.label?.name?.let { Name.identifier(it) }
withContainer(anonymousFunction) {
@@ -600,11 +604,12 @@ class BodyResolveContext(
@OptIn(PrivateForInline::class)
inline fun <T> withAnonymousInitializer(
anonymousInitializer: FirAnonymousInitializer,
session: FirSession,
f: () -> T
): T {
return withTowerDataCleanup {
getPrimaryConstructorPureParametersScope()?.let { addLocalScope(it) }
addLocalScope(FirLocalScope())
addLocalScope(FirLocalScope(session))
withContainer(anonymousInitializer, f)
}
}
@@ -612,10 +617,11 @@ class BodyResolveContext(
@OptIn(PrivateForInline::class)
inline fun <T> withValueParameter(
valueParameter: FirValueParameter,
session: FirSession,
f: () -> T
): T {
if (!valueParameter.name.isSpecial || valueParameter.name != UNDERSCORE_FOR_UNUSED_VAR) {
storeVariable(valueParameter)
storeVariable(valueParameter, session)
}
return withContainer(valueParameter, f)
}
@@ -641,17 +647,17 @@ class BodyResolveContext(
if (accessor is FirDefaultPropertyAccessor || accessor.body == null) {
return if (accessor.isGetter) withContainer(accessor, f)
else withTowerDataCleanup {
addLocalScope(FirLocalScope())
addLocalScope(FirLocalScope(holder.session))
withContainer(accessor, f)
}
}
return withTowerDataCleanup {
val receiverTypeRef = property.receiverTypeRef
addLocalScope(FirLocalScope())
addLocalScope(FirLocalScope(holder.session))
if (!forContracts && receiverTypeRef == null && property.returnTypeRef !is FirImplicitTypeRef &&
!property.isLocal && property.delegate == null
) {
storeBackingField(property)
storeBackingField(property, holder.session)
}
withContainer(accessor) {
withLabelAndReceiverType(property.name, property, receiverTypeRef?.coneType, holder, f)
@@ -731,8 +737,8 @@ class BodyResolveContext(
} else {
addInaccessibleImplicitReceiverValue(owningClass, holder)
withTowerDataCleanup {
addLocalScope(buildSecondaryConstructorParametersScope(constructor))
constructor.valueParameters.forEach { storeVariable(it) }
addLocalScope(buildSecondaryConstructorParametersScope(constructor, holder.session))
constructor.valueParameters.forEach { storeVariable(it, holder.session) }
f()
}
}
@@ -747,15 +753,15 @@ class BodyResolveContext(
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()
return forBlock(f)
return forBlock(session, f)
}
@OptIn(PrivateForInline::class)
inline fun <T> forBlock(f: () -> T): T {
inline fun <T> forBlock(session: FirSession, f: () -> T): T {
return withTowerDataCleanup {
addLocalScope(FirLocalScope())
addLocalScope(FirLocalScope(session))
f()
}
}
@@ -70,7 +70,8 @@ open class FirBodyResolveTransformer(
typeRef,
ScopeClassDeclaration(
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 {
// 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
doWhileLoop.also(dataFlowAnalyzer::enterDoWhileLoop)
.also {
@@ -61,7 +61,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
}
whenExpression.annotations.forEach { it.accept(this, data) }
dataFlowAnalyzer.enterWhenExpression(whenExpression)
return context.withWhenExpression(whenExpression) with@{
return context.withWhenExpression(whenExpression, session) with@{
@Suppress("NAME_SHADOWING")
var whenExpression = whenExpression.transformSubject(transformer, ResolutionMode.ContextIndependent)
@@ -164,7 +164,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
override fun transformCatch(catch: FirCatch, data: ResolutionMode): FirCatch {
dataFlowAnalyzer.enterCatchClause(catch)
catch.parameter.transformReturnTypeRef(transformer, ResolutionMode.ContextIndependent)
return context.forBlock {
return context.forBlock(session) {
catch.transformParameter(transformer, ResolutionMode.ContextIndependent)
catch.transformBlock(transformer, ResolutionMode.ContextDependent)
}.also { dataFlowAnalyzer.exitCatchClause(it) }
@@ -330,7 +330,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
variable.transformAccessors()
}
variable.transformOtherChildren(transformer, ResolutionMode.ContextIndependent)
context.storeVariable(variable)
context.storeVariable(variable, session)
dataFlowAnalyzer.exitLocalVariableDeclaration(variable, hadExplicitType)
return variable
}
@@ -540,7 +540,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
doTransformTypeParameters(simpleFunction)
val containingDeclaration = context.containerIfAny
return context.withSimpleFunction(simpleFunction) {
return context.withSimpleFunction(simpleFunction, session) {
// TODO: I think it worth creating something like runAllPhasesForLocalFunction
if (containingDeclaration != null && containingDeclaration !is FirClass) {
// For class members everything should be already prepared
@@ -635,7 +635,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
constructor.transformValueParameters(transformer, data)
}
constructor.transformDelegatedConstructor(transformer, data)
context.forConstructorBody(constructor) {
context.forConstructorBody(constructor, session) {
constructor.transformBody(transformer, data)
}
}
@@ -651,7 +651,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
): FirAnonymousInitializer {
if (implicitTypeOnly) return anonymousInitializer
dataFlowAnalyzer.enterInitBlock(anonymousInitializer)
return context.withAnonymousInitializer(anonymousInitializer) {
return context.withAnonymousInitializer(anonymousInitializer, session) {
val result =
transformDeclarationContent(anonymousInitializer, ResolutionMode.ContextIndependent) as FirAnonymousInitializer
val graph = dataFlowAnalyzer.exitInitBlock(result)
@@ -671,7 +671,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
}
dataFlowAnalyzer.enterValueParameter(valueParameter)
val result = context.withValueParameter(valueParameter) {
val result = context.withValueParameter(valueParameter, session) {
transformDeclarationContent(
valueParameter,
withExpectedType(valueParameter.returnTypeRef)
@@ -384,7 +384,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
}
override fun transformBlock(block: FirBlock, data: ResolutionMode): FirStatement {
context.forBlock {
context.forBlock(session) {
transformBlockInCurrentScope(block, data)
}
return block
@@ -22,7 +22,7 @@ fun <F : FirClassLikeDeclaration> F.runAllPhasesForLocalClass(
): F {
if (status is FirResolvedDeclarationStatus) return this
if (this is FirRegularClass) {
components.context.storeClassIfNotNested(this)
components.context.storeClassIfNotNested(this, components.session)
}
this.transformAnnotations(transformer, ResolutionMode.ContextIndependent)
val localClassesNavigationInfo = collectLocalClassesNavigationInfo()
@@ -71,7 +71,7 @@ open class FirContractResolveTransformer(
return simpleFunction
}
@Suppress("UNCHECKED_CAST")
return context.withSimpleFunction(simpleFunction) {
return context.withSimpleFunction(simpleFunction, session) {
context.forFunctionBody(simpleFunction, components) {
transformContractDescriptionOwner(simpleFunction)
}
@@ -129,7 +129,7 @@ open class FirContractResolveTransformer(
): T {
val valueParameters = owner.valueParameters
for (valueParameter in valueParameters) {
context.storeVariable(valueParameter)
context.storeVariable(valueParameter, session)
}
val contractCall = contractDescription.contractCall.transformSingle(transformer, ResolutionMode.ContextIndependent)
val resolvedId = contractCall.toResolvedCallableSymbol()?.callableId ?: return transformOwnerWithUnresolvedContract(owner)
@@ -32,31 +32,38 @@ fun FirClassLikeDeclaration.getContainingDeclaration(session: FirSession): FirCl
return null
}
fun isValidTypeParameterFromOuterClass(
fun isValidTypeParameterFromOuterDeclaration(
typeParameterSymbol: FirTypeParameterSymbol,
classDeclaration: FirRegularClass?,
declaration: FirDeclaration?,
session: FirSession
): Boolean {
if (classDeclaration == null) {
if (declaration == null) {
return true // Extra check is required because of classDeclaration will be resolved later
}
fun containsTypeParameter(currentClassDeclaration: FirRegularClass): Boolean {
if (currentClassDeclaration.typeParameters.any { it.symbol == typeParameterSymbol }) {
return true
}
for (superTypeRef in currentClassDeclaration.superTypeRefs) {
val superClassFir = superTypeRef.firClassLike(session)
if (superClassFir == null || superClassFir is FirRegularClass && containsTypeParameter(superClassFir)) {
fun containsTypeParameter(currentDeclaration: FirDeclaration?): Boolean {
if (currentDeclaration is FirTypeParameterRefsOwner) {
if (currentDeclaration.typeParameters.any { it.symbol == typeParameterSymbol }) {
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 containsTypeParameter(classDeclaration)
return containsTypeParameter(declaration)
}
fun FirTypeRef.firClassLike(session: FirSession): FirClassLikeDeclaration? {
@@ -19,14 +19,14 @@ private class Outer<E> {
private var doubleStringInt = Outer<Double>().Inner<String>().foo<Int>()()
private fun bar() {
doubleCharSequenceInt = doubleStringNumber
doubleCharSequenceInt = <!ASSIGNMENT_TYPE_MISMATCH!>doubleStringNumber<!>
doubleCharSequenceInt = doubleStringInt
doubleStringInt = Outer<Double>().Inner<String>().foo<Int>()()
doubleStringInt.e.checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Double>() }
doubleStringInt.f.checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><String>() }
doubleStringInt.g.checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Int>() }
doubleStringInt.e.checkType { _<Double>() }
doubleStringInt.f.checkType { _<String>() }
doubleStringInt.g.checkType { _<Int>() }
}
}
}
@@ -14,11 +14,11 @@ class Q {
private var y = foo<String>()()
fun bar() {
x = y
x = <!ASSIGNMENT_TYPE_MISMATCH!>y<!>
x = foo<CharSequence>()()
y = foo<String>()()
x.prop.checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><CharSequence>() }
y.prop.checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><String>() }
x.prop.checkType { _<CharSequence>() }
y.prop.checkType { _<String>() }
}
}
@@ -15,8 +15,8 @@ class Q {
private var x = foo<CharSequence, Number>()()
fun bar() {
x.e.checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><CharSequence>() }
x.f.checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Number>() }
x.e.checkType { _<CharSequence>() }
x.f.checkType { _<Number>() }
x.g.checkType { _<Number>() }
}
}
@@ -1,16 +1,16 @@
fun <E> foo(x: Any, y: Any) : Any {
class C
// without E?
if(x is C) {
if(x is <!NO_TYPE_ARGUMENTS_ON_RHS!>C<!>) {
return x
}
if (1 == 2) {
x as C
x as <!NO_TYPE_ARGUMENTS_ON_RHS!>C<!>
}
if (2 == 3) {
x as? C
x as? <!NO_TYPE_ARGUMENTS_ON_RHS, NO_TYPE_ARGUMENTS_ON_RHS!>C<!>
}
class Outer<F> {
@@ -41,10 +41,10 @@ fun test() {
var 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 = foobar<Int>()
x = <!ASSIGNMENT_TYPE_MISMATCH!>foobar<Int>()<!>
var y = noParameters()
y = noParameters()
@@ -42,11 +42,11 @@ class Outer<T> {
var 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 = foobar<Int>()
x = z.foobar<String>()
x = <!ASSIGNMENT_TYPE_MISMATCH!>foobar<Int>()<!>
x = <!ASSIGNMENT_TYPE_MISMATCH!>z.foobar<String>()<!>
var 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 {
fun test() {
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<!>>
}
@@ -18,12 +18,12 @@ class Outer<T> {
fun test5(x: <!UNRESOLVED_REFERENCE!>GenericInnerAlias<Int><!>) = x
fun <T> test6(x: <!UNRESOLVED_REFERENCE!>GenericInnerAlias<T><!>) = x
}
fun test1(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>.NestedAlias) = x
fun <T> test2(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T><!>.NestedAlias) = x
fun test1(x: Outer<Int>.NestedAlias) = x
fun <T> test2(x: Outer<T>.NestedAlias) = x
fun test3(x: Outer.NestedAlias) = x
fun test4(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>.GenericNestedAlias<Int>) = x
fun <T> test5(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T><!>.GenericNestedAlias<Int>) = x
fun <T> test6(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>.GenericNestedAlias<T>) = x
fun test4(x: Outer<Int>.GenericNestedAlias<Int>) = x
fun <T> test5(x: Outer<T>.GenericNestedAlias<Int>) = x
fun <T> test6(x: Outer<Int>.GenericNestedAlias<T>) = x
fun test7(x: Outer.GenericNestedAlias<Int>) = x
fun <T> test8(x: Outer.GenericNestedAlias<T>) = 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 ON2<T1, T2> = OuterClass<T1>.NestedType<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T2><!>
typealias ON3<T2> = OuterClass.NestedType<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T2><!>
typealias ON2<T1, T2> = OuterClass<T1>.NestedType<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) {
class 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<!>) {}
}
@@ -70,9 +70,9 @@ FILE fqName:<root> fileName:/genericLocalClassConstructorReference.kt
$receiver: VALUE_PARAMETER name:<this> type:<root>.Rec<PT of <root>.<get-p>>
BLOCK_BODY
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?]
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:pt index:1 type:PT of <root>.<get-p>
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]
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
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]
$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
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
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]
overridden:
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
$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>'
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>
<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
$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
$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>
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?]
$receiver: VALUE_PARAMETER name:<this> type:<root>.Rec<FT of <root>.fn>
BLOCK_BODY
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?]
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:pt index:1 type:FT of <root>.fn
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]
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
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]
$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
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
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]
overridden:
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
$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>'
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
<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
$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
$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
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?]
@@ -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> {
@@ -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 {
return bb.invoke(p1 = t1, p2 = t2)
}
@@ -11351,6 +11351,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
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
@TestMetadata("Projections.kt")
public void testProjections() throws Exception {