Refine implicit receiver type resolution and enhance related tests.
This commit is contained in:
parent
3b290116b8
commit
79bece94a5
@ -599,6 +599,16 @@ class Compiler(
|
||||
return null
|
||||
}
|
||||
|
||||
private fun implicitReceiverTypeForMember(name: String): String? {
|
||||
for (ctx in codeContexts.asReversed()) {
|
||||
val fn = ctx as? CodeContext.Function ?: continue
|
||||
if (!fn.implicitThisMembers) continue
|
||||
val typeName = fn.implicitThisTypeName ?: continue
|
||||
if (hasImplicitThisMember(name, typeName)) return typeName
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun currentEnclosingClassName(): String? {
|
||||
val ctx = codeContexts.asReversed().firstOrNull { it is CodeContext.ClassBody } as? CodeContext.ClassBody
|
||||
return ctx?.name
|
||||
@ -836,14 +846,12 @@ class Compiler(
|
||||
if (hasImplicitThisMember(name, implicitType)) {
|
||||
resolutionSink?.referenceMember(name, pos, implicitType)
|
||||
val ids = resolveImplicitThisMemberIds(name, pos, implicitType)
|
||||
return ImplicitThisMemberRef(name, pos, ids.fieldId, ids.methodId, implicitType)
|
||||
val preferredType = if (currentImplicitThisTypeName() == null) null else implicitType
|
||||
return ImplicitThisMemberRef(name, pos, ids.fieldId, ids.methodId, preferredType)
|
||||
}
|
||||
}
|
||||
val implicitThisMembers = codeContexts.any { ctx ->
|
||||
(ctx as? CodeContext.Function)?.implicitThisMembers == true
|
||||
}
|
||||
val implicitType = if (implicitThisMembers) currentImplicitThisTypeName() else null
|
||||
if (implicitType != null && hasImplicitThisMember(name, implicitType)) {
|
||||
val implicitType = implicitReceiverTypeForMember(name)
|
||||
if (implicitType != null) {
|
||||
resolutionSink?.referenceMember(name, pos, implicitType)
|
||||
val ids = resolveImplicitThisMemberIds(name, pos, implicitType)
|
||||
return ImplicitThisMemberRef(name, pos, ids.fieldId, ids.methodId, implicitType)
|
||||
@ -4456,7 +4464,7 @@ class Compiler(
|
||||
detectedBlockArgument,
|
||||
isOptional,
|
||||
left.atPos,
|
||||
implicitThisTypeName
|
||||
left.preferredThisTypeName() ?: implicitThisTypeName
|
||||
)
|
||||
}
|
||||
is LocalVarRef -> {
|
||||
@ -4465,7 +4473,8 @@ class Compiler(
|
||||
(ctx as? CodeContext.Function)?.implicitThisMembers == true
|
||||
}
|
||||
if ((classContext || implicitThis) && extensionNames.contains(left.name)) {
|
||||
val ids = resolveImplicitThisMemberIds(left.name, left.pos(), implicitThisTypeName)
|
||||
val receiverTypeName = implicitReceiverTypeForMember(left.name) ?: implicitThisTypeName
|
||||
val ids = resolveImplicitThisMemberIds(left.name, left.pos(), receiverTypeName)
|
||||
ImplicitThisMethodCallRef(
|
||||
left.name,
|
||||
ids.methodId,
|
||||
@ -4473,7 +4482,7 @@ class Compiler(
|
||||
detectedBlockArgument,
|
||||
isOptional,
|
||||
left.pos(),
|
||||
implicitThisTypeName
|
||||
receiverTypeName
|
||||
)
|
||||
} else {
|
||||
checkGenericBoundsAtCall(left.name, args, left.pos())
|
||||
@ -4486,7 +4495,8 @@ class Compiler(
|
||||
(ctx as? CodeContext.Function)?.implicitThisMembers == true
|
||||
}
|
||||
if ((classContext || implicitThis) && extensionNames.contains(left.name)) {
|
||||
val ids = resolveImplicitThisMemberIds(left.name, left.pos(), implicitThisTypeName)
|
||||
val receiverTypeName = implicitReceiverTypeForMember(left.name) ?: implicitThisTypeName
|
||||
val ids = resolveImplicitThisMemberIds(left.name, left.pos(), receiverTypeName)
|
||||
ImplicitThisMethodCallRef(
|
||||
left.name,
|
||||
ids.methodId,
|
||||
@ -4494,7 +4504,7 @@ class Compiler(
|
||||
detectedBlockArgument,
|
||||
isOptional,
|
||||
left.pos(),
|
||||
implicitThisTypeName
|
||||
receiverTypeName
|
||||
)
|
||||
} else {
|
||||
checkGenericBoundsAtCall(left.name, args, left.pos())
|
||||
|
||||
@ -266,7 +266,7 @@ class TypesTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun multipleReceivers() = runTest {
|
||||
fun testMultipleReceivers() = runTest {
|
||||
eval("""
|
||||
class R1(shared,r1="r1")
|
||||
class R2(shared,r2="r2")
|
||||
@ -278,10 +278,20 @@ class TypesTest {
|
||||
assertEquals("r2", r2)
|
||||
assertEquals("t", shared)
|
||||
assertEquals("s", this@R1.shared)
|
||||
// actually we have now this of union type R1 & R2!
|
||||
// println(this::class)
|
||||
assert( this@R2 is R2 )
|
||||
// assert( this@R1 is R1 )
|
||||
assertEquals("r1", this@R1.r1)
|
||||
assertEquals("r2", this@R2.r2)
|
||||
assertEquals("r1", r1)
|
||||
}
|
||||
}
|
||||
with(R1("s")) {
|
||||
assertEquals("r1", r1)
|
||||
assertEquals("s", shared)
|
||||
with(R2("t")) {
|
||||
assertEquals("r2", r2)
|
||||
assertEquals("t", shared)
|
||||
assertEquals("s", this@R1.shared)
|
||||
assertEquals("r1", this@R1.r1)
|
||||
assertEquals("r1", r1)
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user