[FIR] Correctly build scopes for resolve of different parts of constructors

#KT-40409 Fixed
This commit is contained in:
Dmitriy Novozhilov
2020-07-17 15:24:24 +03:00
parent 94ff457e43
commit 236dfe60f1
27 changed files with 287 additions and 124 deletions
@@ -13,11 +13,11 @@ FILE: delegatedSuperType.kt
}
public final class C : R|A| {
local final field $$delegate_0: R|A|
local final field <$$delegate_0>: R|A|
public constructor(b: R|B|): R|C| {
super<R|kotlin/Any|>()
this@R|/C|.R|<local>/$$delegate_0| = R|<local>/b|
this@R|/C|.R|<local>/<$$delegate_0>| = R|<local>/b|
}
public final val b: R|B| = R|<local>/b|
@@ -0,0 +1,17 @@
// ISSUE #KT-40409
interface A {
var b: B
}
interface B
fun A.test_1() {
object : B by this.b {}
}
fun A.test_2() {
object : B by b {}
}
class D(val x: String, val y: String = this.<!UNRESOLVED_REFERENCE!>x<!>) {}
@@ -0,0 +1,45 @@
FILE: anonymousObjectByDelegate.kt
public abstract interface A : R|kotlin/Any| {
public abstract var b: R|B|
public get(): R|B|
public set(value: R|B|): R|kotlin/Unit|
}
public abstract interface B : R|kotlin/Any| {
}
public final fun R|A|.test_1(): R|kotlin/Unit| {
object : R|B| {
local final field <$$delegate_0>: R|B|
private[local] constructor(): R|<anonymous>| {
super<R|kotlin/Any|>()
this@R|/<anonymous>|.R|<local>/<$$delegate_0>| = this@R|/test_1|.R|/A.b|
}
}
}
public final fun R|A|.test_2(): R|kotlin/Unit| {
object : R|B| {
local final field <$$delegate_0>: R|B|
private[local] constructor(): R|<anonymous>| {
super<R|kotlin/Any|>()
this@R|/<anonymous>|.R|<local>/<$$delegate_0>| = this@R|/test_2|.R|/A.b|
}
}
}
public final class D : R|kotlin/Any| {
public constructor(x: R|kotlin/String|, y: R|kotlin/String| = this#.<Unresolved name: x>#): R|D| {
super<R|kotlin/Any|>()
}
public final val x: R|kotlin/String| = R|<local>/x|
public get(): R|kotlin/String|
public final val y: R|kotlin/String| = R|<local>/y|
public get(): R|kotlin/String|
}
@@ -896,6 +896,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationClassMember.kt");
}
@TestMetadata("anonymousObjectByDelegate.kt")
public void testAnonymousObjectByDelegate() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/anonymousObjectByDelegate.kt");
}
@TestMetadata("incompatibleModifiers.kt")
public void testIncompatibleModifiers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/incompatibleModifiers.kt");
@@ -896,6 +896,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationClassMember.kt");
}
@TestMetadata("anonymousObjectByDelegate.kt")
public void testAnonymousObjectByDelegate() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/anonymousObjectByDelegate.kt");
}
@TestMetadata("incompatibleModifiers.kt")
public void testIncompatibleModifiers() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/incompatibleModifiers.kt");
@@ -36,8 +36,11 @@ import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.TypeModifier
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.TypeParameterModifier
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.TypeProjectionModifier
import org.jetbrains.kotlin.fir.references.builder.buildImplicitThisReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
@@ -406,7 +409,7 @@ class DeclarationsConverter(
val selfType = classNode.toDelegatedSelfType(this)
val delegationSpecifiers = superTypeList?.let { convertDelegationSpecifiers(it) }
val delegationSpecifiers = superTypeList?.let { convertDelegationSpecifiers(it, symbol, selfType) }
var delegatedSuperTypeRef: FirTypeRef? = delegationSpecifiers?.delegatedSuperTypeRef
val delegatedConstructorSource: FirLightSourceElement? = delegationSpecifiers?.delegatedConstructorSource
delegationSpecifiers?.delegateFields?.map { declarations += it }
@@ -502,37 +505,6 @@ class DeclarationsConverter(
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitObjectLiteralExpression
*/
fun convertObjectLiteral(objectLiteral: LighterASTNode): FirElement {
var modifiers = Modifier()
var primaryConstructor: LighterASTNode? = null
val superTypeRefs = mutableListOf<FirTypeRef>()
val superTypeCallEntry = mutableListOf<FirExpression>()
var delegatedSuperTypeRef: FirTypeRef? = null
var classBody: LighterASTNode? = null
var delegatedConstructorSource: FirLightSourceElement? = null
var delegateFields: List<FirField>? = null
var primaryConstructorBody: FirBlock? = null
objectLiteral.getChildNodesByType(OBJECT_DECLARATION).first().forEachChildren {
when (it.tokenType) {
MODIFIER_LIST -> modifiers = convertModifierList(it)
PRIMARY_CONSTRUCTOR -> primaryConstructor = it
SUPER_TYPE_LIST -> convertDelegationSpecifiers(it).let {
delegatedSuperTypeRef = it.delegatedSuperTypeRef
superTypeRefs += it.superTypesRef
superTypeCallEntry += it.delegatedConstructorArguments
delegatedConstructorSource = it.delegatedConstructorSource
delegateFields = it.delegateFields
primaryConstructorBody = it.primaryConstructorBody
}
CLASS_BODY -> classBody = it
}
}
superTypeRefs.ifEmpty {
superTypeRefs += implicitAnyType
delegatedSuperTypeRef = implicitAnyType
}
val delegatedSuperType = delegatedSuperTypeRef ?: buildImplicitTypeRef()
return withChildClassName(ANONYMOUS_OBJECT_NAME) {
buildAnonymousObject {
source = objectLiteral.toFirSourceElement()
@@ -541,8 +513,41 @@ class DeclarationsConverter(
classKind = ClassKind.OBJECT
scopeProvider = baseScopeProvider
symbol = FirAnonymousObjectSymbol()
typeParameters += context.capturedTypeParameters.map { buildOuterClassTypeParameterRef { symbol = it } }
typeParameters += context.capturedTypeParameters.map { buildOuterClassTypeParameterRef { this.symbol = it } }
val delegatedSelfType = objectLiteral.toDelegatedSelfType(this)
var modifiers = Modifier()
var primaryConstructor: LighterASTNode? = null
val superTypeRefs = mutableListOf<FirTypeRef>()
val superTypeCallEntry = mutableListOf<FirExpression>()
var delegatedSuperTypeRef: FirTypeRef? = null
var classBody: LighterASTNode? = null
var delegatedConstructorSource: FirLightSourceElement? = null
var delegateFields: List<FirField>? = null
var primaryConstructorBody: FirBlock? = null
objectLiteral.getChildNodesByType(OBJECT_DECLARATION).first().forEachChildren {
when (it.tokenType) {
MODIFIER_LIST -> modifiers = convertModifierList(it)
PRIMARY_CONSTRUCTOR -> primaryConstructor = it
SUPER_TYPE_LIST -> convertDelegationSpecifiers(it, symbol, delegatedSelfType).let {
delegatedSuperTypeRef = it.delegatedSuperTypeRef
superTypeRefs += it.superTypesRef
superTypeCallEntry += it.delegatedConstructorArguments
delegatedConstructorSource = it.delegatedConstructorSource
delegateFields = it.delegateFields
primaryConstructorBody = it.primaryConstructorBody
}
CLASS_BODY -> classBody = it
}
}
superTypeRefs.ifEmpty {
superTypeRefs += implicitAnyType
delegatedSuperTypeRef = implicitAnyType
}
val delegatedSuperType = delegatedSuperTypeRef ?: buildImplicitTypeRef()
annotations += modifiers.annotations
this.superTypeRefs += superTypeRefs
typeRef = delegatedSelfType
@@ -1322,7 +1327,7 @@ class DeclarationsConverter(
val primaryConstructorBody: FirBlock?
)
private fun convertDelegationSpecifiers(delegationSpecifiers: LighterASTNode): DelegationSpecifiers {
private fun convertDelegationSpecifiers(delegationSpecifiers: LighterASTNode, containerSymbol: AbstractFirBasedSymbol<*>, delegatedTypeRef: FirTypeRef): DelegationSpecifiers {
val superTypeRefs = mutableListOf<FirTypeRef>()
val superTypeCallEntry = mutableListOf<FirExpression>()
var delegatedSuperTypeRef: FirTypeRef? = null
@@ -1340,7 +1345,7 @@ class DeclarationsConverter(
delegateConstructorSource = it.toFirSourceElement()
}
DELEGATED_SUPER_TYPE_ENTRY -> {
superTypeRefs += convertExplicitDelegation(it, delegateNumber, delegateFields, initializeDelegateStatements)
superTypeRefs += convertExplicitDelegation(it, delegateNumber, delegateFields, initializeDelegateStatements, containerSymbol, delegatedTypeRef)
delegateNumber++
}
}
@@ -1388,7 +1393,9 @@ class DeclarationsConverter(
explicitDelegation: LighterASTNode,
delegateNumber: Int,
delegateFields: MutableList<FirField>,
initializeDelegateStatements: MutableList<FirStatement>
initializeDelegateStatements: MutableList<FirStatement>,
containerSymbol: AbstractFirBasedSymbol<*>,
delegatedSelfTypeRef: FirTypeRef
): FirTypeRef {
lateinit var firTypeRef: FirTypeRef
var firExpression: FirExpression? = buildErrorExpression(
@@ -1401,14 +1408,14 @@ class DeclarationsConverter(
}
}
val delegateName = Name.identifier("\$\$delegate_$delegateNumber")
val delegateName = Name.special("<\$\$delegate_$delegateNumber>")
delegateFields.add(
buildField {
source = firExpression!!.source
session = baseSession
origin = FirDeclarationOrigin.Synthetic
name = delegateName
returnTypeRef = firTypeRef!!
returnTypeRef = firTypeRef
symbol = FirFieldSymbol(CallableId(name))
isVar = false
status = FirDeclarationStatusImpl(Visibilities.LOCAL, Modality.FINAL)
@@ -1418,10 +1425,17 @@ class DeclarationsConverter(
buildVariableAssignment {
source = firExpression!!.source
calleeReference =
buildSimpleNamedReference {
buildResolvedNamedReference {
name = delegateName
resolvedSymbol = delegateFields[delegateNumber].symbol
}
rValue = firExpression!!
dispatchReceiver = buildThisReceiverExpression {
calleeReference = buildImplicitThisReference {
boundSymbol = containerSymbol
}
typeRef = delegatedSelfTypeRef
}
}
)
return firTypeRef
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.builder.*
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
@@ -455,7 +456,8 @@ class RawFirBuilder(
delegatedSelfTypeRef: FirTypeRef?,
delegatedEnumSuperTypeRef: FirTypeRef?,
classKind: ClassKind,
containerTypeParameters: List<FirTypeParameterRef>
containerTypeParameters: List<FirTypeParameterRef>,
containerSymbol: AbstractFirBasedSymbol<*>
): FirTypeRef {
var superTypeCallEntry: KtSuperTypeCallEntry? = null
var delegatedSuperTypeRef: FirTypeRef? = null
@@ -475,7 +477,7 @@ class RawFirBuilder(
val type = superTypeListEntry.typeReference.toFirOrErrorType()
val delegateExpression = { superTypeListEntry.delegateExpression }.toFirExpression("Should have delegate")
container.superTypeRefs += type
val delegateName = Name.identifier("\$\$delegate_$delegateNumber")
val delegateName = Name.special("<\$\$delegate_$delegateNumber>")
val delegateSource = superTypeListEntry.delegateExpression?.toFirSourceElement()
val delegateField = buildField {
source = delegateSource
@@ -491,10 +493,17 @@ class RawFirBuilder(
buildVariableAssignment {
source = delegateSource
calleeReference =
buildSimpleNamedReference {
buildResolvedNamedReference {
name = delegateName
resolvedSymbol = delegateField.symbol
}
rValue = delegateExpression
dispatchReceiver = buildThisReceiverExpression {
calleeReference = buildImplicitThisReference {
boundSymbol = containerSymbol
}
delegatedSelfTypeRef?.let { typeRef = it }
}
}
)
container.declarations.add(delegateField)
@@ -747,8 +756,14 @@ class RawFirBuilder(
addCapturedTypeParameters(typeParameters.take(classOrObject.typeParameters.size))
val delegatedSelfType = classOrObject.toDelegatedSelfType(this)
val delegatedSuperType =
classOrObject.extractSuperTypeListEntriesTo(this, delegatedSelfType, null, classKind, typeParameters)
val delegatedSuperType = classOrObject.extractSuperTypeListEntriesTo(
this,
delegatedSelfType,
null,
classKind,
typeParameters,
symbol
)
val primaryConstructor = classOrObject.primaryConstructor
val firPrimaryConstructor = declarations.firstOrNull {it is FirConstructor} as? FirConstructor
@@ -827,7 +842,8 @@ class RawFirBuilder(
delegatedSelfType,
null,
ClassKind.CLASS,
containerTypeParameters = emptyList()
containerTypeParameters = emptyList(),
symbol
)
typeRef = delegatedSelfType
@@ -526,13 +526,73 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
if (constructor.isPrimary && containingClass?.classKind == ClassKind.ANNOTATION_CLASS) {
return withFirArrayOfCallTransformer {
@Suppress("UNCHECKED_CAST")
transformFunction(constructor, data) as CompositeTransformResult<FirDeclaration>
doTransformConstructor(constructor, data)
}
}
@Suppress("UNCHECKED_CAST")
return transformFunction(constructor, data) as CompositeTransformResult<FirDeclaration>
return doTransformConstructor(constructor, data)
}
private fun doTransformConstructor(constructor: FirConstructor, data: ResolutionMode): CompositeTransformResult<FirConstructor> {
return context.withContainer(constructor) {
constructor.replaceResolvePhase(transformerPhase)
dataFlowAnalyzer.enterFunction(constructor)
constructor.transformTypeParameters(transformer, data)
.transformAnnotations(transformer, data)
.transformReceiverTypeRef(transformer, data)
.transformReturnTypeRef(transformer, data)
/*
* Default values of constructor can't access members of constructing class
*/
context.withTowerDataContext(context.getTowerDataContextForConstructorResolution()) {
withNewLocalScope {
constructor.transformValueParameters(transformer, data)
}
}
val scopeWithValueParameters = if (constructor.isPrimary) {
context.getPrimaryConstructorParametersScope()
} else {
constructor.scopeWithParameters()
}
/*
* Delegated constructor call is called before constructor body, so we need to
* analyze it before body, so body can access smartcasts from that call
*/
context.withTowerDataCleanup {
addLocalScope(scopeWithValueParameters)
constructor.transformDelegatedConstructor(transformer, data)
}
if (constructor.body != null) {
if (constructor.isPrimary) {
/*
* Primary constructor may have body only if class delegates implementation to some property
* In it's body we don't have this receiver for building class, so we need to use
* special towerDataContext
*/
context.withTowerDataContext(context.getTowerDataContextForConstructorResolution()) {
addLocalScope(scopeWithValueParameters)
constructor.transformBody(transformer, data)
}
} else {
withLocalScopeCleanup {
addLocalScope(scopeWithValueParameters)
constructor.transformBody(transformer, data)
}
}
}
val graph = dataFlowAnalyzer.exitFunction(constructor)
constructor.transformControlFlowGraphReference(ControlFlowGraphReferenceTransformer, graph)
constructor.compose()
}
}
override fun transformAnonymousInitializer(
anonymousInitializer: FirAnonymousInitializer,
data: ResolutionMode
@@ -753,7 +813,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
val constructor = (owner as? FirRegularClass)?.declarations?.firstOrNull { it is FirConstructor } as? FirConstructor
val primaryConstructorParametersScope =
if (constructor?.isPrimary == true) {
constructor.valueParameters.fold(FirLocalScope()) { acc, param -> acc.storeVariable(param) }
constructor.scopeWithParameters()
} else null
components.context.replaceTowerDataContext(forMembersResolution)
@@ -770,6 +830,10 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
}
}
private fun FirConstructor.scopeWithParameters(): FirLocalScope {
return valueParameters.fold(FirLocalScope()) { acc, param -> acc.storeVariable(param) }
}
protected inline fun <T> withLabelAndReceiverType(
labelName: Name?,
owner: FirCallableDeclaration<*>,