diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolutionContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolutionContext.java index 90f8be301a4..17c9e4cc839 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolutionContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolutionContext.java @@ -24,11 +24,12 @@ public class TypeResolutionContext { public final BindingTrace trace; public final boolean checkBounds; public final boolean allowBareTypes; + public final boolean allowIntersectionTypes; public final boolean isDebuggerContext; public final boolean abbreviated; public TypeResolutionContext(@NotNull LexicalScope scope, @NotNull BindingTrace trace, boolean checkBounds, boolean allowBareTypes, boolean isDebuggerContext) { - this(scope, trace, checkBounds, allowBareTypes, isDebuggerContext, false); + this(scope, trace, checkBounds, allowBareTypes, isDebuggerContext, false, false); } public TypeResolutionContext( @@ -38,6 +39,18 @@ public class TypeResolutionContext { boolean allowBareTypes, boolean isDebuggerContext, boolean abbreviated + ) { + this(scope, trace, checkBounds, allowBareTypes, isDebuggerContext, abbreviated, false); + } + + public TypeResolutionContext( + @NotNull LexicalScope scope, + @NotNull BindingTrace trace, + boolean checkBounds, + boolean allowBareTypes, + boolean isDebuggerContext, + boolean abbreviated, + boolean allowIntersectionTypes ) { this.scope = scope; this.trace = trace; @@ -45,10 +58,11 @@ public class TypeResolutionContext { this.allowBareTypes = allowBareTypes; this.isDebuggerContext = isDebuggerContext; this.abbreviated = abbreviated; + this.allowIntersectionTypes = allowIntersectionTypes; } @NotNull public TypeResolutionContext noBareTypes() { - return new TypeResolutionContext(scope, trace, checkBounds, false, isDebuggerContext, abbreviated); + return new TypeResolutionContext(scope, trace, checkBounds, false, isDebuggerContext, abbreviated, allowIntersectionTypes); } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt index 0bcb367aed3..9ca2b143c9e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt @@ -86,6 +86,14 @@ class TypeResolver( open fun transformType(kotlinType: KotlinType): KotlinType? = null } + // Entry point for KotlinTypeCheckerTest + fun resolveTypeWithPossibleIntersections(scope: LexicalScope, typeReference: KtTypeReference, trace: BindingTrace): KotlinType { + return resolveType( + TypeResolutionContext(scope, trace, false, false, typeReference.suppressDiagnosticsInDebugMode(), false, true), + typeReference + ) + } + fun resolveType(scope: LexicalScope, typeReference: KtTypeReference, trace: BindingTrace, checkBounds: Boolean): KotlinType { // bare types are not allowed return resolveType( @@ -322,37 +330,41 @@ class TypeResolver( } } - if (!languageVersionSettings.supportsFeature(LanguageFeature.DefinitelyNonNullableTypes)) { - c.trace.report( - UNSUPPORTED_FEATURE.on( - intersectionType, - LanguageFeature.DefinitelyNonNullableTypes to languageVersionSettings + if (!c.allowIntersectionTypes) { + if (!languageVersionSettings.supportsFeature(LanguageFeature.DefinitelyNonNullableTypes)) { + c.trace.report( + UNSUPPORTED_FEATURE.on( + intersectionType, + LanguageFeature.DefinitelyNonNullableTypes to languageVersionSettings + ) ) - ) - return + return + } + + if (!leftType.isTypeParameter() || leftType.isMarkedNullable || !leftType.isNullableOrUninitializedTypeParameter()) { + 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) + } else { + result = type(IntersectionTypeConstructor(listOf(leftType, rightType)).createType()) } - - if (!leftType.isTypeParameter() || leftType.isMarkedNullable || !leftType.isNullableOrUninitializedTypeParameter()) { - 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) } private fun KotlinType.isNullableOrUninitializedTypeParameter(): Boolean { diff --git a/compiler/tests/org/jetbrains/kotlin/types/KotlinTypeCheckerTest.java b/compiler/tests/org/jetbrains/kotlin/types/KotlinTypeCheckerTest.java index 19abaad83fa..b45aff4ad3e 100644 --- a/compiler/tests/org/jetbrains/kotlin/types/KotlinTypeCheckerTest.java +++ b/compiler/tests/org/jetbrains/kotlin/types/KotlinTypeCheckerTest.java @@ -28,8 +28,10 @@ import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl; import org.jetbrains.kotlin.psi.KtExpression; import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtPsiFactoryKt; +import org.jetbrains.kotlin.psi.KtTypeReference; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingTraceContext; +import org.jetbrains.kotlin.resolve.TypeResolutionContext; import org.jetbrains.kotlin.resolve.TypeResolver; import org.jetbrains.kotlin.resolve.calls.components.InferenceSession; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory; @@ -174,7 +176,7 @@ public class KotlinTypeCheckerTest extends KotlinTestWithEnvironment { assertCommonSupertype("Derived_T", "DDerived_T", "Derived_T"); assertCommonSupertype("Derived_T", "DDerived_T", "DDerived1_T"); - assertCommonSupertype("Comparable<*>", "Comparable", "Comparable"); + assertCommonSupertype("Comparable", "Comparable", "Comparable"); assertCommonSupertype("Base_T", "Base_T", "Base_T"); assertCommonSupertype("Base_T", "Base_T", "Base_T"); assertCommonSupertype("Base_T", "Derived_T", "Base_T"); @@ -585,6 +587,7 @@ public class KotlinTypeCheckerTest extends KotlinTestWithEnvironment { } private KotlinType makeType(LexicalScope scope, String typeStr) { - return typeResolver.resolveType(scope, KtPsiFactoryKt.KtPsiFactory(getProject()).createType(typeStr), DummyTraces.DUMMY_TRACE, true); + KtTypeReference typeReference = KtPsiFactoryKt.KtPsiFactory(getProject()).createType(typeStr); + return typeResolver.resolveTypeWithPossibleIntersections(scope, typeReference, DummyTraces.DUMMY_TRACE); } }