Forbid dynamic on the RHS of is and as
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
+1
@@ -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);
|
||||
|
||||
+7
@@ -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;
|
||||
|
||||
+11
-6
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user