| 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,
|
|
|