Support new form of definitely non-nullable types: T & Any

^KT-26245 In Progress
This commit is contained in:
Denis.Zharkov
2021-08-09 12:10:51 +03:00
committed by teamcityserver
parent cdd8d1c163
commit 302eacbf59
53 changed files with 2139 additions and 196 deletions
@@ -161,6 +161,8 @@ public interface Errors {
DiagnosticFactory0<KtNullableType> REDUNDANT_NULLABLE = DiagnosticFactory0.create(WARNING, NULLABLE_TYPE);
DiagnosticFactory0<KtDefinitelyNotNullType> DEFINITELY_NOT_NULLABLE_NOT_APPLICABLE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtNullableType> NULLABLE_ON_DEFINITELY_NOT_NULLABLE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeReference> INCORRECT_LEFT_COMPONENT_OF_INTERSECTION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeReference> INCORRECT_RIGHT_COMPONENT_OF_INTERSECTION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory2<KtElement, Integer, DeclarationDescriptor> WRONG_NUMBER_OF_TYPE_ARGUMENTS = DiagnosticFactory2.create(ERROR);
DiagnosticFactory1<KtElement, ClassDescriptor> OUTER_CLASS_ARGUMENTS_REQUIRED = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtElement, String> TYPE_ARGUMENTS_NOT_ALLOWED = DiagnosticFactory1.create(ERROR);
@@ -696,6 +696,8 @@ public class DefaultErrorMessages {
MAP.put(REDUNDANT_NULLABLE, "Redundant '?'");
MAP.put(DEFINITELY_NOT_NULLABLE_NOT_APPLICABLE, "'!!' is only applicable to type parameters with nullable upper bounds");
MAP.put(NULLABLE_ON_DEFINITELY_NOT_NULLABLE, "'!!' type cannot be marked as nullable");
MAP.put(INCORRECT_LEFT_COMPONENT_OF_INTERSECTION, "Intersection types are only supported for definitely non-nullable types: left part should be a type parameter with nullable bounds");
MAP.put(INCORRECT_RIGHT_COMPONENT_OF_INTERSECTION, "Intersection types are only supported for definitely non-nullable types: right part should be non-nullable Any");
MAP.put(UNSAFE_CALL, "Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type {0}", RENDER_TYPE);
MAP.put(UNSAFE_IMPLICIT_INVOKE_CALL, "Reference has a nullable type ''{0}'', use explicit ''?.invoke()'' to make a function-like call instead", RENDER_TYPE);
MAP.put(AMBIGUOUS_LABEL, "Ambiguous label");
@@ -55,9 +55,7 @@ import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.Variance.*
import org.jetbrains.kotlin.types.typeUtil.containsTypeAliasParameters
import org.jetbrains.kotlin.types.typeUtil.containsTypeAliases
import org.jetbrains.kotlin.types.typeUtil.isArrayOfNothing
import org.jetbrains.kotlin.types.typeUtil.*
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import kotlin.math.min
@@ -319,6 +317,57 @@ class TypeResolver(
result = type(definitelyNotNullKotlinType)
}
override fun visitIntersectionType(intersectionType: KtIntersectionType) {
val leftType = resolvePossiblyBareType(c, intersectionType.getLeftTypeRef() ?: return).let {
when {
it.isBare -> error("There should not be bare types for intersections")
else -> it.actualType
}
}
// Just in case of early return
result = type(leftType)
val rightType = resolvePossiblyBareType(c, intersectionType.getRightTypeRef() ?: return).let {
when {
it.isBare -> error("There should not be bare types for intersections")
else -> it.actualType
}
}
if (!languageVersionSettings.supportsFeature(LanguageFeature.DefinitelyNotNullTypeParameters)) {
c.trace.report(
UNSUPPORTED_FEATURE.on(
intersectionType,
LanguageFeature.DefinitelyNotNullTypeParameters to languageVersionSettings
)
)
return
}
if (!leftType.isTypeParameter() || leftType.isMarkedNullable || !TypeUtils.isNullableType(leftType)) {
c.trace.report(INCORRECT_LEFT_COMPONENT_OF_INTERSECTION.on(intersectionType.getLeftTypeRef()!!))
return
}
if (!rightType.isAny()) {
c.trace.report(INCORRECT_RIGHT_COMPONENT_OF_INTERSECTION.on(intersectionType.getRightTypeRef()!!))
return
}
val definitelyNotNullType =
DefinitelyNotNullType.makeDefinitelyNotNull(leftType.unwrap())
?: error(
"Definitely not-nullable type is not created for type parameter with nullable upper bound ${
TypeUtils.getTypeParameterDescriptorOrNull(
leftType
)!!
}"
)
result = type(definitelyNotNullType)
}
override fun visitFunctionType(type: KtFunctionType) {
val receiverTypeRef = type.receiverTypeReference
val receiverType = if (receiverTypeRef == null) null else resolveType(c.noBareTypes(), receiverTypeRef)