Forbid dynamic on the RHS of is and as

This commit is contained in:
Andrey Breslav
2014-11-13 04:21:27 +02:00
parent 645d931a9e
commit c8029307fa
8 changed files with 62 additions and 6 deletions
@@ -533,6 +533,7 @@ public interface Errors {
DiagnosticFactory0<JetSimpleNameExpression> USELESS_CAST_STATIC_ASSERT_IS_FINE = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<JetSimpleNameExpression> USELESS_CAST = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<JetSimpleNameExpression> CAST_NEVER_SUCCEEDS = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<JetTypeReference> DYNAMIC_NOT_ALLOWED = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<JetExpression, JetType> IMPLICIT_CAST_TO_UNIT_OR_ANY = DiagnosticFactory1.create(WARNING);
@@ -259,6 +259,7 @@ public class DefaultErrorMessages {
MAP.put(USELESS_CAST_STATIC_ASSERT_IS_FINE, "No cast needed. You can use ':' if you need a cast to a super type");
MAP.put(USELESS_CAST, "No cast needed");
MAP.put(CAST_NEVER_SUCCEEDS, "This cast can never succeed");
MAP.put(DYNAMIC_NOT_ALLOWED, "Dynamic types are not allowed in this position");
MAP.put(USELESS_NULLABLE_CHECK, "Non-null type is checked for instance of nullable type");
MAP.put(WRONG_SETTER_PARAMETER_TYPE, "Setter parameter type must be equal to the type of the property, i.e. ''{0}''", RENDER_TYPE, RENDER_TYPE);
MAP.put(WRONG_GETTER_RETURN_TYPE, "Getter return type must be equal to the type of the property, i.e. ''{0}''", RENDER_TYPE, RENDER_TYPE);
@@ -209,6 +209,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
) {
if (actualType == null || noExpectedType(targetType)) return;
if (TypesPackage.isDynamic(targetType)) {
JetTypeReference right = expression.getRight();
assert right != null : "We know target is dynamic, but RHS is missing";
context.trace.report(DYNAMIC_NOT_ALLOWED.on(right));
return;
}
if (!CastDiagnosticsUtil.isCastPossible(actualType, targetType, components.platformToKotlinClassMap)) {
context.trace.report(CAST_NEVER_SUCCEEDS.on(expression.getOperationReference()));
return;
@@ -283,18 +283,23 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
}
TypeResolutionContext typeResolutionContext = new TypeResolutionContext(context.scope, context.trace, true, /*allowBareTypes=*/ true);
PossiblyBareType possiblyBareTarget = components.expressionTypingServices.getTypeResolver().resolvePossiblyBareType(typeResolutionContext, typeReferenceAfterIs);
JetType type = TypeReconstructionUtil.reconstructBareType(typeReferenceAfterIs, possiblyBareTarget, subjectType, context.trace);
if (!subjectType.isNullable() && type.isNullable()) {
JetType targetType = TypeReconstructionUtil.reconstructBareType(typeReferenceAfterIs, possiblyBareTarget, subjectType, context.trace);
if (TypesPackage.isDynamic(targetType)) {
context.trace.report(DYNAMIC_NOT_ALLOWED.on(typeReferenceAfterIs));
}
if (!subjectType.isNullable() && targetType.isNullable()) {
JetTypeElement element = typeReferenceAfterIs.getTypeElement();
assert element instanceof JetNullableType : "element must be instance of " + JetNullableType.class.getName();
JetNullableType nullableType = (JetNullableType) element;
context.trace.report(Errors.USELESS_NULLABLE_CHECK.on(nullableType));
}
checkTypeCompatibility(context, type, subjectType, typeReferenceAfterIs);
if (CastDiagnosticsUtil.isCastErased(subjectType, type, JetTypeChecker.DEFAULT)) {
context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(typeReferenceAfterIs, type));
checkTypeCompatibility(context, targetType, subjectType, typeReferenceAfterIs);
if (CastDiagnosticsUtil.isCastErased(subjectType, targetType, JetTypeChecker.DEFAULT)) {
context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(typeReferenceAfterIs, targetType));
}
return new DataFlowInfos(context.dataFlowInfo.establishSubtyping(subjectDataFlowValue, type), context.dataFlowInfo);
return new DataFlowInfos(context.dataFlowInfo.establishSubtyping(subjectDataFlowValue, targetType), context.dataFlowInfo);
}
private static DataFlowInfos noChange(ExpressionTypingContext context) {
@@ -0,0 +1,32 @@
// !DIAGNOSTICS: -REDUNDANT_NULLABLE
// MODULE[js]: m1
// FILE: k.kt
fun test(d: Any, dl: Collection<dynamic>) {
d as <!DYNAMIC_NOT_ALLOWED!>dynamic<!>
d as <!DYNAMIC_NOT_ALLOWED!>dynamic?<!>
d as? <!DYNAMIC_NOT_ALLOWED!>dynamic<!>
d as? <!DYNAMIC_NOT_ALLOWED!>dynamic?<!>
d is <!DYNAMIC_NOT_ALLOWED!>dynamic<!>
d is <!DYNAMIC_NOT_ALLOWED!>dynamic?<!>
d !is <!DYNAMIC_NOT_ALLOWED!>dynamic<!>
d !is <!DYNAMIC_NOT_ALLOWED!>dynamic?<!>
when (d) {
is <!DYNAMIC_NOT_ALLOWED!>dynamic<!> -> {}
is <!DYNAMIC_NOT_ALLOWED!>dynamic?<!> -> {}
!is <!DYNAMIC_NOT_ALLOWED!>dynamic<!> -> {}
!is <!DYNAMIC_NOT_ALLOWED!>dynamic?<!> -> {}
}
dl as List<dynamic>
dl is List<dynamic>
when (dl) {
is List<dynamic> -> {}
}
}
@@ -0,0 +1,3 @@
package
internal fun test(/*0*/ d: kotlin.Any, /*1*/ dl: kotlin.Collection<dynamic>): kotlin.Unit
@@ -3734,6 +3734,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("dynamicCastTarget.kt")
public void testDynamicCastTarget() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/dynamicCastTarget.kt");
doTest(fileName);
}
@TestMetadata("dynamicSafeCalls.kt")
public void testDynamicSafeCalls() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/dynamicSafeCalls.kt");
+1
View File
@@ -79,3 +79,4 @@ but it's hard to be sure it's worth the while
## Notes
- dynamic types are not supported on the JVM back-end
- dynamic types are forbidden on the right-hand side of `is`, `!is`, `as` and `as?` (but not as generic arguments, e.g. `x is List<dynamic>` is allowed)