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

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: Updated cf. comments 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..1861206cc86a0cad7b192a482b332abf76d94a9e 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,62 @@ 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 definitelyFails = false;
+
+ addTypeVariableBoundCheck(GenericType instance,
+ DartType typeArgument,
+ TypeVariableType typeVariable,
+ DartType bound) {
+ if (definitelyFails) return;
+
+ int subtypeRelation = compiler.types.computeSubtypeRelation(typeArgument, bound);
+ if (subtypeRelation == Types.IS_SUBTYPE) return;
+
+ String 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 == instance
+ ? "'${type.element.thisType}'"
+ : "'${instance.element.thisType}' on the supertype "
+ "'${instance}' of '${type}'"
+ }.";
+ if (subtypeRelation == Types.NOT_SUBTYPE) {
+ generateTypeError(node, message);
+ definitelyFails = true;
+ return;
+ } else if (subtypeRelation == 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 (definitelyFails) {
+ return true;
+ }
+ for (InterfaceType supertype in type.element.allSupertypes) {
+ DartType instance = type.asInstanceOf(supertype.element);
+ compiler.types.checkTypeVariableBounds(instance,
+ addTypeVariableBoundCheck);
+ if (definitelyFails) {
+ return true;
+ }
+ }
+ return false;
+ }
+
visitAssert(node) {
if (!compiler.enableUserAssertions) {
stack.add(graph.addConstantNull(compiler));
@@ -3814,6 +3888,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,
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/resolution/members.dart ('k') | sdk/lib/_internal/lib/js_helper.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698