diff --git a/pkg/front_end/lib/src/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/type_inference/inference_visitor.dart index c2aab4f2ea7..2fba1fb7a8c 100644 --- a/pkg/front_end/lib/src/type_inference/inference_visitor.dart +++ b/pkg/front_end/lib/src/type_inference/inference_visitor.dart @@ -16745,6 +16745,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase if (member is Procedure && member.kind == ProcedureKind.Method) { // The shorthand expression is inferred in the empty context and then type // inference infers the type arguments. + ensureMemberType(member); FunctionType functionType = member.function.computeThisFunctionType( Nullability.nonNullable, ); @@ -16827,6 +16828,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase // The shorthand expression is inferred in the empty context and then // type inference infers the type arguments. + ensureMemberType(constructor); FunctionType functionType = constructor.function .computeThisFunctionType(Nullability.nonNullable); InvocationInferenceResult result = inferInvocation( @@ -16872,6 +16874,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase // The shorthand expression is inferred in the empty context and then // type inference infers the type arguments. + ensureMemberType(constructor); FunctionType functionType = constructor.function .computeThisFunctionType(Nullability.nonNullable); InvocationInferenceResult result = inferInvocation( diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart b/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart new file mode 100644 index 00000000000..1c4cd2ae004 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart @@ -0,0 +1,21 @@ +// Copyright (c) 2026, 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. + +final a = A(b: .new(c: .f(0))); + +class A { + final B b; + + const A({required this.b}); +} + +class B { + final C c; + + const B({required this.c}); +} + +class C { + C.f(num n); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.strong.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.strong.expect new file mode 100644 index 00000000000..41de890a51a --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.strong.expect @@ -0,0 +1,22 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::B b; + const constructor •({required self::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +class B extends core::Object /*hasConstConstructor*/ { + final field self::C c; + const constructor •({required self::C c}) → self::B + : self::B::c = c, super core::Object::•() + ; +} +class C extends core::Object { + constructor f(core::num n) → self::C + : super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: new self::B::•(c: new self::C::f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.strong.modular.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.strong.modular.expect new file mode 100644 index 00000000000..41de890a51a --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.strong.modular.expect @@ -0,0 +1,22 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::B b; + const constructor •({required self::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +class B extends core::Object /*hasConstConstructor*/ { + final field self::C c; + const constructor •({required self::C c}) → self::B + : self::B::c = c, super core::Object::•() + ; +} +class C extends core::Object { + constructor f(core::num n) → self::C + : super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: new self::B::•(c: new self::C::f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.strong.outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.strong.outline.expect new file mode 100644 index 00000000000..4534a9b1339 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.strong.outline.expect @@ -0,0 +1,21 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::B b; + const constructor •({required self::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +class B extends core::Object /*hasConstConstructor*/ { + final field self::C c; + const constructor •({required self::C c}) → self::B + : self::B::c = c, super core::Object::•() + ; +} +class C extends core::Object { + constructor f(core::num n) → self::C + ; +} +static final field self::A a; diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.strong.transformed.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.strong.transformed.expect new file mode 100644 index 00000000000..41de890a51a --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.strong.transformed.expect @@ -0,0 +1,22 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::B b; + const constructor •({required self::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +class B extends core::Object /*hasConstConstructor*/ { + final field self::C c; + const constructor •({required self::C c}) → self::B + : self::B::c = c, super core::Object::•() + ; +} +class C extends core::Object { + constructor f(core::num n) → self::C + : super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: new self::B::•(c: new self::C::f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.textual_outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.textual_outline.expect new file mode 100644 index 00000000000..62f05c17d69 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.textual_outline.expect @@ -0,0 +1,15 @@ +final a = A(b: .new(c: .f(0))); + +class A { + final B b; + const A({required this.b}); +} + +class B { + final C c; + const B({required this.c}); +} + +class C { + C.f(num n); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..e479076dfbc --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments.dart.textual_outline_modelled.expect @@ -0,0 +1,15 @@ +class A { + const A({required this.b}); + final B b; +} + +class B { + const B({required this.c}); + final C c; +} + +class C { + C.f(num n); +} + +final a = A(b: .new(c: .f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart new file mode 100644 index 00000000000..29d3bb8d696 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart @@ -0,0 +1,13 @@ +// Copyright (c) 2026, 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 'main_lib.dart'; + +final a = A(b: .new(c: .f(0))); + +class A { + final B b; + + const A({required this.b}); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.strong.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.strong.expect new file mode 100644 index 00000000000..18ca87ad777 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.strong.expect @@ -0,0 +1,30 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::B b; + const constructor •({required mai::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: new mai::B::•(c: new mai::C::f(0))); + +library; +import self as mai; +import "dart:core" as core; + +class B extends core::Object /*hasConstConstructor*/ { + final field mai::C c; + const constructor •({required mai::C c}) → mai::B + : mai::B::c = c, super core::Object::•() + ; +} +class C extends core::Object { + constructor f(core::num n) → mai::C + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.strong.modular.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.strong.modular.expect new file mode 100644 index 00000000000..18ca87ad777 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.strong.modular.expect @@ -0,0 +1,30 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::B b; + const constructor •({required mai::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: new mai::B::•(c: new mai::C::f(0))); + +library; +import self as mai; +import "dart:core" as core; + +class B extends core::Object /*hasConstConstructor*/ { + final field mai::C c; + const constructor •({required mai::C c}) → mai::B + : mai::B::c = c, super core::Object::•() + ; +} +class C extends core::Object { + constructor f(core::num n) → mai::C + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.strong.outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.strong.outline.expect new file mode 100644 index 00000000000..c19a1a464ab --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.strong.outline.expect @@ -0,0 +1,29 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::B b; + const constructor •({required mai::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +static final field self::A a; + +library; +import self as mai; +import "dart:core" as core; + +class B extends core::Object /*hasConstConstructor*/ { + final field mai::C c; + const constructor •({required mai::C c}) → mai::B + : mai::B::c = c, super core::Object::•() + ; +} +class C extends core::Object { + constructor f(core::num n) → mai::C + ; +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.strong.transformed.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.strong.transformed.expect new file mode 100644 index 00000000000..18ca87ad777 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.strong.transformed.expect @@ -0,0 +1,30 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::B b; + const constructor •({required mai::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: new mai::B::•(c: new mai::C::f(0))); + +library; +import self as mai; +import "dart:core" as core; + +class B extends core::Object /*hasConstConstructor*/ { + final field mai::C c; + const constructor •({required mai::C c}) → mai::B + : mai::B::c = c, super core::Object::•() + ; +} +class C extends core::Object { + constructor f(core::num n) → mai::C + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.textual_outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.textual_outline.expect new file mode 100644 index 00000000000..53a5bfb3bf4 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.textual_outline.expect @@ -0,0 +1,8 @@ +import 'main_lib.dart'; + +final a = A(b: .new(c: .f(0))); + +class A { + final B b; + const A({required this.b}); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..ba6709b87fb --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main.dart.textual_outline_modelled.expect @@ -0,0 +1,8 @@ +import 'main_lib.dart'; + +class A { + const A({required this.b}); + final B b; +} + +final a = A(b: .new(c: .f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments/main_lib.dart b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main_lib.dart new file mode 100644 index 00000000000..9de7bf0e251 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments/main_lib.dart @@ -0,0 +1,13 @@ +// Copyright (c) 2026, 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. + +class B { + final C c; + + const B({required this.c}); +} + +class C { + C.f(num n); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart new file mode 100644 index 00000000000..fe194d3dde3 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart @@ -0,0 +1,18 @@ +// Copyright (c) 2026, 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. + +final a = A(bExt: .f(c: .f(0))); + +class A { + final BExt bExt; + const A({required this.bExt}); +} + +class C { + C.f(num n); +} + +extension type BExt(C c) { + BExt.f({required C c}) : this(c); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.strong.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.strong.expect new file mode 100644 index 00000000000..429a400b9da --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.strong.expect @@ -0,0 +1,36 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::BExt% /* erasure=self::C, declared=! */ bExt; + const constructor •({required self::BExt% /* erasure=self::C, declared=! */ bExt}) → self::A + : self::A::bExt = bExt, super core::Object::•() + ; +} +class C extends core::Object { + constructor f(core::num n) → self::C + : super core::Object::•() + ; +} +extension type BExt(self::C c) { + abstract extension-type-member representation-field get c() → self::C; + constructor • = self::BExt|constructor#; + constructor tearoff • = self::BExt|constructor#_#new#tearOff; + constructor f = self::BExt|constructor#f; + constructor tearoff f = self::BExt|constructor#_#f#tearOff; +} +static final field self::A a = new self::A::•(bExt: self::BExt|constructor#f(c: new self::C::f(0))); +static extension-type-member method BExt|constructor#(self::C c) → self::BExt% /* erasure=self::C, declared=! */ { + lowered final self::BExt% /* erasure=self::C, declared=! */ #this = c; + return #this; +} +static extension-type-member synthetic method BExt|constructor#_#new#tearOff(self::C c) → self::BExt% /* erasure=self::C, declared=! */ + return self::BExt|constructor#(c); +static extension-type-member method BExt|constructor#f({required self::C c}) → self::BExt% /* erasure=self::C, declared=! */ { + lowered final self::BExt% /* erasure=self::C, declared=! */ #this; + #this = self::BExt|constructor#(c); + return #this; +} +static extension-type-member synthetic method BExt|constructor#_#f#tearOff({required self::C c}) → self::BExt% /* erasure=self::C, declared=! */ + return self::BExt|constructor#f(c: c); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.strong.modular.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.strong.modular.expect new file mode 100644 index 00000000000..429a400b9da --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.strong.modular.expect @@ -0,0 +1,36 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::BExt% /* erasure=self::C, declared=! */ bExt; + const constructor •({required self::BExt% /* erasure=self::C, declared=! */ bExt}) → self::A + : self::A::bExt = bExt, super core::Object::•() + ; +} +class C extends core::Object { + constructor f(core::num n) → self::C + : super core::Object::•() + ; +} +extension type BExt(self::C c) { + abstract extension-type-member representation-field get c() → self::C; + constructor • = self::BExt|constructor#; + constructor tearoff • = self::BExt|constructor#_#new#tearOff; + constructor f = self::BExt|constructor#f; + constructor tearoff f = self::BExt|constructor#_#f#tearOff; +} +static final field self::A a = new self::A::•(bExt: self::BExt|constructor#f(c: new self::C::f(0))); +static extension-type-member method BExt|constructor#(self::C c) → self::BExt% /* erasure=self::C, declared=! */ { + lowered final self::BExt% /* erasure=self::C, declared=! */ #this = c; + return #this; +} +static extension-type-member synthetic method BExt|constructor#_#new#tearOff(self::C c) → self::BExt% /* erasure=self::C, declared=! */ + return self::BExt|constructor#(c); +static extension-type-member method BExt|constructor#f({required self::C c}) → self::BExt% /* erasure=self::C, declared=! */ { + lowered final self::BExt% /* erasure=self::C, declared=! */ #this; + #this = self::BExt|constructor#(c); + return #this; +} +static extension-type-member synthetic method BExt|constructor#_#f#tearOff({required self::C c}) → self::BExt% /* erasure=self::C, declared=! */ + return self::BExt|constructor#f(c: c); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.strong.outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.strong.outline.expect new file mode 100644 index 00000000000..b49e1069963 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.strong.outline.expect @@ -0,0 +1,30 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::BExt% /* erasure=self::C, declared=! */ bExt; + const constructor •({required self::BExt% /* erasure=self::C, declared=! */ bExt}) → self::A + : self::A::bExt = bExt, super core::Object::•() + ; +} +class C extends core::Object { + constructor f(core::num n) → self::C + ; +} +extension type BExt(self::C c) { + abstract extension-type-member representation-field get c() → self::C; + constructor • = self::BExt|constructor#; + constructor tearoff • = self::BExt|constructor#_#new#tearOff; + constructor f = self::BExt|constructor#f; + constructor tearoff f = self::BExt|constructor#_#f#tearOff; +} +static final field self::A a; +static extension-type-member method BExt|constructor#(self::C c) → self::BExt% /* erasure=self::C, declared=! */ + ; +static extension-type-member synthetic method BExt|constructor#_#new#tearOff(self::C c) → self::BExt% /* erasure=self::C, declared=! */ + return self::BExt|constructor#(c); +static extension-type-member method BExt|constructor#f({required self::C c}) → self::BExt% /* erasure=self::C, declared=! */ + ; +static extension-type-member synthetic method BExt|constructor#_#f#tearOff({required self::C c}) → self::BExt% /* erasure=self::C, declared=! */ + return self::BExt|constructor#f(c: c); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.strong.transformed.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.strong.transformed.expect new file mode 100644 index 00000000000..429a400b9da --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.strong.transformed.expect @@ -0,0 +1,36 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::BExt% /* erasure=self::C, declared=! */ bExt; + const constructor •({required self::BExt% /* erasure=self::C, declared=! */ bExt}) → self::A + : self::A::bExt = bExt, super core::Object::•() + ; +} +class C extends core::Object { + constructor f(core::num n) → self::C + : super core::Object::•() + ; +} +extension type BExt(self::C c) { + abstract extension-type-member representation-field get c() → self::C; + constructor • = self::BExt|constructor#; + constructor tearoff • = self::BExt|constructor#_#new#tearOff; + constructor f = self::BExt|constructor#f; + constructor tearoff f = self::BExt|constructor#_#f#tearOff; +} +static final field self::A a = new self::A::•(bExt: self::BExt|constructor#f(c: new self::C::f(0))); +static extension-type-member method BExt|constructor#(self::C c) → self::BExt% /* erasure=self::C, declared=! */ { + lowered final self::BExt% /* erasure=self::C, declared=! */ #this = c; + return #this; +} +static extension-type-member synthetic method BExt|constructor#_#new#tearOff(self::C c) → self::BExt% /* erasure=self::C, declared=! */ + return self::BExt|constructor#(c); +static extension-type-member method BExt|constructor#f({required self::C c}) → self::BExt% /* erasure=self::C, declared=! */ { + lowered final self::BExt% /* erasure=self::C, declared=! */ #this; + #this = self::BExt|constructor#(c); + return #this; +} +static extension-type-member synthetic method BExt|constructor#_#f#tearOff({required self::C c}) → self::BExt% /* erasure=self::C, declared=! */ + return self::BExt|constructor#f(c: c); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.textual_outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.textual_outline.expect new file mode 100644 index 00000000000..27c2e7001ee --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.textual_outline.expect @@ -0,0 +1,14 @@ +final a = A(bExt: .f(c: .f(0))); + +class A { + final BExt bExt; + const A({required this.bExt}); +} + +class C { + C.f(num n); +} + +extension type BExt(C c) { + BExt.f({required C c}) : this(c); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..0f59a8f9239 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type.dart.textual_outline_modelled.expect @@ -0,0 +1,14 @@ +class A { + const A({required this.bExt}); + final BExt bExt; +} + +class C { + C.f(num n); +} + +extension type BExt(C c) { + BExt.f({required C c}) : this(c); +} + +final a = A(bExt: .f(c: .f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart new file mode 100644 index 00000000000..b7a7362b4fe --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart @@ -0,0 +1,13 @@ +// Copyright (c) 2026, 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 'main_lib.dart'; + +final a = A(bExt: .f(c: .f(0))); + +class A { + final BExt bExt; + + const A({required this.bExt}); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.strong.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.strong.expect new file mode 100644 index 00000000000..9d2bbe42bcb --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.strong.expect @@ -0,0 +1,44 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::BExt% /* erasure=mai::C, declared=! */ bExt; + const constructor •({required mai::BExt% /* erasure=mai::C, declared=! */ bExt}) → self::A + : self::A::bExt = bExt, super core::Object::•() + ; +} +static final field self::A a = new self::A::•(bExt: mai::BExt|constructor#f(c: new mai::C::f(0))); + +library; +import self as mai; +import "dart:core" as core; + +class C extends core::Object { + constructor f(core::num n) → mai::C + : super core::Object::•() + ; +} +extension type BExt(mai::C c) { + abstract extension-type-member representation-field get c() → mai::C; + constructor • = mai::BExt|constructor#; + constructor tearoff • = mai::BExt|constructor#_#new#tearOff; + constructor f = mai::BExt|constructor#f; + constructor tearoff f = mai::BExt|constructor#_#f#tearOff; +} +static extension-type-member method BExt|constructor#(mai::C c) → mai::BExt% /* erasure=mai::C, declared=! */ { + lowered final mai::BExt% /* erasure=mai::C, declared=! */ #this = c; + return #this; +} +static extension-type-member synthetic method BExt|constructor#_#new#tearOff(mai::C c) → mai::BExt% /* erasure=mai::C, declared=! */ + return mai::BExt|constructor#(c); +static extension-type-member method BExt|constructor#f({required mai::C c}) → mai::BExt% /* erasure=mai::C, declared=! */ { + lowered final mai::BExt% /* erasure=mai::C, declared=! */ #this; + #this = mai::BExt|constructor#(c); + return #this; +} +static extension-type-member synthetic method BExt|constructor#_#f#tearOff({required mai::C c}) → mai::BExt% /* erasure=mai::C, declared=! */ + return mai::BExt|constructor#f(c: c); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.strong.modular.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.strong.modular.expect new file mode 100644 index 00000000000..9d2bbe42bcb --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.strong.modular.expect @@ -0,0 +1,44 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::BExt% /* erasure=mai::C, declared=! */ bExt; + const constructor •({required mai::BExt% /* erasure=mai::C, declared=! */ bExt}) → self::A + : self::A::bExt = bExt, super core::Object::•() + ; +} +static final field self::A a = new self::A::•(bExt: mai::BExt|constructor#f(c: new mai::C::f(0))); + +library; +import self as mai; +import "dart:core" as core; + +class C extends core::Object { + constructor f(core::num n) → mai::C + : super core::Object::•() + ; +} +extension type BExt(mai::C c) { + abstract extension-type-member representation-field get c() → mai::C; + constructor • = mai::BExt|constructor#; + constructor tearoff • = mai::BExt|constructor#_#new#tearOff; + constructor f = mai::BExt|constructor#f; + constructor tearoff f = mai::BExt|constructor#_#f#tearOff; +} +static extension-type-member method BExt|constructor#(mai::C c) → mai::BExt% /* erasure=mai::C, declared=! */ { + lowered final mai::BExt% /* erasure=mai::C, declared=! */ #this = c; + return #this; +} +static extension-type-member synthetic method BExt|constructor#_#new#tearOff(mai::C c) → mai::BExt% /* erasure=mai::C, declared=! */ + return mai::BExt|constructor#(c); +static extension-type-member method BExt|constructor#f({required mai::C c}) → mai::BExt% /* erasure=mai::C, declared=! */ { + lowered final mai::BExt% /* erasure=mai::C, declared=! */ #this; + #this = mai::BExt|constructor#(c); + return #this; +} +static extension-type-member synthetic method BExt|constructor#_#f#tearOff({required mai::C c}) → mai::BExt% /* erasure=mai::C, declared=! */ + return mai::BExt|constructor#f(c: c); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.strong.outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.strong.outline.expect new file mode 100644 index 00000000000..395f04f8d70 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.strong.outline.expect @@ -0,0 +1,37 @@ +library; +import self as self; +import "dart:core" as core; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field #lib1::BExt% /* erasure=#lib1::C, declared=! */ bExt; + const constructor •({required #lib1::BExt% /* erasure=#lib1::C, declared=! */ bExt}) → self::A + : self::A::bExt = bExt, super core::Object::•() + ; +} +static final field self::A a; + +library; +import self as self2; +import "dart:core" as core; + +class C extends core::Object { + constructor f(core::num n) → self2::C + ; +} +extension type BExt(self2::C c) { + abstract extension-type-member representation-field get c() → self2::C; + constructor • = self2::BExt|constructor#; + constructor tearoff • = self2::BExt|constructor#_#new#tearOff; + constructor f = self2::BExt|constructor#f; + constructor tearoff f = self2::BExt|constructor#_#f#tearOff; +} +static extension-type-member method BExt|constructor#(self2::C c) → self2::BExt% /* erasure=self2::C, declared=! */ + ; +static extension-type-member synthetic method BExt|constructor#_#new#tearOff(self2::C c) → self2::BExt% /* erasure=self2::C, declared=! */ + return self2::BExt|constructor#(c); +static extension-type-member method BExt|constructor#f({required self2::C c}) → self2::BExt% /* erasure=self2::C, declared=! */ + ; +static extension-type-member synthetic method BExt|constructor#_#f#tearOff({required self2::C c}) → self2::BExt% /* erasure=self2::C, declared=! */ + return self2::BExt|constructor#f(c: c); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.strong.transformed.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.strong.transformed.expect new file mode 100644 index 00000000000..9d2bbe42bcb --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.strong.transformed.expect @@ -0,0 +1,44 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::BExt% /* erasure=mai::C, declared=! */ bExt; + const constructor •({required mai::BExt% /* erasure=mai::C, declared=! */ bExt}) → self::A + : self::A::bExt = bExt, super core::Object::•() + ; +} +static final field self::A a = new self::A::•(bExt: mai::BExt|constructor#f(c: new mai::C::f(0))); + +library; +import self as mai; +import "dart:core" as core; + +class C extends core::Object { + constructor f(core::num n) → mai::C + : super core::Object::•() + ; +} +extension type BExt(mai::C c) { + abstract extension-type-member representation-field get c() → mai::C; + constructor • = mai::BExt|constructor#; + constructor tearoff • = mai::BExt|constructor#_#new#tearOff; + constructor f = mai::BExt|constructor#f; + constructor tearoff f = mai::BExt|constructor#_#f#tearOff; +} +static extension-type-member method BExt|constructor#(mai::C c) → mai::BExt% /* erasure=mai::C, declared=! */ { + lowered final mai::BExt% /* erasure=mai::C, declared=! */ #this = c; + return #this; +} +static extension-type-member synthetic method BExt|constructor#_#new#tearOff(mai::C c) → mai::BExt% /* erasure=mai::C, declared=! */ + return mai::BExt|constructor#(c); +static extension-type-member method BExt|constructor#f({required mai::C c}) → mai::BExt% /* erasure=mai::C, declared=! */ { + lowered final mai::BExt% /* erasure=mai::C, declared=! */ #this; + #this = mai::BExt|constructor#(c); + return #this; +} +static extension-type-member synthetic method BExt|constructor#_#f#tearOff({required mai::C c}) → mai::BExt% /* erasure=mai::C, declared=! */ + return mai::BExt|constructor#f(c: c); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.textual_outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.textual_outline.expect new file mode 100644 index 00000000000..bb99a2f8ae4 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.textual_outline.expect @@ -0,0 +1,8 @@ +import 'main_lib.dart'; + +final a = A(bExt: .f(c: .f(0))); + +class A { + final BExt bExt; + const A({required this.bExt}); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..ffee7ff4995 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main.dart.textual_outline_modelled.expect @@ -0,0 +1,8 @@ +import 'main_lib.dart'; + +class A { + const A({required this.bExt}); + final BExt bExt; +} + +final a = A(bExt: .f(c: .f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main_lib.dart b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main_lib.dart new file mode 100644 index 00000000000..72bb055e657 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_extension_type/main_lib.dart @@ -0,0 +1,11 @@ +// Copyright (c) 2026, 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. + +class C { + C.f(num n); +} + +extension type BExt(C c) { + BExt.f({required C c}) : this(c); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart new file mode 100644 index 00000000000..a4cbcfb5feb --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart @@ -0,0 +1,21 @@ +// Copyright (c) 2026, 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. + +final a = A(b: .redirect(c: .f(0))); + +class A { + final B b; + const A({required this.b}); +} + +class B { + final C c; + const B({required this.c}); + + factory B.redirect({required C c}) = B; +} + +class C { + C.f(num n); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.strong.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.strong.expect new file mode 100644 index 00000000000..f1f08c4b60a --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.strong.expect @@ -0,0 +1,24 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::B b; + const constructor •({required self::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +class B extends core::Object /*hasConstConstructor*/ { + final field self::C c; + const constructor •({required self::C c}) → self::B + : self::B::c = c, super core::Object::•() + ; + static factory redirect({required self::C c}) → self::B /* redirection-target: self::B::• */ + return new self::B::•(c: c); +} +class C extends core::Object { + constructor f(core::num n) → self::C + : super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: new self::B::•(c: new self::C::f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.strong.modular.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.strong.modular.expect new file mode 100644 index 00000000000..f1f08c4b60a --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.strong.modular.expect @@ -0,0 +1,24 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::B b; + const constructor •({required self::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +class B extends core::Object /*hasConstConstructor*/ { + final field self::C c; + const constructor •({required self::C c}) → self::B + : self::B::c = c, super core::Object::•() + ; + static factory redirect({required self::C c}) → self::B /* redirection-target: self::B::• */ + return new self::B::•(c: c); +} +class C extends core::Object { + constructor f(core::num n) → self::C + : super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: new self::B::•(c: new self::C::f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.strong.outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.strong.outline.expect new file mode 100644 index 00000000000..6e23369ef49 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.strong.outline.expect @@ -0,0 +1,23 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::B b; + const constructor •({required self::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +class B extends core::Object /*hasConstConstructor*/ { + final field self::C c; + const constructor •({required self::C c}) → self::B + : self::B::c = c, super core::Object::•() + ; + static factory redirect({required self::C c}) → self::B /* redirection-target: self::B::• */ + return new self::B::•(c: c); +} +class C extends core::Object { + constructor f(core::num n) → self::C + ; +} +static final field self::A a; diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.strong.transformed.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.strong.transformed.expect new file mode 100644 index 00000000000..f1f08c4b60a --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.strong.transformed.expect @@ -0,0 +1,24 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::B b; + const constructor •({required self::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +class B extends core::Object /*hasConstConstructor*/ { + final field self::C c; + const constructor •({required self::C c}) → self::B + : self::B::c = c, super core::Object::•() + ; + static factory redirect({required self::C c}) → self::B /* redirection-target: self::B::• */ + return new self::B::•(c: c); +} +class C extends core::Object { + constructor f(core::num n) → self::C + : super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: new self::B::•(c: new self::C::f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.textual_outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.textual_outline.expect new file mode 100644 index 00000000000..63685d12fa1 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.textual_outline.expect @@ -0,0 +1,16 @@ +final a = A(b: .redirect(c: .f(0))); + +class A { + final B b; + const A({required this.b}); +} + +class B { + final C c; + const B({required this.c}); + factory B.redirect({required C c}) = B; +} + +class C { + C.f(num n); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..f755ebf5ebf --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory.dart.textual_outline_modelled.expect @@ -0,0 +1,16 @@ +class A { + const A({required this.b}); + final B b; +} + +class B { + const B({required this.c}); + factory B.redirect({required C c}) = B; + final C c; +} + +class C { + C.f(num n); +} + +final a = A(b: .redirect(c: .f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart new file mode 100644 index 00000000000..d413b97a331 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart @@ -0,0 +1,13 @@ +// Copyright (c) 2026, 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 'main_lib.dart'; + +final a = A(b: .redirect(c: .f(0))); + +class A { + final B b; + + const A({required this.b}); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.strong.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.strong.expect new file mode 100644 index 00000000000..8ad01f8d9fe --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.strong.expect @@ -0,0 +1,32 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::B b; + const constructor •({required mai::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: new mai::B::•(c: new mai::C::f(0))); + +library; +import self as mai; +import "dart:core" as core; + +class B extends core::Object /*hasConstConstructor*/ { + final field mai::C c; + const constructor •({required mai::C c}) → mai::B + : mai::B::c = c, super core::Object::•() + ; + static factory redirect({required mai::C c}) → mai::B /* redirection-target: mai::B::• */ + return new mai::B::•(c: c); +} +class C extends core::Object { + constructor f(core::num n) → mai::C + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.strong.modular.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.strong.modular.expect new file mode 100644 index 00000000000..8ad01f8d9fe --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.strong.modular.expect @@ -0,0 +1,32 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::B b; + const constructor •({required mai::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: new mai::B::•(c: new mai::C::f(0))); + +library; +import self as mai; +import "dart:core" as core; + +class B extends core::Object /*hasConstConstructor*/ { + final field mai::C c; + const constructor •({required mai::C c}) → mai::B + : mai::B::c = c, super core::Object::•() + ; + static factory redirect({required mai::C c}) → mai::B /* redirection-target: mai::B::• */ + return new mai::B::•(c: c); +} +class C extends core::Object { + constructor f(core::num n) → mai::C + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.strong.outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.strong.outline.expect new file mode 100644 index 00000000000..17b3fc208ba --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.strong.outline.expect @@ -0,0 +1,31 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::B b; + const constructor •({required mai::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +static final field self::A a; + +library; +import self as mai; +import "dart:core" as core; + +class B extends core::Object /*hasConstConstructor*/ { + final field mai::C c; + const constructor •({required mai::C c}) → mai::B + : mai::B::c = c, super core::Object::•() + ; + static factory redirect({required mai::C c}) → mai::B /* redirection-target: mai::B::• */ + return new mai::B::•(c: c); +} +class C extends core::Object { + constructor f(core::num n) → mai::C + ; +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.strong.transformed.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.strong.transformed.expect new file mode 100644 index 00000000000..8ad01f8d9fe --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.strong.transformed.expect @@ -0,0 +1,32 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::B b; + const constructor •({required mai::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: new mai::B::•(c: new mai::C::f(0))); + +library; +import self as mai; +import "dart:core" as core; + +class B extends core::Object /*hasConstConstructor*/ { + final field mai::C c; + const constructor •({required mai::C c}) → mai::B + : mai::B::c = c, super core::Object::•() + ; + static factory redirect({required mai::C c}) → mai::B /* redirection-target: mai::B::• */ + return new mai::B::•(c: c); +} +class C extends core::Object { + constructor f(core::num n) → mai::C + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.textual_outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.textual_outline.expect new file mode 100644 index 00000000000..2a339618d84 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.textual_outline.expect @@ -0,0 +1,8 @@ +import 'main_lib.dart'; + +final a = A(b: .redirect(c: .f(0))); + +class A { + final B b; + const A({required this.b}); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..bf1584c0106 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main.dart.textual_outline_modelled.expect @@ -0,0 +1,8 @@ +import 'main_lib.dart'; + +class A { + const A({required this.b}); + final B b; +} + +final a = A(b: .redirect(c: .f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main_lib.dart b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main_lib.dart new file mode 100644 index 00000000000..5820a98fea3 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_redirecting_factory/main_lib.dart @@ -0,0 +1,14 @@ +// Copyright (c) 2026, 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. + +class B { + final C c; + const B({required this.c}); + + factory B.redirect({required C c}) = B; +} + +class C { + C.f(num n); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart new file mode 100644 index 00000000000..2bdf53e43dc --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart @@ -0,0 +1,21 @@ +// Copyright (c) 2026, 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. + +final a = A(b: .f(.f(0))); + +class A { + final B b; + const A({required this.b}); +} + +class B { + final C c; + const B({required this.c}); + + static B f(C c) => B(c: c); +} + +class C { + C.f(num n); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.strong.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.strong.expect new file mode 100644 index 00000000000..b86370b6162 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.strong.expect @@ -0,0 +1,24 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::B b; + const constructor •({required self::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +class B extends core::Object /*hasConstConstructor*/ { + final field self::C c; + const constructor •({required self::C c}) → self::B + : self::B::c = c, super core::Object::•() + ; + static method f(self::C c) → self::B + return new self::B::•(c: c); +} +class C extends core::Object { + constructor f(core::num n) → self::C + : super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: self::B::f(new self::C::f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.strong.modular.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.strong.modular.expect new file mode 100644 index 00000000000..b86370b6162 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.strong.modular.expect @@ -0,0 +1,24 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::B b; + const constructor •({required self::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +class B extends core::Object /*hasConstConstructor*/ { + final field self::C c; + const constructor •({required self::C c}) → self::B + : self::B::c = c, super core::Object::•() + ; + static method f(self::C c) → self::B + return new self::B::•(c: c); +} +class C extends core::Object { + constructor f(core::num n) → self::C + : super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: self::B::f(new self::C::f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.strong.outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.strong.outline.expect new file mode 100644 index 00000000000..cf56c8bd204 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.strong.outline.expect @@ -0,0 +1,23 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::B b; + const constructor •({required self::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +class B extends core::Object /*hasConstConstructor*/ { + final field self::C c; + const constructor •({required self::C c}) → self::B + : self::B::c = c, super core::Object::•() + ; + static method f(self::C c) → self::B + ; +} +class C extends core::Object { + constructor f(core::num n) → self::C + ; +} +static final field self::A a; diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.strong.transformed.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.strong.transformed.expect new file mode 100644 index 00000000000..b86370b6162 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.strong.transformed.expect @@ -0,0 +1,24 @@ +library; +import self as self; +import "dart:core" as core; + +class A extends core::Object /*hasConstConstructor*/ { + final field self::B b; + const constructor •({required self::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +class B extends core::Object /*hasConstConstructor*/ { + final field self::C c; + const constructor •({required self::C c}) → self::B + : self::B::c = c, super core::Object::•() + ; + static method f(self::C c) → self::B + return new self::B::•(c: c); +} +class C extends core::Object { + constructor f(core::num n) → self::C + : super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: self::B::f(new self::C::f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.textual_outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.textual_outline.expect new file mode 100644 index 00000000000..291a1ff3f6a --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.textual_outline.expect @@ -0,0 +1,16 @@ +final a = A(b: .f(.f(0))); + +class A { + final B b; + const A({required this.b}); +} + +class B { + final C c; + const B({required this.c}); + static B f(C c) => B(c: c); +} + +class C { + C.f(num n); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..b4ddf4fd378 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method.dart.textual_outline_modelled.expect @@ -0,0 +1,16 @@ +class A { + const A({required this.b}); + final B b; +} + +class B { + const B({required this.c}); + final C c; + static B f(C c) => B(c: c); +} + +class C { + C.f(num n); +} + +final a = A(b: .f(.f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart new file mode 100644 index 00000000000..51ad103bf8e --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart @@ -0,0 +1,13 @@ +// Copyright (c) 2026, 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 'main_lib.dart'; + +final a = A(b: .f(.f(0))); + +class A { + final B b; + + const A({required this.b}); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.strong.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.strong.expect new file mode 100644 index 00000000000..1fbfeaf2e65 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.strong.expect @@ -0,0 +1,32 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::B b; + const constructor •({required mai::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: mai::B::f(new mai::C::f(0))); + +library; +import self as mai; +import "dart:core" as core; + +class B extends core::Object /*hasConstConstructor*/ { + final field mai::C c; + const constructor •({required mai::C c}) → mai::B + : mai::B::c = c, super core::Object::•() + ; + static method f(mai::C c) → mai::B + return new mai::B::•(c: c); +} +class C extends core::Object { + constructor f(core::num n) → mai::C + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.strong.modular.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.strong.modular.expect new file mode 100644 index 00000000000..1fbfeaf2e65 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.strong.modular.expect @@ -0,0 +1,32 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::B b; + const constructor •({required mai::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: mai::B::f(new mai::C::f(0))); + +library; +import self as mai; +import "dart:core" as core; + +class B extends core::Object /*hasConstConstructor*/ { + final field mai::C c; + const constructor •({required mai::C c}) → mai::B + : mai::B::c = c, super core::Object::•() + ; + static method f(mai::C c) → mai::B + return new mai::B::•(c: c); +} +class C extends core::Object { + constructor f(core::num n) → mai::C + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.strong.outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.strong.outline.expect new file mode 100644 index 00000000000..61edfe05b03 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.strong.outline.expect @@ -0,0 +1,31 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::B b; + const constructor •({required mai::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +static final field self::A a; + +library; +import self as mai; +import "dart:core" as core; + +class B extends core::Object /*hasConstConstructor*/ { + final field mai::C c; + const constructor •({required mai::C c}) → mai::B + : mai::B::c = c, super core::Object::•() + ; + static method f(mai::C c) → mai::B + ; +} +class C extends core::Object { + constructor f(core::num n) → mai::C + ; +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.strong.transformed.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.strong.transformed.expect new file mode 100644 index 00000000000..1fbfeaf2e65 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.strong.transformed.expect @@ -0,0 +1,32 @@ +library; +import self as self; +import "dart:core" as core; +import "main_lib.dart" as mai; + +import "org-dartlang-testcase:///main_lib.dart"; + +class A extends core::Object /*hasConstConstructor*/ { + final field mai::B b; + const constructor •({required mai::B b}) → self::A + : self::A::b = b, super core::Object::•() + ; +} +static final field self::A a = new self::A::•(b: mai::B::f(new mai::C::f(0))); + +library; +import self as mai; +import "dart:core" as core; + +class B extends core::Object /*hasConstConstructor*/ { + final field mai::C c; + const constructor •({required mai::C c}) → mai::B + : mai::B::c = c, super core::Object::•() + ; + static method f(mai::C c) → mai::B + return new mai::B::•(c: c); +} +class C extends core::Object { + constructor f(core::num n) → mai::C + : super core::Object::•() + ; +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.textual_outline.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.textual_outline.expect new file mode 100644 index 00000000000..75991beb2a7 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.textual_outline.expect @@ -0,0 +1,8 @@ +import 'main_lib.dart'; + +final a = A(b: .f(.f(0))); + +class A { + final B b; + const A({required this.b}); +} diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..34b7ad28820 --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main.dart.textual_outline_modelled.expect @@ -0,0 +1,8 @@ +import 'main_lib.dart'; + +class A { + const A({required this.b}); + final B b; +} + +final a = A(b: .f(.f(0))); diff --git a/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main_lib.dart b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main_lib.dart new file mode 100644 index 00000000000..7b317aa975a --- /dev/null +++ b/pkg/front_end/testcases/dot_shorthands/nested_arguments_static_method/main_lib.dart @@ -0,0 +1,14 @@ +// Copyright (c) 2026, 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. + +class B { + final C c; + const B({required this.c}); + + static B f(C c) => B(c: c); +} + +class C { + C.f(num n); +}