Version 1.3.0-dev.1.1
svn merge -c 33152 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@33192 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
index 86662f7..94d80bb 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
@@ -842,14 +842,19 @@
} else if ("&&" == op.source) {
conditionIsSimple = false;
bool oldAccumulateIsChecks = accumulateIsChecks;
- accumulateIsChecks = true;
- if (isChecks == null) isChecks = <Send>[];
+ List<Send> oldIsChecks = isChecks;
+ if (!accumulateIsChecks) {
+ accumulateIsChecks = true;
+ isChecks = <Send>[];
+ }
visit(node.receiver);
- accumulateIsChecks = oldAccumulateIsChecks;
- if (!accumulateIsChecks) isChecks = null;
LocalsHandler<T> saved = locals;
locals = new LocalsHandler<T>.from(locals, node);
updateIsChecks(isChecks, usePositive: true);
+ if (!oldAccumulateIsChecks) {
+ accumulateIsChecks = false;
+ isChecks = oldIsChecks;
+ }
visit(node.arguments.head);
saved.mergeDiamondFlow(locals, null);
locals = saved;
@@ -857,10 +862,10 @@
} else if ("||" == op.source) {
conditionIsSimple = false;
List<Send> tests = <Send>[];
- handleCondition(node.receiver, tests);
+ bool isSimple = handleCondition(node.receiver, tests);
LocalsHandler<T> saved = locals;
locals = new LocalsHandler<T>.from(locals, node);
- updateIsChecks(tests, usePositive: false);
+ if (isSimple) updateIsChecks(tests, usePositive: false);
bool oldAccumulateIsChecks = accumulateIsChecks;
accumulateIsChecks = false;
visit(node.arguments.head);
diff --git a/tests/compiler/dart2js/simple_inferrer_and_or_test.dart b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
index 97531a6..dea4f69 100644
--- a/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
@@ -45,6 +45,39 @@
return a;
}
+returnDyn7b(x) => x;
+
+returnDyn7() {
+ var a = "foo";
+ if (a.length == 3) a = 52;
+ if ((a is int) || (a is String && true)) returnDyn7b(a);
+ return a;
+}
+
+returnDyn8(x) => x;
+
+test8() {
+ var a = "foo";
+ if (a.length == 3) a = 52;
+ if ((false && a is! String) || returnDyn8(a)) return a;
+}
+
+returnDyn9(x) => x;
+
+test9() {
+ var a = "foo";
+ if (a.length == 3) a = 52;
+ if (!(a is bool && a is bool)) returnDyn9(a);
+}
+
+returnString(x) => x;
+
+test10() {
+ var a = "foo";
+ if (a.length == 3) a = 52;
+ if (!(a is num) && a is String) returnString(a);
+}
+
main() {
returnDyn1();
returnDyn2();
@@ -52,6 +85,10 @@
returnDyn4();
returnDyn5();
returnDyn6();
+ returnDyn7();
+ test8();
+ test9();
+ test10();
}
""";
@@ -77,5 +114,10 @@
checkReturn('returnDyn4', compiler.typesTask.dynamicType.nonNullable());
checkReturn('returnDyn5', compiler.typesTask.dynamicType.nonNullable());
checkReturn('returnDyn6', compiler.typesTask.dynamicType.nonNullable());
+ checkReturn('returnDyn7', subclassOfInterceptor);
+ checkReturn('returnDyn7b', subclassOfInterceptor);
+ checkReturn('returnDyn8', subclassOfInterceptor);
+ checkReturn('returnDyn9', subclassOfInterceptor);
+ checkReturn('returnString', compiler.typesTask.stringType);
}));
}
diff --git a/tests/language/logical_expression2_test.dart b/tests/language/logical_expression2_test.dart
new file mode 100644
index 0000000..7d6ddd5
--- /dev/null
+++ b/tests/language/logical_expression2_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Regression test for issue 17149.
+
+int globalCounter = 0;
+
+void nonInlinedUse(Object object) {
+ if (new DateTime.now().millisecondsSinceEpoch == 42) nonInlinedUse(object);
+ if (object is! String) globalCounter++;
+}
+
+int confuse(x) {
+ if (new DateTime.now().millisecondsSinceEpoch == 42) return confuse(x - 1);
+ return x;
+}
+
+main() {
+ var o = [ "foo", 499 ][confuse(1)];
+
+ // The `o is String` check in the rhs of the logical or must not be
+ // propagated to the `if` body.
+ if ((o is num) ||
+ (o is String && true)) {
+ nonInlinedUse(o);
+ }
+ Expect.equals(1, globalCounter);
+}
diff --git a/tests/language/logical_expression3_test.dart b/tests/language/logical_expression3_test.dart
new file mode 100644
index 0000000..2a90d70
--- /dev/null
+++ b/tests/language/logical_expression3_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+bool nonInlinedNumTypeCheck(Object object) {
+ if (new DateTime.now().millisecondsSinceEpoch == 42) {
+ return nonInlinedNumTypeCheck(object);
+ }
+ return object is num;
+}
+
+int confuse(x) {
+ if (new DateTime.now().millisecondsSinceEpoch == 42) return confuse(x - 1);
+ return x;
+}
+
+main() {
+ var o = [ "foo", 499 ][confuse(0)];
+
+ // When the lhs of a logical or fails, it must not assume that all negative is
+ // checks in it, have failed.
+ // Here, the `o is! num` check succeeds, but the length test failed.
+ if ((o is! num && o.length == 4) ||
+ (nonInlinedNumTypeCheck(o))) {
+ Expect.fail("Type-check failed");
+ }
+}
diff --git a/tests/language/logical_expression4_test.dart b/tests/language/logical_expression4_test.dart
new file mode 100644
index 0000000..4799a88
--- /dev/null
+++ b/tests/language/logical_expression4_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+bool nonInlinedNumTypeCheck(Object object) {
+ if (new DateTime.now().millisecondsSinceEpoch == 42) {
+ return nonInlinedNumTypeCheck(object);
+ }
+ return object is num;
+}
+
+int confuse(x) {
+ if (new DateTime.now().millisecondsSinceEpoch == 42) return confuse(x - 1);
+ return x;
+}
+
+main() {
+ var o = [ "foo", 499 ][confuse(0)];
+
+ // The is-checks in the '!' must not be propagated to the if-body.
+ // This was a bug in dart2js.
+ if (!(o is num && o is num)) {
+ Expect.isFalse((nonInlinedNumTypeCheck(o)));
+ }
+}
diff --git a/tests/language/logical_expression5_test.dart b/tests/language/logical_expression5_test.dart
new file mode 100644
index 0000000..5d983e0
--- /dev/null
+++ b/tests/language/logical_expression5_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+bool nonInlinedNumTypeCheck(Object object) {
+ if (new DateTime.now().millisecondsSinceEpoch == 42) {
+ return nonInlinedNumTypeCheck(object);
+ }
+ return object is num;
+}
+
+bool nonInlinedStringTypeCheck(Object object) {
+ if (new DateTime.now().millisecondsSinceEpoch == 42) {
+ return nonInlinedStringTypeCheck(object);
+ }
+ return object is String;
+}
+
+int confuse(x) {
+ if (new DateTime.now().millisecondsSinceEpoch == 42) return confuse(x - 1);
+ return x;
+}
+
+main() {
+ var o = [ "foo", 499 ][confuse(0)];
+
+ // The is-checks in the '!' must not be propagated to the if-body, but
+ // the second is-check should.
+ if (!(o is num) && o is String) {
+ Expect.isFalse((nonInlinedNumTypeCheck(o)));
+ Expect.isTrue((nonInlinedStringTypeCheck(o)));
+ }
+}
diff --git a/tools/VERSION b/tools/VERSION
index d673332..b392055 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 3
PATCH 0
PRERELEASE 1
-PRERELEASE_PATCH 0
+PRERELEASE_PATCH 1