Report an error on dynamic types used as supertypes or upper bounds

This commit is contained in:
Andrey Breslav
2014-11-21 16:48:21 +03:00
parent 65164e95b5
commit ea36024893
7 changed files with 48 additions and 5 deletions
@@ -149,6 +149,7 @@ public interface Errors {
DiagnosticFactory0<JetTypeReference> FINAL_SUPERTYPE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetTypeReference> SINGLETON_IN_SUPERTYPE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetNullableType> NULLABLE_SUPERTYPE = DiagnosticFactory0.create(ERROR, NULLABLE_TYPE);
DiagnosticFactory0<JetTypeReference> DYNAMIC_SUPERTYPE = DiagnosticFactory0.create(ERROR);
// Trait-specific
@@ -196,6 +197,7 @@ public interface Errors {
DiagnosticFactory1<JetTypeReference, JetType> FINAL_UPPER_BOUND = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<JetTypeReference, JetType> FINAL_CLASS_OBJECT_UPPER_BOUND = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<JetTypeReference> DYNAMIC_UPPER_BOUND = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<JetNamedDeclaration, TypeParameterDescriptor> CONFLICTING_UPPER_BOUNDS =
DiagnosticFactory1.create(ERROR, DECLARATION_NAME);
@@ -322,6 +322,7 @@ public class DefaultErrorMessages {
MAP.put(UPPER_BOUND_VIOLATED, "Type argument is not within its bounds: should be subtype of ''{0}''", RENDER_TYPE, RENDER_TYPE);
MAP.put(FINAL_CLASS_OBJECT_UPPER_BOUND, "''{0}'' is a final type, and thus a class object cannot extend it", RENDER_TYPE);
MAP.put(FINAL_UPPER_BOUND, "''{0}'' is a final type, and thus a value of the type parameter is predetermined", RENDER_TYPE);
MAP.put(DYNAMIC_UPPER_BOUND, "Dynamic type can not be used as an upper bound");
MAP.put(USELESS_ELVIS, "Elvis operator (?:) always returns the left operand of non-nullable type {0}", RENDER_TYPE);
MAP.put(CONFLICTING_UPPER_BOUNDS, "Upper bounds of {0} have empty intersection", NAME);
MAP.put(CONFLICTING_CLASS_OBJECT_UPPER_BOUNDS, "Class object upper bounds of {0} have empty intersection", NAME);
@@ -365,6 +366,7 @@ public class DefaultErrorMessages {
MAP.put(ANONYMOUS_INITIALIZER_IN_TRAIT, "Anonymous initializers are not allowed in traits");
MAP.put(NULLABLE_SUPERTYPE, "A supertype cannot be nullable");
MAP.put(DYNAMIC_SUPERTYPE, "A supertype cannot be dynamic");
MAP.put(REDUNDANT_NULLABLE, "Redundant '?'");
MAP.put(BASE_WITH_NULLABLE_UPPER_BOUND, "''{0}'' has a nullable upper bound. " +
"This means that a value of this type may be null. " +
@@ -238,9 +238,15 @@ public class DescriptorResolver {
for (JetDelegationSpecifier delegationSpecifier : delegationSpecifiers) {
JetTypeReference typeReference = delegationSpecifier.getTypeReference();
if (typeReference != null) {
result.add(resolver.resolveType(extensibleScope, typeReference, trace, checkBounds));
JetTypeElement bareSuperType = checkNullableSupertypeAndStripQuestionMarks(trace, typeReference.getTypeElement());
checkProjectionsInImmediateArguments(trace, bareSuperType);
JetType supertype = resolver.resolveType(extensibleScope, typeReference, trace, checkBounds);
if (TypesPackage.isDynamic(supertype)) {
trace.report(DYNAMIC_SUPERTYPE.on(typeReference));
}
else {
result.add(supertype);
JetTypeElement bareSuperType = checkNullableSupertypeAndStripQuestionMarks(trace, typeReference.getTypeElement());
checkProjectionsInImmediateArguments(trace, bareSuperType);
}
}
else {
result.add(ErrorUtils.createErrorType("No type reference"));
@@ -791,6 +797,9 @@ public class DescriptorResolver {
trace.report(FINAL_UPPER_BOUND.on(upperBound, upperBoundType));
}
}
if (TypesPackage.isDynamic(upperBoundType)) {
trace.report(DYNAMIC_UPPER_BOUND.on(upperBound));
}
}
@NotNull
@@ -1366,7 +1375,7 @@ public class DescriptorResolver {
List<JetTypeReference> jetTypeArguments = typeElement.getTypeArgumentsAsTypes();
// A type reference from Kotlin code can yield a flexible type only if it's `ft<T1, T2>`, whose bounds should not be checked
if (TypesPackage.isFlexible(type)) {
if (TypesPackage.isFlexible(type) && !TypesPackage.isDynamic(type)) {
assert jetTypeArguments.size() == 2
: "Flexible type cannot be denoted in Kotlin otherwise than as ft<T1, T2>, but was: "
+ JetPsiUtil.getElementTextWithContext(typeReference);
@@ -0,0 +1,8 @@
// MODULE[js]: m1
// FILE: k.kt
trait Tr : <!DYNAMIC_SUPERTYPE!>dynamic<!>
fun <T: <!DYNAMIC_UPPER_BOUND!>dynamic<!>> foo() {}
class C<T> where T : <!DYNAMIC_UPPER_BOUND!>dynamic<!>
@@ -0,0 +1,16 @@
package
internal fun </*0*/ T : dynamic> foo(): kotlin.Unit
internal final class C</*0*/ T : dynamic> {
public constructor C</*0*/ T : dynamic>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
internal trait Tr {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -3818,6 +3818,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("supertypesAndBounds.kt")
public void testSupertypesAndBounds() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/supertypesAndBounds.kt");
doTest(fileName);
}
@TestMetadata("unsupported.kt")
public void testUnsupported() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/unsupported.kt");
+1 -1
View File
@@ -31,7 +31,7 @@ fun jsFun(p: dynamic): dynamic
- `lub(T, dynamic) = dynamic`
- ??? `glb(T, dynamic) = T`
- `dynamic` can't be substituted for reified parameters of function/constructor calls (this means that it's not possible to create an array of `dynamic`)
- `dynamic` can't be used as a supertype or upper bound for a tpe parameter
- `dynamic` can't be used as a supertype or upper bound for a type parameter
- `dynamic` is less specific than any other type
## Syntax