K2 resolve: prefer derived class property to base class field
#KT-50082 Fixed
This commit is contained in:
committed by
teamcity
parent
642bbd38ba
commit
59bafedd8a
+34
@@ -3407,6 +3407,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/emptySelectorInQualifiedExpression.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/problems/emptySelectorInQualifiedExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("enumEntryFieldShadow.kt")
|
||||||
|
public void testEnumEntryFieldShadow() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/problems/enumEntryFieldShadow.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("expectConstructor.kt")
|
@TestMetadata("expectConstructor.kt")
|
||||||
public void testExpectConstructor() throws Exception {
|
public void testExpectConstructor() throws Exception {
|
||||||
@@ -3568,6 +3574,34 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/propertyVsField")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class PropertyVsField {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInPropertyVsField() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/propertyVsField"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("fieldPropertyShadow.kt")
|
||||||
|
public void testFieldPropertyShadow() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/propertyVsField/fieldPropertyShadow.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("propertyAndTwoFields.kt")
|
||||||
|
public void testPropertyAndTwoFields() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/propertyVsField/propertyAndTwoFields.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("propertyFieldShadow.kt")
|
||||||
|
public void testPropertyFieldShadow() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/propertyVsField/propertyFieldShadow.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/references")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/references")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+33
@@ -3005,6 +3005,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/emptySelectorInQualifiedExpression.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/problems/emptySelectorInQualifiedExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("enumEntryFieldShadow.kt")
|
||||||
|
public void testEnumEntryFieldShadow() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/problems/enumEntryFieldShadow.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("expectConstructor.kt")
|
@TestMetadata("expectConstructor.kt")
|
||||||
public void testExpectConstructor() throws Exception {
|
public void testExpectConstructor() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/expectConstructor.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/problems/expectConstructor.kt");
|
||||||
@@ -3144,6 +3149,34 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/propertyVsField")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class PropertyVsField extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInPropertyVsField() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/propertyVsField"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("fieldPropertyShadow.kt")
|
||||||
|
public void testFieldPropertyShadow() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/propertyVsField/fieldPropertyShadow.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyAndTwoFields.kt")
|
||||||
|
public void testPropertyAndTwoFields() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/propertyVsField/propertyAndTwoFields.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyFieldShadow.kt")
|
||||||
|
public void testPropertyFieldShadow() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/propertyVsField/propertyFieldShadow.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/references")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/references")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
FILE: DerivedEnum.kt
|
||||||
|
public final enum class DerivedEnum : R|BaseJava|, R|kotlin/Enum<DerivedEnum>| {
|
||||||
|
private constructor(): R|DerivedEnum| {
|
||||||
|
super<R|kotlin/Enum<DerivedEnum>|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static enum entry x: R|DerivedEnum|
|
||||||
|
public final fun foo(): R|kotlin/Unit| {
|
||||||
|
R|/bar|(R|/DerivedEnum.x|)
|
||||||
|
R|/baz|(<Unresolved name: y>#)
|
||||||
|
R|/baz|(Q|BaseJava|.R|/BaseJava.y|)
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static fun values(): R|kotlin/Array<DerivedEnum>| {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static fun valueOf(value: R|kotlin/String|): R|DerivedEnum| {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static val entries: R|kotlin/enums/EnumEntries<DerivedEnum>|
|
||||||
|
public get(): R|kotlin/enums/EnumEntries<DerivedEnum>|
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun bar(e: R|DerivedEnum|): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
|
public final fun baz(s: R|kotlin/String|): R|kotlin/Unit| {
|
||||||
|
Q|DerivedEnum|.R|/DerivedEnum.x|
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
// FILE: BaseJava.java
|
||||||
|
|
||||||
|
public interface BaseJava {
|
||||||
|
String x = "";
|
||||||
|
String y = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: DerivedEnum.kt
|
||||||
|
|
||||||
|
enum class DerivedEnum : BaseJava {
|
||||||
|
x;
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
bar(x)
|
||||||
|
baz(<!UNRESOLVED_REFERENCE!>y<!>)
|
||||||
|
baz(BaseJava.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bar(e: DerivedEnum) {}
|
||||||
|
|
||||||
|
fun baz(s: String) {
|
||||||
|
DerivedEnum.x
|
||||||
|
}
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
FILE: KotlinBase.kt
|
||||||
|
public open class KotlinBase : R|kotlin/Any| {
|
||||||
|
public constructor(): R|KotlinBase| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final val abcd: R|kotlin/String| = String(abcd)
|
||||||
|
public get(): R|kotlin/String|
|
||||||
|
|
||||||
|
}
|
||||||
|
FILE: KotlinProxy.kt
|
||||||
|
public abstract interface KotlinProxy : R|kotlin/Any| {
|
||||||
|
public open val zyxw: R|kotlin/String|
|
||||||
|
public get(): R|kotlin/String| {
|
||||||
|
^ String(zyxw)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
FILE: test.kt
|
||||||
|
public final class Derived : R|Test|, R|KotlinProxy| {
|
||||||
|
public constructor(): R|Derived| {
|
||||||
|
super<R|Test|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final fun test(): R|kotlin/Unit| {
|
||||||
|
this@R|/Derived|.R|/Test.abcd|
|
||||||
|
this@R|/Derived|.R|/Test.zyxw|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
// FILE: Test.java
|
||||||
|
|
||||||
|
public class Test extends KotlinBase {
|
||||||
|
public final String abcd = "ABCD";
|
||||||
|
|
||||||
|
public final String zyxw = "ZYXW";
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: KotlinBase.kt
|
||||||
|
|
||||||
|
open class KotlinBase {
|
||||||
|
val abcd = "abcd"
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: KotlinProxy.kt
|
||||||
|
|
||||||
|
interface KotlinProxy {
|
||||||
|
val zyxw get() = "zyxw"
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
class Derived : Test(), KotlinProxy {
|
||||||
|
fun test() {
|
||||||
|
abcd // field!
|
||||||
|
zyxw // field!
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
FILE: KotlinBase.kt
|
||||||
|
public open class KotlinBase : R|kotlin/Any| {
|
||||||
|
public constructor(): R|KotlinBase| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final val abcd: R|kotlin/String| = String(abcd)
|
||||||
|
public get(): R|kotlin/String|
|
||||||
|
|
||||||
|
}
|
||||||
|
FILE: test.kt
|
||||||
|
public final fun test(d: R|JavaDerived|): R|kotlin/Unit| {
|
||||||
|
R|<local>/d|.R|/JavaDerived.abcd|
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
// FILE: Test.java
|
||||||
|
|
||||||
|
public class Test extends KotlinBase {
|
||||||
|
public final String abcd = "ABCD";
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: KotlinBase.kt
|
||||||
|
|
||||||
|
open class KotlinBase {
|
||||||
|
val abcd = "abcd"
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: JavaDerived.java
|
||||||
|
|
||||||
|
public class JavaDerived extends Test {
|
||||||
|
public final String abcd = "AaBbCcDd"
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
fun test(d: JavaDerived) {
|
||||||
|
d.abcd // JavaDerived
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
FILE: test.kt
|
||||||
|
public final class Test2 : R|Test| {
|
||||||
|
public constructor(): R|Test2| {
|
||||||
|
super<R|Test|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
private final val text: R|kotlin/String| = String(BCDE)
|
||||||
|
private get(): R|kotlin/String|
|
||||||
|
|
||||||
|
private final val publicPrivateText: R|kotlin/String| = String(YXWV)
|
||||||
|
private get(): R|kotlin/String|
|
||||||
|
|
||||||
|
public final fun check(): R|kotlin/String| {
|
||||||
|
^check this@R|/Test2|.R|/Test2.text|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun check(): R|kotlin/String!| {
|
||||||
|
^check R|/Test2.Test2|().R|/Test.publicPrivateText|
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
// FILE: Test.java
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
protected final String text = "ABCD";
|
||||||
|
|
||||||
|
public final String publicPrivateText = "ZYXW";
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
class Test2 : Test() {
|
||||||
|
private val text = "BCDE"
|
||||||
|
|
||||||
|
private val publicPrivateText = "YXWV"
|
||||||
|
|
||||||
|
fun check() = text // Should be resolved to Test2.text, not to Test.text
|
||||||
|
}
|
||||||
|
|
||||||
|
fun check() = Test2().publicPrivateText // Should be resolved to Test.publicPrivateText (Test2 member is private)
|
||||||
|
|
||||||
+34
@@ -3407,6 +3407,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/emptySelectorInQualifiedExpression.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/problems/emptySelectorInQualifiedExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("enumEntryFieldShadow.kt")
|
||||||
|
public void testEnumEntryFieldShadow() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/problems/enumEntryFieldShadow.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("expectConstructor.kt")
|
@TestMetadata("expectConstructor.kt")
|
||||||
public void testExpectConstructor() throws Exception {
|
public void testExpectConstructor() throws Exception {
|
||||||
@@ -3568,6 +3574,34 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/propertyVsField")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class PropertyVsField {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInPropertyVsField() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/propertyVsField"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("fieldPropertyShadow.kt")
|
||||||
|
public void testFieldPropertyShadow() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/propertyVsField/fieldPropertyShadow.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("propertyAndTwoFields.kt")
|
||||||
|
public void testPropertyAndTwoFields() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/propertyVsField/propertyAndTwoFields.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("propertyFieldShadow.kt")
|
||||||
|
public void testPropertyFieldShadow() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/propertyVsField/propertyFieldShadow.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/references")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/references")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+34
@@ -3407,6 +3407,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/emptySelectorInQualifiedExpression.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/problems/emptySelectorInQualifiedExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("enumEntryFieldShadow.kt")
|
||||||
|
public void testEnumEntryFieldShadow() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/problems/enumEntryFieldShadow.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("expectConstructor.kt")
|
@TestMetadata("expectConstructor.kt")
|
||||||
public void testExpectConstructor() throws Exception {
|
public void testExpectConstructor() throws Exception {
|
||||||
@@ -3568,6 +3574,34 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/propertyVsField")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class PropertyVsField {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInPropertyVsField() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/propertyVsField"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("fieldPropertyShadow.kt")
|
||||||
|
public void testFieldPropertyShadow() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/propertyVsField/fieldPropertyShadow.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("propertyAndTwoFields.kt")
|
||||||
|
public void testPropertyAndTwoFields() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/propertyVsField/propertyAndTwoFields.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("propertyFieldShadow.kt")
|
||||||
|
public void testPropertyFieldShadow() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/propertyVsField/propertyFieldShadow.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/references")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/references")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+53
-14
@@ -10,11 +10,12 @@ import org.jetbrains.kotlin.fir.containingClassLookupTag
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirField
|
import org.jetbrains.kotlin.fir.declarations.FirField
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.AbstractConeCallConflictResolver
|
import org.jetbrains.kotlin.fir.resolve.calls.AbstractConeCallConflictResolver
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
||||||
import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents
|
import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||||
|
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||||
|
|
||||||
class JvmPlatformOverloadsConflictResolver(
|
class JvmPlatformOverloadsConflictResolver(
|
||||||
@@ -31,21 +32,59 @@ class JvmPlatformOverloadsConflictResolver(
|
|||||||
return candidates
|
return candidates
|
||||||
}
|
}
|
||||||
val result = mutableSetOf<Candidate>()
|
val result = mutableSetOf<Candidate>()
|
||||||
outerLoop@ for (myCandidate in candidates) {
|
for (myCandidate in candidates) {
|
||||||
val me = myCandidate.symbol.fir
|
when (val me = myCandidate.symbol.fir) {
|
||||||
if (me is FirProperty && me.symbol.containingClassLookupTag() != null) {
|
is FirProperty -> if (!me.isShadowedByFieldCandidate(candidates)) {
|
||||||
for (otherCandidate in candidates) {
|
result += myCandidate
|
||||||
val other = otherCandidate.symbol.fir
|
|
||||||
if (other is FirField && other.symbol.containingClassLookupTag() != null) {
|
|
||||||
// NB: FE 1.0 does class equivalence check here
|
|
||||||
// However, in FIR container classes aren't the same for our samples (see fieldPropertyOverloads.kt)
|
|
||||||
// E.g. we can have SomeConcreteJavaEnum for field and kotlin.Enum for static property 'name'
|
|
||||||
continue@outerLoop
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
is FirField -> if (!me.isShadowedByPropertyCandidate(candidates)) {
|
||||||
|
result += myCandidate
|
||||||
|
}
|
||||||
|
else -> result += myCandidate
|
||||||
}
|
}
|
||||||
result += myCandidate
|
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirProperty.isShadowedByFieldCandidate(candidates: Set<Candidate>): Boolean {
|
||||||
|
val propertyContainingClassLookupTag = unwrapFakeOverrides().symbol.containingClassLookupTag() ?: return false
|
||||||
|
for (otherCandidate in candidates) {
|
||||||
|
val field = otherCandidate.symbol.fir as? FirField ?: continue
|
||||||
|
val fieldContainingClassLookupTag = field.unwrapFakeOverrides().symbol.containingClassLookupTag()
|
||||||
|
if (fieldContainingClassLookupTag != null &&
|
||||||
|
!propertyContainingClassLookupTag.strictlyDerivedFrom(fieldContainingClassLookupTag)
|
||||||
|
) {
|
||||||
|
// NB: FE 1.0 does class equivalence check here ^^^
|
||||||
|
// However, in FIR container classes aren't the same for our samples (see fieldPropertyOverloads.kt)
|
||||||
|
// E.g. we can have SomeConcreteJavaEnum for field and kotlin.Enum for static property 'name'
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirField.isShadowedByPropertyCandidate(candidates: Set<Candidate>): Boolean {
|
||||||
|
val fieldContainingClassLookupTag = unwrapFakeOverrides().symbol.containingClassLookupTag() ?: return false
|
||||||
|
for (otherCandidate in candidates) {
|
||||||
|
val property = otherCandidate.symbol.fir as? FirProperty ?: continue
|
||||||
|
val propertyContainingClassLookupTag = property.unwrapFakeOverrides().symbol.containingClassLookupTag()
|
||||||
|
if (propertyContainingClassLookupTag != null &&
|
||||||
|
propertyContainingClassLookupTag.strictlyDerivedFrom(fieldContainingClassLookupTag)
|
||||||
|
) {
|
||||||
|
// NB: FE 1.0 does class equivalence check here ^^^
|
||||||
|
// However, in FIR container classes aren't the same for our samples (see fieldPropertyOverloads.kt)
|
||||||
|
// E.g. we can have SomeConcreteJavaEnum for field and kotlin.Enum for static property 'name'
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ConeClassLikeLookupTag.strictlyDerivedFrom(other: ConeClassLikeLookupTag): Boolean {
|
||||||
|
if (this == other) return false
|
||||||
|
val session = inferenceComponents.session
|
||||||
|
val thisClass = this.toFirRegularClassSymbol(session)?.fir ?: return false
|
||||||
|
|
||||||
|
return thisClass.isSubclassOf(other, session, isStrict = true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
|||||||
if (isStatic && containingClass != null) {
|
if (isStatic && containingClass != null) {
|
||||||
containingUseSiteDeclarations.firstNotNullOfOrNull {
|
containingUseSiteDeclarations.firstNotNullOfOrNull {
|
||||||
if (it !is FirClass) return@firstNotNullOfOrNull null
|
if (it !is FirClass) return@firstNotNullOfOrNull null
|
||||||
it.takeIf { it.isSubClass(containingLookupTag, session, supertypeSupplier) }
|
it.takeIf { it.isSubclassOf(containingLookupTag, session, isStrict = false, supertypeSupplier) }
|
||||||
}?.let { return it }
|
}?.let { return it }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,10 +380,6 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'local' isn't taken into account here
|
|
||||||
private fun ClassId.isSame(other: ClassId): Boolean =
|
|
||||||
packageFqName == other.packageFqName && relativeClassName == other.relativeClassName
|
|
||||||
|
|
||||||
private fun ConeClassLikeLookupTag.ownerIfCompanion(session: FirSession): ConeClassLikeLookupTag? {
|
private fun ConeClassLikeLookupTag.ownerIfCompanion(session: FirSession): ConeClassLikeLookupTag? {
|
||||||
if (classId.isLocal) return null
|
if (classId.isLocal) return null
|
||||||
val outerClassId = classId.outerClassId ?: return null
|
val outerClassId = classId.outerClassId ?: return null
|
||||||
@@ -405,11 +401,11 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
|||||||
supertypeSupplier: SupertypeSupplier
|
supertypeSupplier: SupertypeSupplier
|
||||||
): Boolean {
|
): Boolean {
|
||||||
dispatchReceiver?.ownerIfCompanion(session)?.let { companionOwnerLookupTag ->
|
dispatchReceiver?.ownerIfCompanion(session)?.let { companionOwnerLookupTag ->
|
||||||
if (containingUseSiteClass.isSubClass(companionOwnerLookupTag, session, supertypeSupplier)) return true
|
if (containingUseSiteClass.isSubclassOf(companionOwnerLookupTag, session, isStrict = false, supertypeSupplier)) return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
!containingUseSiteClass.isSubClass(ownerLookupTag, session, supertypeSupplier) -> false
|
!containingUseSiteClass.isSubclassOf(ownerLookupTag, session, isStrict = false, supertypeSupplier) -> false
|
||||||
isVariableOrNamedFunction -> doesReceiverFitForProtectedVisibility(
|
isVariableOrNamedFunction -> doesReceiverFitForProtectedVisibility(
|
||||||
dispatchReceiver,
|
dispatchReceiver,
|
||||||
containingUseSiteClass,
|
containingUseSiteClass,
|
||||||
@@ -460,26 +456,6 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirClass.isSubClass(
|
|
||||||
ownerLookupTag: ConeClassLikeLookupTag,
|
|
||||||
session: FirSession,
|
|
||||||
supertypeSupplier: SupertypeSupplier
|
|
||||||
): Boolean {
|
|
||||||
if (classId.isSame(ownerLookupTag.classId)) return true
|
|
||||||
|
|
||||||
return lookupSuperTypes(
|
|
||||||
this,
|
|
||||||
lookupInterfaces = true,
|
|
||||||
deep = true,
|
|
||||||
session,
|
|
||||||
substituteTypes = false,
|
|
||||||
supertypeSupplier
|
|
||||||
).any { superType ->
|
|
||||||
// Note: We check just classId here, so type substitution isn't needed ^ (we aren't interested in type arguments)
|
|
||||||
(superType as? ConeClassLikeType)?.fullyExpandedType(session)?.lookupTag?.classId?.isSame(ownerLookupTag.classId) == true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ReceiverValue?.ownerIfCompanion(session: FirSession): ConeClassLikeLookupTag? =
|
private fun ReceiverValue?.ownerIfCompanion(session: FirSession): ConeClassLikeLookupTag? =
|
||||||
(this?.type as? ConeClassLikeType)?.lookupTag?.ownerIfCompanion(session)
|
(this?.type as? ConeClassLikeType)?.lookupTag?.ownerIfCompanion(session)
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.classId
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
|
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
||||||
@@ -21,6 +22,7 @@ import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
|||||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.types.model.CaptureStatus
|
import org.jetbrains.kotlin.types.model.CaptureStatus
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
import org.jetbrains.kotlin.utils.SmartSet
|
import org.jetbrains.kotlin.utils.SmartSet
|
||||||
@@ -90,6 +92,33 @@ fun lookupSuperTypes(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun FirClass.isSubclassOf(
|
||||||
|
ownerLookupTag: ConeClassLikeLookupTag,
|
||||||
|
session: FirSession,
|
||||||
|
isStrict: Boolean,
|
||||||
|
supertypeSupplier: SupertypeSupplier = SupertypeSupplier.Default
|
||||||
|
): Boolean {
|
||||||
|
if (classId.isSame(ownerLookupTag.classId)) {
|
||||||
|
return !isStrict
|
||||||
|
}
|
||||||
|
|
||||||
|
return lookupSuperTypes(
|
||||||
|
this,
|
||||||
|
lookupInterfaces = true,
|
||||||
|
deep = true,
|
||||||
|
session,
|
||||||
|
substituteTypes = false,
|
||||||
|
supertypeSupplier
|
||||||
|
).any { superType ->
|
||||||
|
// Note: We check just classId here, so type substitution isn't needed
|
||||||
|
superType.lookupTag.classId.isSame(ownerLookupTag.classId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'local' isn't taken into account here
|
||||||
|
fun ClassId.isSame(other: ClassId): Boolean =
|
||||||
|
packageFqName == other.packageFqName && relativeClassName == other.relativeClassName
|
||||||
|
|
||||||
fun FirClass.isThereLoopInSupertypes(session: FirSession): Boolean {
|
fun FirClass.isThereLoopInSupertypes(session: FirSession): Boolean {
|
||||||
val visitedSymbols: MutableSet<FirClassifierSymbol<*>> = SmartSet.create()
|
val visitedSymbols: MutableSet<FirClassifierSymbol<*>> = SmartSet.create()
|
||||||
val inProcess: MutableSet<FirClassifierSymbol<*>> = mutableSetOf()
|
val inProcess: MutableSet<FirClassifierSymbol<*>> = mutableSetOf()
|
||||||
|
|||||||
Reference in New Issue
Block a user