Version 2.17.0-158.0.dev
Merge commit '248de89e8c9c32d439827b3a2eae584e019f1e84' into 'dev'
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 26c0537..8109b5f 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -3697,10 +3697,18 @@
/// Fills [typeArguments] with the type arguments needed for [selector] and
/// returns the selector corresponding to the passed type arguments.
+ ///
+ /// If [isImplicitCall] is `true`, the target of the invocation can be either
+ /// the target of the [selector] or of the corresponding `.call` selector. In
+ /// this case we need to check both selectors to see if we need to pass type
+ /// arguments. This occurs for field/getter invocations.
Selector _fillDynamicTypeArguments(
- Selector selector, ir.Arguments arguments, List<DartType> typeArguments) {
+ Selector selector, ir.Arguments arguments, List<DartType> typeArguments,
+ {bool isImplicitCall = false}) {
if (selector.typeArgumentCount > 0) {
- if (_rtiNeed.selectorNeedsTypeArguments(selector)) {
+ if (_rtiNeed.selectorNeedsTypeArguments(selector) ||
+ (isImplicitCall &&
+ _rtiNeed.selectorNeedsTypeArguments(selector.toCallSelector()))) {
typeArguments.addAll(arguments.types.map(_elementMap.getDartType));
} else {
return selector.toNonGeneric();
@@ -5216,12 +5224,14 @@
}
void _handleMethodInvocation(
- ir.Expression node, ir.Expression receiver, ir.Arguments arguments) {
+ ir.Expression node, ir.Expression receiver, ir.Arguments arguments,
+ {bool isImplicitCall = false}) {
receiver.accept(this);
HInstruction receiverInstruction = pop();
Selector selector = _elementMap.getSelector(node);
List<DartType> typeArguments = [];
- selector = _fillDynamicTypeArguments(selector, arguments, typeArguments);
+ selector = _fillDynamicTypeArguments(selector, arguments, typeArguments,
+ isImplicitCall: isImplicitCall);
_pushDynamicInvocation(
node,
_getStaticType(receiver),
@@ -5242,7 +5252,8 @@
@override
void visitInstanceGetterInvocation(ir.InstanceGetterInvocation node) {
- _handleMethodInvocation(node, node.receiver, node.arguments);
+ _handleMethodInvocation(node, node.receiver, node.arguments,
+ isImplicitCall: true);
}
@override
diff --git a/pkg/compiler/test/impact/data/issue48304.dart b/pkg/compiler/test/impact/data/issue48304.dart
new file mode 100644
index 0000000..fe7da9a
--- /dev/null
+++ b/pkg/compiler/test/impact/data/issue48304.dart
@@ -0,0 +1,232 @@
+// Copyright (c) 2022, 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.
+
+abstract class B {
+ call<T>();
+}
+
+/*member: C.:static=[Object.(0)]*/
+class C implements B {
+ /*member: C.call:
+ static=[
+ Rti._bind(1),
+ Rti._eval(1),
+ _arrayInstanceType(1),
+ _asBool(1),
+ _asBoolQ(1),
+ _asBoolS(1),
+ _asDouble(1),
+ _asDoubleQ(1),
+ _asDoubleS(1),
+ _asInt(1),
+ _asIntQ(1),
+ _asIntS(1),
+ _asNum(1),
+ _asNumQ(1),
+ _asNumS(1),
+ _asObject(1),
+ _asString(1),
+ _asStringQ(1),
+ _asStringS(1),
+ _asTop(1),
+ _generalAsCheckImplementation(1),
+ _generalIsTestImplementation(1),
+ _generalNullableAsCheckImplementation(1),
+ _generalNullableIsTestImplementation(1),
+ _installSpecializedAsCheck(1),
+ _installSpecializedIsTest(1),
+ _instanceType(1),
+ _isBool(1),
+ _isInt(1),
+ _isNum(1),
+ _isObject(1),
+ _isString(1),
+ _isTop(1),
+ _setArrayType(2),
+ createRuntimeType(1),
+ findType(1),
+ instanceType(1),
+ print(1),
+ typeLiteral(1)],
+ type=[
+ inst:Closure,
+ inst:JSArray<dynamic>,
+ inst:JSBool,
+ inst:JSExtendableArray<dynamic>,
+ inst:JSFixedArray<dynamic>,
+ inst:JSInt,
+ inst:JSMutableArray<dynamic>,
+ inst:JSNumNotInt,
+ inst:JSNumber,
+ inst:JSPositiveInt,
+ inst:JSUInt31,
+ inst:JSUInt32,
+ inst:JSUnmodifiableArray<dynamic>,
+ inst:Type,
+ inst:_Type,
+ lit:call.T,
+ param:Object?]
+ */
+ call<T>() => print(T);
+}
+
+abstract class A {}
+
+class Wrapper {
+ /*member: Wrapper.:
+ static=[
+ Object.(0),
+ Rti._bind(1),
+ Rti._eval(1),
+ _arrayInstanceType(1),
+ _asBool(1),
+ _asBoolQ(1),
+ _asBoolS(1),
+ _asDouble(1),
+ _asDoubleQ(1),
+ _asDoubleS(1),
+ _asInt(1),
+ _asIntQ(1),
+ _asIntS(1),
+ _asNum(1),
+ _asNumQ(1),
+ _asNumS(1),
+ _asObject(1),
+ _asString(1),
+ _asStringQ(1),
+ _asStringS(1),
+ _asTop(1),
+ _generalAsCheckImplementation(1),
+ _generalIsTestImplementation(1),
+ _generalNullableAsCheckImplementation(1),
+ _generalNullableIsTestImplementation(1),
+ _installSpecializedAsCheck(1),
+ _installSpecializedIsTest(1),
+ _instanceType(1),
+ _isBool(1),
+ _isInt(1),
+ _isNum(1),
+ _isObject(1),
+ _isString(1),
+ _isTop(1),
+ findType(1),
+ init:Wrapper.b,
+ init:Wrapper.call,
+ instanceType(1)],
+ type=[
+ inst:Closure,
+ inst:JSBool,
+ param:B]
+ */
+ Wrapper(this.b, this.call);
+ /*member: Wrapper.b:
+ static=[
+ Rti._bind(1),
+ Rti._eval(1),
+ _arrayInstanceType(1),
+ _asBool(1),
+ _asBoolQ(1),
+ _asBoolS(1),
+ _asDouble(1),
+ _asDoubleQ(1),
+ _asDoubleS(1),
+ _asInt(1),
+ _asIntQ(1),
+ _asIntS(1),
+ _asNum(1),
+ _asNumQ(1),
+ _asNumS(1),
+ _asObject(1),
+ _asString(1),
+ _asStringQ(1),
+ _asStringS(1),
+ _asTop(1),
+ _generalAsCheckImplementation(1),
+ _generalIsTestImplementation(1),
+ _generalNullableAsCheckImplementation(1),
+ _generalNullableIsTestImplementation(1),
+ _installSpecializedAsCheck(1),
+ _installSpecializedIsTest(1),
+ _instanceType(1),
+ _isBool(1),
+ _isInt(1),
+ _isNum(1),
+ _isObject(1),
+ _isString(1),
+ _isTop(1),
+ findType(1),
+ instanceType(1)],
+ type=[
+ inst:Closure,
+ inst:JSBool,
+ inst:JSNull,
+ param:B]
+ */
+ final B b;
+ /*member: Wrapper.call:
+ static=[
+ Rti._bind(1),
+ Rti._eval(1),
+ _arrayInstanceType(1),
+ _asBool(1),
+ _asBoolQ(1),
+ _asBoolS(1),
+ _asDouble(1),
+ _asDoubleQ(1),
+ _asDoubleS(1),
+ _asInt(1),
+ _asIntQ(1),
+ _asIntS(1),
+ _asNum(1),
+ _asNumQ(1),
+ _asNumS(1),
+ _asObject(1),
+ _asString(1),
+ _asStringQ(1),
+ _asStringS(1),
+ _asTop(1),
+ _generalAsCheckImplementation(1),
+ _generalIsTestImplementation(1),
+ _generalNullableAsCheckImplementation(1),
+ _generalNullableIsTestImplementation(1),
+ _installSpecializedAsCheck(1),
+ _installSpecializedIsTest(1),
+ _instanceType(1),
+ _isBool(1),
+ _isInt(1),
+ _isNum(1),
+ _isObject(1),
+ _isString(1),
+ _isTop(1),
+ findType(1),
+ instanceType(1)],
+ type=[
+ inst:Closure,
+ inst:JSBool,
+ inst:JSNull,
+ param:B]
+ */
+ final B call;
+}
+
+/*member: main:
+ dynamic=[
+ B.call<A>(0),
+ exact:C.call<A>(0),
+ exact:Wrapper.b,
+ exact:Wrapper.b<A>(0),
+ exact:Wrapper.call,
+ exact:Wrapper.call<A>(0)],
+ static=[
+ C.(0),
+ Wrapper.(2)]
+*/
+void main() {
+ B b = C();
+ b<A>();
+ Wrapper(b, b).b<A>();
+ (Wrapper(b, b).b)<A>();
+ Wrapper(b, b).call<A>();
+ (Wrapper(b, b).call)<A>();
+}
diff --git a/pkg/compiler/test/inference/data/issue48304.dart b/pkg/compiler/test/inference/data/issue48304.dart
new file mode 100644
index 0000000..dc77fc3
--- /dev/null
+++ b/pkg/compiler/test/inference/data/issue48304.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2022, 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.
+
+abstract class B {
+ call<T>();
+}
+
+/*member: C.:[exact=C]*/
+class C implements B {
+ /*member: C.call:[null]*/
+ call<T>() => print(T);
+}
+
+abstract class A {}
+
+class Wrapper {
+ /*member: Wrapper.:[exact=Wrapper]*/
+ Wrapper(this. /*[exact=C]*/ b, this. /*[exact=C]*/ call);
+ /*member: Wrapper.b:[exact=C]*/
+ final B b;
+ /*member: Wrapper.call:[exact=C]*/
+ final B call;
+}
+
+/*member: main:[null]*/
+void main() {
+ B b = C();
+ b/*invoke: [exact=C]*/ <A>();
+ Wrapper(b, b).b<A> /*invoke: [exact=Wrapper]*/ ();
+ (Wrapper(b, b). /*[exact=Wrapper]*/ b)<A> /*invoke: [exact=C]*/ ();
+ Wrapper(b, b).call<A> /*invoke: [exact=Wrapper]*/ ();
+ (Wrapper(b, b). /*[exact=Wrapper]*/ call)<A> /*invoke: [exact=C]*/ ();
+}
diff --git a/pkg/compiler/test/rti/data/issue48304.dart b/pkg/compiler/test/rti/data/issue48304.dart
new file mode 100644
index 0000000..dfb51be
--- /dev/null
+++ b/pkg/compiler/test/rti/data/issue48304.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2022, 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.
+
+/*spec.class: B:explicit=[B]*/
+abstract class B {
+ call<T>();
+}
+
+class C implements B {
+ /*member: C.call:exp,needsArgs,selectors=[Selector(call, call, arity=0, types=1)]*/
+ call<T>() => print(T);
+}
+
+abstract class A {}
+
+class Wrapper {
+ Wrapper(this.b, this.call);
+ final B b;
+ final B call;
+}
+
+void main() {
+ B b = C();
+ b<A>();
+ Wrapper(b, b).b<A>();
+ (Wrapper(b, b).b)<A>();
+ Wrapper(b, b).call<A>();
+ (Wrapper(b, b).call)<A>();
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro.dart
index f55c0f8..85449b2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -228,8 +228,10 @@
macro.ResolvedIdentifier _resolveIdentifier(macro.Identifier identifier) {
if (identifier is _IdentifierImpl) {
MemberBuilder? memberBuilder = identifier.memberBuilder;
- TypeBuilder? typeBuilder = identifier.typeBuilder;
FormalParameterBuilder? parameterBuilder = identifier.parameterBuilder;
+ TypeDeclarationBuilder? typeDeclarationBuilder =
+ identifier.typeDeclarationBuilder ??
+ identifier.typeBuilder?.declaration;
if (memberBuilder != null) {
Uri? uri;
String? staticScope;
@@ -250,9 +252,7 @@
name: identifier.name,
staticScope: staticScope,
uri: uri);
- } else if (typeBuilder != null) {
- TypeDeclarationBuilder typeDeclarationBuilder =
- typeBuilder.declaration!;
+ } else if (typeDeclarationBuilder != null) {
Uri? uri;
if (typeDeclarationBuilder is ClassBuilder) {
uri = typeDeclarationBuilder.library.importUri;
diff --git a/pkg/front_end/testcases/dart2js/issue48304.dart b/pkg/front_end/testcases/dart2js/issue48304.dart
new file mode 100644
index 0000000..89351f8
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue48304.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2022, 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.
+
+abstract class B {
+ call<T>();
+}
+
+class C implements B {
+ call<T>() => print(T);
+}
+
+abstract class A {}
+
+class Wrapper {
+ Wrapper(this.b, this.call);
+ final B b;
+ final B call;
+}
+
+void main() {
+ B b = C();
+ b<A>();
+ Wrapper(b, b).b<A>();
+ (Wrapper(b, b).b)<A>();
+ Wrapper(b, b).call<A>();
+ (Wrapper(b, b).call)<A>();
+}
diff --git a/pkg/front_end/testcases/dart2js/issue48304.dart.strong.expect b/pkg/front_end/testcases/dart2js/issue48304.dart.strong.expect
new file mode 100644
index 0000000..9f1d34d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue48304.dart.strong.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class B extends core::Object {
+ synthetic constructor •() → self::B
+ : super core::Object::•()
+ ;
+ abstract method call<T extends core::Object? = dynamic>() → dynamic;
+}
+class C extends core::Object implements self::B {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ method call<T extends core::Object? = dynamic>() → dynamic
+ return core::print(self::C::call::T%);
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class Wrapper extends core::Object {
+ final field self::B b;
+ final field self::B call;
+ constructor •(self::B b, self::B call) → self::Wrapper
+ : self::Wrapper::b = b, self::Wrapper::call = call, super core::Object::•()
+ ;
+ static method _#new#tearOff(self::B b, self::B call) → self::Wrapper
+ return new self::Wrapper::•(b, call);
+}
+static method main() → void {
+ self::B b = new self::C::•();
+ b.{self::B::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::b}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::b}{self::B}.{self::B::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::call}{self::B}.{self::B::call}<self::A>(){() → dynamic};
+}
diff --git a/pkg/front_end/testcases/dart2js/issue48304.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/issue48304.dart.strong.transformed.expect
new file mode 100644
index 0000000..9f1d34d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue48304.dart.strong.transformed.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class B extends core::Object {
+ synthetic constructor •() → self::B
+ : super core::Object::•()
+ ;
+ abstract method call<T extends core::Object? = dynamic>() → dynamic;
+}
+class C extends core::Object implements self::B {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ method call<T extends core::Object? = dynamic>() → dynamic
+ return core::print(self::C::call::T%);
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class Wrapper extends core::Object {
+ final field self::B b;
+ final field self::B call;
+ constructor •(self::B b, self::B call) → self::Wrapper
+ : self::Wrapper::b = b, self::Wrapper::call = call, super core::Object::•()
+ ;
+ static method _#new#tearOff(self::B b, self::B call) → self::Wrapper
+ return new self::Wrapper::•(b, call);
+}
+static method main() → void {
+ self::B b = new self::C::•();
+ b.{self::B::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::b}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::b}{self::B}.{self::B::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::call}{self::B}.{self::B::call}<self::A>(){() → dynamic};
+}
diff --git a/pkg/front_end/testcases/dart2js/issue48304.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/issue48304.dart.textual_outline.expect
new file mode 100644
index 0000000..05d076b
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue48304.dart.textual_outline.expect
@@ -0,0 +1,17 @@
+abstract class B {
+ call<T>();
+}
+
+class C implements B {
+ call<T>() => print(T);
+}
+
+abstract class A {}
+
+class Wrapper {
+ Wrapper(this.b, this.call);
+ final B b;
+ final B call;
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/dart2js/issue48304.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/issue48304.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..6997d4b
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue48304.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+abstract class A {}
+
+abstract class B {
+ call<T>();
+}
+
+class C implements B {
+ call<T>() => print(T);
+}
+
+class Wrapper {
+ Wrapper(this.b, this.call);
+ final B b;
+ final B call;
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/dart2js/issue48304.dart.weak.expect b/pkg/front_end/testcases/dart2js/issue48304.dart.weak.expect
new file mode 100644
index 0000000..9f1d34d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue48304.dart.weak.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class B extends core::Object {
+ synthetic constructor •() → self::B
+ : super core::Object::•()
+ ;
+ abstract method call<T extends core::Object? = dynamic>() → dynamic;
+}
+class C extends core::Object implements self::B {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ method call<T extends core::Object? = dynamic>() → dynamic
+ return core::print(self::C::call::T%);
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class Wrapper extends core::Object {
+ final field self::B b;
+ final field self::B call;
+ constructor •(self::B b, self::B call) → self::Wrapper
+ : self::Wrapper::b = b, self::Wrapper::call = call, super core::Object::•()
+ ;
+ static method _#new#tearOff(self::B b, self::B call) → self::Wrapper
+ return new self::Wrapper::•(b, call);
+}
+static method main() → void {
+ self::B b = new self::C::•();
+ b.{self::B::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::b}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::b}{self::B}.{self::B::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::call}{self::B}.{self::B::call}<self::A>(){() → dynamic};
+}
diff --git a/pkg/front_end/testcases/dart2js/issue48304.dart.weak.modular.expect b/pkg/front_end/testcases/dart2js/issue48304.dart.weak.modular.expect
new file mode 100644
index 0000000..9f1d34d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue48304.dart.weak.modular.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class B extends core::Object {
+ synthetic constructor •() → self::B
+ : super core::Object::•()
+ ;
+ abstract method call<T extends core::Object? = dynamic>() → dynamic;
+}
+class C extends core::Object implements self::B {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ method call<T extends core::Object? = dynamic>() → dynamic
+ return core::print(self::C::call::T%);
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class Wrapper extends core::Object {
+ final field self::B b;
+ final field self::B call;
+ constructor •(self::B b, self::B call) → self::Wrapper
+ : self::Wrapper::b = b, self::Wrapper::call = call, super core::Object::•()
+ ;
+ static method _#new#tearOff(self::B b, self::B call) → self::Wrapper
+ return new self::Wrapper::•(b, call);
+}
+static method main() → void {
+ self::B b = new self::C::•();
+ b.{self::B::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::b}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::b}{self::B}.{self::B::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::call}{self::B}.{self::B::call}<self::A>(){() → dynamic};
+}
diff --git a/pkg/front_end/testcases/dart2js/issue48304.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/issue48304.dart.weak.outline.expect
new file mode 100644
index 0000000..f6c8da7
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue48304.dart.weak.outline.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class B extends core::Object {
+ synthetic constructor •() → self::B
+ ;
+ abstract method call<T extends core::Object? = dynamic>() → dynamic;
+}
+class C extends core::Object implements self::B {
+ synthetic constructor •() → self::C
+ ;
+ method call<T extends core::Object? = dynamic>() → dynamic
+ ;
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ ;
+}
+class Wrapper extends core::Object {
+ final field self::B b;
+ final field self::B call;
+ constructor •(self::B b, self::B call) → self::Wrapper
+ ;
+ static method _#new#tearOff(self::B b, self::B call) → self::Wrapper
+ return new self::Wrapper::•(b, call);
+}
+static method main() → void
+ ;
diff --git a/pkg/front_end/testcases/dart2js/issue48304.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/issue48304.dart.weak.transformed.expect
new file mode 100644
index 0000000..9f1d34d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/issue48304.dart.weak.transformed.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class B extends core::Object {
+ synthetic constructor •() → self::B
+ : super core::Object::•()
+ ;
+ abstract method call<T extends core::Object? = dynamic>() → dynamic;
+}
+class C extends core::Object implements self::B {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ method call<T extends core::Object? = dynamic>() → dynamic
+ return core::print(self::C::call::T%);
+ static method _#new#tearOff() → self::C
+ return new self::C::•();
+}
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class Wrapper extends core::Object {
+ final field self::B b;
+ final field self::B call;
+ constructor •(self::B b, self::B call) → self::Wrapper
+ : self::Wrapper::b = b, self::Wrapper::call = call, super core::Object::•()
+ ;
+ static method _#new#tearOff(self::B b, self::B call) → self::Wrapper
+ return new self::Wrapper::•(b, call);
+}
+static method main() → void {
+ self::B b = new self::C::•();
+ b.{self::B::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::b}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::b}{self::B}.{self::B::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::call}<self::A>(){() → dynamic};
+ new self::Wrapper::•(b, b).{self::Wrapper::call}{self::B}.{self::B::call}<self::A>(){() → dynamic};
+}
diff --git a/tests/language/regress/regress48304_test.dart b/tests/language/regress/regress48304_test.dart
new file mode 100644
index 0000000..04de267
--- /dev/null
+++ b/tests/language/regress/regress48304_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2022, 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';
+
+final String expected = '$A';
+
+abstract class B {
+ call<T>();
+}
+
+class C implements B {
+ call<T>() => '$T';
+}
+
+abstract class A {}
+
+class Wrapper {
+ Wrapper(this.b, this.call);
+ final B b;
+ final B call;
+}
+
+void main() {
+ B b = C();
+ Expect.equals(b<A>(), expected);
+ Expect.equals(Wrapper(b, b).b<A>(), expected);
+ Expect.equals((Wrapper(b, b).b)<A>(), expected);
+ Expect.equals(Wrapper(b, b).call<A>(), expected);
+ Expect.equals((Wrapper(b, b).call)<A>(), expected);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 5516267..f27b5c8 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 157
+PRERELEASE 158
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/patches/flutter-engine/apply.sh b/tools/patches/flutter-engine/apply.sh
index 38ce731..5b49564 100755
--- a/tools/patches/flutter-engine/apply.sh
+++ b/tools/patches/flutter-engine/apply.sh
@@ -62,7 +62,7 @@
# DEPS file might have been patched with new version of packages that
# Dart SDK depends on. Get information about dependencies from the
# DEPS file and forcefully update checkouts of those dependencies.
- gclient.py revinfo --ignore-dep-type=cipd | grep 'src/third_party/dart/third_party' | while read -r line; do
+ gclient revinfo --ignore-dep-type=cipd | grep 'src/third_party/dart/third_party' | while read -r line; do
# revinfo would produce lines in the following format:
# path: git-url@tag-or-hash
# Where no spaces occur inside path, git-url or tag-or-hash.
@@ -97,5 +97,5 @@
fi
popd > /dev/null
done
- gclient.py runhooks
+ gclient runhooks
fi