[NI] Add checking @NotNull parameters for candidates
This commit is contained in:
+4
@@ -40,6 +40,10 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext,
|
||||
return StandardClassIds.Nothing(symbolProvider).constructType(emptyArray(), false)
|
||||
}
|
||||
|
||||
override fun anyType(): SimpleTypeMarker {
|
||||
return StandardClassIds.Any(symbolProvider).constructType(emptyArray(), false)
|
||||
}
|
||||
|
||||
override fun createFlexibleType(lowerBound: SimpleTypeMarker, upperBound: SimpleTypeMarker): KotlinTypeMarker {
|
||||
require(lowerBound is ConeKotlinType)
|
||||
require(upperBound is ConeKotlinType)
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@ class DiagnosticReporterByTrackingStrategy(
|
||||
require(diagnostic is ArgumentTypeMismatchDiagnostic)
|
||||
reportIfNonNull(callArgument.safeAs<PSIKotlinCallArgument>()?.valueArgument?.getArgumentExpression()) {
|
||||
if (it.isNull()) {
|
||||
trace.report(NULL_FOR_NONNULL_TYPE.on(it, diagnostic.expectedType))
|
||||
trace.reportDiagnosticOnce(NULL_FOR_NONNULL_TYPE.on(it, diagnostic.expectedType))
|
||||
} else {
|
||||
trace.report(TYPE_MISMATCH.on(it, diagnostic.expectedType, diagnostic.actualType))
|
||||
}
|
||||
|
||||
+15
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosi
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ReceiverConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.types.NotNullTypeVariable
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.checker.captureFromExpression
|
||||
import org.jetbrains.kotlin.types.checker.hasSupertypeWithGivenTypeConstructor
|
||||
@@ -81,6 +82,20 @@ private fun checkExpressionArgument(
|
||||
|
||||
val expectedNullableType = expectedType.makeNullableAsSpecified(true)
|
||||
val position = if (isReceiver) ReceiverConstraintPosition(expressionArgument) else ArgumentConstraintPosition(expressionArgument)
|
||||
|
||||
// Used only for arguments with @NotNull annotation
|
||||
if (expectedType is NotNullTypeVariable) {
|
||||
var expectedTypeIsNull: Boolean = false
|
||||
csBuilder.runTransaction {
|
||||
addNotNullUpperConstraint(argumentType, position)
|
||||
expectedTypeIsNull = hasContradiction
|
||||
false
|
||||
}
|
||||
if (expectedTypeIsNull) {
|
||||
diagnosticsHolder.addDiagnostic(ArgumentTypeMismatchDiagnostic(expectedType, argumentType, expressionArgument))
|
||||
}
|
||||
}
|
||||
|
||||
if (expressionArgument.isSafeCall) {
|
||||
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedNullableType, position)) {
|
||||
diagnosticsHolder.addDiagnosticIfNotNull(
|
||||
|
||||
+2
@@ -40,6 +40,8 @@ interface ConstraintSystemOperation {
|
||||
fun isPostponedTypeVariable(typeVariable: TypeVariableMarker): Boolean
|
||||
|
||||
fun getProperSuperTypeConstructors(type: KotlinTypeMarker): List<TypeConstructorMarker>
|
||||
|
||||
fun addNotNullUpperConstraint(type: KotlinTypeMarker, position: ConstraintPosition)
|
||||
}
|
||||
|
||||
interface ConstraintSystemBuilder : ConstraintSystemOperation {
|
||||
|
||||
+4
@@ -302,4 +302,8 @@ class NewConstraintSystemImpl(
|
||||
|
||||
return constraints.any { (it.kind == ConstraintKind.UPPER || it.kind == ConstraintKind.EQUALITY) && it.type.isUnit() }
|
||||
}
|
||||
|
||||
override fun addNotNullUpperConstraint(type: KotlinTypeMarker, position: ConstraintPosition) {
|
||||
addSubtypeConstraint(type, anyType(), position)
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -5,6 +5,5 @@ interface A<T : A<T?>?> {
|
||||
fun foo(): T?
|
||||
}
|
||||
fun testA(a: A<*>) {
|
||||
// in new inference here we have A<A<A<*>>>
|
||||
a.foo() checkType { <!NI;DEBUG_INFO_UNRESOLVED_WITH_TARGET, NI;UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><A<*>?>() }
|
||||
a.foo() checkType { _<A<*>?>() }
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ public interface J2 extends J {
|
||||
fun main() {
|
||||
J <!NI;TYPE_MISMATCH!>{ <!EXPECTED_PARAMETER_TYPE_MISMATCH!>s: String<!> -> s}<!> // should be prohibited, because SAM value parameter has nullable type
|
||||
J { "" + it<!UNSAFE_CALL!>.<!>length }
|
||||
J { <!NI;NULL_FOR_NONNULL_TYPE, NULL_FOR_NONNULL_TYPE!>null<!> }
|
||||
J { <!NULL_FOR_NONNULL_TYPE!>null<!> }
|
||||
J { <!NI;TYPE_MISMATCH, TYPE_MISMATCH!>it?.length?.toString()<!> }
|
||||
|
||||
J2 <!NI;TYPE_MISMATCH!>{ <!EXPECTED_PARAMETER_TYPE_MISMATCH!>s: String<!> -> s}<!>
|
||||
J2 { "" + it<!UNSAFE_CALL!>.<!>length }
|
||||
J2 { <!NI;NULL_FOR_NONNULL_TYPE, NULL_FOR_NONNULL_TYPE!>null<!> }
|
||||
J2 { <!NULL_FOR_NONNULL_TYPE!>null<!> }
|
||||
J2 { <!NI;TYPE_MISMATCH, TYPE_MISMATCH!>it?.length?.toString()<!> }
|
||||
}
|
||||
|
||||
Vendored
+7
-5
@@ -11,13 +11,15 @@ public class A {
|
||||
// FILE: k.kt
|
||||
|
||||
fun test() {
|
||||
A.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>bar<!>(<!OI;NULL_FOR_NONNULL_TYPE!>null<!>, "")
|
||||
A.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>bar<!>(<!NULL_FOR_NONNULL_TYPE!>null<!>, "")
|
||||
|
||||
A.bar<String>(<!NULL_FOR_NONNULL_TYPE!>null<!>, "")
|
||||
A.bar<String?>(<!OI;NULL_FOR_NONNULL_TYPE!>null<!>, "")
|
||||
A.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>bar<!>(<!OI;NULL_FOR_NONNULL_TYPE!>null<!>, A.platformString())
|
||||
A.bar<String?>(<!NULL_FOR_NONNULL_TYPE!>null<!>, "")
|
||||
A.bar<String?>("", "")
|
||||
|
||||
A.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>bar<!>(<!NULL_FOR_NONNULL_TYPE!>null<!>, A.platformString())
|
||||
|
||||
val x: String? = null
|
||||
A.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>bar<!>(<!OI;TYPE_MISMATCH!>x<!>, "")
|
||||
A.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>bar<!>(<!OI;NULL_FOR_NONNULL_TYPE!>null<!>, "")
|
||||
A.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>bar<!>(<!TYPE_MISMATCH!>x<!>, "")
|
||||
A.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>bar<!>(<!NULL_FOR_NONNULL_TYPE!>null<!>, "")
|
||||
}
|
||||
|
||||
+1
-1
@@ -215,7 +215,7 @@ private object EnhancedTypeAnnotationDescriptor : AnnotationDescriptor {
|
||||
override fun toString() = "[EnhancedType]"
|
||||
}
|
||||
|
||||
internal class NotNullTypeParameter(override val delegate: SimpleType) : CustomTypeVariable, DelegatingSimpleType() {
|
||||
internal class NotNullTypeParameter(override val delegate: SimpleType) : NotNullTypeVariable, DelegatingSimpleType() {
|
||||
|
||||
override val isTypeVariable: Boolean
|
||||
get() = true
|
||||
|
||||
@@ -27,6 +27,10 @@ interface CustomTypeVariable {
|
||||
fun substitutionResult(replacement: KotlinType): KotlinType
|
||||
}
|
||||
|
||||
// That interface is needed to provide information about definitely not null
|
||||
// type parameters (e.g. from @NotNull annotation) to type system
|
||||
interface NotNullTypeVariable : CustomTypeVariable
|
||||
|
||||
fun KotlinType.isCustomTypeVariable(): Boolean = (unwrap() as? CustomTypeVariable)?.isTypeVariable ?: false
|
||||
fun KotlinType.getCustomTypeVariable(): CustomTypeVariable? =
|
||||
(unwrap() as? CustomTypeVariable)?.let {
|
||||
|
||||
@@ -333,6 +333,10 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext {
|
||||
return builtIns.nothingType
|
||||
}
|
||||
|
||||
override fun anyType(): SimpleTypeMarker {
|
||||
return builtIns.anyType
|
||||
}
|
||||
|
||||
val builtIns: KotlinBuiltIns get() = throw UnsupportedOperationException("Not supported")
|
||||
|
||||
override fun KotlinTypeMarker.makeDefinitelyNotNullOrNotNull(): KotlinTypeMarker {
|
||||
|
||||
@@ -49,6 +49,7 @@ interface TypeSystemBuiltInsContext {
|
||||
fun nullableNothingType(): SimpleTypeMarker
|
||||
fun nullableAnyType(): SimpleTypeMarker
|
||||
fun nothingType(): SimpleTypeMarker
|
||||
fun anyType(): SimpleTypeMarker
|
||||
}
|
||||
|
||||
interface TypeSystemTypeFactoryContext {
|
||||
|
||||
Reference in New Issue
Block a user