Introduce PureReifiable annotation

It prevents reporting unsafe substitution warning on expressions
like 'arrayOf(arrayOf(""))'
This commit is contained in:
Denis Zharkov
2016-01-21 19:09:46 +03:00
parent 32755a269c
commit 6c0cd70a22
16 changed files with 137 additions and 21 deletions
-3
View File
@@ -489,7 +489,6 @@
<fileset dir="${output}/classes/compiler"/>
<fileset dir="${output}/builtins">
<include name="kotlin/**"/>
<exclude name="kotlin/internal/**"/>
</fileset>
<fileset dir="${basedir}/core/descriptor.loader.java/src" includes="META-INF/services/**"/>
<fileset dir="${basedir}/compiler/frontend.java/src" includes="META-INF/services/**"/>
@@ -954,7 +953,6 @@
<fileset dir="${output}/classes/stdlib"/>
<zipfileset dir="${output}/builtins">
<include name="kotlin/**"/>
<exclude name="kotlin/internal/**"/>
<!-- TODO: load metadata from @KotlinClass annotation in KotlinBuiltIns on JVM and restore this exclusion -->
<!-- exclude name="kotlin/reflect/**"/ -->
</zipfileset>
@@ -1106,7 +1104,6 @@
<fileset dir="${output}/classes/compiler"/>
<fileset dir="${output}/builtins">
<include name="kotlin/**"/>
<exclude name="kotlin/internal/**"/>
</fileset>
<fileset dir="${basedir}/core/descriptor.loader.java/src" includes="META-INF/services/**"/>
<fileset dir="${basedir}/compiler/frontend.java/src" includes="META-INF/services/**"/>
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
@@ -53,7 +54,7 @@ public class ReifiedTypeParameterSubstitutionChecker implements CallChecker {
context.trace.report(
Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument));
}
else if (TypeUtilsKt.unsafeAsReifiedArgument(argument)) {
else if (TypeUtilsKt.unsafeAsReifiedArgument(argument) && !hasPureReifiableAnnotation(parameter)) {
context.trace.report(
Errors.REIFIED_TYPE_UNSAFE_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument));
}
@@ -61,6 +62,12 @@ public class ReifiedTypeParameterSubstitutionChecker implements CallChecker {
}
}
private static final FqName PURE_REIFIABLE_ANNOTATION_FQ_NAME = new FqName("kotlin.internal.PureReifiable");
private static boolean hasPureReifiableAnnotation(@NotNull TypeParameterDescriptor parameter) {
return parameter.getAnnotations().hasAnnotation(PURE_REIFIABLE_ANNOTATION_FQ_NAME);
}
@NotNull
private static PsiElement getElementToReport(@NotNull BasicCallResolutionContext context, int parameterIndex) {
if (context.call.getTypeArguments().size() > parameterIndex) {
+4 -4
View File
@@ -1,6 +1,6 @@
package-fragment kotlin
public inline fun </*0*/ reified T> Array(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, T>): kotlin.Array<T>
public inline fun </*0*/ reified @kotlin.internal.PureReifiable() T> Array(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, T>): kotlin.Array<T>
public inline fun BooleanArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Boolean>): kotlin.BooleanArray
public inline fun ByteArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Byte>): kotlin.ByteArray
public inline fun CharArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Char>): kotlin.CharArray
@@ -9,13 +9,13 @@ public inline fun FloatArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function
public inline fun IntArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Int>): kotlin.IntArray
public inline fun LongArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Long>): kotlin.LongArray
public inline fun ShortArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Short>): kotlin.ShortArray
public inline fun </*0*/ reified T> arrayOf(/*0*/ vararg elements: T /*kotlin.Array<out T>*/): kotlin.Array<T>
public fun </*0*/ reified T> arrayOfNulls(/*0*/ size: kotlin.Int): kotlin.Array<T?>
public inline fun </*0*/ reified @kotlin.internal.PureReifiable() T> arrayOf(/*0*/ vararg elements: T /*kotlin.Array<out T>*/): kotlin.Array<T>
public fun </*0*/ reified @kotlin.internal.PureReifiable() T> arrayOfNulls(/*0*/ size: kotlin.Int): kotlin.Array<T?>
public fun booleanArrayOf(/*0*/ vararg elements: kotlin.Boolean /*kotlin.BooleanArray*/): kotlin.BooleanArray
public fun byteArrayOf(/*0*/ vararg elements: kotlin.Byte /*kotlin.ByteArray*/): kotlin.ByteArray
public fun charArrayOf(/*0*/ vararg elements: kotlin.Char /*kotlin.CharArray*/): kotlin.CharArray
public fun doubleArrayOf(/*0*/ vararg elements: kotlin.Double /*kotlin.DoubleArray*/): kotlin.DoubleArray
public inline fun </*0*/ reified T> emptyArray(): kotlin.Array<T>
public inline fun </*0*/ reified @kotlin.internal.PureReifiable() T> emptyArray(): kotlin.Array<T>
public fun floatArrayOf(/*0*/ vararg elements: kotlin.Float /*kotlin.FloatArray*/): kotlin.FloatArray
public fun intArrayOf(/*0*/ vararg elements: kotlin.Int /*kotlin.IntArray*/): kotlin.IntArray
public fun longArrayOf(/*0*/ vararg elements: kotlin.Long /*kotlin.LongArray*/): kotlin.LongArray
@@ -1,6 +1,6 @@
// !CHECK_TYPE
fun test() {
val array = <!REIFIED_TYPE_UNSAFE_SUBSTITUTION!>arrayOf<!>(arrayOf(1))
val array = arrayOf(arrayOf(1))
array checkType { _<Array<Array<Int>>>() }
}
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
inline fun <reified @kotlin.internal.PureReifiable T> foo(x: T) {}
fun test() {
foo<List<String>>(listOf(""))
foo(listOf(""))
foo<Array<String>>(arrayOf(""))
foo(arrayOf(""))
}
@@ -0,0 +1,4 @@
package
@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public inline fun </*0*/ reified @kotlin.internal.PureReifiable() T> foo(/*0*/ x: T): kotlin.Unit
public fun test(): kotlin.Unit
@@ -0,0 +1,18 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
fun test() {
arrayOf<List<String>>(listOf(""))
arrayOf(listOf(""))
arrayOf<Array<String>>(arrayOf(""))
arrayOf(arrayOf(""))
arrayOfNulls<Array<String>>(1)
Array<Array<String>>(1) { arrayOf("") }
Array(1) { arrayOf("") }
Array(1) { arrayOf("") }
emptyArray<Array<String>>()
val x: Array<Array<String>> = emptyArray()
}
@@ -0,0 +1,3 @@
package
public fun test(): kotlin.Unit
@@ -125,6 +125,18 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
doTest(fileName);
}
@TestMetadata("pureReifiable.kt")
public void testPureReifiable() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/pureReifiable.kt");
doTest(fileName);
}
@TestMetadata("pureReifiableArrayOperations.kt")
public void testPureReifiableArrayOperations() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/pureReifiableArrayOperations.kt");
doTest(fileName);
}
@TestMetadata("RedeclarationMainInMultiFileClass.kt")
public void testRedeclarationMainInMultiFileClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/RedeclarationMainInMultiFileClass.kt");
+3 -1
View File
@@ -16,6 +16,8 @@
package kotlin
import kotlin.internal.PureReifiable
/**
* Returns a string representation of the object. Can be called with a null receiver, in which case
* it returns the string "null".
@@ -31,4 +33,4 @@ public operator fun String?.plus(other: Any?): String
/**
* Returns an array of objects of the given type with the given [size], initialized with null values.
*/
public fun arrayOfNulls<reified T>(size: Int): Array<T?>
public fun <reified @PureReifiable T> arrayOfNulls(size: Int): Array<T?>
+5 -3
View File
@@ -16,11 +16,13 @@
package kotlin
import kotlin.internal.PureReifiable
/**
* Returns an array with the specified [size], where each element is calculated by calling the specified
* [init] function. The `init` function returns an array element given its index.
*/
public inline fun <reified T> Array(size: Int, init: (Int) -> T): Array<T> {
public inline fun <reified @PureReifiable T> Array(size: Int, init: (Int) -> T): Array<T> {
val result = arrayOfNulls<T>(size)
for (i in 0..size - 1)
result[i] = init(i)
@@ -126,14 +128,14 @@ public inline fun BooleanArray(size: Int, init: (Int) -> Boolean): BooleanArray
/**
* Returns an empty array of the specified type [T].
*/
public inline fun <reified T> emptyArray(): Array<T> = arrayOfNulls<T>(0) as Array<T>
public inline fun <reified @PureReifiable T> emptyArray(): Array<T> = arrayOfNulls<T>(0) as Array<T>
// Array "constructor"
/**
* Returns an array containing the specified elements.
*/
public inline fun <reified T> arrayOf(vararg elements: T) : Array<T> = elements as Array<T>
public inline fun <reified @PureReifiable T> arrayOf(vararg elements: T) : Array<T> = elements as Array<T>
// "constructors" for primitive types array
/**
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package kotlin.internal
/**
* Specifies that the corresponding type parameter is not used for unsafe operations such as casts or 'is' checks
* That means it's completely safe to use generic types as argument for such parameter.
*/
@Target(AnnotationTarget.TYPE_PARAMETER)
@Retention(AnnotationRetention.BINARY)
internal annotation class PureReifiable
@@ -58,7 +58,8 @@ public abstract class KotlinBuiltIns {
COLLECTIONS_PACKAGE_FQ_NAME,
RANGES_PACKAGE_FQ_NAME,
ANNOTATION_PACKAGE_FQ_NAME,
ReflectionTypesKt.getKOTLIN_REFLECT_FQ_NAME()
ReflectionTypesKt.getKOTLIN_REFLECT_FQ_NAME(),
BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("internal"))
);
protected final ModuleDescriptorImpl builtInsModule;
+36
View File
@@ -7,6 +7,15 @@ PsiJetFileStubImpl[package=kotlin]
TYPE_PARAMETER_LIST:
TYPE_PARAMETER:[fqName=null, isInVariance=false, isOutVariance=false, name=T]
MODIFIER_LIST:[reified]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=PureReifiable]
CONSTRUCTOR_CALLEE:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=internal]
REFERENCE_EXPRESSION:[referencedName=PureReifiable]
VALUE_PARAMETER_LIST:
VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=size]
TYPE_REFERENCE:
@@ -274,6 +283,15 @@ PsiJetFileStubImpl[package=kotlin]
TYPE_PARAMETER_LIST:
TYPE_PARAMETER:[fqName=null, isInVariance=false, isOutVariance=false, name=T]
MODIFIER_LIST:[reified]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=PureReifiable]
CONSTRUCTOR_CALLEE:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=internal]
REFERENCE_EXPRESSION:[referencedName=PureReifiable]
VALUE_PARAMETER_LIST:
VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=elements]
MODIFIER_LIST:[vararg]
@@ -295,6 +313,15 @@ PsiJetFileStubImpl[package=kotlin]
TYPE_PARAMETER_LIST:
TYPE_PARAMETER:[fqName=null, isInVariance=false, isOutVariance=false, name=T]
MODIFIER_LIST:[reified]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=PureReifiable]
CONSTRUCTOR_CALLEE:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=internal]
REFERENCE_EXPRESSION:[referencedName=PureReifiable]
VALUE_PARAMETER_LIST:
VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=size]
TYPE_REFERENCE:
@@ -378,6 +405,15 @@ PsiJetFileStubImpl[package=kotlin]
TYPE_PARAMETER_LIST:
TYPE_PARAMETER:[fqName=null, isInVariance=false, isOutVariance=false, name=T]
MODIFIER_LIST:[reified]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=PureReifiable]
CONSTRUCTOR_CALLEE:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=internal]
REFERENCE_EXPRESSION:[referencedName=PureReifiable]
VALUE_PARAMETER_LIST:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
+4 -4
View File
@@ -3,7 +3,7 @@
package kotlin
public inline fun <reified T> Array(size: kotlin.Int, init: (kotlin.Int) -> T): kotlin.Array<T> { /* compiled code */ }
public inline fun <reified @kotlin.internal.PureReifiable T> Array(size: kotlin.Int, init: (kotlin.Int) -> T): kotlin.Array<T> { /* compiled code */ }
public inline fun BooleanArray(size: kotlin.Int, init: (kotlin.Int) -> kotlin.Boolean): kotlin.BooleanArray { /* compiled code */ }
@@ -21,9 +21,9 @@ public inline fun LongArray(size: kotlin.Int, init: (kotlin.Int) -> kotlin.Long)
public inline fun ShortArray(size: kotlin.Int, init: (kotlin.Int) -> kotlin.Short): kotlin.ShortArray { /* compiled code */ }
public inline fun <reified T> arrayOf(vararg elements: T): kotlin.Array<T> { /* compiled code */ }
public inline fun <reified @kotlin.internal.PureReifiable T> arrayOf(vararg elements: T): kotlin.Array<T> { /* compiled code */ }
public fun <reified T> arrayOfNulls(size: kotlin.Int): kotlin.Array<T?> { /* compiled code */ }
public fun <reified @kotlin.internal.PureReifiable T> arrayOfNulls(size: kotlin.Int): kotlin.Array<T?> { /* compiled code */ }
public fun booleanArrayOf(vararg elements: kotlin.Boolean): kotlin.BooleanArray { /* compiled code */ }
@@ -33,7 +33,7 @@ public fun charArrayOf(vararg elements: kotlin.Char): kotlin.CharArray { /* comp
public fun doubleArrayOf(vararg elements: kotlin.Double): kotlin.DoubleArray { /* compiled code */ }
public inline fun <reified T> emptyArray(): kotlin.Array<T> { /* compiled code */ }
public inline fun <reified @kotlin.internal.PureReifiable T> emptyArray(): kotlin.Array<T> { /* compiled code */ }
public fun floatArrayOf(vararg elements: kotlin.Float): kotlin.FloatArray { /* compiled code */ }
-3
View File
@@ -24,9 +24,6 @@
<includes>
<include>**/*.kotlin_*</include>
</includes>
<excludes>
<exclude>kotlin/internal/**/*</exclude>
</excludes>
</resource>
</resources>