diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart index a39f604889f..c60a2f6bda5 100644 --- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart +++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart @@ -4,6 +4,7 @@ library fasta.source_class_builder; +import 'package:front_end/src/api_prototype/lowering_predicates.dart'; import 'package:kernel/ast.dart'; import 'package:kernel/class_hierarchy.dart' show ClassHierarchy, ClassHierarchyBase, ClassHierarchyMembers; @@ -1256,7 +1257,19 @@ class SourceClassBuilder extends ClassBuilderImpl if (field.isInstanceMember && !field.isFinal && _isPrivateNameInThisLibrary(field.name)) { - unpromotablePrivateFieldNames.add(field.name.text); + if (isLateLoweredField(field)) { + // Late lowered fields do not have the finality of the declaration + // so we use lookup the corresponding [SourceFieldBuilder]. + String fieldName = extractFieldNameFromLateLoweredField(field).text; + Builder? builder = scope.lookupLocalMember(fieldName, setter: false); + assert(builder is SourceFieldBuilder, + "Unexpected late-lowered field '$fieldName' in $this: $builder"); + if (builder is SourceFieldBuilder && !builder.isFinal) { + unpromotablePrivateFieldNames.add(fieldName); + } + } else if (!isLateLoweredIsSetField(field)) { + unpromotablePrivateFieldNames.add(field.name.text); + } } } for (Procedure procedure in cls.procedures) { @@ -1265,13 +1278,17 @@ class SourceClassBuilder extends ClassBuilderImpl // abstract non-final field makes fields with the same name unpromotable. if (procedure.isInstanceMember && _isPrivateNameInThisLibrary(procedure.name)) { - if (procedure.isGetter && !procedure.isAbstract) { + if (procedure.isGetter && + !procedure.isAbstract && + !isLateLoweredFieldGetter(procedure)) { ProcedureStubKind procedureStubKind = procedure.stubKind; if (procedureStubKind == ProcedureStubKind.Regular || procedureStubKind == ProcedureStubKind.NoSuchMethodForwarder) { unpromotablePrivateFieldNames.add(procedure.name.text); } - } else if (procedure.isSetter && procedure.isAbstractFieldAccessor) { + } else if (procedure.isSetter && + procedure.isAbstractFieldAccessor && + !isLateLoweredFieldSetter(procedure)) { unpromotablePrivateFieldNames.add(procedure.name.text); } } diff --git a/pkg/front_end/testcases/dart2wasm/inference_update_2/folder.options b/pkg/front_end/testcases/dart2wasm/inference_update_2/folder.options new file mode 100644 index 00000000000..44fa81eb0cc --- /dev/null +++ b/pkg/front_end/testcases/dart2wasm/inference_update_2/folder.options @@ -0,0 +1,2 @@ +--target=wasm +--enable-experiment=inference-update-2 \ No newline at end of file diff --git a/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart b/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart new file mode 100644 index 00000000000..23fa4648de4 --- /dev/null +++ b/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart @@ -0,0 +1,85 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Tests that field promotion is prevented if there is a synthetic instance +// getter of the same name in the library that's a noSuchMethod forwarder. + +// SharedOptions=--enable-experiment=inference-update-2 + +class C { + final int? _f2; + final int? _f3; + final int? _f4; + + C(int? i) + : _f2 = i, + _f3 = i, + _f4 = i; +} + +class A { + A(int? i); +} + +mixin M3 {} + +abstract class D extends A with M3 { + final int? _f4; + + D(int? i) + : _f4 = i, + super(i); +} + +mixin M1 { + late int? _f2; + late final int? _f3; + late final int? _f4 = 0; +} + +class B { + B(int? i); +} + +class E extends B with M1 implements D { + E(super.i); + // Inherits _f4 from M1, so there is no noSuchMethod forwarder + + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +void acceptsInt(int x) {} + +void testConflictWithNoSuchMethodForwarderIfImplementedInMixin(C c) { + if (c._f2 != null) { + var x = c._f2; + // `x` has type `int?` so this is ok + x = null; + } +} + +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(C c) { + if (c._f3 != null) { + var x = c._f3; + // `x` has type `int` so this is ok + acceptsInt(x); + } +} + +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(C c) { + if (c._f4 != null) { + var x = c._f4; + // `x` has type `int` so this is ok + acceptsInt(x); + } +} + +main() { + for (var c in [C(null), C(0)]) { + testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } +} diff --git a/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart.strong.expect b/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart.strong.expect new file mode 100644 index 00000000000..f8946dde998 --- /dev/null +++ b/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart.strong.expect @@ -0,0 +1,154 @@ +library; +import self as self; +import "dart:core" as core; +import "dart:_internal" as _in; + +class C extends core::Object { + final field core::int? _f2; + final field core::int? _f3; + final field core::int? _f4; + constructor •(core::int? i) → self::C + : self::C::_f2 = i, self::C::_f3 = i, self::C::_f4 = i, super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::C + return new self::C::•(i); +} +class A extends core::Object { + constructor •(core::int? i) → self::A + : super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::A + return new self::A::•(i); +} +abstract class M3 extends core::Object /*isMixinDeclaration*/ { +} +abstract class _D&A&M3 = self::A with self::M3 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_D&A&M3 + : super self::A::•(i) + ; +} +abstract class D extends self::_D&A&M3 { + final field core::int? _f4; + constructor •(core::int? i) → self::D + : self::D::_f4 = i, super self::_D&A&M3::•(i) + ; +} +abstract class M1 extends core::Object /*isMixinDeclaration*/ { + field core::int? _#M1#_f2 = null; + field core::bool _#M1#_f2#isSet = false; + field core::int? _#M1#_f3 = null; + field core::bool _#M1#_f3#isSet = false; + field core::int? _#M1#_f4 = null; + field core::bool _#M1#_f4#isSet = false; + get _f2() → core::int? + return this.{self::M1::_#M1#_f2#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f2}{core::int?} : throw new _in::LateError::fieldNI("_f2"); + set _f2(core::int? _f2#param) → void { + this.{self::M1::_#M1#_f2#isSet} = true; + this.{self::M1::_#M1#_f2} = _f2#param; + } + get _f3() → core::int? + return this.{self::M1::_#M1#_f3#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f3}{core::int?} : throw new _in::LateError::fieldNI("_f3"); + set _f3(core::int? _f3#param) → void + if(this.{self::M1::_#M1#_f3#isSet}{core::bool}) + throw new _in::LateError::fieldAI("_f3"); + else { + this.{self::M1::_#M1#_f3#isSet} = true; + this.{self::M1::_#M1#_f3} = _f3#param; + } + get _f4() → core::int? { + if(!this.{self::M1::_#M1#_f4#isSet}{core::bool}) { + final core::int? #t1 = 0; + if(this.{self::M1::_#M1#_f4#isSet}{core::bool}) + throw new _in::LateError::fieldADI("_f4"); + this.{self::M1::_#M1#_f4} = #t1; + this.{self::M1::_#M1#_f4#isSet} = true; + } + return this.{self::M1::_#M1#_f4}{core::int?}; + } +} +class B extends core::Object { + constructor •(core::int? i) → self::B + : super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::B + return new self::B::•(i); +} +abstract class _E&B&M1 = self::B with self::M1 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_E&B&M1 + : super self::B::•(i) + ; + mixin-super-stub get _#M1#_f2() → core::int? + return super.{self::M1::_#M1#_f2}; + mixin-super-stub set _#M1#_f2(core::int? value) → void + return super.{self::M1::_#M1#_f2} = value; + mixin-super-stub get _f2() → core::int? + return super.{self::M1::_f2}; + mixin-super-stub set _f2(core::int? _f2#param) → void + return super.{self::M1::_f2} = _f2#param; + mixin-super-stub get _#M1#_f2#isSet() → core::bool + return super.{self::M1::_#M1#_f2#isSet}; + mixin-super-stub set _#M1#_f2#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f2#isSet} = value; + mixin-super-stub get _#M1#_f3() → core::int? + return super.{self::M1::_#M1#_f3}; + mixin-super-stub set _#M1#_f3(core::int? value) → void + return super.{self::M1::_#M1#_f3} = value; + mixin-super-stub get _f3() → core::int? + return super.{self::M1::_f3}; + mixin-super-stub set _f3(core::int? _f3#param) → void + return super.{self::M1::_f3} = _f3#param; + mixin-super-stub get _#M1#_f3#isSet() → core::bool + return super.{self::M1::_#M1#_f3#isSet}; + mixin-super-stub set _#M1#_f3#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f3#isSet} = value; + mixin-super-stub get _#M1#_f4() → core::int? + return super.{self::M1::_#M1#_f4}; + mixin-super-stub set _#M1#_f4(core::int? value) → void + return super.{self::M1::_#M1#_f4} = value; + mixin-super-stub get _#M1#_f4#isSet() → core::bool + return super.{self::M1::_#M1#_f4#isSet}; + mixin-super-stub set _#M1#_f4#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f4#isSet} = value; + mixin-super-stub get _f4() → core::int? + return super.{self::M1::_f4}; +} +class E extends self::_E&B&M1 implements self::D { + constructor •(core::int? i) → self::E + : super self::_E&B&M1::•(i) + ; + static method _#new#tearOff(core::int? i) → self::E + return new self::E::•(i); + @#C1 + method noSuchMethod(core::Invocation invocation) → dynamic + return super.{core::Object::noSuchMethod}(invocation); +} +static method acceptsInt(core::int x) → void {} +static method testConflictWithNoSuchMethodForwarderIfImplementedInMixin(self::C c) → void { + if(!(c.{self::C::_f2}{core::int?} == null)) { + core::int? x = c.{self::C::_f2}{core::int?}; + x = null; + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(self::C c) → void { + if(!(c.{self::C::_f3}{core::int?} == null)) { + core::int x = c.{self::C::_f3}{core::int}; + self::acceptsInt(x); + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(self::C c) → void { + if(!(c.{self::C::_f4}{core::int?} == null)) { + core::int x = c.{self::C::_f4}{core::int}; + self::acceptsInt(x); + } +} +static method main() → dynamic { + for (self::C c in [new self::C::•(null), new self::C::•(0)]) { + self::testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } +} + +constants { + #C1 = core::_Override {} +} diff --git a/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart.strong.transformed.expect new file mode 100644 index 00000000000..bfe955baaab --- /dev/null +++ b/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart.strong.transformed.expect @@ -0,0 +1,157 @@ +library; +import self as self; +import "dart:core" as core; +import "dart:_internal" as _in; + +class C extends core::Object { + final field core::int? _f2; + final field core::int? _f3; + final field core::int? _f4; + constructor •(core::int? i) → self::C + : self::C::_f2 = i, self::C::_f3 = i, self::C::_f4 = i, super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::C + return new self::C::•(i); +} +class A extends core::Object { + constructor •(core::int? i) → self::A + : super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::A + return new self::A::•(i); +} +abstract class M3 extends core::Object /*isMixinDeclaration*/ { +} +abstract class _D&A&M3 extends self::A implements self::M3 /*isAnonymousMixin,isEliminatedMixin*/ { + synthetic constructor •(core::int? i) → self::_D&A&M3 + : super self::A::•(i) + ; +} +abstract class D extends self::_D&A&M3 { + final field core::int? _f4; + constructor •(core::int? i) → self::D + : self::D::_f4 = i, super self::_D&A&M3::•(i) + ; +} +abstract class M1 extends core::Object /*isMixinDeclaration*/ { + field core::int? _#M1#_f2 = null; + field core::bool _#M1#_f2#isSet = false; + field core::int? _#M1#_f3 = null; + field core::bool _#M1#_f3#isSet = false; + field core::int? _#M1#_f4 = null; + field core::bool _#M1#_f4#isSet = false; + get _f2() → core::int? + return this.{self::M1::_#M1#_f2#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f2}{core::int?} : throw new _in::LateError::fieldNI("_f2"); + set _f2(core::int? _f2#param) → void { + this.{self::M1::_#M1#_f2#isSet} = true; + this.{self::M1::_#M1#_f2} = _f2#param; + } + get _f3() → core::int? + return this.{self::M1::_#M1#_f3#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f3}{core::int?} : throw new _in::LateError::fieldNI("_f3"); + set _f3(core::int? _f3#param) → void + if(this.{self::M1::_#M1#_f3#isSet}{core::bool}) + throw new _in::LateError::fieldAI("_f3"); + else { + this.{self::M1::_#M1#_f3#isSet} = true; + this.{self::M1::_#M1#_f3} = _f3#param; + } + get _f4() → core::int? { + if(!this.{self::M1::_#M1#_f4#isSet}{core::bool}) { + final core::int? #t1 = 0; + if(this.{self::M1::_#M1#_f4#isSet}{core::bool}) + throw new _in::LateError::fieldADI("_f4"); + this.{self::M1::_#M1#_f4} = #t1; + this.{self::M1::_#M1#_f4#isSet} = true; + } + return this.{self::M1::_#M1#_f4}{core::int?}; + } +} +class B extends core::Object { + constructor •(core::int? i) → self::B + : super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::B + return new self::B::•(i); +} +abstract class _E&B&M1 extends self::B implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/ { + field core::int? _#M1#_f2 = null; + field core::bool _#M1#_f2#isSet = false; + field core::int? _#M1#_f3 = null; + field core::bool _#M1#_f3#isSet = false; + field core::int? _#M1#_f4 = null; + field core::bool _#M1#_f4#isSet = false; + synthetic constructor •(core::int? i) → self::_E&B&M1 + : super self::B::•(i) + ; + get _f2() → core::int? + return this.{self::M1::_#M1#_f2#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f2}{core::int?} : throw new _in::LateError::fieldNI("_f2"); + get _f3() → core::int? + return this.{self::M1::_#M1#_f3#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f3}{core::int?} : throw new _in::LateError::fieldNI("_f3"); + get _f4() → core::int? { + if(!this.{self::M1::_#M1#_f4#isSet}{core::bool}) { + final core::int? #t2 = 0; + if(this.{self::M1::_#M1#_f4#isSet}{core::bool}) + throw new _in::LateError::fieldADI("_f4"); + this.{self::M1::_#M1#_f4} = #t2; + this.{self::M1::_#M1#_f4#isSet} = true; + } + return this.{self::M1::_#M1#_f4}{core::int?}; + } + set _f2(core::int? _f2#param) → void { + this.{self::M1::_#M1#_f2#isSet} = true; + this.{self::M1::_#M1#_f2} = _f2#param; + } + set _f3(core::int? _f3#param) → void + if(this.{self::M1::_#M1#_f3#isSet}{core::bool}) + throw new _in::LateError::fieldAI("_f3"); + else { + this.{self::M1::_#M1#_f3#isSet} = true; + this.{self::M1::_#M1#_f3} = _f3#param; + } +} +class E extends self::_E&B&M1 implements self::D { + constructor •(core::int? i) → self::E + : super self::_E&B&M1::•(i) + ; + static method _#new#tearOff(core::int? i) → self::E + return new self::E::•(i); + @#C1 + method noSuchMethod(core::Invocation invocation) → dynamic + return super.{core::Object::noSuchMethod}(invocation); +} +static method acceptsInt(core::int x) → void {} +static method testConflictWithNoSuchMethodForwarderIfImplementedInMixin(self::C c) → void { + if(!(c.{self::C::_f2}{core::int?} == null)) { + core::int? x = c.{self::C::_f2}{core::int?}; + x = null; + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(self::C c) → void { + if(!(c.{self::C::_f3}{core::int?} == null)) { + core::int x = c.{self::C::_f3}{core::int}; + self::acceptsInt(x); + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(self::C c) → void { + if(!(c.{self::C::_f4}{core::int?} == null)) { + core::int x = c.{self::C::_f4}{core::int}; + self::acceptsInt(x); + } +} +static method main() → dynamic { + { + synthesized core::Iterator #forIterator = [new self::C::•(null), new self::C::•(0)].{core::Iterable::iterator}{core::Iterator}; + for (; #forIterator.{core::Iterator::moveNext}(){() → core::bool}; ) { + self::C c = #forIterator.{core::Iterator::current}{self::C}; + { + self::testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } + } + } +} + +constants { + #C1 = core::_Override {} +} diff --git a/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart.textual_outline.expect b/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart.textual_outline.expect new file mode 100644 index 00000000000..b2bc14ac548 --- /dev/null +++ b/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart.textual_outline.expect @@ -0,0 +1,44 @@ +class C { + final int? _f2; + final int? _f3; + final int? _f4; + C(int? i) + : _f2 = i, + _f3 = i, + _f4 = i; +} + +class A { + A(int? i); +} + +mixin M3 {} + +abstract class D extends A with M3 { + final int? _f4; + D(int? i) + : _f4 = i, + super(i); +} + +mixin M1 { + late int? _f2; + late final int? _f3; + late final int? _f4 = 0; +} + +class B { + B(int? i); +} + +class E extends B with M1 implements D { + E(super.i); + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +void acceptsInt(int x) {} +void testConflictWithNoSuchMethodForwarderIfImplementedInMixin(C c) {} +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(C c) {} +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(C c) {} +main() {} diff --git a/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..a36b7418e8c --- /dev/null +++ b/pkg/front_end/testcases/dart2wasm/inference_update_2/issue52452.dart.textual_outline_modelled.expect @@ -0,0 +1,42 @@ +abstract class D extends A with M3 { + D(int? i) + : _f4 = i, + super(i); + final int? _f4; +} + +class A { + A(int? i); +} + +class B { + B(int? i); +} + +class C { + C(int? i) + : _f2 = i, + _f3 = i, + _f4 = i; + final int? _f2; + final int? _f3; + final int? _f4; +} + +class E extends B with M1 implements D { + E(super.i); + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +main() {} +mixin M1 { + late final int? _f3; + late final int? _f4 = 0; + late int? _f2; +} +mixin M3 {} +void acceptsInt(int x) {} +void testConflictWithNoSuchMethodForwarderIfImplementedInMixin(C c) {} +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(C c) {} +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(C c) {} diff --git a/pkg/front_end/testcases/dartdevc/inference_update_2/folder.options b/pkg/front_end/testcases/dartdevc/inference_update_2/folder.options new file mode 100644 index 00000000000..c8971b36e73 --- /dev/null +++ b/pkg/front_end/testcases/dartdevc/inference_update_2/folder.options @@ -0,0 +1,2 @@ +--target=dartdevc +--enable-experiment=inference-update-2 \ No newline at end of file diff --git a/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart new file mode 100644 index 00000000000..23fa4648de4 --- /dev/null +++ b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart @@ -0,0 +1,85 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Tests that field promotion is prevented if there is a synthetic instance +// getter of the same name in the library that's a noSuchMethod forwarder. + +// SharedOptions=--enable-experiment=inference-update-2 + +class C { + final int? _f2; + final int? _f3; + final int? _f4; + + C(int? i) + : _f2 = i, + _f3 = i, + _f4 = i; +} + +class A { + A(int? i); +} + +mixin M3 {} + +abstract class D extends A with M3 { + final int? _f4; + + D(int? i) + : _f4 = i, + super(i); +} + +mixin M1 { + late int? _f2; + late final int? _f3; + late final int? _f4 = 0; +} + +class B { + B(int? i); +} + +class E extends B with M1 implements D { + E(super.i); + // Inherits _f4 from M1, so there is no noSuchMethod forwarder + + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +void acceptsInt(int x) {} + +void testConflictWithNoSuchMethodForwarderIfImplementedInMixin(C c) { + if (c._f2 != null) { + var x = c._f2; + // `x` has type `int?` so this is ok + x = null; + } +} + +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(C c) { + if (c._f3 != null) { + var x = c._f3; + // `x` has type `int` so this is ok + acceptsInt(x); + } +} + +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(C c) { + if (c._f4 != null) { + var x = c._f4; + // `x` has type `int` so this is ok + acceptsInt(x); + } +} + +main() { + for (var c in [C(null), C(0)]) { + testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } +} diff --git a/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.strong.expect b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.strong.expect new file mode 100644 index 00000000000..f8946dde998 --- /dev/null +++ b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.strong.expect @@ -0,0 +1,154 @@ +library; +import self as self; +import "dart:core" as core; +import "dart:_internal" as _in; + +class C extends core::Object { + final field core::int? _f2; + final field core::int? _f3; + final field core::int? _f4; + constructor •(core::int? i) → self::C + : self::C::_f2 = i, self::C::_f3 = i, self::C::_f4 = i, super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::C + return new self::C::•(i); +} +class A extends core::Object { + constructor •(core::int? i) → self::A + : super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::A + return new self::A::•(i); +} +abstract class M3 extends core::Object /*isMixinDeclaration*/ { +} +abstract class _D&A&M3 = self::A with self::M3 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_D&A&M3 + : super self::A::•(i) + ; +} +abstract class D extends self::_D&A&M3 { + final field core::int? _f4; + constructor •(core::int? i) → self::D + : self::D::_f4 = i, super self::_D&A&M3::•(i) + ; +} +abstract class M1 extends core::Object /*isMixinDeclaration*/ { + field core::int? _#M1#_f2 = null; + field core::bool _#M1#_f2#isSet = false; + field core::int? _#M1#_f3 = null; + field core::bool _#M1#_f3#isSet = false; + field core::int? _#M1#_f4 = null; + field core::bool _#M1#_f4#isSet = false; + get _f2() → core::int? + return this.{self::M1::_#M1#_f2#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f2}{core::int?} : throw new _in::LateError::fieldNI("_f2"); + set _f2(core::int? _f2#param) → void { + this.{self::M1::_#M1#_f2#isSet} = true; + this.{self::M1::_#M1#_f2} = _f2#param; + } + get _f3() → core::int? + return this.{self::M1::_#M1#_f3#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f3}{core::int?} : throw new _in::LateError::fieldNI("_f3"); + set _f3(core::int? _f3#param) → void + if(this.{self::M1::_#M1#_f3#isSet}{core::bool}) + throw new _in::LateError::fieldAI("_f3"); + else { + this.{self::M1::_#M1#_f3#isSet} = true; + this.{self::M1::_#M1#_f3} = _f3#param; + } + get _f4() → core::int? { + if(!this.{self::M1::_#M1#_f4#isSet}{core::bool}) { + final core::int? #t1 = 0; + if(this.{self::M1::_#M1#_f4#isSet}{core::bool}) + throw new _in::LateError::fieldADI("_f4"); + this.{self::M1::_#M1#_f4} = #t1; + this.{self::M1::_#M1#_f4#isSet} = true; + } + return this.{self::M1::_#M1#_f4}{core::int?}; + } +} +class B extends core::Object { + constructor •(core::int? i) → self::B + : super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::B + return new self::B::•(i); +} +abstract class _E&B&M1 = self::B with self::M1 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_E&B&M1 + : super self::B::•(i) + ; + mixin-super-stub get _#M1#_f2() → core::int? + return super.{self::M1::_#M1#_f2}; + mixin-super-stub set _#M1#_f2(core::int? value) → void + return super.{self::M1::_#M1#_f2} = value; + mixin-super-stub get _f2() → core::int? + return super.{self::M1::_f2}; + mixin-super-stub set _f2(core::int? _f2#param) → void + return super.{self::M1::_f2} = _f2#param; + mixin-super-stub get _#M1#_f2#isSet() → core::bool + return super.{self::M1::_#M1#_f2#isSet}; + mixin-super-stub set _#M1#_f2#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f2#isSet} = value; + mixin-super-stub get _#M1#_f3() → core::int? + return super.{self::M1::_#M1#_f3}; + mixin-super-stub set _#M1#_f3(core::int? value) → void + return super.{self::M1::_#M1#_f3} = value; + mixin-super-stub get _f3() → core::int? + return super.{self::M1::_f3}; + mixin-super-stub set _f3(core::int? _f3#param) → void + return super.{self::M1::_f3} = _f3#param; + mixin-super-stub get _#M1#_f3#isSet() → core::bool + return super.{self::M1::_#M1#_f3#isSet}; + mixin-super-stub set _#M1#_f3#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f3#isSet} = value; + mixin-super-stub get _#M1#_f4() → core::int? + return super.{self::M1::_#M1#_f4}; + mixin-super-stub set _#M1#_f4(core::int? value) → void + return super.{self::M1::_#M1#_f4} = value; + mixin-super-stub get _#M1#_f4#isSet() → core::bool + return super.{self::M1::_#M1#_f4#isSet}; + mixin-super-stub set _#M1#_f4#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f4#isSet} = value; + mixin-super-stub get _f4() → core::int? + return super.{self::M1::_f4}; +} +class E extends self::_E&B&M1 implements self::D { + constructor •(core::int? i) → self::E + : super self::_E&B&M1::•(i) + ; + static method _#new#tearOff(core::int? i) → self::E + return new self::E::•(i); + @#C1 + method noSuchMethod(core::Invocation invocation) → dynamic + return super.{core::Object::noSuchMethod}(invocation); +} +static method acceptsInt(core::int x) → void {} +static method testConflictWithNoSuchMethodForwarderIfImplementedInMixin(self::C c) → void { + if(!(c.{self::C::_f2}{core::int?} == null)) { + core::int? x = c.{self::C::_f2}{core::int?}; + x = null; + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(self::C c) → void { + if(!(c.{self::C::_f3}{core::int?} == null)) { + core::int x = c.{self::C::_f3}{core::int}; + self::acceptsInt(x); + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(self::C c) → void { + if(!(c.{self::C::_f4}{core::int?} == null)) { + core::int x = c.{self::C::_f4}{core::int}; + self::acceptsInt(x); + } +} +static method main() → dynamic { + for (self::C c in [new self::C::•(null), new self::C::•(0)]) { + self::testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } +} + +constants { + #C1 = core::_Override {} +} diff --git a/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.strong.transformed.expect b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.strong.transformed.expect new file mode 100644 index 00000000000..f8946dde998 --- /dev/null +++ b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.strong.transformed.expect @@ -0,0 +1,154 @@ +library; +import self as self; +import "dart:core" as core; +import "dart:_internal" as _in; + +class C extends core::Object { + final field core::int? _f2; + final field core::int? _f3; + final field core::int? _f4; + constructor •(core::int? i) → self::C + : self::C::_f2 = i, self::C::_f3 = i, self::C::_f4 = i, super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::C + return new self::C::•(i); +} +class A extends core::Object { + constructor •(core::int? i) → self::A + : super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::A + return new self::A::•(i); +} +abstract class M3 extends core::Object /*isMixinDeclaration*/ { +} +abstract class _D&A&M3 = self::A with self::M3 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_D&A&M3 + : super self::A::•(i) + ; +} +abstract class D extends self::_D&A&M3 { + final field core::int? _f4; + constructor •(core::int? i) → self::D + : self::D::_f4 = i, super self::_D&A&M3::•(i) + ; +} +abstract class M1 extends core::Object /*isMixinDeclaration*/ { + field core::int? _#M1#_f2 = null; + field core::bool _#M1#_f2#isSet = false; + field core::int? _#M1#_f3 = null; + field core::bool _#M1#_f3#isSet = false; + field core::int? _#M1#_f4 = null; + field core::bool _#M1#_f4#isSet = false; + get _f2() → core::int? + return this.{self::M1::_#M1#_f2#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f2}{core::int?} : throw new _in::LateError::fieldNI("_f2"); + set _f2(core::int? _f2#param) → void { + this.{self::M1::_#M1#_f2#isSet} = true; + this.{self::M1::_#M1#_f2} = _f2#param; + } + get _f3() → core::int? + return this.{self::M1::_#M1#_f3#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f3}{core::int?} : throw new _in::LateError::fieldNI("_f3"); + set _f3(core::int? _f3#param) → void + if(this.{self::M1::_#M1#_f3#isSet}{core::bool}) + throw new _in::LateError::fieldAI("_f3"); + else { + this.{self::M1::_#M1#_f3#isSet} = true; + this.{self::M1::_#M1#_f3} = _f3#param; + } + get _f4() → core::int? { + if(!this.{self::M1::_#M1#_f4#isSet}{core::bool}) { + final core::int? #t1 = 0; + if(this.{self::M1::_#M1#_f4#isSet}{core::bool}) + throw new _in::LateError::fieldADI("_f4"); + this.{self::M1::_#M1#_f4} = #t1; + this.{self::M1::_#M1#_f4#isSet} = true; + } + return this.{self::M1::_#M1#_f4}{core::int?}; + } +} +class B extends core::Object { + constructor •(core::int? i) → self::B + : super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::B + return new self::B::•(i); +} +abstract class _E&B&M1 = self::B with self::M1 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_E&B&M1 + : super self::B::•(i) + ; + mixin-super-stub get _#M1#_f2() → core::int? + return super.{self::M1::_#M1#_f2}; + mixin-super-stub set _#M1#_f2(core::int? value) → void + return super.{self::M1::_#M1#_f2} = value; + mixin-super-stub get _f2() → core::int? + return super.{self::M1::_f2}; + mixin-super-stub set _f2(core::int? _f2#param) → void + return super.{self::M1::_f2} = _f2#param; + mixin-super-stub get _#M1#_f2#isSet() → core::bool + return super.{self::M1::_#M1#_f2#isSet}; + mixin-super-stub set _#M1#_f2#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f2#isSet} = value; + mixin-super-stub get _#M1#_f3() → core::int? + return super.{self::M1::_#M1#_f3}; + mixin-super-stub set _#M1#_f3(core::int? value) → void + return super.{self::M1::_#M1#_f3} = value; + mixin-super-stub get _f3() → core::int? + return super.{self::M1::_f3}; + mixin-super-stub set _f3(core::int? _f3#param) → void + return super.{self::M1::_f3} = _f3#param; + mixin-super-stub get _#M1#_f3#isSet() → core::bool + return super.{self::M1::_#M1#_f3#isSet}; + mixin-super-stub set _#M1#_f3#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f3#isSet} = value; + mixin-super-stub get _#M1#_f4() → core::int? + return super.{self::M1::_#M1#_f4}; + mixin-super-stub set _#M1#_f4(core::int? value) → void + return super.{self::M1::_#M1#_f4} = value; + mixin-super-stub get _#M1#_f4#isSet() → core::bool + return super.{self::M1::_#M1#_f4#isSet}; + mixin-super-stub set _#M1#_f4#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f4#isSet} = value; + mixin-super-stub get _f4() → core::int? + return super.{self::M1::_f4}; +} +class E extends self::_E&B&M1 implements self::D { + constructor •(core::int? i) → self::E + : super self::_E&B&M1::•(i) + ; + static method _#new#tearOff(core::int? i) → self::E + return new self::E::•(i); + @#C1 + method noSuchMethod(core::Invocation invocation) → dynamic + return super.{core::Object::noSuchMethod}(invocation); +} +static method acceptsInt(core::int x) → void {} +static method testConflictWithNoSuchMethodForwarderIfImplementedInMixin(self::C c) → void { + if(!(c.{self::C::_f2}{core::int?} == null)) { + core::int? x = c.{self::C::_f2}{core::int?}; + x = null; + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(self::C c) → void { + if(!(c.{self::C::_f3}{core::int?} == null)) { + core::int x = c.{self::C::_f3}{core::int}; + self::acceptsInt(x); + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(self::C c) → void { + if(!(c.{self::C::_f4}{core::int?} == null)) { + core::int x = c.{self::C::_f4}{core::int}; + self::acceptsInt(x); + } +} +static method main() → dynamic { + for (self::C c in [new self::C::•(null), new self::C::•(0)]) { + self::testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } +} + +constants { + #C1 = core::_Override {} +} diff --git a/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.textual_outline.expect b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.textual_outline.expect new file mode 100644 index 00000000000..b2bc14ac548 --- /dev/null +++ b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.textual_outline.expect @@ -0,0 +1,44 @@ +class C { + final int? _f2; + final int? _f3; + final int? _f4; + C(int? i) + : _f2 = i, + _f3 = i, + _f4 = i; +} + +class A { + A(int? i); +} + +mixin M3 {} + +abstract class D extends A with M3 { + final int? _f4; + D(int? i) + : _f4 = i, + super(i); +} + +mixin M1 { + late int? _f2; + late final int? _f3; + late final int? _f4 = 0; +} + +class B { + B(int? i); +} + +class E extends B with M1 implements D { + E(super.i); + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +void acceptsInt(int x) {} +void testConflictWithNoSuchMethodForwarderIfImplementedInMixin(C c) {} +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(C c) {} +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(C c) {} +main() {} diff --git a/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..a36b7418e8c --- /dev/null +++ b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.textual_outline_modelled.expect @@ -0,0 +1,42 @@ +abstract class D extends A with M3 { + D(int? i) + : _f4 = i, + super(i); + final int? _f4; +} + +class A { + A(int? i); +} + +class B { + B(int? i); +} + +class C { + C(int? i) + : _f2 = i, + _f3 = i, + _f4 = i; + final int? _f2; + final int? _f3; + final int? _f4; +} + +class E extends B with M1 implements D { + E(super.i); + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +main() {} +mixin M1 { + late final int? _f3; + late final int? _f4 = 0; + late int? _f2; +} +mixin M3 {} +void acceptsInt(int x) {} +void testConflictWithNoSuchMethodForwarderIfImplementedInMixin(C c) {} +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(C c) {} +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(C c) {} diff --git a/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.weak.expect b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.weak.expect new file mode 100644 index 00000000000..f8946dde998 --- /dev/null +++ b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.weak.expect @@ -0,0 +1,154 @@ +library; +import self as self; +import "dart:core" as core; +import "dart:_internal" as _in; + +class C extends core::Object { + final field core::int? _f2; + final field core::int? _f3; + final field core::int? _f4; + constructor •(core::int? i) → self::C + : self::C::_f2 = i, self::C::_f3 = i, self::C::_f4 = i, super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::C + return new self::C::•(i); +} +class A extends core::Object { + constructor •(core::int? i) → self::A + : super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::A + return new self::A::•(i); +} +abstract class M3 extends core::Object /*isMixinDeclaration*/ { +} +abstract class _D&A&M3 = self::A with self::M3 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_D&A&M3 + : super self::A::•(i) + ; +} +abstract class D extends self::_D&A&M3 { + final field core::int? _f4; + constructor •(core::int? i) → self::D + : self::D::_f4 = i, super self::_D&A&M3::•(i) + ; +} +abstract class M1 extends core::Object /*isMixinDeclaration*/ { + field core::int? _#M1#_f2 = null; + field core::bool _#M1#_f2#isSet = false; + field core::int? _#M1#_f3 = null; + field core::bool _#M1#_f3#isSet = false; + field core::int? _#M1#_f4 = null; + field core::bool _#M1#_f4#isSet = false; + get _f2() → core::int? + return this.{self::M1::_#M1#_f2#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f2}{core::int?} : throw new _in::LateError::fieldNI("_f2"); + set _f2(core::int? _f2#param) → void { + this.{self::M1::_#M1#_f2#isSet} = true; + this.{self::M1::_#M1#_f2} = _f2#param; + } + get _f3() → core::int? + return this.{self::M1::_#M1#_f3#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f3}{core::int?} : throw new _in::LateError::fieldNI("_f3"); + set _f3(core::int? _f3#param) → void + if(this.{self::M1::_#M1#_f3#isSet}{core::bool}) + throw new _in::LateError::fieldAI("_f3"); + else { + this.{self::M1::_#M1#_f3#isSet} = true; + this.{self::M1::_#M1#_f3} = _f3#param; + } + get _f4() → core::int? { + if(!this.{self::M1::_#M1#_f4#isSet}{core::bool}) { + final core::int? #t1 = 0; + if(this.{self::M1::_#M1#_f4#isSet}{core::bool}) + throw new _in::LateError::fieldADI("_f4"); + this.{self::M1::_#M1#_f4} = #t1; + this.{self::M1::_#M1#_f4#isSet} = true; + } + return this.{self::M1::_#M1#_f4}{core::int?}; + } +} +class B extends core::Object { + constructor •(core::int? i) → self::B + : super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::B + return new self::B::•(i); +} +abstract class _E&B&M1 = self::B with self::M1 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_E&B&M1 + : super self::B::•(i) + ; + mixin-super-stub get _#M1#_f2() → core::int? + return super.{self::M1::_#M1#_f2}; + mixin-super-stub set _#M1#_f2(core::int? value) → void + return super.{self::M1::_#M1#_f2} = value; + mixin-super-stub get _f2() → core::int? + return super.{self::M1::_f2}; + mixin-super-stub set _f2(core::int? _f2#param) → void + return super.{self::M1::_f2} = _f2#param; + mixin-super-stub get _#M1#_f2#isSet() → core::bool + return super.{self::M1::_#M1#_f2#isSet}; + mixin-super-stub set _#M1#_f2#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f2#isSet} = value; + mixin-super-stub get _#M1#_f3() → core::int? + return super.{self::M1::_#M1#_f3}; + mixin-super-stub set _#M1#_f3(core::int? value) → void + return super.{self::M1::_#M1#_f3} = value; + mixin-super-stub get _f3() → core::int? + return super.{self::M1::_f3}; + mixin-super-stub set _f3(core::int? _f3#param) → void + return super.{self::M1::_f3} = _f3#param; + mixin-super-stub get _#M1#_f3#isSet() → core::bool + return super.{self::M1::_#M1#_f3#isSet}; + mixin-super-stub set _#M1#_f3#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f3#isSet} = value; + mixin-super-stub get _#M1#_f4() → core::int? + return super.{self::M1::_#M1#_f4}; + mixin-super-stub set _#M1#_f4(core::int? value) → void + return super.{self::M1::_#M1#_f4} = value; + mixin-super-stub get _#M1#_f4#isSet() → core::bool + return super.{self::M1::_#M1#_f4#isSet}; + mixin-super-stub set _#M1#_f4#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f4#isSet} = value; + mixin-super-stub get _f4() → core::int? + return super.{self::M1::_f4}; +} +class E extends self::_E&B&M1 implements self::D { + constructor •(core::int? i) → self::E + : super self::_E&B&M1::•(i) + ; + static method _#new#tearOff(core::int? i) → self::E + return new self::E::•(i); + @#C1 + method noSuchMethod(core::Invocation invocation) → dynamic + return super.{core::Object::noSuchMethod}(invocation); +} +static method acceptsInt(core::int x) → void {} +static method testConflictWithNoSuchMethodForwarderIfImplementedInMixin(self::C c) → void { + if(!(c.{self::C::_f2}{core::int?} == null)) { + core::int? x = c.{self::C::_f2}{core::int?}; + x = null; + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(self::C c) → void { + if(!(c.{self::C::_f3}{core::int?} == null)) { + core::int x = c.{self::C::_f3}{core::int}; + self::acceptsInt(x); + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(self::C c) → void { + if(!(c.{self::C::_f4}{core::int?} == null)) { + core::int x = c.{self::C::_f4}{core::int}; + self::acceptsInt(x); + } +} +static method main() → dynamic { + for (self::C c in [new self::C::•(null), new self::C::•(0)]) { + self::testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } +} + +constants { + #C1 = core::_Override {} +} diff --git a/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.weak.modular.expect b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.weak.modular.expect new file mode 100644 index 00000000000..f8946dde998 --- /dev/null +++ b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.weak.modular.expect @@ -0,0 +1,154 @@ +library; +import self as self; +import "dart:core" as core; +import "dart:_internal" as _in; + +class C extends core::Object { + final field core::int? _f2; + final field core::int? _f3; + final field core::int? _f4; + constructor •(core::int? i) → self::C + : self::C::_f2 = i, self::C::_f3 = i, self::C::_f4 = i, super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::C + return new self::C::•(i); +} +class A extends core::Object { + constructor •(core::int? i) → self::A + : super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::A + return new self::A::•(i); +} +abstract class M3 extends core::Object /*isMixinDeclaration*/ { +} +abstract class _D&A&M3 = self::A with self::M3 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_D&A&M3 + : super self::A::•(i) + ; +} +abstract class D extends self::_D&A&M3 { + final field core::int? _f4; + constructor •(core::int? i) → self::D + : self::D::_f4 = i, super self::_D&A&M3::•(i) + ; +} +abstract class M1 extends core::Object /*isMixinDeclaration*/ { + field core::int? _#M1#_f2 = null; + field core::bool _#M1#_f2#isSet = false; + field core::int? _#M1#_f3 = null; + field core::bool _#M1#_f3#isSet = false; + field core::int? _#M1#_f4 = null; + field core::bool _#M1#_f4#isSet = false; + get _f2() → core::int? + return this.{self::M1::_#M1#_f2#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f2}{core::int?} : throw new _in::LateError::fieldNI("_f2"); + set _f2(core::int? _f2#param) → void { + this.{self::M1::_#M1#_f2#isSet} = true; + this.{self::M1::_#M1#_f2} = _f2#param; + } + get _f3() → core::int? + return this.{self::M1::_#M1#_f3#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f3}{core::int?} : throw new _in::LateError::fieldNI("_f3"); + set _f3(core::int? _f3#param) → void + if(this.{self::M1::_#M1#_f3#isSet}{core::bool}) + throw new _in::LateError::fieldAI("_f3"); + else { + this.{self::M1::_#M1#_f3#isSet} = true; + this.{self::M1::_#M1#_f3} = _f3#param; + } + get _f4() → core::int? { + if(!this.{self::M1::_#M1#_f4#isSet}{core::bool}) { + final core::int? #t1 = 0; + if(this.{self::M1::_#M1#_f4#isSet}{core::bool}) + throw new _in::LateError::fieldADI("_f4"); + this.{self::M1::_#M1#_f4} = #t1; + this.{self::M1::_#M1#_f4#isSet} = true; + } + return this.{self::M1::_#M1#_f4}{core::int?}; + } +} +class B extends core::Object { + constructor •(core::int? i) → self::B + : super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::B + return new self::B::•(i); +} +abstract class _E&B&M1 = self::B with self::M1 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_E&B&M1 + : super self::B::•(i) + ; + mixin-super-stub get _#M1#_f2() → core::int? + return super.{self::M1::_#M1#_f2}; + mixin-super-stub set _#M1#_f2(core::int? value) → void + return super.{self::M1::_#M1#_f2} = value; + mixin-super-stub get _f2() → core::int? + return super.{self::M1::_f2}; + mixin-super-stub set _f2(core::int? _f2#param) → void + return super.{self::M1::_f2} = _f2#param; + mixin-super-stub get _#M1#_f2#isSet() → core::bool + return super.{self::M1::_#M1#_f2#isSet}; + mixin-super-stub set _#M1#_f2#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f2#isSet} = value; + mixin-super-stub get _#M1#_f3() → core::int? + return super.{self::M1::_#M1#_f3}; + mixin-super-stub set _#M1#_f3(core::int? value) → void + return super.{self::M1::_#M1#_f3} = value; + mixin-super-stub get _f3() → core::int? + return super.{self::M1::_f3}; + mixin-super-stub set _f3(core::int? _f3#param) → void + return super.{self::M1::_f3} = _f3#param; + mixin-super-stub get _#M1#_f3#isSet() → core::bool + return super.{self::M1::_#M1#_f3#isSet}; + mixin-super-stub set _#M1#_f3#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f3#isSet} = value; + mixin-super-stub get _#M1#_f4() → core::int? + return super.{self::M1::_#M1#_f4}; + mixin-super-stub set _#M1#_f4(core::int? value) → void + return super.{self::M1::_#M1#_f4} = value; + mixin-super-stub get _#M1#_f4#isSet() → core::bool + return super.{self::M1::_#M1#_f4#isSet}; + mixin-super-stub set _#M1#_f4#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f4#isSet} = value; + mixin-super-stub get _f4() → core::int? + return super.{self::M1::_f4}; +} +class E extends self::_E&B&M1 implements self::D { + constructor •(core::int? i) → self::E + : super self::_E&B&M1::•(i) + ; + static method _#new#tearOff(core::int? i) → self::E + return new self::E::•(i); + @#C1 + method noSuchMethod(core::Invocation invocation) → dynamic + return super.{core::Object::noSuchMethod}(invocation); +} +static method acceptsInt(core::int x) → void {} +static method testConflictWithNoSuchMethodForwarderIfImplementedInMixin(self::C c) → void { + if(!(c.{self::C::_f2}{core::int?} == null)) { + core::int? x = c.{self::C::_f2}{core::int?}; + x = null; + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(self::C c) → void { + if(!(c.{self::C::_f3}{core::int?} == null)) { + core::int x = c.{self::C::_f3}{core::int}; + self::acceptsInt(x); + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(self::C c) → void { + if(!(c.{self::C::_f4}{core::int?} == null)) { + core::int x = c.{self::C::_f4}{core::int}; + self::acceptsInt(x); + } +} +static method main() → dynamic { + for (self::C c in [new self::C::•(null), new self::C::•(0)]) { + self::testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } +} + +constants { + #C1 = core::_Override {} +} diff --git a/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.weak.outline.expect b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.weak.outline.expect new file mode 100644 index 00000000000..62e95c01780 --- /dev/null +++ b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.weak.outline.expect @@ -0,0 +1,113 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + final field core::int? _f2; + final field core::int? _f3; + final field core::int? _f4; + constructor •(core::int? i) → self::C + ; + static method _#new#tearOff(core::int? i) → self::C + return new self::C::•(i); +} +class A extends core::Object { + constructor •(core::int? i) → self::A + ; + static method _#new#tearOff(core::int? i) → self::A + return new self::A::•(i); +} +abstract class M3 extends core::Object /*isMixinDeclaration*/ { +} +abstract class _D&A&M3 = self::A with self::M3 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_D&A&M3 + : super self::A::•(i) + ; +} +abstract class D extends self::_D&A&M3 { + final field core::int? _f4; + constructor •(core::int? i) → self::D + ; +} +abstract class M1 extends core::Object /*isMixinDeclaration*/ { + field core::int? _#M1#_f2; + field core::bool _#M1#_f2#isSet; + field core::int? _#M1#_f3; + field core::bool _#M1#_f3#isSet; + field core::int? _#M1#_f4; + field core::bool _#M1#_f4#isSet; + get _f2() → core::int?; + set _f2(core::int? _f2#param) → void; + get _f3() → core::int?; + set _f3(core::int? _f3#param) → void; + get _f4() → core::int?; +} +class B extends core::Object { + constructor •(core::int? i) → self::B + ; + static method _#new#tearOff(core::int? i) → self::B + return new self::B::•(i); +} +abstract class _E&B&M1 = self::B with self::M1 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_E&B&M1 + : super self::B::•(i) + ; + mixin-super-stub get _#M1#_f2() → core::int? + return super.{self::M1::_#M1#_f2}; + mixin-super-stub set _#M1#_f2(core::int? value) → void + return super.{self::M1::_#M1#_f2} = value; + mixin-super-stub get _f2() → core::int? + return super.{self::M1::_f2}; + mixin-super-stub set _f2(core::int? _f2#param) → void + return super.{self::M1::_f2} = _f2#param; + mixin-super-stub get _#M1#_f2#isSet() → core::bool + return super.{self::M1::_#M1#_f2#isSet}; + mixin-super-stub set _#M1#_f2#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f2#isSet} = value; + mixin-super-stub get _#M1#_f3() → core::int? + return super.{self::M1::_#M1#_f3}; + mixin-super-stub set _#M1#_f3(core::int? value) → void + return super.{self::M1::_#M1#_f3} = value; + mixin-super-stub get _f3() → core::int? + return super.{self::M1::_f3}; + mixin-super-stub set _f3(core::int? _f3#param) → void + return super.{self::M1::_f3} = _f3#param; + mixin-super-stub get _#M1#_f3#isSet() → core::bool + return super.{self::M1::_#M1#_f3#isSet}; + mixin-super-stub set _#M1#_f3#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f3#isSet} = value; + mixin-super-stub get _#M1#_f4() → core::int? + return super.{self::M1::_#M1#_f4}; + mixin-super-stub set _#M1#_f4(core::int? value) → void + return super.{self::M1::_#M1#_f4} = value; + mixin-super-stub get _#M1#_f4#isSet() → core::bool + return super.{self::M1::_#M1#_f4#isSet}; + mixin-super-stub set _#M1#_f4#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f4#isSet} = value; + mixin-super-stub get _f4() → core::int? + return super.{self::M1::_f4}; +} +class E extends self::_E&B&M1 implements self::D { + constructor •(core::int? i) → self::E + ; + static method _#new#tearOff(core::int? i) → self::E + return new self::E::•(i); + @core::override + method noSuchMethod(core::Invocation invocation) → dynamic + ; +} +static method acceptsInt(core::int x) → void + ; +static method testConflictWithNoSuchMethodForwarderIfImplementedInMixin(self::C c) → void + ; +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(self::C c) → void + ; +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(self::C c) → void + ; +static method main() → dynamic + ; + + +Extra constant evaluation status: +Evaluated: StaticGet @ org-dartlang-testcase:///issue52452.dart:49:4 -> InstanceConstant(const _Override{}) +Extra constant evaluation: evaluated: 36, effectively constant: 1 diff --git a/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.weak.transformed.expect b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.weak.transformed.expect new file mode 100644 index 00000000000..f8946dde998 --- /dev/null +++ b/pkg/front_end/testcases/dartdevc/inference_update_2/issue52452.dart.weak.transformed.expect @@ -0,0 +1,154 @@ +library; +import self as self; +import "dart:core" as core; +import "dart:_internal" as _in; + +class C extends core::Object { + final field core::int? _f2; + final field core::int? _f3; + final field core::int? _f4; + constructor •(core::int? i) → self::C + : self::C::_f2 = i, self::C::_f3 = i, self::C::_f4 = i, super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::C + return new self::C::•(i); +} +class A extends core::Object { + constructor •(core::int? i) → self::A + : super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::A + return new self::A::•(i); +} +abstract class M3 extends core::Object /*isMixinDeclaration*/ { +} +abstract class _D&A&M3 = self::A with self::M3 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_D&A&M3 + : super self::A::•(i) + ; +} +abstract class D extends self::_D&A&M3 { + final field core::int? _f4; + constructor •(core::int? i) → self::D + : self::D::_f4 = i, super self::_D&A&M3::•(i) + ; +} +abstract class M1 extends core::Object /*isMixinDeclaration*/ { + field core::int? _#M1#_f2 = null; + field core::bool _#M1#_f2#isSet = false; + field core::int? _#M1#_f3 = null; + field core::bool _#M1#_f3#isSet = false; + field core::int? _#M1#_f4 = null; + field core::bool _#M1#_f4#isSet = false; + get _f2() → core::int? + return this.{self::M1::_#M1#_f2#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f2}{core::int?} : throw new _in::LateError::fieldNI("_f2"); + set _f2(core::int? _f2#param) → void { + this.{self::M1::_#M1#_f2#isSet} = true; + this.{self::M1::_#M1#_f2} = _f2#param; + } + get _f3() → core::int? + return this.{self::M1::_#M1#_f3#isSet}{core::bool} ?{core::int?} this.{self::M1::_#M1#_f3}{core::int?} : throw new _in::LateError::fieldNI("_f3"); + set _f3(core::int? _f3#param) → void + if(this.{self::M1::_#M1#_f3#isSet}{core::bool}) + throw new _in::LateError::fieldAI("_f3"); + else { + this.{self::M1::_#M1#_f3#isSet} = true; + this.{self::M1::_#M1#_f3} = _f3#param; + } + get _f4() → core::int? { + if(!this.{self::M1::_#M1#_f4#isSet}{core::bool}) { + final core::int? #t1 = 0; + if(this.{self::M1::_#M1#_f4#isSet}{core::bool}) + throw new _in::LateError::fieldADI("_f4"); + this.{self::M1::_#M1#_f4} = #t1; + this.{self::M1::_#M1#_f4#isSet} = true; + } + return this.{self::M1::_#M1#_f4}{core::int?}; + } +} +class B extends core::Object { + constructor •(core::int? i) → self::B + : super core::Object::•() + ; + static method _#new#tearOff(core::int? i) → self::B + return new self::B::•(i); +} +abstract class _E&B&M1 = self::B with self::M1 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_E&B&M1 + : super self::B::•(i) + ; + mixin-super-stub get _#M1#_f2() → core::int? + return super.{self::M1::_#M1#_f2}; + mixin-super-stub set _#M1#_f2(core::int? value) → void + return super.{self::M1::_#M1#_f2} = value; + mixin-super-stub get _f2() → core::int? + return super.{self::M1::_f2}; + mixin-super-stub set _f2(core::int? _f2#param) → void + return super.{self::M1::_f2} = _f2#param; + mixin-super-stub get _#M1#_f2#isSet() → core::bool + return super.{self::M1::_#M1#_f2#isSet}; + mixin-super-stub set _#M1#_f2#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f2#isSet} = value; + mixin-super-stub get _#M1#_f3() → core::int? + return super.{self::M1::_#M1#_f3}; + mixin-super-stub set _#M1#_f3(core::int? value) → void + return super.{self::M1::_#M1#_f3} = value; + mixin-super-stub get _f3() → core::int? + return super.{self::M1::_f3}; + mixin-super-stub set _f3(core::int? _f3#param) → void + return super.{self::M1::_f3} = _f3#param; + mixin-super-stub get _#M1#_f3#isSet() → core::bool + return super.{self::M1::_#M1#_f3#isSet}; + mixin-super-stub set _#M1#_f3#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f3#isSet} = value; + mixin-super-stub get _#M1#_f4() → core::int? + return super.{self::M1::_#M1#_f4}; + mixin-super-stub set _#M1#_f4(core::int? value) → void + return super.{self::M1::_#M1#_f4} = value; + mixin-super-stub get _#M1#_f4#isSet() → core::bool + return super.{self::M1::_#M1#_f4#isSet}; + mixin-super-stub set _#M1#_f4#isSet(core::bool value) → void + return super.{self::M1::_#M1#_f4#isSet} = value; + mixin-super-stub get _f4() → core::int? + return super.{self::M1::_f4}; +} +class E extends self::_E&B&M1 implements self::D { + constructor •(core::int? i) → self::E + : super self::_E&B&M1::•(i) + ; + static method _#new#tearOff(core::int? i) → self::E + return new self::E::•(i); + @#C1 + method noSuchMethod(core::Invocation invocation) → dynamic + return super.{core::Object::noSuchMethod}(invocation); +} +static method acceptsInt(core::int x) → void {} +static method testConflictWithNoSuchMethodForwarderIfImplementedInMixin(self::C c) → void { + if(!(c.{self::C::_f2}{core::int?} == null)) { + core::int? x = c.{self::C::_f2}{core::int?}; + x = null; + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(self::C c) → void { + if(!(c.{self::C::_f3}{core::int?} == null)) { + core::int x = c.{self::C::_f3}{core::int}; + self::acceptsInt(x); + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(self::C c) → void { + if(!(c.{self::C::_f4}{core::int?} == null)) { + core::int x = c.{self::C::_f4}{core::int}; + self::acceptsInt(x); + } +} +static method main() → dynamic { + for (self::C c in [new self::C::•(null), new self::C::•(0)]) { + self::testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } +} + +constants { + #C1 = core::_Override {} +} diff --git a/pkg/front_end/testcases/inference_update_2/issue52452.dart b/pkg/front_end/testcases/inference_update_2/issue52452.dart new file mode 100644 index 00000000000..23fa4648de4 --- /dev/null +++ b/pkg/front_end/testcases/inference_update_2/issue52452.dart @@ -0,0 +1,85 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Tests that field promotion is prevented if there is a synthetic instance +// getter of the same name in the library that's a noSuchMethod forwarder. + +// SharedOptions=--enable-experiment=inference-update-2 + +class C { + final int? _f2; + final int? _f3; + final int? _f4; + + C(int? i) + : _f2 = i, + _f3 = i, + _f4 = i; +} + +class A { + A(int? i); +} + +mixin M3 {} + +abstract class D extends A with M3 { + final int? _f4; + + D(int? i) + : _f4 = i, + super(i); +} + +mixin M1 { + late int? _f2; + late final int? _f3; + late final int? _f4 = 0; +} + +class B { + B(int? i); +} + +class E extends B with M1 implements D { + E(super.i); + // Inherits _f4 from M1, so there is no noSuchMethod forwarder + + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +void acceptsInt(int x) {} + +void testConflictWithNoSuchMethodForwarderIfImplementedInMixin(C c) { + if (c._f2 != null) { + var x = c._f2; + // `x` has type `int?` so this is ok + x = null; + } +} + +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(C c) { + if (c._f3 != null) { + var x = c._f3; + // `x` has type `int` so this is ok + acceptsInt(x); + } +} + +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(C c) { + if (c._f4 != null) { + var x = c._f4; + // `x` has type `int` so this is ok + acceptsInt(x); + } +} + +main() { + for (var c in [C(null), C(0)]) { + testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } +} diff --git a/pkg/front_end/testcases/inference_update_2/issue52452.dart.strong.expect b/pkg/front_end/testcases/inference_update_2/issue52452.dart.strong.expect new file mode 100644 index 00000000000..88dc8d1bddf --- /dev/null +++ b/pkg/front_end/testcases/inference_update_2/issue52452.dart.strong.expect @@ -0,0 +1,93 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + final field core::int? _f2; + final field core::int? _f3; + final field core::int? _f4; + constructor •(core::int? i) → self::C + : self::C::_f2 = i, self::C::_f3 = i, self::C::_f4 = i, super core::Object::•() + ; +} +class A extends core::Object { + constructor •(core::int? i) → self::A + : super core::Object::•() + ; +} +abstract class M3 extends core::Object /*isMixinDeclaration*/ { +} +abstract class _D&A&M3 = self::A with self::M3 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_D&A&M3 + : super self::A::•(i) + ; +} +abstract class D extends self::_D&A&M3 { + final field core::int? _f4; + constructor •(core::int? i) → self::D + : self::D::_f4 = i, super self::_D&A&M3::•(i) + ; +} +abstract class M1 extends core::Object /*isMixinDeclaration*/ { + late field core::int? _f2; + late final [setter] field core::int? _f3; + late final field core::int? _f4 = 0; +} +class B extends core::Object { + constructor •(core::int? i) → self::B + : super core::Object::•() + ; +} +abstract class _E&B&M1 = self::B with self::M1 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_E&B&M1 + : super self::B::•(i) + ; + mixin-super-stub get _f2() → core::int? + return super.{self::M1::_f2}; + mixin-super-stub set _f2(core::int? value) → void + return super.{self::M1::_f2} = value; + mixin-super-stub get _f3() → core::int? + return super.{self::M1::_f3}; + mixin-super-stub set _f3(core::int? value) → void + return super.{self::M1::_f3} = value; + mixin-super-stub get _f4() → core::int? + return super.{self::M1::_f4}; +} +class E extends self::_E&B&M1 implements self::D { + constructor •(core::int? i) → self::E + : super self::_E&B&M1::•(i) + ; + @#C1 + method noSuchMethod(core::Invocation invocation) → dynamic + return super.{core::Object::noSuchMethod}(invocation); +} +static method acceptsInt(core::int x) → void {} +static method testConflictWithNoSuchMethodForwarderIfImplementedInMixin(self::C c) → void { + if(!(c.{self::C::_f2}{core::int?} == null)) { + core::int? x = c.{self::C::_f2}{core::int?}; + x = null; + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(self::C c) → void { + if(!(c.{self::C::_f3}{core::int?} == null)) { + core::int x = c.{self::C::_f3}{core::int}; + self::acceptsInt(x); + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(self::C c) → void { + if(!(c.{self::C::_f4}{core::int?} == null)) { + core::int x = c.{self::C::_f4}{core::int}; + self::acceptsInt(x); + } +} +static method main() → dynamic { + for (self::C c in [new self::C::•(null), new self::C::•(0)]) { + self::testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } +} + +constants { + #C1 = core::_Override {} +} diff --git a/pkg/front_end/testcases/inference_update_2/issue52452.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_update_2/issue52452.dart.strong.transformed.expect new file mode 100644 index 00000000000..e6ec5b74d87 --- /dev/null +++ b/pkg/front_end/testcases/inference_update_2/issue52452.dart.strong.transformed.expect @@ -0,0 +1,92 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + final field core::int? _f2; + final field core::int? _f3; + final field core::int? _f4; + constructor •(core::int? i) → self::C + : self::C::_f2 = i, self::C::_f3 = i, self::C::_f4 = i, super core::Object::•() + ; +} +class A extends core::Object { + constructor •(core::int? i) → self::A + : super core::Object::•() + ; +} +abstract class M3 extends core::Object /*isMixinDeclaration*/ { +} +abstract class _D&A&M3 extends self::A implements self::M3 /*isAnonymousMixin,isEliminatedMixin*/ { + synthetic constructor •(core::int? i) → self::_D&A&M3 + : super self::A::•(i) + ; +} +abstract class D extends self::_D&A&M3 { + final field core::int? _f4; + constructor •(core::int? i) → self::D + : self::D::_f4 = i, super self::_D&A&M3::•(i) + ; +} +abstract class M1 extends core::Object /*isMixinDeclaration*/ { + late field core::int? _f2; + late final [setter] field core::int? _f3; + late final field core::int? _f4 = 0; +} +class B extends core::Object { + constructor •(core::int? i) → self::B + : super core::Object::•() + ; +} +abstract class _E&B&M1 extends self::B implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/ { + late field core::int? _f2; + late final [setter] field core::int? _f3; + late final field core::int? _f4 = 0; + synthetic constructor •(core::int? i) → self::_E&B&M1 + : super self::B::•(i) + ; +} +class E extends self::_E&B&M1 implements self::D { + constructor •(core::int? i) → self::E + : super self::_E&B&M1::•(i) + ; + @#C1 + method noSuchMethod(core::Invocation invocation) → dynamic + return super.{core::Object::noSuchMethod}(invocation); +} +static method acceptsInt(core::int x) → void {} +static method testConflictWithNoSuchMethodForwarderIfImplementedInMixin(self::C c) → void { + if(!(c.{self::C::_f2}{core::int?} == null)) { + core::int? x = c.{self::C::_f2}{core::int?}; + x = null; + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(self::C c) → void { + if(!(c.{self::C::_f3}{core::int?} == null)) { + core::int x = c.{self::C::_f3}{core::int}; + self::acceptsInt(x); + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(self::C c) → void { + if(!(c.{self::C::_f4}{core::int?} == null)) { + core::int x = c.{self::C::_f4}{core::int}; + self::acceptsInt(x); + } +} +static method main() → dynamic { + { + synthesized core::Iterator :sync-for-iterator = core::_GrowableList::_literal2(new self::C::•(null), new self::C::•(0)).{core::Iterable::iterator}{core::Iterator}; + for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) { + self::C c = :sync-for-iterator.{core::Iterator::current}{self::C}; + { + self::testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } + } + } +} + +constants { + #C1 = core::_Override {} +} diff --git a/pkg/front_end/testcases/inference_update_2/issue52452.dart.textual_outline.expect b/pkg/front_end/testcases/inference_update_2/issue52452.dart.textual_outline.expect new file mode 100644 index 00000000000..b2bc14ac548 --- /dev/null +++ b/pkg/front_end/testcases/inference_update_2/issue52452.dart.textual_outline.expect @@ -0,0 +1,44 @@ +class C { + final int? _f2; + final int? _f3; + final int? _f4; + C(int? i) + : _f2 = i, + _f3 = i, + _f4 = i; +} + +class A { + A(int? i); +} + +mixin M3 {} + +abstract class D extends A with M3 { + final int? _f4; + D(int? i) + : _f4 = i, + super(i); +} + +mixin M1 { + late int? _f2; + late final int? _f3; + late final int? _f4 = 0; +} + +class B { + B(int? i); +} + +class E extends B with M1 implements D { + E(super.i); + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +void acceptsInt(int x) {} +void testConflictWithNoSuchMethodForwarderIfImplementedInMixin(C c) {} +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(C c) {} +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(C c) {} +main() {} diff --git a/pkg/front_end/testcases/inference_update_2/issue52452.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/inference_update_2/issue52452.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..a36b7418e8c --- /dev/null +++ b/pkg/front_end/testcases/inference_update_2/issue52452.dart.textual_outline_modelled.expect @@ -0,0 +1,42 @@ +abstract class D extends A with M3 { + D(int? i) + : _f4 = i, + super(i); + final int? _f4; +} + +class A { + A(int? i); +} + +class B { + B(int? i); +} + +class C { + C(int? i) + : _f2 = i, + _f3 = i, + _f4 = i; + final int? _f2; + final int? _f3; + final int? _f4; +} + +class E extends B with M1 implements D { + E(super.i); + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +main() {} +mixin M1 { + late final int? _f3; + late final int? _f4 = 0; + late int? _f2; +} +mixin M3 {} +void acceptsInt(int x) {} +void testConflictWithNoSuchMethodForwarderIfImplementedInMixin(C c) {} +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(C c) {} +void testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(C c) {} diff --git a/pkg/front_end/testcases/inference_update_2/issue52452.dart.weak.expect b/pkg/front_end/testcases/inference_update_2/issue52452.dart.weak.expect new file mode 100644 index 00000000000..88dc8d1bddf --- /dev/null +++ b/pkg/front_end/testcases/inference_update_2/issue52452.dart.weak.expect @@ -0,0 +1,93 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + final field core::int? _f2; + final field core::int? _f3; + final field core::int? _f4; + constructor •(core::int? i) → self::C + : self::C::_f2 = i, self::C::_f3 = i, self::C::_f4 = i, super core::Object::•() + ; +} +class A extends core::Object { + constructor •(core::int? i) → self::A + : super core::Object::•() + ; +} +abstract class M3 extends core::Object /*isMixinDeclaration*/ { +} +abstract class _D&A&M3 = self::A with self::M3 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_D&A&M3 + : super self::A::•(i) + ; +} +abstract class D extends self::_D&A&M3 { + final field core::int? _f4; + constructor •(core::int? i) → self::D + : self::D::_f4 = i, super self::_D&A&M3::•(i) + ; +} +abstract class M1 extends core::Object /*isMixinDeclaration*/ { + late field core::int? _f2; + late final [setter] field core::int? _f3; + late final field core::int? _f4 = 0; +} +class B extends core::Object { + constructor •(core::int? i) → self::B + : super core::Object::•() + ; +} +abstract class _E&B&M1 = self::B with self::M1 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_E&B&M1 + : super self::B::•(i) + ; + mixin-super-stub get _f2() → core::int? + return super.{self::M1::_f2}; + mixin-super-stub set _f2(core::int? value) → void + return super.{self::M1::_f2} = value; + mixin-super-stub get _f3() → core::int? + return super.{self::M1::_f3}; + mixin-super-stub set _f3(core::int? value) → void + return super.{self::M1::_f3} = value; + mixin-super-stub get _f4() → core::int? + return super.{self::M1::_f4}; +} +class E extends self::_E&B&M1 implements self::D { + constructor •(core::int? i) → self::E + : super self::_E&B&M1::•(i) + ; + @#C1 + method noSuchMethod(core::Invocation invocation) → dynamic + return super.{core::Object::noSuchMethod}(invocation); +} +static method acceptsInt(core::int x) → void {} +static method testConflictWithNoSuchMethodForwarderIfImplementedInMixin(self::C c) → void { + if(!(c.{self::C::_f2}{core::int?} == null)) { + core::int? x = c.{self::C::_f2}{core::int?}; + x = null; + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(self::C c) → void { + if(!(c.{self::C::_f3}{core::int?} == null)) { + core::int x = c.{self::C::_f3}{core::int}; + self::acceptsInt(x); + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(self::C c) → void { + if(!(c.{self::C::_f4}{core::int?} == null)) { + core::int x = c.{self::C::_f4}{core::int}; + self::acceptsInt(x); + } +} +static method main() → dynamic { + for (self::C c in [new self::C::•(null), new self::C::•(0)]) { + self::testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } +} + +constants { + #C1 = core::_Override {} +} diff --git a/pkg/front_end/testcases/inference_update_2/issue52452.dart.weak.modular.expect b/pkg/front_end/testcases/inference_update_2/issue52452.dart.weak.modular.expect new file mode 100644 index 00000000000..88dc8d1bddf --- /dev/null +++ b/pkg/front_end/testcases/inference_update_2/issue52452.dart.weak.modular.expect @@ -0,0 +1,93 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + final field core::int? _f2; + final field core::int? _f3; + final field core::int? _f4; + constructor •(core::int? i) → self::C + : self::C::_f2 = i, self::C::_f3 = i, self::C::_f4 = i, super core::Object::•() + ; +} +class A extends core::Object { + constructor •(core::int? i) → self::A + : super core::Object::•() + ; +} +abstract class M3 extends core::Object /*isMixinDeclaration*/ { +} +abstract class _D&A&M3 = self::A with self::M3 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_D&A&M3 + : super self::A::•(i) + ; +} +abstract class D extends self::_D&A&M3 { + final field core::int? _f4; + constructor •(core::int? i) → self::D + : self::D::_f4 = i, super self::_D&A&M3::•(i) + ; +} +abstract class M1 extends core::Object /*isMixinDeclaration*/ { + late field core::int? _f2; + late final [setter] field core::int? _f3; + late final field core::int? _f4 = 0; +} +class B extends core::Object { + constructor •(core::int? i) → self::B + : super core::Object::•() + ; +} +abstract class _E&B&M1 = self::B with self::M1 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_E&B&M1 + : super self::B::•(i) + ; + mixin-super-stub get _f2() → core::int? + return super.{self::M1::_f2}; + mixin-super-stub set _f2(core::int? value) → void + return super.{self::M1::_f2} = value; + mixin-super-stub get _f3() → core::int? + return super.{self::M1::_f3}; + mixin-super-stub set _f3(core::int? value) → void + return super.{self::M1::_f3} = value; + mixin-super-stub get _f4() → core::int? + return super.{self::M1::_f4}; +} +class E extends self::_E&B&M1 implements self::D { + constructor •(core::int? i) → self::E + : super self::_E&B&M1::•(i) + ; + @#C1 + method noSuchMethod(core::Invocation invocation) → dynamic + return super.{core::Object::noSuchMethod}(invocation); +} +static method acceptsInt(core::int x) → void {} +static method testConflictWithNoSuchMethodForwarderIfImplementedInMixin(self::C c) → void { + if(!(c.{self::C::_f2}{core::int?} == null)) { + core::int? x = c.{self::C::_f2}{core::int?}; + x = null; + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(self::C c) → void { + if(!(c.{self::C::_f3}{core::int?} == null)) { + core::int x = c.{self::C::_f3}{core::int}; + self::acceptsInt(x); + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(self::C c) → void { + if(!(c.{self::C::_f4}{core::int?} == null)) { + core::int x = c.{self::C::_f4}{core::int}; + self::acceptsInt(x); + } +} +static method main() → dynamic { + for (self::C c in [new self::C::•(null), new self::C::•(0)]) { + self::testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } +} + +constants { + #C1 = core::_Override {} +} diff --git a/pkg/front_end/testcases/inference_update_2/issue52452.dart.weak.outline.expect b/pkg/front_end/testcases/inference_update_2/issue52452.dart.weak.outline.expect new file mode 100644 index 00000000000..efca1a3ca7f --- /dev/null +++ b/pkg/front_end/testcases/inference_update_2/issue52452.dart.weak.outline.expect @@ -0,0 +1,73 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + final field core::int? _f2; + final field core::int? _f3; + final field core::int? _f4; + constructor •(core::int? i) → self::C + ; +} +class A extends core::Object { + constructor •(core::int? i) → self::A + ; +} +abstract class M3 extends core::Object /*isMixinDeclaration*/ { +} +abstract class _D&A&M3 = self::A with self::M3 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_D&A&M3 + : super self::A::•(i) + ; +} +abstract class D extends self::_D&A&M3 { + final field core::int? _f4; + constructor •(core::int? i) → self::D + ; +} +abstract class M1 extends core::Object /*isMixinDeclaration*/ { + late field core::int? _f2; + late final [setter] field core::int? _f3; + late final field core::int? _f4; +} +class B extends core::Object { + constructor •(core::int? i) → self::B + ; +} +abstract class _E&B&M1 = self::B with self::M1 /*isAnonymousMixin*/ { + synthetic constructor •(core::int? i) → self::_E&B&M1 + : super self::B::•(i) + ; + mixin-super-stub get _f2() → core::int? + return super.{self::M1::_f2}; + mixin-super-stub set _f2(core::int? value) → void + return super.{self::M1::_f2} = value; + mixin-super-stub get _f3() → core::int? + return super.{self::M1::_f3}; + mixin-super-stub set _f3(core::int? value) → void + return super.{self::M1::_f3} = value; + mixin-super-stub get _f4() → core::int? + return super.{self::M1::_f4}; +} +class E extends self::_E&B&M1 implements self::D { + constructor •(core::int? i) → self::E + ; + @core::override + method noSuchMethod(core::Invocation invocation) → dynamic + ; +} +static method acceptsInt(core::int x) → void + ; +static method testConflictWithNoSuchMethodForwarderIfImplementedInMixin(self::C c) → void + ; +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(self::C c) → void + ; +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(self::C c) → void + ; +static method main() → dynamic + ; + + +Extra constant evaluation status: +Evaluated: StaticGet @ org-dartlang-testcase:///issue52452.dart:49:4 -> InstanceConstant(const _Override{}) +Extra constant evaluation: evaluated: 10, effectively constant: 1 diff --git a/pkg/front_end/testcases/inference_update_2/issue52452.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_update_2/issue52452.dart.weak.transformed.expect new file mode 100644 index 00000000000..e6ec5b74d87 --- /dev/null +++ b/pkg/front_end/testcases/inference_update_2/issue52452.dart.weak.transformed.expect @@ -0,0 +1,92 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + final field core::int? _f2; + final field core::int? _f3; + final field core::int? _f4; + constructor •(core::int? i) → self::C + : self::C::_f2 = i, self::C::_f3 = i, self::C::_f4 = i, super core::Object::•() + ; +} +class A extends core::Object { + constructor •(core::int? i) → self::A + : super core::Object::•() + ; +} +abstract class M3 extends core::Object /*isMixinDeclaration*/ { +} +abstract class _D&A&M3 extends self::A implements self::M3 /*isAnonymousMixin,isEliminatedMixin*/ { + synthetic constructor •(core::int? i) → self::_D&A&M3 + : super self::A::•(i) + ; +} +abstract class D extends self::_D&A&M3 { + final field core::int? _f4; + constructor •(core::int? i) → self::D + : self::D::_f4 = i, super self::_D&A&M3::•(i) + ; +} +abstract class M1 extends core::Object /*isMixinDeclaration*/ { + late field core::int? _f2; + late final [setter] field core::int? _f3; + late final field core::int? _f4 = 0; +} +class B extends core::Object { + constructor •(core::int? i) → self::B + : super core::Object::•() + ; +} +abstract class _E&B&M1 extends self::B implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/ { + late field core::int? _f2; + late final [setter] field core::int? _f3; + late final field core::int? _f4 = 0; + synthetic constructor •(core::int? i) → self::_E&B&M1 + : super self::B::•(i) + ; +} +class E extends self::_E&B&M1 implements self::D { + constructor •(core::int? i) → self::E + : super self::_E&B&M1::•(i) + ; + @#C1 + method noSuchMethod(core::Invocation invocation) → dynamic + return super.{core::Object::noSuchMethod}(invocation); +} +static method acceptsInt(core::int x) → void {} +static method testConflictWithNoSuchMethodForwarderIfImplementedInMixin(self::C c) → void { + if(!(c.{self::C::_f2}{core::int?} == null)) { + core::int? x = c.{self::C::_f2}{core::int?}; + x = null; + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(self::C c) → void { + if(!(c.{self::C::_f3}{core::int?} == null)) { + core::int x = c.{self::C::_f3}{core::int}; + self::acceptsInt(x); + } +} +static method testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(self::C c) → void { + if(!(c.{self::C::_f4}{core::int?} == null)) { + core::int x = c.{self::C::_f4}{core::int}; + self::acceptsInt(x); + } +} +static method main() → dynamic { + { + synthesized core::Iterator :sync-for-iterator = core::_GrowableList::_literal2(new self::C::•(null), new self::C::•(0)).{core::Iterable::iterator}{core::Iterator}; + for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) { + self::C c = :sync-for-iterator.{core::Iterator::current}{self::C}; + { + self::testConflictWithNoSuchMethodForwarderIfImplementedInMixin(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin1(c); + self::testNoConflictWithNoSuchMethodForwarderIfImplementedInMixin2(c); + } + } + } +} + +constants { + #C1 = core::_Override {} +}