FIR: fix source of callee reference in delegated constructor call

Previously the callee reference of a delegated constructor call is
always the same as the call itself. This violates the contract that no
two FIR elements can have identical sources.  In addition, this sets the
entire call expression as the source of the callee expression.

This change instead sets the proper constructor ref as the callee.

Also fixed EXPLICIT_DELEGATION_CALL_REQUIRED type. It should be an error
instead of a warning.
This commit is contained in:
Tianyu Geng
2021-03-25 16:27:03 -07:00
committed by Dmitriy Novozhilov
parent fb14b03824
commit ae902e6fe5
16 changed files with 59 additions and 22 deletions
@@ -10,18 +10,18 @@ open class A3(x: String, y: String = "") {
constructor(x: String, b: Boolean = true) : this(x, x)
}
class B3_1 : <!AMBIGUITY{LT}!><!AMBIGUITY{PSI}!>A3<!>("")<!>
class B3_1 : <!AMBIGUITY!>A3<!>("")
class B3_2 : A3("", "asas")
class B3_3 : A3("", true)
class B3_4 : <!NONE_APPLICABLE{LT}!><!NONE_APPLICABLE{PSI}!>A3<!>("", Unit)<!>
class B3_4 : <!NONE_APPLICABLE!>A3<!>("", Unit)
open class A4(val x: Byte)
class B4 : <!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>A4<!>( 1 + 1)<!>
class B4 : <!INAPPLICABLE_CANDIDATE!>A4<!>( 1 + 1)
open class A5 {
constructor(x: Byte)
constructor(x: Short)
}
class B5_1 : <!NONE_APPLICABLE{LT}!><!NONE_APPLICABLE{PSI}!>A5<!>(1 + 1)<!>
class B5_2 : <!NONE_APPLICABLE{LT}!><!NONE_APPLICABLE{PSI}!>A5<!>(100 * 2)<!>
class B5_1 : <!NONE_APPLICABLE!>A5<!>(1 + 1)
class B5_2 : <!NONE_APPLICABLE!>A5<!>(100 * 2)
@@ -26,7 +26,7 @@ class G<E : Double>(val balue: E) : F<E>(balue) {
override var rest: E = balue
}
class H<E : String>(val balue: E) : <!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>F<E><!>(balue)<!> {
class H<E : String>(val balue: E) : <!INAPPLICABLE_CANDIDATE!>F<E><!>(balue) {
override var rest: E = balue // no report because of INAPPLICABLE_CANDIDATE
}
@@ -27,7 +27,7 @@ class G<E : Double>(val balue: E) : F<E>(balue) {
override fun rest(): E = balue
}
class H<E : String>(val balue: E) : <!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>F<E><!>(balue)<!> {
class H<E : String>(val balue: E) : <!INAPPLICABLE_CANDIDATE!>F<E><!>(balue) {
override fun rest(): E = balue // no report because of INAPPLICABLE_CANDIDATE
}
@@ -21,7 +21,7 @@ class CallBasedInExpressionGenerator(
gen(argument).let { if (isInverted) <!UNRESOLVED_REFERENCE!>Invert<!>(it) else it }
private fun gen(argument: StackValue): BranchedValue =
object : <!INAPPLICABLE_CANDIDATE{LT}!><!INAPPLICABLE_CANDIDATE{PSI}!>BranchedValue<!>(argument, null, argument.<!UNRESOLVED_REFERENCE!>type<!>, <!UNRESOLVED_REFERENCE!>Opcodes<!>.IFEQ)<!> {
object : <!INAPPLICABLE_CANDIDATE!>BranchedValue<!>(argument, null, argument.<!UNRESOLVED_REFERENCE!>type<!>, <!UNRESOLVED_REFERENCE!>Opcodes<!>.IFEQ) {
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
invokeFunction(v)
<!UNRESOLVED_REFERENCE!>coerceTo<!>(type, kotlinType, v)
@@ -1,4 +1,4 @@
class Outer { inner class Inner }
fun test() {
val x = object : <!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>Outer.Inner<!>()<!> { }
val x = object : <!UNRESOLVED_REFERENCE!>Outer.Inner<!>() { }
}
@@ -6,5 +6,5 @@ sealed class WithPrivateConstructor private constructor(val x: Int) {
private constructor() : this(42)
}
object First : <!NONE_APPLICABLE{LT}!><!NONE_APPLICABLE{PSI}!>WithPrivateConstructor<!>()<!> // error
object Second : <!NONE_APPLICABLE{LT}!><!NONE_APPLICABLE{PSI}!>WithPrivateConstructor<!>(0)<!> // error
object First : <!NONE_APPLICABLE!>WithPrivateConstructor<!>() // error
object Second : <!NONE_APPLICABLE!>WithPrivateConstructor<!>(0) // error
@@ -13,7 +13,7 @@ abstract class My<T : Some> {
abstract val z: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>test.My.T<!>
class Some : <!UNRESOLVED_REFERENCE{LT}!><!SUPERTYPE_NOT_A_CLASS_OR_INTERFACE, UNRESOLVED_REFERENCE{PSI}!>T<!>()<!>
class Some : <!SUPERTYPE_NOT_A_CLASS_OR_INTERFACE, UNRESOLVED_REFERENCE!>T<!>()
}
abstract class Your<T : Some> : <!SUPERTYPE_NOT_A_CLASS_OR_INTERFACE!>T<!>
@@ -38,7 +38,7 @@ interface E {
}
class Test2 : A.APublicI, <!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>B.BInner<!>()<!> {
class Test2 : A.APublicI, <!UNRESOLVED_REFERENCE!>B.BInner<!>() {
}
@@ -50,7 +50,7 @@ class Test4 : E, A.AProtectedI {
}
class Test5 : C.CPublicI, <!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>B.BInner<!>()<!> {
class Test5 : C.CPublicI, <!UNRESOLVED_REFERENCE!>B.BInner<!>() {
}
@@ -118,7 +118,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR by error<FirSourceElement, PsiElement>()
val DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR by warning<FirSourceElement, PsiElement>()
val PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS by error<FirSourceElement, KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME)
val EXPLICIT_DELEGATION_CALL_REQUIRED by warning<FirSourceElement, PsiElement>(PositioningStrategy.SECONDARY_CONSTRUCTOR_DELEGATION_CALL)
val EXPLICIT_DELEGATION_CALL_REQUIRED by error<FirSourceElement, PsiElement>(PositioningStrategy.SECONDARY_CONSTRUCTOR_DELEGATION_CALL)
val SEALED_CLASS_CONSTRUCTOR_CALL by error<FirSourceElement, PsiElement>()
// TODO: Consider creating a parameter list position strategy and report on the parameter list instead
@@ -115,7 +115,7 @@ object FirErrors {
val SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR by error0<FirSourceElement, PsiElement>()
val DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR by warning0<FirSourceElement, PsiElement>()
val PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS by error0<FirSourceElement, KtNamedDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
val EXPLICIT_DELEGATION_CALL_REQUIRED by warning0<FirSourceElement, PsiElement>(SourceElementPositioningStrategies.SECONDARY_CONSTRUCTOR_DELEGATION_CALL)
val EXPLICIT_DELEGATION_CALL_REQUIRED by error0<FirSourceElement, PsiElement>(SourceElementPositioningStrategies.SECONDARY_CONSTRUCTOR_DELEGATION_CALL)
val SEALED_CLASS_CONSTRUCTOR_CALL by error0<FirSourceElement, PsiElement>()
val DATA_CLASS_WITHOUT_PARAMETERS by error0<FirSourceElement, KtPrimaryConstructor>()
val DATA_CLASS_VARARG_PARAMETER by error0<FirSourceElement, KtParameter>()
@@ -37,6 +37,8 @@ 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.buildExplicitSuperReference
import org.jetbrains.kotlin.fir.references.builder.buildExplicitThisReference
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.references.impl.FirReferencePlaceholderForResolvedAnnotations
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
@@ -736,6 +738,11 @@ class DeclarationsConverter(
source = delegatedConstructorSource ?: selfTypeSource?.fakeElement(FirFakeSourceElementKind.DelegatingConstructorCall)
constructedTypeRef = classWrapper.delegatedSuperTypeRef.copyWithNewSourceKind(FirFakeSourceElementKind.ImplicitTypeRef)
isThis = false
calleeReference = buildExplicitSuperReference {
source = classWrapper.delegatedSuperTypeRef.source?.fakeElement(FirFakeSourceElementKind.DelegatingConstructorCall)
?: this@buildDelegatedConstructorCall.source?.fakeElement(FirFakeSourceElementKind.DelegatingConstructorCall)
superTypeRef = this@buildDelegatedConstructorCall.constructedTypeRef
}
extractArgumentsFrom(classWrapper.superTypeCallEntry, stubMode)
}
@@ -875,6 +882,20 @@ class DeclarationsConverter(
}
constructedTypeRef = delegatedType.copyWithNewSourceKind(FirFakeSourceElementKind.ImplicitTypeRef)
this.isThis = isThis
val calleeKind = if (isImplicit) FirFakeSourceElementKind.ImplicitConstructor else FirFakeSourceElementKind.DelegatingConstructorCall
val calleeSource = constructorDelegationCall.getChildNodeByType(CONSTRUCTOR_DELEGATION_REFERENCE)
?.toFirSourceElement(calleeKind)
?: this@buildDelegatedConstructorCall.source?.fakeElement(calleeKind)
calleeReference = if (isThis) {
buildExplicitThisReference {
this.source = calleeSource
}
} else {
buildExplicitSuperReference {
source = calleeSource
superTypeRef = this@buildDelegatedConstructorCall.constructedTypeRef
}
}
extractArgumentsFrom(firValueArguments, stubMode)
}
}
@@ -632,6 +632,11 @@ open class RawFirBuilder(
source = constructorCall ?: constructorSource.fakeElement(FirFakeSourceElementKind.DelegatingConstructorCall)
constructedTypeRef = delegatedSuperTypeRef.copyWithNewSourceKind(FirFakeSourceElementKind.ImplicitTypeRef)
isThis = false
calleeReference = buildExplicitSuperReference {
source = superTypeCallEntry?.calleeExpression?.toFirSourceElement(FirFakeSourceElementKind.DelegatingConstructorCall)
?: this@buildDelegatedConstructorCall.source?.fakeElement(FirFakeSourceElementKind.DelegatingConstructorCall)
superTypeRef = this@buildDelegatedConstructorCall.constructedTypeRef
}
if (!stubMode) {
superTypeCallEntry?.extractArgumentsTo(this)
}
@@ -1189,6 +1194,19 @@ open class RawFirBuilder(
this.source = source
constructedTypeRef = delegatedType.copyWithNewSourceKind(FirFakeSourceElementKind.ImplicitTypeRef)
this.isThis = isThis
val calleeKind = if (isImplicit)FirFakeSourceElementKind.ImplicitConstructor else FirFakeSourceElementKind.DelegatingConstructorCall
val calleeSource = this@convert.calleeExpression?.toFirSourceElement(calleeKind)
?: source.fakeElement(calleeKind)
this.calleeReference = if (isThis) {
buildExplicitThisReference {
this.source = calleeSource
}
} else {
buildExplicitSuperReference {
this.source = calleeSource
this.superTypeRef = this@buildDelegatedConstructorCall.constructedTypeRef
}
}
if (!stubMode) {
extractArgumentsTo(this)
}
@@ -35,6 +35,7 @@ class FirDelegatedConstructorCallBuilder : FirCallBuilder, FirAnnotationContaine
override var argumentList: FirArgumentList = FirEmptyArgumentList
lateinit var constructedTypeRef: FirTypeRef
var dispatchReceiver: FirExpression = FirNoReceiverExpression
lateinit var calleeReference: FirReference
var isThis: Boolean by kotlin.properties.Delegates.notNull<Boolean>()
override fun build(): FirDelegatedConstructorCall {
@@ -44,6 +45,7 @@ class FirDelegatedConstructorCallBuilder : FirCallBuilder, FirAnnotationContaine
argumentList,
constructedTypeRef,
dispatchReceiver,
calleeReference,
isThis,
)
}
@@ -27,9 +27,9 @@ internal class FirDelegatedConstructorCallImpl(
override var argumentList: FirArgumentList,
override var constructedTypeRef: FirTypeRef,
override var dispatchReceiver: FirExpression,
override var calleeReference: FirReference,
override val isThis: Boolean,
) : FirDelegatedConstructorCall() {
override var calleeReference: FirReference = if (isThis) FirExplicitThisReference(source, null) else FirExplicitSuperReference(source, null, constructedTypeRef)
override val isSuper: Boolean get() = !isThis
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
@@ -87,10 +87,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(doWhileLoop)
impl(delegatedConstructorCall) {
default(
"calleeReference",
"if (isThis) FirExplicitThisReference(source, null) else FirExplicitSuperReference(source, null, constructedTypeRef)"
)
default("isSuper") {
value = "!isThis"
withGetter = true
+1 -1
View File
@@ -26,4 +26,4 @@ package toplevelObjectDeclarations
override fun foo() : Int = 1
}
val z = y.foo()
val z = y.foo()