| Index: sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| index 1ea01a85e38bdbc3d007b9cf76a1c7b54b4d5018..e5b2b8b6137ac7632ad876c4acd2ed8585a40059 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| @@ -3465,6 +3465,91 @@ class ResolverVisitor extends MappingVisitor<Element> {
|
| visit(node.expression);
|
| }
|
|
|
| + DartType typeOfConstant(Constant constant) {
|
| + if (constant.isInt()) return compiler.intClass.rawType;
|
| + if (constant.isBool()) return compiler.boolClass.rawType;
|
| + if (constant.isDouble()) return compiler.doubleClass.rawType;
|
| + if (constant.isString()) return compiler.stringClass.rawType;
|
| + if (constant.isNull()) return compiler.nullClass.rawType;
|
| + if (constant.isFunction()) return compiler.functionClass.rawType;
|
| + assert(constant.isObject());
|
| + ObjectConstant objectConstant = constant;
|
| + return objectConstant.type;
|
| + }
|
| +
|
| + bool overridesEquals(DartType type) {
|
| + ClassElement cls = type.element;
|
| + Element equals = cls.lookupMember('==');
|
| + return equals.getEnclosingClass() != compiler.objectClass;
|
| + }
|
| +
|
| + void checkCaseExpressions(SwitchStatement node) {
|
| + TargetElement breakElement = getOrCreateTargetElement(node);
|
| + Map<String, LabelElement> continueLabels = <String, LabelElement>{};
|
| +
|
| + Link<Node> cases = node.cases.nodes;
|
| + SwitchCase switchCase = cases.head;
|
| + CaseMatch firstCase = null;
|
| + DartType firstCaseType = null;
|
| + bool hasReportedProblem = false;
|
| +
|
| + for (Link<Node> cases = node.cases.nodes;
|
| + !cases.isEmpty;
|
| + cases = cases.tail) {
|
| + SwitchCase switchCase = cases.head;
|
| +
|
| + for (Node labelOrCase in switchCase.labelsAndCases) {
|
| + CaseMatch caseMatch = labelOrCase.asCaseMatch();
|
| + if (caseMatch == null) continue;
|
| +
|
| + // Analyze the constant.
|
| + Constant constant = mapping.getConstant(caseMatch.expression);
|
| + assert(invariant(node, constant != null,
|
| + message: 'No constant computed for $node'));
|
| +
|
| + DartType caseType = typeOfConstant(constant);
|
| +
|
| + if (firstCaseType == null) {
|
| + firstCase = caseMatch;
|
| + firstCaseType = caseType;
|
| +
|
| + // We only report the bad type on the first class element. All others
|
| + // get a "type differs" error.
|
| + if (caseType.element == compiler.doubleClass) {
|
| + compiler.reportError(node,
|
| + MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS,
|
| + {'type': "double"});
|
| + } else if (caseType.element == compiler.functionClass) {
|
| + compiler.reportError(node, MessageKind.SWITCH_CASE_FORBIDDEN,
|
| + {'type': "Function"});
|
| + } else if (constant.isObject() && overridesEquals(caseType)) {
|
| + compiler.reportError(firstCase.expression,
|
| + MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS,
|
| + {'type': caseType});
|
| + }
|
| + } else {
|
| + if (caseType != firstCaseType) {
|
| + if (!hasReportedProblem) {
|
| + compiler.reportError(
|
| + node,
|
| + MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL,
|
| + {'type': firstCaseType});
|
| + compiler.reportInfo(
|
| + firstCase.expression,
|
| + MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE,
|
| + {'type': firstCaseType});
|
| + hasReportedProblem = true;
|
| + }
|
| + compiler.reportInfo(
|
| + caseMatch.expression,
|
| + MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE,
|
| + {'type': caseType});
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| visitSwitchStatement(SwitchStatement node) {
|
| node.expression.accept(this);
|
|
|
| @@ -3516,6 +3601,10 @@ class ResolverVisitor extends MappingVisitor<Element> {
|
| }
|
| }
|
|
|
| + addDeferredAction(enclosingElement, () {
|
| + checkCaseExpressions(node);
|
| + });
|
| +
|
| statementScope.enterSwitch(breakElement, continueLabels);
|
| node.cases.accept(this);
|
| statementScope.exitSwitch();
|
|
|