Prohibit using array based on non-reified type parameters as reified type arguments
#KT-31227 fixed
This commit is contained in:
@@ -740,6 +740,8 @@ public interface Errors {
|
||||
DiagnosticFactory1<PsiElement, Collection<? extends CallableDescriptor>> CALLABLE_REFERENCE_RESOLUTION_AMBIGUITY = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory1<PsiElement, TypeParameterDescriptor> TYPE_PARAMETER_AS_REIFIED = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, TypeParameterDescriptor> TYPE_PARAMETER_AS_REIFIED_ARRAY = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, TypeParameterDescriptor> TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory1<PsiElement, KotlinType> REIFIED_TYPE_FORBIDDEN_SUBSTITUTION = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, KotlinType> REIFIED_TYPE_UNSAFE_SUBSTITUTION = DiagnosticFactory1.create(WARNING);
|
||||
|
||||
|
||||
+2
@@ -872,6 +872,8 @@ public class DefaultErrorMessages {
|
||||
MAP.put(TYPE_ARGUMENTS_NOT_ALLOWED, "Type arguments are not allowed {0}", STRING);
|
||||
|
||||
MAP.put(TYPE_PARAMETER_AS_REIFIED, "Cannot use ''{0}'' as reified type parameter. Use a class instead.", NAME);
|
||||
MAP.put(TYPE_PARAMETER_AS_REIFIED_ARRAY, "Cannot use ''{0}'' as reified type parameter, since the array type parameter is not reified.", NAME);
|
||||
MAP.put(TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING, "Cannot use ''{0}'' as reified type parameter, since the array type parameter is not reified.", 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);
|
||||
|
||||
+42
-12
@@ -20,10 +20,12 @@ import com.intellij.psi.PsiElement;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.psi.KtTypeProjection;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
@@ -46,22 +48,50 @@ public class ReifiedTypeParameterSubstitutionChecker implements CallChecker {
|
||||
}
|
||||
|
||||
KtTypeProjection typeProjection = CollectionsKt.getOrNull(resolvedCall.getCall().getTypeArguments(), parameter.getIndex());
|
||||
PsiElement reportErrorOn = typeProjection != null ? typeProjection : reportOn;
|
||||
|
||||
if (argumentDeclarationDescriptor instanceof TypeParameterDescriptor &&
|
||||
!((TypeParameterDescriptor) argumentDeclarationDescriptor).isReified()) {
|
||||
context.getTrace().report(Errors.TYPE_PARAMETER_AS_REIFIED.on(reportErrorOn, (TypeParameterDescriptor) argumentDeclarationDescriptor));
|
||||
}
|
||||
else if (TypeUtilsKt.cannotBeReified(argument)) {
|
||||
context.getTrace().report(Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(reportErrorOn, argument));
|
||||
}
|
||||
// REIFIED_TYPE_UNSAFE_SUBSTITUTION is temporary disabled because it seems too strict now (see KT-10847)
|
||||
//else if (TypeUtilsKt.unsafeAsReifiedArgument(argument) && !hasPureReifiableAnnotation(parameter)) {
|
||||
// context.getTrace().report(Errors.REIFIED_TYPE_UNSAFE_SUBSTITUTION.on(reportErrorOn, argument));
|
||||
//}
|
||||
checkTypeArgument(typeProjection != null ? typeProjection : reportOn, context, argument, argumentDeclarationDescriptor, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkTypeArgument(
|
||||
@NotNull PsiElement reportErrorOn,
|
||||
@NotNull CallCheckerContext context,
|
||||
KotlinType argument,
|
||||
ClassifierDescriptor argumentDeclarationDescriptor,
|
||||
boolean isArrayArgumentCheck
|
||||
) {
|
||||
if (argumentDeclarationDescriptor instanceof TypeParameterDescriptor) {
|
||||
TypeParameterDescriptor typeParameter = (TypeParameterDescriptor) argumentDeclarationDescriptor;
|
||||
if (typeParameter.isReified()) return;
|
||||
|
||||
DiagnosticFactory1<PsiElement, TypeParameterDescriptor> diagnosticFactory;
|
||||
|
||||
if (isArrayArgumentCheck) {
|
||||
if (context.getLanguageVersionSettings().supportsFeature(LanguageFeature.ProhibitNonReifiedArraysAsReifiedTypeArguments)) {
|
||||
diagnosticFactory = Errors.TYPE_PARAMETER_AS_REIFIED_ARRAY;
|
||||
} else {
|
||||
diagnosticFactory = Errors.TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING;
|
||||
}
|
||||
} else {
|
||||
diagnosticFactory = Errors.TYPE_PARAMETER_AS_REIFIED;
|
||||
}
|
||||
context.getTrace().report(diagnosticFactory.on(reportErrorOn, typeParameter));
|
||||
}
|
||||
else if (TypeUtilsKt.cannotBeReified(argument)) {
|
||||
context.getTrace().report(Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(reportErrorOn, argument));
|
||||
}
|
||||
else if (argumentDeclarationDescriptor instanceof ClassDescriptor &&
|
||||
KotlinBuiltIns.isNonPrimitiveArray((ClassDescriptor) argumentDeclarationDescriptor)) {
|
||||
KotlinType arrayTypeArgument = argument.getArguments().get(0).getType();
|
||||
ClassifierDescriptor arrayTypeArgumentDescriptor = arrayTypeArgument.getConstructor().getDeclarationDescriptor();
|
||||
checkTypeArgument(reportErrorOn, context, arrayTypeArgument, arrayTypeArgumentDescriptor, true);
|
||||
}
|
||||
// REIFIED_TYPE_UNSAFE_SUBSTITUTION is temporary disabled because it seems too strict now (see KT-10847)
|
||||
//else if (TypeUtilsKt.unsafeAsReifiedArgument(argument) && !hasPureReifiableAnnotation(parameter)) {
|
||||
// context.getTrace().report(Errors.REIFIED_TYPE_UNSAFE_SUBSTITUTION.on(reportErrorOn, argument));
|
||||
//}
|
||||
}
|
||||
|
||||
/*
|
||||
private static final FqName PURE_REIFIABLE_ANNOTATION_FQ_NAME = new FqName("kotlin.internal.PureReifiable");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user