Version 2.11.0-198.0.dev
Merge commit 'b4f265290c75fd6c6370cf1403f2b2649c59ad39' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index 637e387..de9e6cc 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -351,6 +351,9 @@
/// Call this method when visiting a boolean literal expression.
void booleanLiteral(Expression expression, bool value);
+ /// Call this method just before visiting a conditional expression ("?:").
+ void conditional_conditionBegin();
+
/// Call this method upon reaching the ":" part of a conditional expression
/// ("?:"). [thenExpression] should be the expression preceding the ":".
void conditional_elseBegin(Expression thenExpression);
@@ -867,6 +870,12 @@
}
@override
+ void conditional_conditionBegin() {
+ _wrap('conditional_conditionBegin()',
+ () => _wrapped.conditional_conditionBegin());
+ }
+
+ @override
void conditional_elseBegin(Expression thenExpression) {
_wrap('conditional_elseBegin($thenExpression',
() => _wrapped.conditional_elseBegin(thenExpression));
@@ -2732,6 +2741,11 @@
}
@override
+ void conditional_conditionBegin() {
+ _current = _current.split();
+ }
+
+ @override
void conditional_elseBegin(Expression thenExpression) {
_ConditionalContext<Variable, Type> context =
_stack.last as _ConditionalContext<Variable, Type>;
@@ -2749,9 +2763,9 @@
_storeExpressionInfo(
conditionalExpression,
new ExpressionInfo(
- _join(thenInfo.after, elseInfo.after),
- _join(thenInfo.ifTrue, elseInfo.ifTrue),
- _join(thenInfo.ifFalse, elseInfo.ifFalse)));
+ _merge(thenInfo.after, elseInfo.after),
+ _merge(thenInfo.ifTrue, elseInfo.ifTrue),
+ _merge(thenInfo.ifFalse, elseInfo.ifFalse)));
}
@override
@@ -2771,9 +2785,9 @@
AssignedVariablesNodeInfo<Variable> info =
_assignedVariables._getInfoForNode(doStatement);
_BranchTargetContext<Variable, Type> context =
- new _BranchTargetContext<Variable, Type>(_current.reachable.parent);
+ new _BranchTargetContext<Variable, Type>(_current.reachable);
_stack.add(context);
- _current = _current.conservativeJoin(info._written, info._captured);
+ _current = _current.conservativeJoin(info._written, info._captured).split();
_statementToContext[doStatement] = context;
}
@@ -2788,7 +2802,7 @@
void doStatement_end(Expression condition) {
_BranchTargetContext<Variable, Type> context =
_stack.removeLast() as _BranchTargetContext<Variable, Type>;
- _current = _join(_expressionEnd(condition).ifFalse, context._breakModel);
+ _current = _merge(_expressionEnd(condition).ifFalse, context._breakModel);
}
@override
@@ -2868,7 +2882,7 @@
void for_conditionBegin(Node node) {
AssignedVariablesNodeInfo<Variable> info =
_assignedVariables._getInfoForNode(node);
- _current = _current.conservativeJoin(info._written, info._captured);
+ _current = _current.conservativeJoin(info._written, info._captured).split();
}
@override
@@ -2879,7 +2893,7 @@
FlowModel<Variable, Type> breakState = context._breakModel;
FlowModel<Variable, Type> falseCondition = context._conditionInfo.ifFalse;
- _current = _join(falseCondition, breakState)
+ _current = _merge(falseCondition, breakState)
.inheritTested(typeOperations, _current);
}
@@ -2894,7 +2908,7 @@
void forEach_bodyBegin(Node node, Variable loopVariable, Type writtenType) {
AssignedVariablesNodeInfo<Variable> info =
_assignedVariables._getInfoForNode(node);
- _current = _current.conservativeJoin(info._written, info._captured);
+ _current = _current.conservativeJoin(info._written, info._captured).split();
_SimpleStatementContext<Variable, Type> context =
new _SimpleStatementContext<Variable, Type>(
_current.reachable.parent, _current);
@@ -2908,7 +2922,7 @@
void forEach_end() {
_SimpleStatementContext<Variable, Type> context =
_stack.removeLast() as _SimpleStatementContext<Variable, Type>;
- _current = _join(_current, context._previous);
+ _current = _merge(_current, context._previous);
}
@override
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
index 0af6a2f..979be2e 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
@@ -76,6 +76,7 @@
var x = h.addVar('x', 'int?');
h.run((flow) {
h.declare(x, initialized: true);
+ flow.conditional_conditionBegin();
flow.conditional_thenBegin(h.notNull(x, _Type('int?'))());
expect(flow.promotedType(x).type, 'int');
flow.conditional_elseBegin(_Expression());
@@ -90,6 +91,7 @@
var x = h.addVar('x', 'int?');
h.run((flow) {
h.declare(x, initialized: true);
+ flow.conditional_conditionBegin();
flow.conditional_thenBegin(h.eqNull(x, _Type('int?'))());
expect(flow.promotedType(x), isNull);
flow.conditional_elseBegin(_Expression());
@@ -109,6 +111,7 @@
h.declare(x, initialized: true);
h.declare(y, initialized: true);
h.declare(z, initialized: true);
+ flow.conditional_conditionBegin();
flow.conditional_thenBegin(_Expression());
h.promote(x, 'int');
h.promote(y, 'int');
@@ -4176,6 +4179,7 @@
LazyExpression cond, LazyExpression ifTrue, LazyExpression ifFalse) {
return () {
var expr = _Expression();
+ _flow.conditional_conditionBegin();
_flow.conditional_thenBegin(cond());
_flow.conditional_elseBegin(ifTrue());
_flow.conditional_end(expr, ifFalse());
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart
index 9b8e497..4f93355 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart
@@ -29,3 +29,19 @@
x is int? ? /*int?*/ x : /*num*/ x;
x;
}
+
+void conditional_join_then(bool b, Object x) {
+ if (b ? x is int : x is int) {
+ /*int*/ x;
+ } else {
+ x;
+ }
+}
+
+void conditional_join_else(bool b, Object x) {
+ if (b ? x is! int : x is! int) {
+ x;
+ } else {
+ /*int*/ x;
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart
index 4a3c9a5..e8dfacd 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart
@@ -6,6 +6,69 @@
// promotion continue to function properly even when used inside unreachable
// code.
+conditionalIs(Object o) {
+ return;
+ o is int ? null : throw 'bad';
+ /*int*/ o;
+}
+
+conditionalIsNot(Object o) {
+ return;
+ o is! int ? throw 'bad' : null;
+ /*int*/ o;
+}
+
+conditionalJoinFalse(Object o, bool b) {
+ return;
+ if (b ? o is! int : o is! int) return;
+ /*int*/ o;
+}
+
+conditionalJoinTrue(Object o, bool b) {
+ return;
+ if (!(b ? o is int : o is int)) return;
+ /*int*/ o;
+}
+
+doBreak(Object o) {
+ return;
+ do {
+ if (o is int) break;
+ } while (true);
+ /*int*/ o;
+}
+
+doContinue(Object o) {
+ return;
+ do {
+ if (o is int) continue;
+ return;
+ } while (false);
+ /*int*/ o;
+}
+
+doCondition(Object o) {
+ return;
+ do {} while (o is! int);
+ /*int*/ o;
+}
+
+forBreak(Object o) {
+ return;
+ for (;;) {
+ if (o is int) break;
+ }
+ /*int*/ o;
+}
+
+forContinue(Object o) {
+ return;
+ for (;; /*int*/ o) {
+ if (o is int) continue;
+ return;
+ }
+}
+
ifIsNot(Object o) {
return;
if (o is! int) return;
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 0d46f4a..46728e7 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -1093,6 +1093,7 @@
void visitConditionalExpression(ConditionalExpression node) {
Expression condition = node.condition;
var flow = _flowAnalysis?.flow;
+ flow?.conditional_conditionBegin();
// TODO(scheglov) Do we need these checks for null?
condition?.accept(this);
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 7288dd8..e380a35 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -378,6 +378,7 @@
@override
ExpressionInferenceResult visitConditionalExpression(
ConditionalExpression node, DartType typeContext) {
+ inferrer.flowAnalysis.conditional_conditionBegin();
InterfaceType expectedType =
inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
ExpressionInferenceResult conditionResult = inferrer.inferExpression(
@@ -401,7 +402,7 @@
node.otherwise = otherwiseResult.expression..parent = node;
inferrer.registerIfUnreachableForTesting(node.otherwise,
isReachable: isOtherwiseReachable);
- inferrer.flowAnalysis.conditional_end(node.condition, node.otherwise);
+ inferrer.flowAnalysis.conditional_end(node, node.otherwise);
DartType inferredType = inferrer.typeSchemaEnvironment
.getStandardUpperBound(thenResult.inferredType,
otherwiseResult.inferredType, inferrer.library.library);
diff --git a/pkg/meta/pubspec.yaml b/pkg/meta/pubspec.yaml
index be6237c..28a9847 100644
--- a/pkg/meta/pubspec.yaml
+++ b/pkg/meta/pubspec.yaml
@@ -1,5 +1,5 @@
name: meta
-version: 1.3.0-nullsafety.3
+version: 1.3.0-nullsafety.4
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/meta
description: >
This library contains the declarations of annotations that developers can use
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index 7d4a32e..3f22a7d 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -619,6 +619,7 @@
@override
DecoratedType visitConditionalExpression(ConditionalExpression node) {
+ _flowAnalysis.conditional_conditionBegin();
_checkExpressionNotNull(node.condition);
NullabilityNode trueGuard;
NullabilityNode falseGuard;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 2b1195d..25776cd 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -9361,6 +9361,13 @@
return Symbols::New(thread, printer.buffer());
}
+const char* Function::QualifiedUserVisibleNameCString() const {
+ Thread* thread = Thread::Current();
+ ZoneTextBuffer printer(thread->zone());
+ PrintName(NameFormattingParams(kUserVisibleName), &printer);
+ return printer.buffer();
+}
+
void Function::PrintName(const NameFormattingParams& params,
BaseTextBuffer* printer) const {
// If |this| is the generated asynchronous body closure, use the
@@ -24410,10 +24417,10 @@
intptr_t frame_index) {
ASSERT(!function.IsNull());
const auto& script = Script::Handle(zone, function.script());
- auto& handle = String::Handle(zone, function.QualifiedUserVisibleName());
- auto const function_name = handle.ToCString();
- handle = script.IsNull() ? String::New("Kernel") : script.url();
- auto url = handle.ToCString();
+ const char* function_name = function.QualifiedUserVisibleNameCString();
+ const char* url = script.IsNull()
+ ? "Kernel"
+ : String::Handle(zone, script.url()).ToCString();
// If the URI starts with "data:application/dart;" this is a URI encoded
// script so we shouldn't print the entire URI because it could be very long.
@@ -24443,6 +24450,7 @@
auto& code = Code::Handle(zone);
auto& bytecode = Bytecode::Handle(zone);
+ NoSafepointScope no_allocation;
GrowableArray<const Function*> inlined_functions;
GrowableArray<TokenPosition> inlined_token_positions;
ZoneTextBuffer buffer(zone, 1024);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 9a9702f..e9a388b 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2482,6 +2482,7 @@
BaseTextBuffer* printer) const;
StringPtr QualifiedScrubbedName() const;
StringPtr QualifiedUserVisibleName() const;
+ const char* QualifiedUserVisibleNameCString() const;
virtual StringPtr DictionaryName() const { return name(); }
diff --git a/tools/VERSION b/tools/VERSION
index 7d7e434..245fc79 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 11
PATCH 0
-PRERELEASE 197
+PRERELEASE 198
PRERELEASE_PATCH 0
\ No newline at end of file