diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index fe66bef4cf4..9b2e7d529a6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -510,6 +510,7 @@ public interface Errors { DiagnosticFactory1 TYPE_PARAMETER_AS_REIFIED = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 REIFIED_TYPE_FORBIDDEN_SUBSTITUTION = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 REIFIED_TYPE_UNSAFE_SUBSTITUTION = DiagnosticFactory1.create(WARNING); // Type inference diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 7ce12e1fb30..7ab3b01f7ec 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -664,6 +664,7 @@ public class DefaultErrorMessages { MAP.put(TYPE_PARAMETER_AS_REIFIED, "Cannot use ''{0}'' as reified type parameter. Use a class instead.", NAME); MAP.put(REIFIED_TYPE_PARAMETER_NO_INLINE, "Only type parameters of inline functions can be reified"); MAP.put(REIFIED_TYPE_FORBIDDEN_SUBSTITUTION, "Cannot use ''{0}'' as reified type parameter", RENDER_TYPE); + MAP.put(REIFIED_TYPE_UNSAFE_SUBSTITUTION, "It may be not safe to use ''{0}'' as an argument for a reified type parameter. Use a non-generic type or * if possible", RENDER_TYPE); MAP.put(TYPE_PARAMETERS_NOT_ALLOWED, "Type parameters are not allowed here"); MAP.put(TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER, "Type parameter of a property must be used in its receiver type"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java index 70990227b63..c01becf7d95 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ReifiedTypeParameterSubstitutionChecker.java @@ -53,6 +53,10 @@ public class ReifiedTypeParameterSubstitutionChecker implements CallChecker { context.trace.report( Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument)); } + else if (TypeUtilsKt.unsafeAsReifiedArgument(argument)) { + context.trace.report( + Errors.REIFIED_TYPE_UNSAFE_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument)); + } } } } diff --git a/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericAsReifiedArgument.kt b/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericAsReifiedArgument.kt new file mode 100644 index 00000000000..1869f86a885 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericAsReifiedArgument.kt @@ -0,0 +1,24 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +inline fun foo() {} + +inline fun bar() { + foo<Array>() + foo<List>() +} + +inline fun baz(x: E) {} + +fun test(x: Array, y: Array<*>) { + foo<List>() + foo>() + foo<Map<*, String>>() + foo>() + + foo<Array>() + foo>() + + baz(x) + baz(y) +} + diff --git a/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericAsReifiedArgument.txt b/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericAsReifiedArgument.txt new file mode 100644 index 00000000000..c485cf184c8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/tpAsReified/GenericAsReifiedArgument.txt @@ -0,0 +1,6 @@ +package + +public inline fun bar(): kotlin.Unit +public inline fun baz(/*0*/ x: E): kotlin.Unit +public inline fun foo(): kotlin.Unit +public fun test(/*0*/ x: kotlin.Array, /*1*/ y: kotlin.Array<*>): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/inference/commonSystem/theSameFunctionInArgs.kt b/compiler/testData/diagnostics/tests/inference/commonSystem/theSameFunctionInArgs.kt index ee5966fe5f2..c68b5b9c953 100644 --- a/compiler/testData/diagnostics/tests/inference/commonSystem/theSameFunctionInArgs.kt +++ b/compiler/testData/diagnostics/tests/inference/commonSystem/theSameFunctionInArgs.kt @@ -1,6 +1,6 @@ // !CHECK_TYPE fun test() { - val array = arrayOf(arrayOf(1)) + val array = arrayOf(arrayOf(1)) array checkType { _>>() } } \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 3668a9aeaba..e22562baff9 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -7382,6 +7382,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("GenericAsReifiedArgument.kt") + public void testGenericAsReifiedArgument() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/tpAsReified/GenericAsReifiedArgument.kt"); + doTest(fileName); + } + @TestMetadata("InConstructor.kt") public void testInConstructor() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/tpAsReified/InConstructor.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt index 5929775975c..a38e4928c3a 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt @@ -67,6 +67,7 @@ fun KotlinType?.isArrayOfNothing(): Boolean { fun KotlinType.isSubtypeOf(superType: KotlinType): Boolean = KotlinTypeChecker.DEFAULT.isSubtypeOf(this, superType) fun KotlinType.cannotBeReified(): Boolean = KotlinBuiltIns.isNothingOrNullableNothing(this) || this.isDynamic() +fun KotlinType.unsafeAsReifiedArgument(): Boolean = arguments.any { !it.isStarProjection } fun TypeProjection.substitute(doSubstitute: (KotlinType) -> KotlinType): TypeProjection { return if (isStarProjection)