From e89c777fc687d302adc856ef3c94870c8216917d Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Mon, 9 Dec 2019 16:39:44 +0300 Subject: [PATCH] FIR: Create DefinitelyNotNull only for annotated types --- .../enhancement/EnhancementSignatureParts.kt | 11 +++++-- .../fir/java/enhancement/javaTypeUtils.kt | 11 ++++--- .../resolve/stdlib/hashTableWithForEach.txt | 2 +- .../resolve/stdlib/j+k/MyIterable.txt | 4 +-- .../testData/resolve/stdlib/j+k/MyMap.txt | 4 +-- .../stdlib/j+k/SyntheticWithForEach.txt | 2 +- .../testData/resolve/stdlib/j+k/smartSet.kt | 14 +++++++++ .../testData/resolve/stdlib/j+k/smartSet.txt | 30 +++++++++++++++++++ .../resolve/stdlib/typeAliasWithForEach.txt | 2 +- ...FirDiagnosticsWithStdlibTestGenerated.java | 5 ++++ .../return/SubclassOfMapEntry.fir.txt | 2 +- 11 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 compiler/fir/resolve/testData/resolve/stdlib/j+k/smartSet.kt create mode 100644 compiler/fir/resolve/testData/resolve/stdlib/j+k/smartSet.txt diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/EnhancementSignatureParts.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/EnhancementSignatureParts.kt index 0455a381bd2..d4700040f68 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/EnhancementSignatureParts.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/EnhancementSignatureParts.kt @@ -15,12 +15,14 @@ import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack import org.jetbrains.kotlin.fir.java.toConeKotlinTypeWithNullability import org.jetbrains.kotlin.fir.java.toFirJavaTypeRef import org.jetbrains.kotlin.fir.java.toNotNullConeKotlinType -import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef import org.jetbrains.kotlin.load.java.AnnotationTypeQualifierResolver import org.jetbrains.kotlin.load.java.MUTABLE_ANNOTATIONS import org.jetbrains.kotlin.load.java.READ_ONLY_ANNOTATIONS +import org.jetbrains.kotlin.load.java.structure.JavaClassifierType +import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter import org.jetbrains.kotlin.load.java.structure.JavaWildcardType import org.jetbrains.kotlin.load.java.typeEnhancement.* import org.jetbrains.kotlin.name.ClassId @@ -133,7 +135,7 @@ internal class EnhancementSignatureParts( mapping.isMutable(upper.toFqNameUnsafe()) -> MutabilityQualifier.MUTABLE else -> null }, - isNotNullTypeParameter = false //TODO: unwrap() is NotNullTypeParameter + isNotNullTypeParameter = lower is ConeDefinitelyNotNullType ) } @@ -212,11 +214,14 @@ internal class EnhancementSignatureParts( MutabilityQualifier.MUTABLE ) ), - isNotNullTypeParameter = nullabilityInfo?.qualifier == NullabilityQualifier.NOT_NULL && true, /* TODO: isTypeParameter()*/ + isNotNullTypeParameter = nullabilityInfo?.qualifier == NullabilityQualifier.NOT_NULL && this.isTypeParameterBasedType(), isNullabilityQualifierForWarning = nullabilityInfo?.isForWarningOnly == true ) } + private fun FirTypeRef?.isTypeParameterBasedType() = + ((this as? FirJavaTypeRef)?.type as? JavaClassifierType)?.classifier is JavaTypeParameter + private fun FirTypeRef?.computeQualifiersForOverride( session: FirSession, fromSupertypes: Collection, diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt index da3238678e2..00d51053c27 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt @@ -18,7 +18,6 @@ import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass import org.jetbrains.kotlin.fir.java.declarations.FirJavaField import org.jetbrains.kotlin.fir.java.toConeProjection import org.jetbrains.kotlin.fir.java.toNotNullConeKotlinType -import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef import org.jetbrains.kotlin.fir.references.impl.FirResolvedNamedReferenceImpl import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.resolve.* @@ -32,6 +31,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl +import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_NULL_FQ_NAME import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_VALUE_FQ_NAME import org.jetbrains.kotlin.load.java.descriptors.AnnotationDefaultValue @@ -87,7 +87,9 @@ private fun JavaType?.enhancePossiblyFlexible( when { type.isRaw -> ConeRawType(lowerResult, upperResult) - else -> coneFlexibleOrSimpleType(session, lowerResult, upperResult) + else -> coneFlexibleOrSimpleType( + session, lowerResult, upperResult, isNotNullTypeParameter = qualifiers(index).isNotNullTypeParameter + ) } } is JavaArrayType -> { @@ -122,11 +124,12 @@ private fun JavaType?.subtreeSize(): Int { private fun coneFlexibleOrSimpleType( session: FirSession, lowerBound: ConeLookupTagBasedType, - upperBound: ConeLookupTagBasedType + upperBound: ConeLookupTagBasedType, + isNotNullTypeParameter: Boolean ): ConeKotlinType { if (AbstractStrictEqualityTypeChecker.strictEqualTypes(session.typeContext, lowerBound, upperBound)) { val lookupTag = lowerBound.lookupTag - if (lookupTag is ConeTypeParameterLookupTag && !lowerBound.isMarkedNullable) { + if (isNotNullTypeParameter && lookupTag is ConeTypeParameterLookupTag && !lowerBound.isMarkedNullable) { // TODO: we need enhancement for type parameter bounds for this code to work properly // At this moment, this condition is always true if (lookupTag.typeParameterSymbol.fir.bounds.any { diff --git a/compiler/fir/resolve/testData/resolve/stdlib/hashTableWithForEach.txt b/compiler/fir/resolve/testData/resolve/stdlib/hashTableWithForEach.txt index 73121d103f0..a730effbe3c 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/hashTableWithForEach.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/hashTableWithForEach.txt @@ -14,7 +14,7 @@ FILE: hashTableWithForEach.kt when () { R|/DEBUG| -> { ^ Q|java/util/Collections|.R|java/util/Collections.unmodifiableSet||>(R|kotlin/collections/mutableSetOf||>().R|kotlin/apply|>|>( = apply@fun R|kotlin/collections/MutableSet>|.(): R|kotlin/Unit| { - this@R|/SomeHashTable|.R|FakeOverride|( = forEach@fun (key: R|K!|, value: R|V!|): R|kotlin/Unit| { + this@R|/SomeHashTable|.R|FakeOverride|( = forEach@fun (key: R|K|, value: R|V|): R|kotlin/Unit| { this@R|kotlin/collections/MutableSet|.R|FakeOverride|(R|/SomeHashTable.Entry.Entry|(R|/key|, R|/value|)) } ) diff --git a/compiler/fir/resolve/testData/resolve/stdlib/j+k/MyIterable.txt b/compiler/fir/resolve/testData/resolve/stdlib/j+k/MyIterable.txt index 8b94d9d8b95..6290c2ff595 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/j+k/MyIterable.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/j+k/MyIterable.txt @@ -2,11 +2,11 @@ FILE: test.kt public abstract interface UseIterable : R|MyIterable| { public open fun test(): R|kotlin/Unit| { lval it: R|kotlin/collections/MutableIterator| = this@R|kotlin/collections/MutableIterable|.R|FakeOverride|>|() - lval split: R|java/util/Spliterator| = this@R|java/lang/Iterable|.R|FakeOverride|>|() + lval split: R|java/util/Spliterator| = this@R|java/lang/Iterable|.R|FakeOverride|>|() } } public final fun test(some: R|kotlin/collections/Iterable|): R|kotlin/Unit| { lval it: R|kotlin/collections/Iterator| = R|/some|.R|FakeOverride|>|() - lval split: R|java/util/Spliterator| = R|/some|.R|FakeOverride|>|() + lval split: R|java/util/Spliterator| = R|/some|.R|FakeOverride|>|() } diff --git a/compiler/fir/resolve/testData/resolve/stdlib/j+k/MyMap.txt b/compiler/fir/resolve/testData/resolve/stdlib/j+k/MyMap.txt index be1c6675bb5..5874a26facb 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/j+k/MyMap.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/j+k/MyMap.txt @@ -6,7 +6,7 @@ FILE: test.kt ) lval otherResult: R|kotlin/String| = R|/map|.R|FakeOverride|(String(key), String(value)) lval anotherResult: = R|/map|.#(String(key), String(value)) - R|/map|.R|FakeOverride|( = forEach@fun (key: R|kotlin/String!|, value: R|kotlin/String!|): R|kotlin/Unit| { + R|/map|.R|FakeOverride|( = forEach@fun (key: R|kotlin/String|, value: R|kotlin/String|): R|kotlin/Unit| { R|kotlin/io/println|((R|/key|.R|kotlin/Any.toString|(), String(: ), R|/value|.R|kotlin/Any.toString|())) R|/key|.R|kotlin/String.length| R|/value|.R|kotlin/String.length| @@ -28,7 +28,7 @@ FILE: test.kt ) lval otherResult: R|kotlin/String| = R|/map|.R|FakeOverride|(String(key), String(value)) lval anotherResult: = R|/map|.#(String(key), String(value)) - R|/map|.R|FakeOverride|( = forEach@fun (key: R|kotlin/String!|, value: R|kotlin/String!|): R|kotlin/Unit| { + R|/map|.R|FakeOverride|( = forEach@fun (key: R|kotlin/String|, value: R|kotlin/String|): R|kotlin/Unit| { R|kotlin/io/println|((R|/key|.R|kotlin/Any.toString|(), String(: ), R|/value|.R|kotlin/Any.toString|())) R|/key|.R|kotlin/String.length| R|/value|.R|kotlin/String.length| diff --git a/compiler/fir/resolve/testData/resolve/stdlib/j+k/SyntheticWithForEach.txt b/compiler/fir/resolve/testData/resolve/stdlib/j+k/SyntheticWithForEach.txt index e98dad788f9..fe200e0b0b5 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/j+k/SyntheticWithForEach.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/j+k/SyntheticWithForEach.txt @@ -1,6 +1,6 @@ FILE: test.kt public final fun R|Call|.testForEach(): R|kotlin/Unit| { - this@R|/Call|.R|/Call.arguments|.R|FakeOverride|( = forEach@fun (key: R|kotlin/String!|, value: R|kotlin/String!|): R|kotlin/Unit| { + this@R|/Call|.R|/Call.arguments|.R|FakeOverride|( = forEach@fun (key: R|ft!|, value: R|ft!|): R|kotlin/Unit| { R|/key|.R|kotlin/String.length| R|/value|.R|kotlin/String.length| } diff --git a/compiler/fir/resolve/testData/resolve/stdlib/j+k/smartSet.kt b/compiler/fir/resolve/testData/resolve/stdlib/j+k/smartSet.kt new file mode 100644 index 00000000000..fa730ad2897 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/stdlib/j+k/smartSet.kt @@ -0,0 +1,14 @@ +import java.util.AbstractSet + +class SmartSet : AbstractSet() { + override var size: Int = 0 + override fun iterator(): MutableIterator = TODO() + override fun add(element: T): Boolean = true + override fun clear() {} + override fun contains(element: T): Boolean = false +} + +fun foo(x: Any) { + val s = SmartSet() + s.add(x) +} diff --git a/compiler/fir/resolve/testData/resolve/stdlib/j+k/smartSet.txt b/compiler/fir/resolve/testData/resolve/stdlib/j+k/smartSet.txt new file mode 100644 index 00000000000..89352ac84bb --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/stdlib/j+k/smartSet.txt @@ -0,0 +1,30 @@ +FILE: smartSet.kt + public final class SmartSet : R|java/util/AbstractSet| { + public constructor(): R|SmartSet| { + super|>() + } + + public final override var size: R|kotlin/Int| = Int(0) + public get(): R|kotlin/Int| + public set(value: R|kotlin/Int|): R|kotlin/Unit| + + public final override fun iterator(): R|kotlin/collections/MutableIterator| { + ^iterator R|kotlin/TODO|() + } + + public final override fun add(element: R|T|): R|kotlin/Boolean| { + ^add Boolean(true) + } + + public final override fun clear(): R|kotlin/Unit| { + } + + public final override fun contains(element: R|T|): R|kotlin/Boolean| { + ^contains Boolean(false) + } + + } + public final fun foo(x: R|kotlin/Any|): R|kotlin/Unit| { + lval s: R|SmartSet| = R|/SmartSet.SmartSet|() + R|/s|.R|FakeOverride|(R|/x|) + } diff --git a/compiler/fir/resolve/testData/resolve/stdlib/typeAliasWithForEach.txt b/compiler/fir/resolve/testData/resolve/stdlib/typeAliasWithForEach.txt index 505a7674e41..4ca2ee9fc78 100644 --- a/compiler/fir/resolve/testData/resolve/stdlib/typeAliasWithForEach.txt +++ b/compiler/fir/resolve/testData/resolve/stdlib/typeAliasWithForEach.txt @@ -10,7 +10,7 @@ FILE: typeAliasWithForEach.kt public final typealias Arguments = R|kotlin/collections/Map| public final fun R|Arguments|.deepCopy(): R|Arguments| { lval result: R|java/util/HashMap| = R|java/util/HashMap.HashMap|() - this@R|/deepCopy|.R|FakeOverride|( = forEach@fun (key: R|kotlin/String!|, value: R|ArgsInfo!|): R|kotlin/Unit| { + this@R|/deepCopy|.R|FakeOverride|( = forEach@fun (key: R|kotlin/String|, value: R|ArgsInfo|): R|kotlin/Unit| { R|/result|.R|kotlin/collections/set|(R|/key|, R|/ArgsInfoImpl.ArgsInfoImpl|(R|/value|)) } ) diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java index 796e8a2d945..dcaae0ff01b 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithStdlibTestGenerated.java @@ -534,6 +534,11 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic runTest("compiler/fir/resolve/testData/resolve/stdlib/j+k/RawType.kt"); } + @TestMetadata("smartSet.kt") + public void testSmartSet() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/stdlib/j+k/smartSet.kt"); + } + @TestMetadata("StaticClassConstructorFromBaseClass.kt") public void testStaticClassConstructorFromBaseClass() throws Exception { runTest("compiler/fir/resolve/testData/resolve/stdlib/j+k/StaticClassConstructorFromBaseClass.kt"); diff --git a/compiler/testData/loadJava/compiledJava/kotlinSignature/propagation/return/SubclassOfMapEntry.fir.txt b/compiler/testData/loadJava/compiledJava/kotlinSignature/propagation/return/SubclassOfMapEntry.fir.txt index a69735fdf33..99af87fa9e7 100644 --- a/compiler/testData/loadJava/compiledJava/kotlinSignature/propagation/return/SubclassOfMapEntry.fir.txt +++ b/compiler/testData/loadJava/compiledJava/kotlinSignature/propagation/return/SubclassOfMapEntry.fir.txt @@ -1,4 +1,4 @@ public abstract interface SubclassOfMapEntry : R|kotlin/collections/MutableMap.MutableEntry| { - public abstract operator fun setValue(value: R|V!|): R|V!| + public abstract operator fun setValue(value: R|V|): R|V| }