[cfe] Add support for set/map disambiguation for pattern elements

Part of https://github.com/dart-lang/sdk/issues/49749

Change-Id: Idb7f8e4bd1537abbe4133e69d2e51ae6b1e96a0d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/283862
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Chloe Stefantsova 2023-02-19 21:07:36 +00:00 committed by Commit Queue
parent 0c05e33836
commit 89639ba268
11 changed files with 512 additions and 2 deletions

View file

@ -17,6 +17,8 @@ import '../problems.dart' show getFileUri, unsupported;
import '../type_inference/inference_helper.dart' show InferenceHelper; import '../type_inference/inference_helper.dart' show InferenceHelper;
import 'internal_ast.dart';
/// Mixin for spread and control-flow elements. /// Mixin for spread and control-flow elements.
/// ///
/// Spread and control-flow elements are not truly expressions and they cannot /// Spread and control-flow elements are not truly expressions and they cannot
@ -849,6 +851,11 @@ bool isConvertibleToMapEntry(Expression element) {
(element.otherwise == null || (element.otherwise == null ||
isConvertibleToMapEntry(element.otherwise!)); isConvertibleToMapEntry(element.otherwise!));
} }
if (element is IfCaseElement) {
return isConvertibleToMapEntry(element.then) &&
(element.otherwise == null ||
isConvertibleToMapEntry(element.otherwise!));
}
if (element is ForElement) { if (element is ForElement) {
return isConvertibleToMapEntry(element.body); return isConvertibleToMapEntry(element.body);
} }
@ -883,6 +890,18 @@ MapLiteralEntry convertToMapEntry(Expression element, InferenceHelper helper,
onConvertElement(element, result); onConvertElement(element, result);
return result; return result;
} }
if (element is IfCaseElement) {
IfCaseMapEntry result = new IfCaseMapEntry(
element.expression,
element.patternGuard,
convertToMapEntry(element.then, helper, onConvertElement),
element.otherwise == null
? null
: convertToMapEntry(element.otherwise!, helper, onConvertElement))
..fileOffset = element.fileOffset;
onConvertElement(element, result);
return result;
}
if (element is ForElement) { if (element is ForElement) {
ForMapEntry result = new ForMapEntry( ForMapEntry result = new ForMapEntry(
element.variables, element.variables,

View file

@ -4845,8 +4845,27 @@ class IfCaseElement extends InternalExpression with ControlFlowElement {
@override @override
MapLiteralEntry? toMapLiteralEntry( MapLiteralEntry? toMapLiteralEntry(
void Function(TreeNode from, TreeNode to) onConvertElement) { void Function(TreeNode from, TreeNode to) onConvertElement) {
// TODO(cstefantsova): implement toMapLiteralEntry MapLiteralEntry? thenEntry;
throw new UnimplementedError(); Expression then = this.then;
if (then is ControlFlowElement) {
ControlFlowElement thenElement = then;
thenEntry = thenElement.toMapLiteralEntry(onConvertElement);
}
if (thenEntry == null) return null;
MapLiteralEntry? otherwiseEntry;
Expression? otherwise = this.otherwise;
if (otherwise != null) {
if (otherwise is ControlFlowElement) {
ControlFlowElement otherwiseElement = otherwise;
otherwiseEntry = otherwiseElement.toMapLiteralEntry(onConvertElement);
}
if (otherwiseEntry == null) return null;
}
IfCaseMapEntry result =
new IfCaseMapEntry(expression, patternGuard, thenEntry, otherwiseEntry)
..fileOffset = fileOffset;
onConvertElement(this, result);
return result;
} }
@override @override

View file

@ -0,0 +1,67 @@
// Copyright (c) 2023, 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.
test1(dynamic x, dynamic another) {
return {1: 1, if (x case String y) ...another, 3: 3};
}
test2(bool b, dynamic x, dynamic another) {
return {1: 1, if (b) if (x case String y) ...another, 3: 3};
}
test3(dynamic x, dynamic y, dynamic another) {
return {1: 1, if (x case int x2) 2: x2 else if (y case int y2) ...another, 3: 3};
}
main() {
expectEquals(
mapToString(test1("foo", {2: 2})),
mapToString({1: 1, 2: 2, 3: 3}),
);
expectEquals(
mapToString(test1(false, {2: 2})),
mapToString({1: 1, 3: 3}),
);
expectEquals(
mapToString(test2(true, "foo", {2: 2})),
mapToString({1: 1, 2: 2, 3: 3}),
);
expectEquals(
mapToString(test2(false, "foo", {2: 2})),
mapToString({1: 1, 3: 3}),
);
expectEquals(
mapToString(test2(true, false, {2: 2})),
mapToString({1: 1, 3: 3}),
);
expectEquals(
mapToString(test3(0, 1, {2: 2})),
mapToString({1: 1, 2: 0, 3: 3}),
);
expectEquals(
mapToString(test3("foo", 1, {2: 2})),
mapToString({1: 1, 2: 2, 3: 3}),
);
expectEquals(
mapToString(test3("foo", "bar", {2, 2})),
mapToString({1: 1, 3: 3}),
);
}
expectEquals(x, y) {
if (x != y) {
throw "Expected '${x}' to be equals to '${y}'.";
}
}
mapToString(Map map) {
List<String> entryStrings = [];
for (var entry in map.entries) {
entryStrings.add("${entry.key}:${entry.value}");
}
entryStrings.sort();
return "{${entryStrings.join(',')}}";
}

View file

@ -0,0 +1,73 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:collection" as col;
static method test1(dynamic x, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t1 = <dynamic, dynamic>{};
#t1.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
core::String y;
final dynamic #0#0 = x;
if(#0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t2 = y = #0#0{core::String} in true))
#t1.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
#t1.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t1;
}
static method test2(core::bool b, dynamic x, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t3 = <dynamic, dynamic>{};
#t3.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
if(b) {
core::String y;
final dynamic #0#0 = x;
if(#0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t4 = y = #0#0{core::String} in true))
#t3.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
}
#t3.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t3;
}
static method test3(dynamic x, dynamic y, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t5 = <dynamic, dynamic>{};
#t5.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
core::int x2;
final dynamic #1#0 = x;
if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t6 = x2 = #1#0{core::int} in true))
#t5.{core::Map::[]=}{Invariant}(2, x2){(dynamic, dynamic) → void};
else {
core::int y2;
final dynamic #0#0 = y;
if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = y2 = #0#0{core::int} in true))
#t5.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
}
#t5.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t5;
}
static method main() → dynamic {
self::expectEquals(self::mapToString(self::test1("foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test1(false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test2(true, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test2(false, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test2(true, false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test3(0, 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 0, 3: 3}));
self::expectEquals(self::mapToString(self::test3("foo", 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test3("foo", "bar", block {
final core::Set<core::int> #t8 = col::LinkedHashSet::•<core::int>();
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
} =>#t8) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected '${x}' to be equals to '${y}'.";
}
}
static method mapToString(core::Map<dynamic, dynamic> map) → dynamic {
core::List<core::String> entryStrings = <core::String>[];
for (core::MapEntry<dynamic, dynamic> entry in map.{core::Map::entries}{core::Iterable<core::MapEntry<dynamic, dynamic>>}) {
entryStrings.{core::List::add}("${entry.{core::MapEntry::key}{dynamic}}:${entry.{core::MapEntry::value}{dynamic}}"){(core::String) → void};
}
entryStrings.{core::List::sort}(){([(core::String, core::String) →? core::int]) → void};
return "{${entryStrings.{core::Iterable::join}(","){([core::String]) → core::String}}}";
}

View file

@ -0,0 +1,79 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:collection" as col;
static method test1(dynamic x, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t1 = <dynamic, dynamic>{};
#t1.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
core::String y;
final dynamic #0#0 = x;
if(#0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t2 = y = #0#0{core::String} in true))
#t1.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
#t1.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t1;
}
static method test2(core::bool b, dynamic x, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t3 = <dynamic, dynamic>{};
#t3.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
if(b) {
core::String y;
final dynamic #0#0 = x;
if(#0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t4 = y = #0#0{core::String} in true))
#t3.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
}
#t3.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t3;
}
static method test3(dynamic x, dynamic y, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t5 = <dynamic, dynamic>{};
#t5.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
core::int x2;
final dynamic #1#0 = x;
if(#1#0 is{ForNonNullableByDefault} core::int && (let final core::int #t6 = x2 = #1#0{core::int} in true))
#t5.{core::Map::[]=}{Invariant}(2, x2){(dynamic, dynamic) → void};
else {
core::int y2;
final dynamic #0#0 = y;
if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t7 = y2 = #0#0{core::int} in true))
#t5.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
}
#t5.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t5;
}
static method main() → dynamic {
self::expectEquals(self::mapToString(self::test1("foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test1(false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test2(true, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test2(false, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test2(true, false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test3(0, 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 0, 3: 3}));
self::expectEquals(self::mapToString(self::test3("foo", 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test3("foo", "bar", block {
final core::Set<core::int> #t8 = new col::_Set::•<core::int>();
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
} =>#t8) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected '${x}' to be equals to '${y}'.";
}
}
static method mapToString(core::Map<dynamic, dynamic> map) → dynamic {
core::List<core::String> entryStrings = core::_GrowableList::•<core::String>(0);
{
core::Iterator<core::MapEntry<dynamic, dynamic>> :sync-for-iterator = map.{core::Map::entries}{core::Iterable<core::MapEntry<dynamic, dynamic>>}.{core::Iterable::iterator}{core::Iterator<core::MapEntry<dynamic, dynamic>>};
for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
core::MapEntry<dynamic, dynamic> entry = :sync-for-iterator.{core::Iterator::current}{core::MapEntry<dynamic, dynamic>};
{
entryStrings.{core::List::add}("${entry.{core::MapEntry::key}{dynamic}}:${entry.{core::MapEntry::value}{dynamic}}"){(core::String) → void};
}
}
}
entryStrings.{core::List::sort}(){([(core::String, core::String) →? core::int]) → void};
return "{${entryStrings.{core::Iterable::join}(","){([core::String]) → core::String}}}";
}

View file

@ -0,0 +1,6 @@
test1(dynamic x, dynamic another) {}
test2(bool b, dynamic x, dynamic another) {}
test3(dynamic x, dynamic y, dynamic another) {}
main() {}
expectEquals(x, y) {}
mapToString(Map map) {}

View file

@ -0,0 +1,6 @@
expectEquals(x, y) {}
main() {}
mapToString(Map map) {}
test1(dynamic x, dynamic another) {}
test2(bool b, dynamic x, dynamic another) {}
test3(dynamic x, dynamic y, dynamic another) {}

View file

@ -0,0 +1,73 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:collection" as col;
static method test1(dynamic x, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t1 = <dynamic, dynamic>{};
#t1.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
core::String y;
final dynamic #0#0 = x;
if(#0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t2 = y = #0#0{core::String} in true))
#t1.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
#t1.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t1;
}
static method test2(core::bool b, dynamic x, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t3 = <dynamic, dynamic>{};
#t3.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
if(b) {
core::String y;
final dynamic #0#0 = x;
if(#0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t4 = y = #0#0{core::String} in true))
#t3.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
}
#t3.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t3;
}
static method test3(dynamic x, dynamic y, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t5 = <dynamic, dynamic>{};
#t5.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
core::int x2;
final dynamic #1#0 = x;
if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t6 = x2 = #1#0{core::int} in true))
#t5.{core::Map::[]=}{Invariant}(2, x2){(dynamic, dynamic) → void};
else {
core::int y2;
final dynamic #0#0 = y;
if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = y2 = #0#0{core::int} in true))
#t5.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
}
#t5.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t5;
}
static method main() → dynamic {
self::expectEquals(self::mapToString(self::test1("foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test1(false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test2(true, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test2(false, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test2(true, false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test3(0, 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 0, 3: 3}));
self::expectEquals(self::mapToString(self::test3("foo", 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test3("foo", "bar", block {
final core::Set<core::int> #t8 = col::LinkedHashSet::•<core::int>();
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
} =>#t8) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected '${x}' to be equals to '${y}'.";
}
}
static method mapToString(core::Map<dynamic, dynamic> map) → dynamic {
core::List<core::String> entryStrings = <core::String>[];
for (core::MapEntry<dynamic, dynamic> entry in map.{core::Map::entries}{core::Iterable<core::MapEntry<dynamic, dynamic>>}) {
entryStrings.{core::List::add}("${entry.{core::MapEntry::key}{dynamic}}:${entry.{core::MapEntry::value}{dynamic}}"){(core::String) → void};
}
entryStrings.{core::List::sort}(){([(core::String, core::String) →? core::int]) → void};
return "{${entryStrings.{core::Iterable::join}(","){([core::String]) → core::String}}}";
}

View file

@ -0,0 +1,73 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:collection" as col;
static method test1(dynamic x, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t1 = <dynamic, dynamic>{};
#t1.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
core::String y;
final dynamic #0#0 = x;
if(#0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t2 = y = #0#0{core::String} in true))
#t1.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
#t1.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t1;
}
static method test2(core::bool b, dynamic x, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t3 = <dynamic, dynamic>{};
#t3.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
if(b) {
core::String y;
final dynamic #0#0 = x;
if(#0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t4 = y = #0#0{core::String} in true))
#t3.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
}
#t3.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t3;
}
static method test3(dynamic x, dynamic y, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t5 = <dynamic, dynamic>{};
#t5.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
core::int x2;
final dynamic #1#0 = x;
if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t6 = x2 = #1#0{core::int} in true))
#t5.{core::Map::[]=}{Invariant}(2, x2){(dynamic, dynamic) → void};
else {
core::int y2;
final dynamic #0#0 = y;
if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = y2 = #0#0{core::int} in true))
#t5.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
}
#t5.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t5;
}
static method main() → dynamic {
self::expectEquals(self::mapToString(self::test1("foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test1(false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test2(true, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test2(false, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test2(true, false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test3(0, 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 0, 3: 3}));
self::expectEquals(self::mapToString(self::test3("foo", 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test3("foo", "bar", block {
final core::Set<core::int> #t8 = col::LinkedHashSet::•<core::int>();
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
} =>#t8) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected '${x}' to be equals to '${y}'.";
}
}
static method mapToString(core::Map<dynamic, dynamic> map) → dynamic {
core::List<core::String> entryStrings = <core::String>[];
for (core::MapEntry<dynamic, dynamic> entry in map.{core::Map::entries}{core::Iterable<core::MapEntry<dynamic, dynamic>>}) {
entryStrings.{core::List::add}("${entry.{core::MapEntry::key}{dynamic}}:${entry.{core::MapEntry::value}{dynamic}}"){(core::String) → void};
}
entryStrings.{core::List::sort}(){([(core::String, core::String) →? core::int]) → void};
return "{${entryStrings.{core::Iterable::join}(","){([core::String]) → core::String}}}";
}

View file

@ -0,0 +1,16 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
static method test1(dynamic x, dynamic another) → dynamic
;
static method test2(core::bool b, dynamic x, dynamic another) → dynamic
;
static method test3(dynamic x, dynamic y, dynamic another) → dynamic
;
static method main() → dynamic
;
static method expectEquals(dynamic x, dynamic y) → dynamic
;
static method mapToString(core::Map<dynamic, dynamic> map) → dynamic
;

View file

@ -0,0 +1,79 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:collection" as col;
static method test1(dynamic x, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t1 = <dynamic, dynamic>{};
#t1.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
core::String y;
final dynamic #0#0 = x;
if(#0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t2 = y = #0#0{core::String} in true))
#t1.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
#t1.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t1;
}
static method test2(core::bool b, dynamic x, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t3 = <dynamic, dynamic>{};
#t3.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
if(b) {
core::String y;
final dynamic #0#0 = x;
if(#0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t4 = y = #0#0{core::String} in true))
#t3.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
}
#t3.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t3;
}
static method test3(dynamic x, dynamic y, dynamic another) → dynamic {
return block {
final core::Map<dynamic, dynamic> #t5 = <dynamic, dynamic>{};
#t5.{core::Map::[]=}{Invariant}(1, 1){(dynamic, dynamic) → void};
core::int x2;
final dynamic #1#0 = x;
if(#1#0 is{ForNonNullableByDefault} core::int && (let final core::int #t6 = x2 = #1#0{core::int} in true))
#t5.{core::Map::[]=}{Invariant}(2, x2){(dynamic, dynamic) → void};
else {
core::int y2;
final dynamic #0#0 = y;
if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t7 = y2 = #0#0{core::int} in true))
#t5.{core::Map::addAll}{Invariant}(another){(core::Map<dynamic, dynamic>) → void};
}
#t5.{core::Map::[]=}{Invariant}(3, 3){(dynamic, dynamic) → void};
} =>#t5;
}
static method main() → dynamic {
self::expectEquals(self::mapToString(self::test1("foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test1(false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test2(true, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test2(false, "foo", <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test2(true, false, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
self::expectEquals(self::mapToString(self::test3(0, 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 0, 3: 3}));
self::expectEquals(self::mapToString(self::test3("foo", 1, <core::int, core::int>{2: 2}) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 2: 2, 3: 3}));
self::expectEquals(self::mapToString(self::test3("foo", "bar", block {
final core::Set<core::int> #t8 = new col::_Set::•<core::int>();
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
#t8.{core::Set::add}{Invariant}(2){(core::int) → core::bool};
} =>#t8) as{TypeError,ForDynamic,ForNonNullableByDefault} core::Map<dynamic, dynamic>), self::mapToString(<dynamic, dynamic>{1: 1, 3: 3}));
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected '${x}' to be equals to '${y}'.";
}
}
static method mapToString(core::Map<dynamic, dynamic> map) → dynamic {
core::List<core::String> entryStrings = core::_GrowableList::•<core::String>(0);
{
core::Iterator<core::MapEntry<dynamic, dynamic>> :sync-for-iterator = map.{core::Map::entries}{core::Iterable<core::MapEntry<dynamic, dynamic>>}.{core::Iterable::iterator}{core::Iterator<core::MapEntry<dynamic, dynamic>>};
for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
core::MapEntry<dynamic, dynamic> entry = :sync-for-iterator.{core::Iterator::current}{core::MapEntry<dynamic, dynamic>};
{
entryStrings.{core::List::add}("${entry.{core::MapEntry::key}{dynamic}}:${entry.{core::MapEntry::value}{dynamic}}"){(core::String) → void};
}
}
}
entryStrings.{core::List::sort}(){([(core::String, core::String) →? core::int]) → void};
return "{${entryStrings.{core::Iterable::join}(","){([core::String]) → core::String}}}";
}