FIR: Fix scope intersection types

Otherwise overload resolution ambiguity is reported in the test
This commit is contained in:
Denis Zharkov
2020-01-29 17:35:47 +03:00
parent d28e1f156a
commit 47ecaa5b06
24 changed files with 114 additions and 61 deletions
@@ -12,7 +12,10 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirTypeParametersOwner import org.jetbrains.kotlin.fir.declarations.FirTypeParametersOwner
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.* import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerLiteralTypeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
import org.jetbrains.kotlin.fir.scopes.impl.FirSuperTypeScope
import org.jetbrains.kotlin.fir.scopes.scope import org.jetbrains.kotlin.fir.scopes.scope
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
@@ -43,7 +46,9 @@ fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: ScopeSession)
} }
is ConeRawType -> lowerBound.scope(useSiteSession, scopeSession) is ConeRawType -> lowerBound.scope(useSiteSession, scopeSession)
is ConeFlexibleType -> lowerBound.scope(useSiteSession, scopeSession) is ConeFlexibleType -> lowerBound.scope(useSiteSession, scopeSession)
is ConeIntersectionType -> FirCompositeScope( is ConeIntersectionType -> FirSuperTypeScope.prepareSupertypeScope(
useSiteSession,
FirStandardOverrideChecker(useSiteSession),
intersectedTypes.mapNotNullTo(mutableListOf()) { intersectedTypes.mapNotNullTo(mutableListOf()) {
it.scope(useSiteSession, scopeSession) it.scope(useSiteSession, scopeSession)
} }
@@ -0,0 +1,14 @@
interface A {
fun foo()
}
abstract class B : A {
override fun foo() {}
}
interface C : A {}
fun main(c: C) {
if (c !is B) return
c.foo()
}
@@ -0,0 +1,25 @@
FILE: intersectionScope.kt
public abstract interface A : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Unit|
}
public abstract class B : R|A| {
public constructor(): R|B| {
super<R|kotlin/Any|>()
}
public open override fun foo(): R|kotlin/Unit| {
}
}
public abstract interface C : R|A| {
}
public final fun main(c: R|C|): R|kotlin/Unit| {
when () {
(R|<local>/c| !is R|B|) -> {
^main Unit
}
}
R|<local>/c|.R|/B.foo|()
}
@@ -143,6 +143,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/genericFunctions.kt"); runTest("compiler/fir/resolve/testData/resolve/genericFunctions.kt");
} }
@TestMetadata("intersectionScope.kt")
public void testIntersectionScope() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/intersectionScope.kt");
}
@TestMetadata("intersectionTypes.kt") @TestMetadata("intersectionTypes.kt")
public void testIntersectionTypes() throws Exception { public void testIntersectionTypes() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/intersectionTypes.kt"); runTest("compiler/fir/resolve/testData/resolve/intersectionTypes.kt");
@@ -143,6 +143,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/genericFunctions.kt"); runTest("compiler/fir/resolve/testData/resolve/genericFunctions.kt");
} }
@TestMetadata("intersectionScope.kt")
public void testIntersectionScope() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/intersectionScope.kt");
}
@TestMetadata("intersectionTypes.kt") @TestMetadata("intersectionTypes.kt")
public void testIntersectionTypes() throws Exception { public void testIntersectionTypes() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/intersectionTypes.kt"); runTest("compiler/fir/resolve/testData/resolve/intersectionTypes.kt");
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
public fun box() : String { public fun box() : String {
var i : Short? var i : Short?
i = 10 i = 10
+3 -3
View File
@@ -23,9 +23,9 @@ class WrongIncDec() {
fun testWrongIncDec() { fun testWrongIncDec() {
var x = WrongIncDec() var x = WrongIncDec()
x++ x++
<!AMBIGUITY!>++<!>x ++x
x-- x--
<!AMBIGUITY!>--<!>x --x
} }
class UnitIncDec() { class UnitIncDec() {
@@ -43,4 +43,4 @@ fun testUnitIncDec() {
x = x-- x = x--
x = ++x x = ++x
x = --x x = --x
} }
@@ -10,7 +10,7 @@ class C() {
fun test(a : Any?) { fun test(a : Any?) {
if (a is B) { if (a is B) {
if (a is C) { if (a is C) {
a.<!AMBIGUITY!>bar<!>(); a.bar();
} }
} }
} }
@@ -27,8 +27,8 @@ fun <T : CharSequence?> foo(x: T) {
x.length x.length
if (x is String) { if (x is String) {
x.<!AMBIGUITY!>length<!> x.length
x?.<!AMBIGUITY!>length<!> x?.length
x.bar1() x.bar1()
x.bar2() x.bar2()
@@ -31,6 +31,6 @@ import p.*
fun test(b: B<String>?) { fun test(b: B<String>?) {
if (b is C) { if (b is C) {
b?.<!AMBIGUITY!>foo<!>() b?.foo()
} }
} }
@@ -33,6 +33,6 @@ import p.*
fun test(b: B?) { fun test(b: B?) {
if (b is C && b is D) { if (b is C && b is D) {
b?.<!AMBIGUITY!>getParent<!>() b?.getParent()
} }
} }
@@ -4,31 +4,31 @@ fun intBinEq() {
x += 1.toByte() x += 1.toByte()
x += 1.toShort() x += 1.toShort()
x += 1L x += 1L
<!UNRESOLVED_REFERENCE!>x += 1f<!> x += 1f
<!UNRESOLVED_REFERENCE!>x += 1.0<!> x += 1.0
<!UNRESOLVED_REFERENCE!>x *= 'a'<!> <!UNRESOLVED_REFERENCE!>x *= 'a'<!>
<!UNRESOLVED_REFERENCE!>x *= 1.toByte()<!> x *= 1.toByte()
<!UNRESOLVED_REFERENCE!>x *= 1.toShort()<!> x *= 1.toShort()
<!UNRESOLVED_REFERENCE!>x *= 1L<!> x *= 1L
<!UNRESOLVED_REFERENCE!>x *= 1f<!> x *= 1f
<!UNRESOLVED_REFERENCE!>x *= 1.0<!> x *= 1.0
} }
fun shortBinEq() { fun shortBinEq() {
var x = 0.toShort() var x = 0.toShort()
<!UNRESOLVED_REFERENCE!>x += 'a'<!> <!UNRESOLVED_REFERENCE!>x += 'a'<!>
x += 1.toByte() x += 1.toByte()
<!UNRESOLVED_REFERENCE!>x += 1.toShort()<!> x += 1.toShort()
<!UNRESOLVED_REFERENCE!>x += 1L<!> x += 1L
<!UNRESOLVED_REFERENCE!>x += 1f<!> x += 1f
<!UNRESOLVED_REFERENCE!>x += 1.0<!> x += 1.0
<!UNRESOLVED_REFERENCE!>x *= 'a'<!> <!UNRESOLVED_REFERENCE!>x *= 'a'<!>
<!UNRESOLVED_REFERENCE!>x *= 1.toByte()<!> x *= 1.toByte()
<!UNRESOLVED_REFERENCE!>x *= 1.toShort()<!> x *= 1.toShort()
<!UNRESOLVED_REFERENCE!>x *= 1L<!> x *= 1L
<!UNRESOLVED_REFERENCE!>x *= 1f<!> x *= 1f
<!UNRESOLVED_REFERENCE!>x *= 1.0<!> x *= 1.0
} }
class A { class A {
@@ -37,7 +37,7 @@ fun main(
a.foo(it) a.foo(it)
// Iterators // Iterators
a.<!AMBIGUITY!>foo<!>(ml.<!AMBIGUITY!>iterator<!>()) a.foo(ml.iterator())
a.foo(l.iterator()) a.foo(l.iterator())
// Sets // Sets
@@ -15,7 +15,7 @@ interface IFoo {
fun test() { fun test() {
val foo : Foo = Foo2() val foo : Foo = Foo2()
foo as IFoo foo as IFoo
foo.<!AMBIGUITY!>bar<!>() // Should be resolved to Foo#bar foo.bar() // Should be resolved to Foo#bar
} }
interface IFoo2 { interface IFoo2 {
@@ -24,5 +24,5 @@ interface IFoo2 {
fun test2(foo: Foo) { fun test2(foo: Foo) {
foo as IFoo2 foo as IFoo2
foo.<!AMBIGUITY!>bar<!>() // should be ambiguity foo.bar() // should be ambiguity
} }
@@ -12,7 +12,7 @@ class C() {
fun test(a : Any?) { fun test(a : Any?) {
if (a is B) { if (a is B) {
if (a is C) { if (a is C) {
a.<!AMBIGUITY!>bar<!>(); a.bar();
} }
} }
} }
@@ -8,6 +8,6 @@ interface B {
fun test(c: Any) { fun test(c: Any) {
if (c is B && c is A) { if (c is B && c is A) {
c.<!AMBIGUITY!>foo<!><String, Int>() c.foo<String, Int>()
} }
} }
@@ -10,6 +10,6 @@ interface B {
fun test(c: Any) { fun test(c: Any) {
if (c is B && c is A) { if (c is B && c is A) {
c.<!AMBIGUITY!>foo<!>() c.foo()
} }
} }
@@ -17,37 +17,37 @@ interface C {
fun foo(x: Any?) { fun foo(x: Any?) {
if (x is A && x is B) { if (x is A && x is B) {
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() } x.foo().checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String?>() } x.foo().checkType { _<String?>() }
} }
if (x is B && x is A) { if (x is B && x is A) {
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() } x.foo().checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String?>() } x.foo().checkType { _<String?>() }
} }
if (x is A && x is C) { if (x is A && x is C) {
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() } x.foo().checkType { _<String>() }
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String?>() } x.foo().checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String?>() }
} }
if (x is C && x is A) { if (x is C && x is A) {
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() } x.foo().checkType { _<String>() }
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String?>() } x.foo().checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String?>() }
} }
if (x is A && x is B && x is C) { if (x is A && x is B && x is C) {
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() } x.foo().checkType { _<String>() }
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String?>() } x.foo().checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String?>() }
} }
if (x is B && x is A && x is C) { if (x is B && x is A && x is C) {
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() } x.foo().checkType { _<String>() }
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String?>() } x.foo().checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String?>() }
} }
if (x is B && x is C && x is A) { if (x is B && x is C && x is A) {
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() } x.foo().checkType { _<String>() }
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String?>() } x.foo().checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String?>() }
} }
} }
@@ -14,6 +14,6 @@ interface B : Common {
fun test(c: Common) { fun test(c: Common) {
if (c is B && c is A) { if (c is B && c is A) {
c.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() } c.foo().checkType { _<String>() }
} }
} }
@@ -10,6 +10,6 @@ interface B {
fun test(c: Any) { fun test(c: Any) {
if (c is B && c is A) { if (c is B && c is A) {
c.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() } c.foo().checkType { _<String>() }
} }
} }
@@ -13,9 +13,9 @@ interface B: A {
fun test(a: A) { fun test(a: A) {
if (a is B && a is C) { if (a is B && a is C) {
a.<!AMBIGUITY!>foo<!> = "" a.foo = ""
a.<!AMBIGUITY!>foo<!> = null a.foo = null
a.<!AMBIGUITY!>foo<!>.<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() } a.foo.checkType { _<String>() }
} }
} }
@@ -13,8 +13,8 @@ interface B: A {
fun test(a: A) { fun test(a: A) {
if (a is B && a is C) { if (a is B && a is C) {
a.<!AMBIGUITY!>foo<!> = "" a.foo = ""
a.<!AMBIGUITY!>foo<!> = null a.foo = null
a.<!AMBIGUITY!>foo<!> a.foo
} }
} }
@@ -28,11 +28,11 @@ fun test() {
x.foo().checkType { _<CharSequence?>() } x.foo().checkType { _<CharSequence?>() }
if (x is B && x is C) { if (x is B && x is C) {
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><CharSequence?>() } x.foo().checkType { <!INAPPLICABLE_CANDIDATE!>_<!><CharSequence?>() }
x.baz("") x.baz("")
x.<!AMBIGUITY!>baz<!>(1).<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Unit>() } x.baz(1).checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Unit>() }
x.<!AMBIGUITY!>baz<!>(1, 2) x.baz(1, 2)
x.<!AMBIGUITY!>foobar<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() } x.foobar().checkType { _<String>() }
} }
} }
@@ -10,6 +10,6 @@ interface B {
fun test(c: Any) { fun test(c: Any) {
if (c is B && c is A) { if (c is B && c is A) {
c.<!AMBIGUITY!>foo<!><String, Int>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Int>() } c.foo<String, Int>().checkType { _<Int>() }
} }
} }