Report warning on generic type as argument for reified parameter

#KT-6484 Fixed
This commit is contained in:
Denis Zharkov
2016-01-19 10:31:26 +03:00
parent ae6c62ddff
commit 751f66c656
8 changed files with 44 additions and 1 deletions
@@ -510,6 +510,7 @@ public interface Errors {
DiagnosticFactory1<PsiElement, TypeParameterDescriptor> TYPE_PARAMETER_AS_REIFIED = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, KotlinType> REIFIED_TYPE_FORBIDDEN_SUBSTITUTION = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, KotlinType> REIFIED_TYPE_UNSAFE_SUBSTITUTION = DiagnosticFactory1.create(WARNING);
// Type inference
@@ -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");
@@ -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));
}
}
}
}
@@ -0,0 +1,24 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
inline fun <reified T> foo() {}
inline fun <reified F> bar() {
foo<<!REIFIED_TYPE_UNSAFE_SUBSTITUTION!>Array<F><!>>()
foo<<!REIFIED_TYPE_UNSAFE_SUBSTITUTION!>List<F><!>>()
}
inline fun <reified E> baz(x: E) {}
fun test(x: Array<String>, y: Array<*>) {
foo<<!REIFIED_TYPE_UNSAFE_SUBSTITUTION!>List<String><!>>()
foo<List<*>>()
foo<<!REIFIED_TYPE_UNSAFE_SUBSTITUTION!>Map<*, String><!>>()
foo<Map<*, *>>()
foo<<!REIFIED_TYPE_UNSAFE_SUBSTITUTION!>Array<String><!>>()
foo<Array<*>>()
<!REIFIED_TYPE_UNSAFE_SUBSTITUTION!>baz<!>(x)
baz(y)
}
@@ -0,0 +1,6 @@
package
public inline fun </*0*/ reified F> bar(): kotlin.Unit
public inline fun </*0*/ reified E> baz(/*0*/ x: E): kotlin.Unit
public inline fun </*0*/ reified T> foo(): kotlin.Unit
public fun test(/*0*/ x: kotlin.Array<kotlin.String>, /*1*/ y: kotlin.Array<*>): kotlin.Unit
@@ -1,6 +1,6 @@
// !CHECK_TYPE
fun test() {
val array = arrayOf(arrayOf(1))
val array = <!REIFIED_TYPE_UNSAFE_SUBSTITUTION!>arrayOf<!>(arrayOf(1))
array checkType { _<Array<Array<Int>>>() }
}
@@ -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");
@@ -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)