[kernel] Account for defaultType in some of the Kernel visitors
Fixes #33324
Bug: http://dartbug.com/33324
Change-Id: I6c6a503a1fe016d7a8743df1597660c979ce27ea
Reviewed-on: https://dart-review.googlesource.com/58720
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Kevin Millikin <kmillikin@google.com>
diff --git a/pkg/front_end/testcases/inference/bug33324.dart b/pkg/front_end/testcases/inference/bug33324.dart
new file mode 100644
index 0000000..cdce5f17
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug33324.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that the greatest closure uses 'dynamic' and not Object as
+// the top type.
+
+int foo() {
+ Function f = (x) => x;
+ var l = ["bar"].map(f).toList();
+ l.add(42);
+ return l.first.length;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/bug33324.dart.direct.expect b/pkg/front_end/testcases/inference/bug33324.dart.direct.expect
new file mode 100644
index 0000000..2e1ecb9
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug33324.dart.direct.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int {
+ core::Function f = (dynamic x) → dynamic => x;
+ dynamic l = <dynamic>["bar"].map(f).toList();
+ l.add(42);
+ return l.first.length;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/bug33324.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bug33324.dart.direct.transformed.expect
new file mode 100644
index 0000000..2e1ecb9
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug33324.dart.direct.transformed.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int {
+ core::Function f = (dynamic x) → dynamic => x;
+ dynamic l = <dynamic>["bar"].map(f).toList();
+ l.add(42);
+ return l.first.length;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/bug33324.dart.outline.expect b/pkg/front_end/testcases/inference/bug33324.dart.outline.expect
new file mode 100644
index 0000000..06c9cfc
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug33324.dart.outline.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/inference/bug33324.dart.strong.expect b/pkg/front_end/testcases/inference/bug33324.dart.strong.expect
new file mode 100644
index 0000000..f88135b
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug33324.dart.strong.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int {
+ core::Function f = (dynamic x) → dynamic => x;
+ core::List<dynamic> l = <core::String>["bar"].{core::Iterable::map}<dynamic>(f as{TypeError} (core::String) → dynamic).{core::Iterable::toList}();
+ l.{core::List::add}(42);
+ return l.{core::Iterable::first}.length as{TypeError} core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/bug33324.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/bug33324.dart.strong.transformed.expect
new file mode 100644
index 0000000..f88135b
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug33324.dart.strong.transformed.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int {
+ core::Function f = (dynamic x) → dynamic => x;
+ core::List<dynamic> l = <core::String>["bar"].{core::Iterable::map}<dynamic>(f as{TypeError} (core::String) → dynamic).{core::Iterable::toList}();
+ l.{core::List::add}(42);
+ return l.{core::Iterable::first}.length as{TypeError} core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.expect b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.expect
index e3ccda9..e9adaf2 100644
--- a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.expect
@@ -10,6 +10,6 @@
return (self::C::T y) → core::Null {};
}
static method test(self::C<core::String> c) → void {
- (core::int) → (core::String) → void tearoff = c.{self::C::f} as{TypeError} <U extends core::Object>(U) → (core::String) → void<core::int>;
+ (core::int) → (core::String) → void tearoff = c.{self::C::f} as{TypeError} <U extends core::Object = dynamic>(U) → (core::String) → void<core::int>;
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.transformed.expect
index e3ccda9..e9adaf2 100644
--- a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.transformed.expect
@@ -10,6 +10,6 @@
return (self::C::T y) → core::Null {};
}
static method test(self::C<core::String> c) → void {
- (core::int) → (core::String) → void tearoff = c.{self::C::f} as{TypeError} <U extends core::Object>(U) → (core::String) → void<core::int>;
+ (core::int) → (core::String) → void tearoff = c.{self::C::f} as{TypeError} <U extends core::Object = dynamic>(U) → (core::String) → void<core::int>;
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.direct.expect b/pkg/front_end/testcases/regress/issue_30838.dart.direct.expect
index 9e4af92..9efb697 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.direct.expect
@@ -4,7 +4,7 @@
typedef Foo<S extends core::Object = dynamic> = <T extends core::Object = dynamic>(T) → S;
class A extends core::Object {
- field <T extends core::Object>(T) → core::int f = null;
+ field <T extends core::Object = dynamic>(T) → core::int f = null;
synthetic constructor •() → void
: super core::Object::•()
;
@@ -14,7 +14,7 @@
}
static method foo<T extends core::Object = dynamic>(self::foo::T x) → core::int
return 3;
-static method bar() → <T extends core::Object>(T) → core::int
+static method bar() → <T extends core::Object = dynamic>(T) → core::int
return self::foo;
static method test1() → void {
self::bar().call<core::String>("hello");
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_30838.dart.direct.transformed.expect
index 9e4af92..9efb697 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.direct.transformed.expect
@@ -4,7 +4,7 @@
typedef Foo<S extends core::Object = dynamic> = <T extends core::Object = dynamic>(T) → S;
class A extends core::Object {
- field <T extends core::Object>(T) → core::int f = null;
+ field <T extends core::Object = dynamic>(T) → core::int f = null;
synthetic constructor •() → void
: super core::Object::•()
;
@@ -14,7 +14,7 @@
}
static method foo<T extends core::Object = dynamic>(self::foo::T x) → core::int
return 3;
-static method bar() → <T extends core::Object>(T) → core::int
+static method bar() → <T extends core::Object = dynamic>(T) → core::int
return self::foo;
static method test1() → void {
self::bar().call<core::String>("hello");
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.outline.expect b/pkg/front_end/testcases/regress/issue_30838.dart.outline.expect
index 55709ba..10ab505 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.outline.expect
@@ -4,7 +4,7 @@
typedef Foo<S extends core::Object = dynamic> = <T extends core::Object = dynamic>(T) → S;
class A extends core::Object {
- field <T extends core::Object>(T) → core::int f;
+ field <T extends core::Object = dynamic>(T) → core::int f;
synthetic constructor •() → void
;
method test() → void
@@ -12,7 +12,7 @@
}
static method foo<T extends core::Object = dynamic>(self::foo::T x) → core::int
;
-static method bar() → <T extends core::Object>(T) → core::int
+static method bar() → <T extends core::Object = dynamic>(T) → core::int
;
static method test1() → void
;
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.strong.expect b/pkg/front_end/testcases/regress/issue_30838.dart.strong.expect
index f08b8e7..7526f86 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.strong.expect
@@ -4,7 +4,7 @@
typedef Foo<S extends core::Object = dynamic> = <T extends core::Object = dynamic>(T) → S;
class A extends core::Object {
- field <T extends core::Object>(T) → core::int f = null;
+ field <T extends core::Object = dynamic>(T) → core::int f = null;
synthetic constructor •() → void
: super core::Object::•()
;
@@ -14,7 +14,7 @@
}
static method foo<T extends core::Object = dynamic>(self::foo::T x) → core::int
return 3;
-static method bar() → <T extends core::Object>(T) → core::int
+static method bar() → <T extends core::Object = dynamic>(T) → core::int
return self::foo;
static method test1() → void {
self::bar().call<core::String>("hello");
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_30838.dart.strong.transformed.expect
index f08b8e7..7526f86 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.strong.transformed.expect
@@ -4,7 +4,7 @@
typedef Foo<S extends core::Object = dynamic> = <T extends core::Object = dynamic>(T) → S;
class A extends core::Object {
- field <T extends core::Object>(T) → core::int f = null;
+ field <T extends core::Object = dynamic>(T) → core::int f = null;
synthetic constructor •() → void
: super core::Object::•()
;
@@ -14,7 +14,7 @@
}
static method foo<T extends core::Object = dynamic>(self::foo::T x) → core::int
return 3;
-static method bar() → <T extends core::Object>(T) → core::int
+static method bar() → <T extends core::Object = dynamic>(T) → core::int
return self::foo;
static method test1() → void {
self::bar().call<core::String>("hello");
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31213.dart.direct.expect
index a54adf0..da2a301 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.direct.expect
@@ -3,12 +3,12 @@
import "dart:core" as core;
typedef C<A extends core::Object = dynamic, K extends core::Object = dynamic> = <B extends core::Object = dynamic>(A, K, B) → core::int;
-typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object>(A, K, B) → core::int;
+typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, K, B) → core::int;
static method producer<K extends core::Object = dynamic>() → dynamic {
return <A extends core::Object = dynamic>(core::int v1) → dynamic {
return <B extends core::Object = dynamic>(A v2, self::producer::K v3, B v4) → dynamic => 0;
};
}
static method main() → dynamic {
- assert(self::producer<core::String>() is <A extends core::Object>(core::int) → <B extends core::Object>(A, core::String, B) → core::int);
+ assert(self::producer<core::String>() is <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, core::String, B) → core::int);
}
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31213.dart.direct.transformed.expect
index a54adf0..da2a301 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.direct.transformed.expect
@@ -3,12 +3,12 @@
import "dart:core" as core;
typedef C<A extends core::Object = dynamic, K extends core::Object = dynamic> = <B extends core::Object = dynamic>(A, K, B) → core::int;
-typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object>(A, K, B) → core::int;
+typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, K, B) → core::int;
static method producer<K extends core::Object = dynamic>() → dynamic {
return <A extends core::Object = dynamic>(core::int v1) → dynamic {
return <B extends core::Object = dynamic>(A v2, self::producer::K v3, B v4) → dynamic => 0;
};
}
static method main() → dynamic {
- assert(self::producer<core::String>() is <A extends core::Object>(core::int) → <B extends core::Object>(A, core::String, B) → core::int);
+ assert(self::producer<core::String>() is <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, core::String, B) → core::int);
}
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect b/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect
index 2626a19..a1d78e7 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
typedef C<A extends core::Object = dynamic, K extends core::Object = dynamic> = <B extends core::Object = dynamic>(A, K, B) → core::int;
-typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object>(A, K, B) → core::int;
+typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, K, B) → core::int;
static method producer<K extends core::Object = dynamic>() → dynamic
;
static method main() → dynamic
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect
index 730da9b..2bb9fe5 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect
@@ -3,12 +3,12 @@
import "dart:core" as core;
typedef C<A extends core::Object = dynamic, K extends core::Object = dynamic> = <B extends core::Object = dynamic>(A, K, B) → core::int;
-typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object>(A, K, B) → core::int;
+typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, K, B) → core::int;
static method producer<K extends core::Object = dynamic>() → dynamic {
return <A extends core::Object = dynamic>(core::int v1) → <B extends core::Object = dynamic>(A, self::producer::K, B) → core::int {
return <B extends core::Object = dynamic>(A v2, self::producer::K v3, B v4) → core::int => 0;
};
}
static method main() → dynamic {
- assert(self::producer<core::String>() is <A extends core::Object>(core::int) → <B extends core::Object>(A, core::String, B) → core::int);
+ assert(self::producer<core::String>() is <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, core::String, B) → core::int);
}
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect
index 730da9b..2bb9fe5 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect
@@ -3,12 +3,12 @@
import "dart:core" as core;
typedef C<A extends core::Object = dynamic, K extends core::Object = dynamic> = <B extends core::Object = dynamic>(A, K, B) → core::int;
-typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object>(A, K, B) → core::int;
+typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, K, B) → core::int;
static method producer<K extends core::Object = dynamic>() → dynamic {
return <A extends core::Object = dynamic>(core::int v1) → <B extends core::Object = dynamic>(A, self::producer::K, B) → core::int {
return <B extends core::Object = dynamic>(A v2, self::producer::K v3, B v4) → core::int => 0;
};
}
static method main() → dynamic {
- assert(self::producer<core::String>() is <A extends core::Object>(core::int) → <B extends core::Object>(A, core::String, B) → core::int);
+ assert(self::producer<core::String>() is <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, core::String, B) → core::int);
}
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index 821f9d5..8b47a74 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -229,12 +229,9 @@
}
for (int i = 0; i < typeParameters.length; ++i) {
freshParameters[i].bound = substitute(typeParameters[i].bound, map);
-
- // [defaultType] is populated using instantiate-to-bound algorithm, so it
- // shouldn't refer to type parameters from the same declaration. However,
- // if a transformation changes [defaultType], it may get such references,
- // and the line below should invoke [substitute], like for [bound] above.
- freshParameters[i].defaultType = typeParameters[i].defaultType;
+ freshParameters[i].defaultType = typeParameters[i].defaultType != null
+ ? substitute(typeParameters[i].defaultType, map)
+ : null;
}
return new FreshTypeParameters(freshParameters, Substitution.fromMap(map));
}
@@ -479,6 +476,9 @@
var fresh = new TypeParameter(node.name);
substitution[node] = new TypeParameterType(fresh);
fresh.bound = visit(node.bound);
+ if (node.defaultType != null) {
+ fresh.defaultType = visit(node.defaultType);
+ }
return fresh;
}
}
@@ -846,7 +846,9 @@
bool handleTypeParameter(TypeParameter node) {
assert(!variables.contains(node));
- return node.bound.accept(this);
+ if (node.bound.accept(this)) return true;
+ if (node.defaultType == null) return false;
+ return node.defaultType.accept(this);
}
}
@@ -882,6 +884,7 @@
visitFunctionType(FunctionType node) {
for (TypeParameter typeParameter in node.typeParameters) {
typeParameter.bound.accept(this);
+ typeParameter.defaultType?.accept(this);
}
for (DartType parameter in node.positionalParameters) {
parameter.accept(this);