From 03d8aa272bf596b5335503c01f0165b283b5fed0 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Tue, 8 Nov 2016 15:38:03 +0300 Subject: [PATCH] Infer type arguments of type alias constructors. --- .../kotlin/diagnostics/rendering/Renderers.kt | 60 +++++++++++++++--- .../kotlin/resolve/calls/CandidateResolver.kt | 2 +- .../resolve/calls/GenericCandidateResolver.kt | 40 +++++++++++- .../calls/inference/ConstraintPosition.kt | 22 ++++++- .../typeAliasConstructorCrazyProjections.kt | 13 ++++ .../typeAliasConstructorCrazyProjections.txt | 17 ++++++ ...eAliasConstructorTypeArgumentsInference.kt | 27 ++++++++ ...AliasConstructorTypeArgumentsInference.txt | 61 +++++++++++++++++++ ...NumberOfArgumentsInTypeAliasConstructor.kt | 10 +-- ...umberOfArgumentsInTypeAliasConstructor.txt | 2 +- .../checkers/DiagnosticsTestGenerated.java | 12 ++++ ...BoundViolatedInTypeAliasConstructorCall.kt | 8 +++ ...undViolatedInTypeAliasConstructorCall1.txt | 3 + .../DiagnosticMessageTestGenerated.java | 6 ++ 14 files changed, 265 insertions(+), 18 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/typealias/typeAliasConstructorCrazyProjections.kt create mode 100644 compiler/testData/diagnostics/tests/typealias/typeAliasConstructorCrazyProjections.txt create mode 100644 compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInference.kt create mode 100644 compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInference.txt create mode 100644 idea/testData/diagnosticMessage/upperBoundViolatedInTypeAliasConstructorCall.kt create mode 100644 idea/testData/diagnosticMessage/upperBoundViolatedInTypeAliasConstructorCall1.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt index 2ef84d92eaa..44a116545e4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt @@ -38,10 +38,11 @@ import org.jetbrains.kotlin.resolve.calls.inference.* import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.LOWER_BOUND import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.UPPER_BOUND +import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ValidityConstraintForConstituentType import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind -import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION -import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION +import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.* +import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.getValidityConstraintForConstituentType import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeIntersector @@ -52,6 +53,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import java.io.PrintWriter import java.io.StringWriter import java.lang.AssertionError +import java.util.* object Renderers { @@ -273,12 +275,20 @@ object Renderers { val typeParameterDescriptor = inferenceErrorData.descriptor.typeParameters.firstOrNull { !ConstraintsUtil.checkUpperBoundIsSatisfied(systemWithoutWeakConstraints, it, inferenceErrorData.call, true) } - if (typeParameterDescriptor == null && status.hasConflictingConstraints()) { - return renderConflictingSubstitutionsInferenceError(inferenceErrorData, result) - } + if (typeParameterDescriptor == null) { - LOG.error(debugMessage("There is no type parameter with violated upper bound for 'upper bound violated' error", inferenceErrorData)) - return result + if (inferenceErrorData.descriptor is TypeAliasConstructorDescriptor) { + renderUpperBoundViolatedInferenceErrorForTypeAliasConstructor(inferenceErrorData, result, systemWithoutWeakConstraints)?.let { + return it + } + } + + return if (status.hasConflictingConstraints()) + renderConflictingSubstitutionsInferenceError(inferenceErrorData, result) + else { + LOG.error(debugMessage("There is no type parameter with violated upper bound for 'upper bound violated' error", inferenceErrorData)) + result + } } val typeVariable = systemWithoutWeakConstraints.descriptorToVariable(inferenceErrorData.call.toHandle(), typeParameterDescriptor) @@ -322,6 +332,42 @@ object Renderers { return result } + private fun renderUpperBoundViolatedInferenceErrorForTypeAliasConstructor( + inferenceErrorData: InferenceErrorData, + result: TabledDescriptorRenderer, + systemWithoutWeakConstraints: ConstraintSystem + ): TabledDescriptorRenderer? { + val descriptor = inferenceErrorData.descriptor + if (descriptor !is TypeAliasConstructorDescriptor) { + LOG.error("Type alias constructor descriptor expected: $descriptor") + return result + } + + val inferredTypeSubstitutor = systemWithoutWeakConstraints.resultingSubstitutor + + for (constraintError in inferenceErrorData.constraintSystem.status.constraintErrors) { + val constraintInfo = constraintError.constraintPosition.getValidityConstraintForConstituentType() ?: continue + if (constraintInfo.typeParameter.variance == Variance.IN_VARIANCE) continue + + val violatedUpperBound = inferredTypeSubstitutor.safeSubstitute(constraintInfo.bound, Variance.INVARIANT) + val violatingInferredType = inferredTypeSubstitutor.safeSubstitute(constraintInfo.typeArgument, Variance.INVARIANT) + + val context = RenderingContext.of(violatingInferredType, violatedUpperBound) + val typeRenderer = result.typeRenderer + + result.text(newText().normal("Type parameter bound for ").strong(constraintInfo.typeParameter.name) + .normal(" in type inferred from type alias expansion for ")) + .table(newTable().descriptor(inferenceErrorData.descriptor)) + + result.text(newText().normal(" is not satisfied: inferred type ").error(typeRenderer.render(violatingInferredType, context)) + .normal(" is not a subtype of ").strong(typeRenderer.render(violatedUpperBound, context))) + + return result + } + + return null + } + @JvmStatic fun renderCannotCaptureTypeParameterError( inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer ): TabledDescriptorRenderer { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt index 035e540b5a6..ae96f07377f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt @@ -115,7 +115,7 @@ class CandidateResolver( if (candidateCall.knownTypeParametersSubstitutor != null) { candidateCall.setResultingSubstitutor(candidateCall.knownTypeParametersSubstitutor!!) } - else if (ktTypeArguments.isNotEmpty() || candidateDescriptor is TypeAliasConstructorDescriptor) { + else if (ktTypeArguments.isNotEmpty()) { // Explicit type arguments passed val typeArguments = ArrayList() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt index eb5fdeecb96..49e03c96d40 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt @@ -18,9 +18,8 @@ package org.jetbrains.kotlin.resolve.calls import org.jetbrains.kotlin.builtins.ReflectionTypes import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype -import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.FunctionDescriptorUtil import org.jetbrains.kotlin.resolve.calls.callResolverUtil.* @@ -34,8 +33,10 @@ import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.resolve.calls.context.ResolutionResultsCache import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache import org.jetbrains.kotlin.resolve.calls.inference.* +import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ValidityConstraintForConstituentType import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION +import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.TYPE_BOUND_POSITION import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.makeNullableTypeIfSafeReceiver import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus @@ -74,6 +75,11 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes } } + if (candidate is TypeAliasConstructorDescriptor) { + val substitutedReturnType = builder.compositeSubstitutor().safeSubstitute(candidate.returnType, Variance.INVARIANT) + addValidityConstraintsForConstituentTypes(builder, substitutedReturnType) + } + // Receiver // Error is already reported if something is missing val receiverArgument = candidateCall.extensionReceiver @@ -105,6 +111,34 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes return OTHER_ERROR } + private fun addValidityConstraintsForConstituentTypes(builder: ConstraintSystem.Builder, type: KotlinType) { + val typeConstructor = type.constructor + if (typeConstructor.declarationDescriptor is TypeParameterDescriptor) return + + val boundsSubstitutor = TypeSubstitutor.create(type) + + type.arguments.forEachIndexed forEachArgument@{ i, typeProjection -> + if (typeProjection.isStarProjection) return@forEachArgument // continue + + val typeParameter = typeConstructor.parameters[i] + addValidityConstraintsForTypeArgument(builder, typeProjection, typeParameter, boundsSubstitutor) + } + } + + private fun addValidityConstraintsForTypeArgument( + builder: ConstraintSystem.Builder, + typeProjection: TypeProjection, + typeParameter: TypeParameterDescriptor, + boundsSubstitutor: TypeSubstitutor + ) { + val typeArgument = typeProjection.type + for (upperBound in typeParameter.upperBounds) { + val substitutedUpperBound = boundsSubstitutor.safeSubstitute(upperBound, Variance.INVARIANT) + val constraintPosition = ValidityConstraintForConstituentType(typeArgument, typeParameter, substitutedUpperBound) + builder.addSubtypeConstraint(typeArgument, substitutedUpperBound, constraintPosition) + } + } + // Creates a substitutor which maps types to their representation in the constraint system. // In case when some type parameter descriptor is represented by more than one variable in the system, the behavior is undefined. private fun ConstraintSystem.Builder.compositeSubstitutor(): TypeSubstitutor { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintPosition.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintPosition.kt index 16c6015f902..a344b1d0ab9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintPosition.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintPosition.kt @@ -16,7 +16,9 @@ package org.jetbrains.kotlin.resolve.calls.inference.constraintPosition +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.* +import org.jetbrains.kotlin.types.KotlinType enum class ConstraintPositionKind { RECEIVER_POSITION, @@ -71,4 +73,22 @@ class CompoundConstraintPosition(vararg positions: ConstraintPosition) : Constra fun ConstraintPosition.derivedFrom(kind: ConstraintPositionKind): Boolean { return if (this !is CompoundConstraintPosition) this.kind == kind else positions.any { it.kind == kind } -} \ No newline at end of file +} + +class ValidityConstraintForConstituentType( + val typeArgument: KotlinType, + val typeParameter: TypeParameterDescriptor, + val bound: KotlinType +) : ConstraintPosition { + override val kind: ConstraintPositionKind get() = TYPE_BOUND_POSITION +} + +fun ConstraintPosition.getValidityConstraintForConstituentType(): ValidityConstraintForConstituentType? = + when (this) { + is ValidityConstraintForConstituentType -> + this + is CompoundConstraintPosition -> + positions.asSequence().map { it.getValidityConstraintForConstituentType() }.firstOrNull { it != null } + else -> + null + } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorCrazyProjections.kt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorCrazyProjections.kt new file mode 100644 index 00000000000..857418f7f00 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorCrazyProjections.kt @@ -0,0 +1,13 @@ +class Bound(val x: X, val y: Y) +typealias B = Bound +typealias BOutIn = Bound, in T> +typealias BInIn = Bound, in T> + +fun listOf(): List = null!! + +// Unresolved reference is ok here: +// we can't create a substituted signature for type alias constructor +// since it has 'out' type projection in 'in' position. +val test1 = BOutIn(listOf(), null!!) + +val test2 = BInIn(listOf(), null!!) \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorCrazyProjections.txt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorCrazyProjections.txt new file mode 100644 index 00000000000..d0cd0d3a9a6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorCrazyProjections.txt @@ -0,0 +1,17 @@ +package + +public val test1: [ERROR : Type for BOutIn(listOf(), null!!)] +public val test2: Bound, in kotlin.Nothing> +public fun listOf(): kotlin.collections.List + +public final class Bound { + public constructor Bound(/*0*/ x: X, /*1*/ y: Y) + public final val x: X + public final val y: Y + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} +public typealias B = Bound +public typealias BInIn = Bound, in T> +public typealias BOutIn = Bound, in T> diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInference.kt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInference.kt new file mode 100644 index 00000000000..025132738f4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInference.kt @@ -0,0 +1,27 @@ +class Num(val x: Tn) +typealias N = Num + +class Cons(val head: T, val tail: Cons?) +typealias C = Cons +typealias CC = C> + +class Pair(val x: X, val y: Y) +typealias PL = Pair> + +class Bound(val x: X, val y: Y) +typealias B = Bound + +class Foo(val p: Pair) +typealias F = Foo + +val test0 = N(1) +val test1 = N("1") +val test2 = C(1, 2) +val test3 = PL(1, null) +val test4 = CC(1, 2) +val test4a = CC(C(1, null), null) + +fun testProjections1(x: Pair) = F(x) +fun testProjections2(x: Pair) = F(x) +fun testProjections3(x: Pair) = F(x) +fun testProjections4(x: Pair) = F(x) \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInference.txt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInference.txt new file mode 100644 index 00000000000..4e3ecfd4548 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInference.txt @@ -0,0 +1,61 @@ +package + +public val test0: Num +public val test1: [ERROR : Type for N("1")] +public val test2: Cons +public val test3: Pair> +public val test4: [ERROR : Type for CC(1, 2)] +public val test4a: Cons> +public fun testProjections1(/*0*/ x: Pair): [ERROR : Error function type] +public fun testProjections2(/*0*/ x: Pair): [ERROR : Error function type] +public fun testProjections3(/*0*/ x: Pair): [ERROR : Error function type] +public fun testProjections4(/*0*/ x: Pair): [ERROR : Error function type] + +public final class Bound { + public constructor Bound(/*0*/ x: X, /*1*/ y: Y) + public final val x: X + public final val y: Y + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Cons { + public constructor Cons(/*0*/ head: T, /*1*/ tail: Cons?) + public final val head: T + public final val tail: Cons? + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Foo { + public constructor Foo(/*0*/ p: Pair) + public final val p: Pair + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Num { + public constructor Num(/*0*/ x: Tn) + public final val x: Tn + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Pair { + public constructor Pair(/*0*/ x: X, /*1*/ y: Y) + public final val x: X + public final val y: Y + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} +public typealias B = Bound +public typealias C = Cons +public typealias CC = C> +public typealias F = Foo +public typealias N = Num +public typealias PL = Pair> diff --git a/compiler/testData/diagnostics/tests/typealias/wrongNumberOfArgumentsInTypeAliasConstructor.kt b/compiler/testData/diagnostics/tests/typealias/wrongNumberOfArgumentsInTypeAliasConstructor.kt index 6908a19bf36..87464372375 100644 --- a/compiler/testData/diagnostics/tests/typealias/wrongNumberOfArgumentsInTypeAliasConstructor.kt +++ b/compiler/testData/diagnostics/tests/typealias/wrongNumberOfArgumentsInTypeAliasConstructor.kt @@ -6,18 +6,18 @@ typealias P2 = Pair typealias PR = Pair -val test0 = P(1, 2) +val test0 = P(1, 2) val test1 = P(1, 2) val test2 = P(1, 2) val test3 = P(1, 2) -val test0p2 = P2(1, 1) -val test0p2a = P2(1, "") +val test0p2 = P2(1, 1) +val test0p2a = P2(1, "") val test1p2 = P2(1, 1) val test2p2 = P2(1, 1) val test3p2 = P2(1, 1) -val test0pr = PR(1, "") +val test0pr = PR(1, "") val test1pr = PR(1, "") val test2pr = PR(1, "") val test2pra = PR(1, "") @@ -26,7 +26,7 @@ val test3pr = P2((val x: T) typealias N = Num -val testN0 = N("") +val testN0 = N("") val testN1 = N(1) val testN1a = N<String>("") val testN2 = N(1) diff --git a/compiler/testData/diagnostics/tests/typealias/wrongNumberOfArgumentsInTypeAliasConstructor.txt b/compiler/testData/diagnostics/tests/typealias/wrongNumberOfArgumentsInTypeAliasConstructor.txt index eca2cf7af29..9b68e43e926 100644 --- a/compiler/testData/diagnostics/tests/typealias/wrongNumberOfArgumentsInTypeAliasConstructor.txt +++ b/compiler/testData/diagnostics/tests/typealias/wrongNumberOfArgumentsInTypeAliasConstructor.txt @@ -14,7 +14,7 @@ public val test2pra: Pair public val test3: Pair public val test3p2: Pair public val test3pr: Pair -public val testN0: Num +public val testN0: [ERROR : Type for N("")] public val testN1: Num public val testN1a: Num public val testN2: Num diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 8d45692dc7b..4b814deb16e 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -21027,12 +21027,24 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("typeAliasConstructorCrazyProjections.kt") + public void testTypeAliasConstructorCrazyProjections() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typeAliasConstructorCrazyProjections.kt"); + doTest(fileName); + } + @TestMetadata("typeAliasConstructorInSuperCall.kt") public void testTypeAliasConstructorInSuperCall() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typeAliasConstructorInSuperCall.kt"); doTest(fileName); } + @TestMetadata("typeAliasConstructorTypeArgumentsInference.kt") + public void testTypeAliasConstructorTypeArgumentsInference() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInference.kt"); + doTest(fileName); + } + @TestMetadata("typeAliasConstructorWrongClass.kt") public void testTypeAliasConstructorWrongClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongClass.kt"); diff --git a/idea/testData/diagnosticMessage/upperBoundViolatedInTypeAliasConstructorCall.kt b/idea/testData/diagnosticMessage/upperBoundViolatedInTypeAliasConstructorCall.kt new file mode 100644 index 00000000000..0e890c57a39 --- /dev/null +++ b/idea/testData/diagnosticMessage/upperBoundViolatedInTypeAliasConstructorCall.kt @@ -0,0 +1,8 @@ +// !DIAGNOSTICS_NUMBER: 1 +// !DIAGNOSTICS: TYPE_INFERENCE_UPPER_BOUND_VIOLATED +// !MESSAGE_TYPE: TEXT + +class Num(val x: Tn) +typealias N = Num + +val test = N("") \ No newline at end of file diff --git a/idea/testData/diagnosticMessage/upperBoundViolatedInTypeAliasConstructorCall1.txt b/idea/testData/diagnosticMessage/upperBoundViolatedInTypeAliasConstructorCall1.txt new file mode 100644 index 00000000000..89ef6a1e62d --- /dev/null +++ b/idea/testData/diagnosticMessage/upperBoundViolatedInTypeAliasConstructorCall1.txt @@ -0,0 +1,3 @@ + +Type parameter bound for Tn in type inferred from type alias expansion for fun (x: T): Num + is not satisfied: inferred type T is not a subtype of Number \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/highlighter/DiagnosticMessageTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/highlighter/DiagnosticMessageTestGenerated.java index c7fda336374..36550ef793b 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/highlighter/DiagnosticMessageTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/highlighter/DiagnosticMessageTestGenerated.java @@ -310,4 +310,10 @@ public class DiagnosticMessageTestGenerated extends AbstractDiagnosticMessageTes String fileName = KotlinTestUtils.navigationMetadata("idea/testData/diagnosticMessage/upperBoundViolated.kt"); doTest(fileName); } + + @TestMetadata("upperBoundViolatedInTypeAliasConstructorCall.kt") + public void testUpperBoundViolatedInTypeAliasConstructorCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/diagnosticMessage/upperBoundViolatedInTypeAliasConstructorCall.kt"); + doTest(fileName); + } }