[cfe] Preserve the required flag in synthesized mixin constructors

Closes https://github.com/dart-lang/sdk/issues/52872

Change-Id: I9089683f4fb2027211c96ad2065044c8181a282f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/313781
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
Chloe Stefantsova 2023-07-14 11:33:45 +00:00 committed by Commit Queue
parent 0ae3368fb6
commit 7a232bb3e2
16 changed files with 306 additions and 6 deletions

View file

@ -1007,6 +1007,7 @@ class KernelTarget extends TargetImplementation {
VariableDeclaration copy = new VariableDeclaration(formal.name,
isFinal: formal.isFinal,
isConst: formal.isConst,
isRequired: formal.isRequired,
hasDeclaredInitializer: formal.hasDeclaredInitializer,
type: const UnknownType());
if (!hasTypeDependency && formal.type is! UnknownType) {

View file

@ -0,0 +1,19 @@
// 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.
class A {
bool v1;
num v2;
A(bool this.v1, {required num this.v2});
}
mixin class M1 {
num v2 = -1;
}
class C = A with M1;
test() {
C c = C(true);
}

View file

@ -0,0 +1,45 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/issue52872.dart:18:10: Error: Required named parameter 'v2' must be provided.
// C c = C(true);
// ^
// pkg/front_end/testcases/general/issue52872.dart:15:7: Context: The class 'C' has a constructor that takes no arguments.
// class C = A with M1;
// ^
//
import self as self;
import "dart:core" as core;
class A extends core::Object {
field core::bool v1;
field core::num v2;
constructor •(core::bool v1, {required core::num v2 = #C1}) → self::A
: self::A::v1 = v1, self::A::v2 = v2, super core::Object::•()
;
}
mixin class M1 extends core::Object {
field core::num v2 = 1.{core::int::unary-}(){() → core::int};
synthetic constructor •() → self::M1
: super core::Object::•()
;
}
class C = self::A with self::M1 {
synthetic constructor •(core::bool v1, {required core::num v2 = #C1}) → self::C
: super self::A::•(v1, v2: v2)
;
mixin-super-stub get v2() → core::num
return super.{self::M1::v2};
mixin-super-stub set v2(core::num value) → void
return super.{self::M1::v2} = value;
}
static method test() → dynamic {
self::C c = invalid-expression "pkg/front_end/testcases/general/issue52872.dart:18:10: Error: Required named parameter 'v2' must be provided.
C c = C(true);
^";
}
constants {
#C1 = null
}

View file

@ -0,0 +1,47 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/issue52872.dart:18:10: Error: Required named parameter 'v2' must be provided.
// C c = C(true);
// ^
// pkg/front_end/testcases/general/issue52872.dart:15:7: Context: The class 'C' has a constructor that takes no arguments.
// class C = A with M1;
// ^
//
import self as self;
import "dart:core" as core;
class A extends core::Object {
field core::bool v1;
field core::num v2;
constructor •(core::bool v1, {required core::num v2 = #C1}) → self::A
: self::A::v1 = v1, self::A::v2 = v2, super core::Object::•()
;
}
mixin class M1 extends core::Object {
field core::num v2 = 1.{core::int::unary-}(){() → core::int};
synthetic constructor •() → self::M1
: super core::Object::•()
;
}
class C extends self::A implements self::M1 /*isEliminatedMixin*/ {
field core::num v2 = 1.{core::int::unary-}(){() → core::int};
synthetic constructor •(core::bool v1, {required core::num v2 = #C1}) → self::C
: super self::A::•(v1, v2: v2)
;
}
static method test() → dynamic {
self::C c = invalid-expression "pkg/front_end/testcases/general/issue52872.dart:18:10: Error: Required named parameter 'v2' must be provided.
C c = C(true);
^";
}
constants {
#C1 = null
}
Extra constant evaluation status:
Evaluated: InstanceInvocation @ org-dartlang-testcase:///issue52872.dart:12:12 -> IntConstant(-1)
Evaluated: InstanceInvocation @ org-dartlang-testcase:///issue52872.dart:12:12 -> IntConstant(-1)
Extra constant evaluation: evaluated: 6, effectively constant: 2

View file

@ -0,0 +1,12 @@
class A {
bool v1;
num v2;
A(bool this.v1, {required num this.v2});
}
mixin class M1 {
num v2 = -1;
}
class C = A with M1;
test() {}

View file

@ -0,0 +1,13 @@
class A {
A(bool this.v1, {required num this.v2});
bool v1;
num v2;
}
class C = A with M1;
mixin class M1 {
num v2 = -1;
}
test() {}

View file

@ -0,0 +1,45 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/issue52872.dart:18:10: Error: Required named parameter 'v2' must be provided.
// C c = C(true);
// ^
// pkg/front_end/testcases/general/issue52872.dart:15:7: Context: The class 'C' has a constructor that takes no arguments.
// class C = A with M1;
// ^
//
import self as self;
import "dart:core" as core;
class A extends core::Object {
field core::bool v1;
field core::num v2;
constructor •(core::bool v1, {required core::num v2 = #C1}) → self::A
: self::A::v1 = v1, self::A::v2 = v2, super core::Object::•()
;
}
mixin class M1 extends core::Object {
field core::num v2 = 1.{core::int::unary-}(){() → core::int};
synthetic constructor •() → self::M1
: super core::Object::•()
;
}
class C = self::A with self::M1 {
synthetic constructor •(core::bool v1, {required core::num v2 = #C1}) → self::C
: super self::A::•(v1, v2: v2)
;
mixin-super-stub get v2() → core::num
return super.{self::M1::v2};
mixin-super-stub set v2(core::num value) → void
return super.{self::M1::v2} = value;
}
static method test() → dynamic {
self::C c = invalid-expression "pkg/front_end/testcases/general/issue52872.dart:18:10: Error: Required named parameter 'v2' must be provided.
C c = C(true);
^";
}
constants {
#C1 = null
}

View file

@ -0,0 +1,45 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/issue52872.dart:18:10: Error: Required named parameter 'v2' must be provided.
// C c = C(true);
// ^
// pkg/front_end/testcases/general/issue52872.dart:15:7: Context: The class 'C' has a constructor that takes no arguments.
// class C = A with M1;
// ^
//
import self as self;
import "dart:core" as core;
class A extends core::Object {
field core::bool v1;
field core::num v2;
constructor •(core::bool v1, {required core::num v2 = #C1}) → self::A
: self::A::v1 = v1, self::A::v2 = v2, super core::Object::•()
;
}
mixin class M1 extends core::Object {
field core::num v2 = 1.{core::int::unary-}(){() → core::int};
synthetic constructor •() → self::M1
: super core::Object::•()
;
}
class C = self::A with self::M1 {
synthetic constructor •(core::bool v1, {required core::num v2 = #C1}) → self::C
: super self::A::•(v1, v2: v2)
;
mixin-super-stub get v2() → core::num
return super.{self::M1::v2};
mixin-super-stub set v2(core::num value) → void
return super.{self::M1::v2} = value;
}
static method test() → dynamic {
self::C c = invalid-expression "pkg/front_end/testcases/general/issue52872.dart:18:10: Error: Required named parameter 'v2' must be provided.
C c = C(true);
^";
}
constants {
#C1 = null
}

View file

@ -0,0 +1,26 @@
library;
import self as self;
import "dart:core" as core;
class A extends core::Object {
field core::bool v1;
field core::num v2;
constructor •(core::bool v1, {required core::num v2 = null}) → self::A
;
}
mixin class M1 extends core::Object {
field core::num v2;
synthetic constructor •() → self::M1
;
}
class C = self::A with self::M1 {
synthetic constructor •(core::bool v1, {required core::num v2 = null}) → self::C
: super self::A::•(v1, v2: v2)
;
mixin-super-stub get v2() → core::num
return super.{self::M1::v2};
mixin-super-stub set v2(core::num value) → void
return super.{self::M1::v2} = value;
}
static method test() → dynamic
;

View file

@ -0,0 +1,47 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/issue52872.dart:18:10: Error: Required named parameter 'v2' must be provided.
// C c = C(true);
// ^
// pkg/front_end/testcases/general/issue52872.dart:15:7: Context: The class 'C' has a constructor that takes no arguments.
// class C = A with M1;
// ^
//
import self as self;
import "dart:core" as core;
class A extends core::Object {
field core::bool v1;
field core::num v2;
constructor •(core::bool v1, {required core::num v2 = #C1}) → self::A
: self::A::v1 = v1, self::A::v2 = v2, super core::Object::•()
;
}
mixin class M1 extends core::Object {
field core::num v2 = 1.{core::int::unary-}(){() → core::int};
synthetic constructor •() → self::M1
: super core::Object::•()
;
}
class C extends self::A implements self::M1 /*isEliminatedMixin*/ {
field core::num v2 = 1.{core::int::unary-}(){() → core::int};
synthetic constructor •(core::bool v1, {required core::num v2 = #C1}) → self::C
: super self::A::•(v1, v2: v2)
;
}
static method test() → dynamic {
self::C c = invalid-expression "pkg/front_end/testcases/general/issue52872.dart:18:10: Error: Required named parameter 'v2' must be provided.
C c = C(true);
^";
}
constants {
#C1 = null
}
Extra constant evaluation status:
Evaluated: InstanceInvocation @ org-dartlang-testcase:///issue52872.dart:12:12 -> IntConstant(-1)
Evaluated: InstanceInvocation @ org-dartlang-testcase:///issue52872.dart:12:12 -> IntConstant(-1)
Extra constant evaluation: evaluated: 6, effectively constant: 2

View file

@ -16,7 +16,7 @@ abstract class B<D extends core::Object? = dynamic> extends core::Object {
;
}
abstract class _C&B&Mixin = self::B<self::A> with self::Mixin /*isAnonymousMixin*/ {
synthetic constructor •({self::A field = #C1}) → self::_C&B&Mixin
synthetic constructor •({required self::A field = #C1}) → self::_C&B&Mixin
: super self::B::•(field: field)
;
}

View file

@ -16,7 +16,7 @@ abstract class B<D extends core::Object? = dynamic> extends core::Object {
;
}
abstract class _C&B&Mixin extends self::B<self::A> implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/ {
synthetic constructor •({self::A field = #C1}) → self::_C&B&Mixin
synthetic constructor •({required self::A field = #C1}) → self::_C&B&Mixin
: super self::B::•(field: field)
;
}

View file

@ -16,7 +16,7 @@ abstract class B<D extends core::Object? = dynamic> extends core::Object {
;
}
abstract class _C&B&Mixin = self::B<self::A> with self::Mixin /*isAnonymousMixin*/ {
synthetic constructor •({self::A field = #C1}) → self::_C&B&Mixin
synthetic constructor •({required self::A field = #C1}) → self::_C&B&Mixin
: super self::B::•(field: field)
;
}

View file

@ -16,7 +16,7 @@ abstract class B<D extends core::Object? = dynamic> extends core::Object {
;
}
abstract class _C&B&Mixin = self::B<self::A> with self::Mixin /*isAnonymousMixin*/ {
synthetic constructor •({self::A field = #C1}) → self::_C&B&Mixin
synthetic constructor •({required self::A field = #C1}) → self::_C&B&Mixin
: super self::B::•(field: field)
;
}

View file

@ -14,7 +14,7 @@ abstract class B<D extends core::Object? = dynamic> extends core::Object {
;
}
abstract class _C&B&Mixin = self::B<self::A> with self::Mixin /*isAnonymousMixin*/ {
synthetic constructor •({self::A field = null}) → self::_C&B&Mixin
synthetic constructor •({required self::A field = null}) → self::_C&B&Mixin
: super self::B::•(field: field)
;
}

View file

@ -16,7 +16,7 @@ abstract class B<D extends core::Object? = dynamic> extends core::Object {
;
}
abstract class _C&B&Mixin extends self::B<self::A> implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/ {
synthetic constructor •({self::A field = #C1}) → self::_C&B&Mixin
synthetic constructor •({required self::A field = #C1}) → self::_C&B&Mixin
: super self::B::•(field: field)
;
}