Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(320)

Unified Diff: sdk/lib/_internal/compiler/implementation/ssa/builder.dart

Issue 48383003: Support checking of malbounded types. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index c3b9ed91b625bcab9a7ee11f1a4b0fa465fe3dc9..c682305f0a2bcba41e93d8e6c15f2014e96dce49 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -1921,6 +1921,22 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
return other;
}
+ void assertIsSubtype(Node node, DartType subtype, DartType supertype,
+ String message) {
+ HInstruction subtypeInstruction = analyzeTypeArgument(subtype);
+ HInstruction supertypeInstruction = analyzeTypeArgument(supertype);
+ HInstruction messageInstruction =
+ graph.addConstantString(new DartString.literal(message),
+ node, compiler);
+ Element element = backend.getAssertIsSubtype();
+ var inputs = <HInstruction>[subtypeInstruction, supertypeInstruction,
+ messageInstruction];
+ HInstruction assertIsSubtype = new HInvokeStatic(
+ element, inputs, subtypeInstruction.instructionType);
+ compiler.backend.registerTypeVariableBoundsSubtypeCheck(subtype, supertype);
+ add(assertIsSubtype);
+ }
+
HGraph closeFunction() {
// TODO(kasperl): Make this goto an implicit return.
if (!isAborted()) closeAndGotoExit(new HGoto());
@@ -3645,6 +3661,8 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
type = functionElement.computeTargetType(compiler, type);
}
+ if (checkTypeVariableBounds(node, type)) return;
+
var inputs = <HInstruction>[];
if (constructor.isGenerativeConstructor() &&
Elements.isNativeOrExtendsNative(constructor.getEnclosingClass())) {
@@ -3702,6 +3720,66 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
}
}
+ /// In checked mode checks the [type] of [node] to be well-bounded. The method
+ /// returns [:true:] if an error can be statically determined.
+ bool checkTypeVariableBounds(NewExpression node, InterfaceType type) {
+ if (!compiler.enableTypeAssertions) return false;
+
+ Map<DartType, Set<DartType>> seenChecksMap =
+ new Map<DartType, Set<DartType>>();
+ bool staticError = false;
karlklose 2013/10/30 09:47:43 How about 'definitelyFails'?
Johnni Winther 2013/10/30 11:19:42 Done.
+
+ addTypeVariableBoundCheck(GenericType instance,
+ DartType typeArgument,
+ TypeVariableType typeVariable,
+ DartType bound) {
+ if (staticError) return;
+
+ int maybeSubtype = compiler.types.isMaybeSubtype(typeArgument, bound);
karlklose 2013/10/30 09:47:43 'maybeSubtype' -> 'subtypeRelation'?
Johnni Winther 2013/10/30 11:19:42 Done.
+ if (maybeSubtype == Types.IS_SUBTYPE) return;
+
+ String message;
karlklose 2013/10/30 09:47:43 You can merge the two branches like this: String
Johnni Winther 2013/10/30 11:19:42 Done.
+ if (type == instance) {
+ message = "Can't create an instance of malbounded type '$type': "
+ "'${typeArgument}' is not a subtype of bound '${bound}' for "
+ "type variable '${typeVariable}' of type "
+ "'${type.element.thisType}'.";
+ } else {
+ message = "Can't create an instance of malbounded type '$type': "
+ "'${typeArgument}' is not a subtype of bound '${bound}' for "
+ "type variable '${typeVariable}' of type "
+ "'${instance.element.thisType}' on the supertype '${instance}' of "
+ "'${type}'.";
+ }
+ if (maybeSubtype == Types.NOT_SUBTYPE) {
+ generateTypeError(node, message);
+ staticError = true;
+ return;
+ } else if (maybeSubtype == Types.MAYBE_SUBTYPE) {
+ Set<DartType> seenChecks =
+ seenChecksMap.putIfAbsent(typeArgument, () => new Set<DartType>());
+ if (!seenChecks.contains(bound)) {
+ seenChecks.add(bound);
+ assertIsSubtype(node, typeArgument, bound, message);
+ }
+ }
+ }
+
+ compiler.types.checkTypeVariableBounds(type, addTypeVariableBoundCheck);
+ if (staticError) {
+ return true;
+ }
+ for (InterfaceType supertype in type.element.allSupertypes) {
+ DartType instance = type.asInstanceOf(supertype.element);
+ compiler.types.checkTypeVariableBounds(instance,
+ addTypeVariableBoundCheck);
+ if (staticError) {
+ return true;
+ }
+ }
+ return false;
+ }
+
visitAssert(node) {
if (!compiler.enableUserAssertions) {
stack.add(graph.addConstantNull(compiler));
@@ -3814,6 +3892,10 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
generateError(node, message, backend.getThrowRuntimeError());
}
+ void generateTypeError(Node node, String message) {
+ generateError(node, message, backend.getThrowTypeError());
+ }
+
void generateAbstractClassInstantiationError(Node node, String message) {
generateError(node,
message,

Powered by Google App Engine
This is Rietveld 408576698