| Index: sdk/lib/_internal/compiler/implementation/typechecker.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart
|
| index b58a0eb6c5e99eb269c61455a61225bb5b4b5215..c08092655ab2816cec09837a2012a8431c7d76a0 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/typechecker.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
|
| @@ -680,6 +680,20 @@ class TypeCheckerVisitor implements Visitor<DartType> {
|
| }
|
| }
|
|
|
| + /// Returns the first type in the list or [:dynamic:] if the list is empty.
|
| + DartType firstType(Link<DartType> link) {
|
| + return link.isEmpty ? types.dynamicType : link.head;
|
| + }
|
| +
|
| + /**
|
| + * Returns the second type in the list or [:dynamic:] if the list is too
|
| + * short.
|
| + */
|
| + DartType secondType(Link<DartType> link) {
|
| + return link.isEmpty || link.tail.isEmpty
|
| + ? types.dynamicType : link.tail.head;
|
| + }
|
| +
|
| /**
|
| * Checks [: target o= value :] for some operator o, and returns the type
|
| * of the result. This method also handles increment/decrement expressions
|
| @@ -701,7 +715,7 @@ class TypeCheckerVisitor implements Visitor<DartType> {
|
| FunctionType operatorType = operator;
|
| // [result] is the type of target o value.
|
| DartType result = operatorType.returnType;
|
| - DartType operatorArgument = operatorType.parameterTypes.head;
|
| + DartType operatorArgument = firstType(operatorType.parameterTypes);
|
| // Check target o value.
|
| bool validValue = checkAssignable(valueNode, value, operatorArgument);
|
| if (validValue || !(node.isPrefix || node.isPostfix)) {
|
| @@ -732,7 +746,7 @@ class TypeCheckerVisitor implements Visitor<DartType> {
|
| node, base, const SourceString('[]'), MemberKind.OPERATOR);
|
| if (indexGet is FunctionType) {
|
| FunctionType indexGetType = indexGet;
|
| - DartType indexGetKey = indexGetType.parameterTypes.head;
|
| + DartType indexGetKey = firstType(indexGetType.parameterTypes);
|
| // Check base[key].
|
| bool validKey = checkAssignable(keyNode, key, indexGetKey);
|
|
|
| @@ -745,7 +759,7 @@ class TypeCheckerVisitor implements Visitor<DartType> {
|
| FunctionType operatorType = operator;
|
|
|
| // Check base[key] o value.
|
| - DartType operatorArgument = operatorType.parameterTypes.head;
|
| + DartType operatorArgument = firstType(operatorType.parameterTypes);
|
| bool validValue = checkAssignable(valueNode, value, operatorArgument);
|
|
|
| // [result] is the type of base[key] o value.
|
| @@ -756,9 +770,8 @@ class TypeCheckerVisitor implements Visitor<DartType> {
|
| node, base, const SourceString('[]='), MemberKind.OPERATOR);
|
| if (indexSet is FunctionType) {
|
| FunctionType indexSetType = indexSet;
|
| - DartType indexSetKey = indexSetType.parameterTypes.head;
|
| - DartType indexSetValue =
|
| - indexSetType.parameterTypes.tail.head;
|
| + DartType indexSetKey = firstType(indexSetType.parameterTypes);
|
| + DartType indexSetValue = secondType(indexSetType.parameterTypes);
|
|
|
| if (validKey || indexGetKey != indexSetKey) {
|
| // Only check base[key] on []= if base[key] was valid for [] or
|
| @@ -793,9 +806,9 @@ class TypeCheckerVisitor implements Visitor<DartType> {
|
| node, base, const SourceString('[]='), MemberKind.OPERATOR);
|
| if (indexSet is FunctionType) {
|
| FunctionType indexSetType = indexSet;
|
| - DartType indexSetKey = indexSetType.parameterTypes.head;
|
| + DartType indexSetKey = firstType(indexSetType.parameterTypes);
|
| checkAssignable(keyNode, key, indexSetKey);
|
| - DartType indexSetValue = indexSetType.parameterTypes.tail.head;
|
| + DartType indexSetValue = secondType(indexSetType.parameterTypes);
|
| checkAssignable(node.assignmentOperator, value, indexSetValue);
|
| }
|
| return value;
|
| @@ -899,7 +912,7 @@ class TypeCheckerVisitor implements Visitor<DartType> {
|
|
|
| DartType visitLiteralList(LiteralList node) {
|
| InterfaceType listType = elements.getType(node);
|
| - DartType listElementType = listType.typeArguments.head;
|
| + DartType listElementType = firstType(listType.typeArguments);
|
| for (Link<Node> link = node.elements.nodes;
|
| !link.isEmpty;
|
| link = link.tail) {
|
| @@ -1087,8 +1100,8 @@ class TypeCheckerVisitor implements Visitor<DartType> {
|
|
|
| visitLiteralMap(LiteralMap node) {
|
| InterfaceType mapType = elements.getType(node);
|
| - DartType mapKeyType = mapType.typeArguments.head;
|
| - DartType mapValueType = mapType.typeArguments.tail.head;
|
| + DartType mapKeyType = firstType(mapType.typeArguments);
|
| + DartType mapValueType = secondType(mapType.typeArguments);
|
| for (Link<Node> link = node.entries.nodes;
|
| !link.isEmpty;
|
| link = link.tail) {
|
| @@ -1122,7 +1135,15 @@ class TypeCheckerVisitor implements Visitor<DartType> {
|
| }
|
|
|
| visitTryStatement(TryStatement node) {
|
| - return unhandledStatement();
|
| + // TODO(johnniwinther): Use reachability information of try-block,
|
| + // catch-blocks and finally-block to compute the whether the try statement
|
| + // is returning.
|
| + analyze(node.tryBlock);
|
| + for (CatchBlock catchBlock in node.catchBlocks) {
|
| + analyze(catchBlock);
|
| + }
|
| + analyzeWithDefault(node.finallyBlock, null);
|
| + return StatementType.NOT_RETURNING;
|
| }
|
|
|
| visitScriptTag(ScriptTag node) {
|
| @@ -1130,7 +1151,7 @@ class TypeCheckerVisitor implements Visitor<DartType> {
|
| }
|
|
|
| visitCatchBlock(CatchBlock node) {
|
| - return unhandledStatement();
|
| + return analyze(node.block);
|
| }
|
|
|
| visitTypedef(Typedef node) {
|
|
|