mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:49:00 +00:00
[cfe] Support typedefs in object patterns
Part of https://github.com/dart-lang/sdk/issues/49749 Change-Id: I0d29a875a6a0d3bac5c20309a1b4a6c8b48618f5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/277960 Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
parent
157641dc3d
commit
628dd02bc8
19 changed files with 711 additions and 2 deletions
|
@ -8347,8 +8347,37 @@ class BodyBuilder extends StackListenerImpl
|
|||
// TODO(cstefantsova): Handle the case of secondIdentifier != null
|
||||
handleIdentifier(firstIdentifier, IdentifierContext.typeReference);
|
||||
Object? resolvedIdentifier = pop();
|
||||
|
||||
if (resolvedIdentifier is TypeUseGenerator) {
|
||||
TypeDeclarationBuilder typeDeclaration = resolvedIdentifier.declaration;
|
||||
|
||||
if (typeDeclaration is TypeAliasBuilder) {
|
||||
if (typeArguments == null ||
|
||||
typeArguments.length ==
|
||||
typeDeclaration.typedef.typeParameters.length) {
|
||||
TypeDeclarationBuilder? unaliasedTypeDeclaration =
|
||||
typeDeclaration.unaliasDeclaration(typeArguments);
|
||||
List<TypeBuilder>? unaliasedTypeArguments =
|
||||
typeDeclaration.unaliasTypeArguments(typeArguments);
|
||||
if (unaliasedTypeDeclaration == null) {
|
||||
// TODO(cstefantsova): Make sure an error is reported elsewhere.
|
||||
push(new DummyPattern(firstIdentifier.charOffset));
|
||||
return;
|
||||
} else {
|
||||
typeDeclaration = unaliasedTypeDeclaration;
|
||||
typeArguments = unaliasedTypeArguments;
|
||||
}
|
||||
} else {
|
||||
addProblem(
|
||||
fasta.templateTypeArgumentMismatch
|
||||
.withArguments(typeDeclaration.typedef.typeParameters.length),
|
||||
firstIdentifier.charOffset,
|
||||
noLength);
|
||||
push(new DummyPattern(firstIdentifier.charOffset));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeDeclaration is ClassBuilder) {
|
||||
List<DartType>? builtTypeArguments;
|
||||
if (typeArguments != null) {
|
||||
|
@ -8359,7 +8388,13 @@ class BodyBuilder extends StackListenerImpl
|
|||
.add(typeBuilder.build(libraryBuilder, TypeUse.typeArgument));
|
||||
}
|
||||
} else {
|
||||
// TODO(cstefantsova): Report an error.
|
||||
addProblem(
|
||||
fasta.templateTypeArgumentMismatch
|
||||
.withArguments(typeDeclaration.cls.typeParameters.length),
|
||||
firstIdentifier.charOffset,
|
||||
noLength);
|
||||
push(new DummyPattern(firstIdentifier.charOffset));
|
||||
return;
|
||||
}
|
||||
}
|
||||
push(new ObjectPattern(
|
||||
|
@ -8368,7 +8403,7 @@ class BodyBuilder extends StackListenerImpl
|
|||
builtTypeArguments,
|
||||
firstIdentifier.offset));
|
||||
} else {
|
||||
// TODO(cstefantsova): Handle this case.
|
||||
// TODO(cstefantsova): Handle other possibilities.
|
||||
push(new DummyPattern(firstIdentifier.charOffset));
|
||||
}
|
||||
} else {
|
||||
|
|
14
pkg/front_end/testcases/patterns/object_pattern_errors.dart
Normal file
14
pkg/front_end/testcases/patterns/object_pattern_errors.dart
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
class A {}
|
||||
|
||||
typedef B<X> = A;
|
||||
|
||||
test(dynamic x) {
|
||||
if (x case A<int>()) {} // Error.
|
||||
if (x case B()) {} // Ok: the type argument is inferred.
|
||||
if (x case B<int>()) {} // Ok.
|
||||
if (x case B<String, num>()) {} // Error.
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/patterns/object_pattern_errors.dart:10:14: Error: Expected 0 type arguments.
|
||||
// if (x case A<int>()) {} // Error.
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/patterns/object_pattern_errors.dart:13:14: Error: Expected 1 type arguments.
|
||||
// if (x case B<String, num>()) {} // Error.
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
typedef B<unrelated X extends core::Object? = dynamic> = self::A;
|
||||
class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
static method test(dynamic x) → dynamic {
|
||||
final dynamic #t1 = x;
|
||||
final dynamic #t2 = x;
|
||||
final dynamic #t3 = #t2;
|
||||
if(#t3 is self::A) {
|
||||
}
|
||||
final dynamic #t4 = x;
|
||||
final dynamic #t5 = #t4;
|
||||
if(#t5 is self::A) {
|
||||
}
|
||||
final dynamic #t6 = x;
|
||||
}
|
||||
static method _#B#new#tearOff<unrelated X extends core::Object? = dynamic>() → self::A
|
||||
return new self::A::•();
|
|
@ -0,0 +1,35 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/patterns/object_pattern_errors.dart:10:14: Error: Expected 0 type arguments.
|
||||
// if (x case A<int>()) {} // Error.
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/patterns/object_pattern_errors.dart:13:14: Error: Expected 1 type arguments.
|
||||
// if (x case B<String, num>()) {} // Error.
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
typedef B<unrelated X extends core::Object? = dynamic> = self::A;
|
||||
class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
static method test(dynamic x) → dynamic {
|
||||
final dynamic #t1 = x;
|
||||
final dynamic #t2 = x;
|
||||
final dynamic #t3 = #t2;
|
||||
if(#t3 is self::A) {
|
||||
}
|
||||
final dynamic #t4 = x;
|
||||
final dynamic #t5 = #t4;
|
||||
if(#t5 is self::A) {
|
||||
}
|
||||
final dynamic #t6 = x;
|
||||
}
|
||||
static method _#B#new#tearOff<unrelated X extends core::Object? = dynamic>() → self::A
|
||||
return new self::A::•();
|
|
@ -0,0 +1,4 @@
|
|||
class A {}
|
||||
|
||||
typedef B<X> = A;
|
||||
test(dynamic x) {}
|
|
@ -0,0 +1,4 @@
|
|||
class A {}
|
||||
|
||||
test(dynamic x) {}
|
||||
typedef B<X> = A;
|
|
@ -0,0 +1,35 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/patterns/object_pattern_errors.dart:10:14: Error: Expected 0 type arguments.
|
||||
// if (x case A<int>()) {} // Error.
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/patterns/object_pattern_errors.dart:13:14: Error: Expected 1 type arguments.
|
||||
// if (x case B<String, num>()) {} // Error.
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
typedef B<unrelated X extends core::Object? = dynamic> = self::A;
|
||||
class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
static method test(dynamic x) → dynamic {
|
||||
final dynamic #t1 = x;
|
||||
final dynamic #t2 = x;
|
||||
final dynamic #t3 = #t2;
|
||||
if(#t3 is self::A) {
|
||||
}
|
||||
final dynamic #t4 = x;
|
||||
final dynamic #t5 = #t4;
|
||||
if(#t5 is self::A) {
|
||||
}
|
||||
final dynamic #t6 = x;
|
||||
}
|
||||
static method _#B#new#tearOff<unrelated X extends core::Object? = dynamic>() → self::A
|
||||
return new self::A::•();
|
|
@ -0,0 +1,35 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/patterns/object_pattern_errors.dart:10:14: Error: Expected 0 type arguments.
|
||||
// if (x case A<int>()) {} // Error.
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/patterns/object_pattern_errors.dart:13:14: Error: Expected 1 type arguments.
|
||||
// if (x case B<String, num>()) {} // Error.
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
typedef B<unrelated X extends core::Object? = dynamic> = self::A;
|
||||
class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
static method test(dynamic x) → dynamic {
|
||||
final dynamic #t1 = x;
|
||||
final dynamic #t2 = x;
|
||||
final dynamic #t3 = #t2;
|
||||
if(#t3 is self::A) {
|
||||
}
|
||||
final dynamic #t4 = x;
|
||||
final dynamic #t5 = #t4;
|
||||
if(#t5 is self::A) {
|
||||
}
|
||||
final dynamic #t6 = x;
|
||||
}
|
||||
static method _#B#new#tearOff<unrelated X extends core::Object? = dynamic>() → self::A
|
||||
return new self::A::•();
|
|
@ -0,0 +1,13 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
typedef B<unrelated X extends core::Object? = dynamic> = self::A;
|
||||
class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
;
|
||||
}
|
||||
static method test(dynamic x) → dynamic
|
||||
;
|
||||
static method _#B#new#tearOff<unrelated X extends core::Object? = dynamic>() → self::A
|
||||
return new self::A::•();
|
|
@ -0,0 +1,35 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/patterns/object_pattern_errors.dart:10:14: Error: Expected 0 type arguments.
|
||||
// if (x case A<int>()) {} // Error.
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/patterns/object_pattern_errors.dart:13:14: Error: Expected 1 type arguments.
|
||||
// if (x case B<String, num>()) {} // Error.
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
typedef B<unrelated X extends core::Object? = dynamic> = self::A;
|
||||
class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
static method test(dynamic x) → dynamic {
|
||||
final dynamic #t1 = x;
|
||||
final dynamic #t2 = x;
|
||||
final dynamic #t3 = #t2;
|
||||
if(#t3 is self::A) {
|
||||
}
|
||||
final dynamic #t4 = x;
|
||||
final dynamic #t5 = #t4;
|
||||
if(#t5 is self::A) {
|
||||
}
|
||||
final dynamic #t6 = x;
|
||||
}
|
||||
static method _#B#new#tearOff<unrelated X extends core::Object? = dynamic>() → self::A
|
||||
return new self::A::•();
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
class A {
|
||||
int foo;
|
||||
|
||||
A(this.foo);
|
||||
}
|
||||
|
||||
typedef B = A;
|
||||
|
||||
class C<X, Y> {
|
||||
X x;
|
||||
Y y;
|
||||
|
||||
C(this.x, this.y);
|
||||
}
|
||||
|
||||
typedef D<X> = C<X, X>;
|
||||
|
||||
test1(dynamic x) {
|
||||
if (x case B(:var foo)) {
|
||||
return foo;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
test2(dynamic x) {
|
||||
if (x case D<String>(:var x)) {
|
||||
return x;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
main() {
|
||||
expectEquals(0, test1(new A(0)));
|
||||
expectEquals(1, test1(new B(1)));
|
||||
expectEquals(null, test1(null));
|
||||
|
||||
expectEquals("one", test2(new C("one", "two")));
|
||||
expectEquals("one", test2(new D("one", "two")));
|
||||
expectEquals(null, test2(null));
|
||||
}
|
||||
|
||||
expectEquals(x, y) {
|
||||
if (x != y) {
|
||||
throw "Expected ${x} to be equal to ${y}.";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
typedef B = self::A;
|
||||
typedef D<X extends core::Object? = dynamic> = self::C<X%, X%>;
|
||||
class A extends core::Object {
|
||||
field core::int foo;
|
||||
constructor •(core::int foo) → self::A
|
||||
: self::A::foo = foo, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
|
||||
covariant-by-class field self::C::X% x;
|
||||
covariant-by-class field self::C::Y% y;
|
||||
constructor •(self::C::X% x, self::C::Y% y) → self::C<self::C::X%, self::C::Y%>
|
||||
: self::C::x = x, self::C::y = y, super core::Object::•()
|
||||
;
|
||||
}
|
||||
static method test1(dynamic x) → dynamic {
|
||||
final dynamic #t1 = x;
|
||||
final core::bool #t2 = true;
|
||||
final dynamic #t3 = #t1;
|
||||
if(#t3 is self::A) {
|
||||
final core::int #t4 = #t3{self::A}.{self::A::foo}{core::int};
|
||||
#t2 = false;
|
||||
{
|
||||
dynamic foo = #t4;
|
||||
{
|
||||
return foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(#t2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
static method test2(dynamic x) → dynamic {
|
||||
final dynamic #t5 = x;
|
||||
final core::bool #t6 = true;
|
||||
final dynamic #t7 = #t5;
|
||||
if(#t7 is self::C<core::String, core::String>) {
|
||||
final core::String #t8 = #t7{self::C<core::String, core::String>}.{self::C::x}{core::String};
|
||||
#t6 = false;
|
||||
{
|
||||
dynamic x = #t8;
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(#t6) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
static method main() → dynamic {
|
||||
self::expectEquals(0, self::test1(new self::A::•(0)));
|
||||
self::expectEquals(1, self::test1(new self::A::•(1)));
|
||||
self::expectEquals(null, self::test1(null));
|
||||
self::expectEquals("one", self::test2(new self::C::•<core::String, core::String>("one", "two")));
|
||||
self::expectEquals("one", self::test2(new self::C::•<core::String, core::String>("one", "two")));
|
||||
self::expectEquals(null, self::test2(null));
|
||||
}
|
||||
static method expectEquals(dynamic x, dynamic y) → dynamic {
|
||||
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
|
||||
throw "Expected ${x} to be equal to ${y}.";
|
||||
}
|
||||
}
|
||||
static method _#D#new#tearOff<X extends core::Object? = dynamic>(self::_#D#new#tearOff::X% x, self::_#D#new#tearOff::X% y) → self::C<self::_#D#new#tearOff::X%, self::_#D#new#tearOff::X%>
|
||||
return new self::C::•<self::_#D#new#tearOff::X%, self::_#D#new#tearOff::X%>(x, y);
|
|
@ -0,0 +1,70 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
typedef B = self::A;
|
||||
typedef D<X extends core::Object? = dynamic> = self::C<X%, X%>;
|
||||
class A extends core::Object {
|
||||
field core::int foo;
|
||||
constructor •(core::int foo) → self::A
|
||||
: self::A::foo = foo, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
|
||||
covariant-by-class field self::C::X% x;
|
||||
covariant-by-class field self::C::Y% y;
|
||||
constructor •(self::C::X% x, self::C::Y% y) → self::C<self::C::X%, self::C::Y%>
|
||||
: self::C::x = x, self::C::y = y, super core::Object::•()
|
||||
;
|
||||
}
|
||||
static method test1(dynamic x) → dynamic {
|
||||
final dynamic #t1 = x;
|
||||
final core::bool #t2 = true;
|
||||
final dynamic #t3 = #t1;
|
||||
if(#t3 is self::A) {
|
||||
final core::int #t4 = #t3{self::A}.{self::A::foo}{core::int};
|
||||
#t2 = false;
|
||||
{
|
||||
dynamic foo = #t4;
|
||||
{
|
||||
return foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(#t2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
static method test2(dynamic x) → dynamic {
|
||||
final dynamic #t5 = x;
|
||||
final core::bool #t6 = true;
|
||||
final dynamic #t7 = #t5;
|
||||
if(#t7 is self::C<core::String, core::String>) {
|
||||
final core::String #t8 = #t7{self::C<core::String, core::String>}.{self::C::x}{core::String};
|
||||
#t6 = false;
|
||||
{
|
||||
dynamic x = #t8;
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(#t6) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
static method main() → dynamic {
|
||||
self::expectEquals(0, self::test1(new self::A::•(0)));
|
||||
self::expectEquals(1, self::test1(new self::A::•(1)));
|
||||
self::expectEquals(null, self::test1(null));
|
||||
self::expectEquals("one", self::test2(new self::C::•<core::String, core::String>("one", "two")));
|
||||
self::expectEquals("one", self::test2(new self::C::•<core::String, core::String>("one", "two")));
|
||||
self::expectEquals(null, self::test2(null));
|
||||
}
|
||||
static method expectEquals(dynamic x, dynamic y) → dynamic {
|
||||
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
|
||||
throw "Expected ${x} to be equal to ${y}.";
|
||||
}
|
||||
}
|
||||
static method _#D#new#tearOff<X extends core::Object? = dynamic>(self::_#D#new#tearOff::X% x, self::_#D#new#tearOff::X% y) → self::C<self::_#D#new#tearOff::X%, self::_#D#new#tearOff::X%>
|
||||
return new self::C::•<self::_#D#new#tearOff::X%, self::_#D#new#tearOff::X%>(x, y);
|
|
@ -0,0 +1,18 @@
|
|||
class A {
|
||||
int foo;
|
||||
A(this.foo);
|
||||
}
|
||||
|
||||
typedef B = A;
|
||||
|
||||
class C<X, Y> {
|
||||
X x;
|
||||
Y y;
|
||||
C(this.x, this.y);
|
||||
}
|
||||
|
||||
typedef D<X> = C<X, X>;
|
||||
test1(dynamic x) {}
|
||||
test2(dynamic x) {}
|
||||
main() {}
|
||||
expectEquals(x, y) {}
|
|
@ -0,0 +1,17 @@
|
|||
class A {
|
||||
A(this.foo);
|
||||
int foo;
|
||||
}
|
||||
|
||||
class C<X, Y> {
|
||||
C(this.x, this.y);
|
||||
X x;
|
||||
Y y;
|
||||
}
|
||||
|
||||
expectEquals(x, y) {}
|
||||
main() {}
|
||||
test1(dynamic x) {}
|
||||
test2(dynamic x) {}
|
||||
typedef B = A;
|
||||
typedef D<X> = C<X, X>;
|
|
@ -0,0 +1,70 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
typedef B = self::A;
|
||||
typedef D<X extends core::Object? = dynamic> = self::C<X%, X%>;
|
||||
class A extends core::Object {
|
||||
field core::int foo;
|
||||
constructor •(core::int foo) → self::A
|
||||
: self::A::foo = foo, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
|
||||
covariant-by-class field self::C::X% x;
|
||||
covariant-by-class field self::C::Y% y;
|
||||
constructor •(self::C::X% x, self::C::Y% y) → self::C<self::C::X%, self::C::Y%>
|
||||
: self::C::x = x, self::C::y = y, super core::Object::•()
|
||||
;
|
||||
}
|
||||
static method test1(dynamic x) → dynamic {
|
||||
final dynamic #t1 = x;
|
||||
final core::bool #t2 = true;
|
||||
final dynamic #t3 = #t1;
|
||||
if(#t3 is self::A) {
|
||||
final core::int #t4 = #t3{self::A}.{self::A::foo}{core::int};
|
||||
#t2 = false;
|
||||
{
|
||||
dynamic foo = #t4;
|
||||
{
|
||||
return foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(#t2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
static method test2(dynamic x) → dynamic {
|
||||
final dynamic #t5 = x;
|
||||
final core::bool #t6 = true;
|
||||
final dynamic #t7 = #t5;
|
||||
if(#t7 is self::C<core::String, core::String>) {
|
||||
final core::String #t8 = #t7{self::C<core::String, core::String>}.{self::C::x}{core::String};
|
||||
#t6 = false;
|
||||
{
|
||||
dynamic x = #t8;
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(#t6) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
static method main() → dynamic {
|
||||
self::expectEquals(0, self::test1(new self::A::•(0)));
|
||||
self::expectEquals(1, self::test1(new self::A::•(1)));
|
||||
self::expectEquals(null, self::test1(null));
|
||||
self::expectEquals("one", self::test2(new self::C::•<core::String, core::String>("one", "two")));
|
||||
self::expectEquals("one", self::test2(new self::C::•<core::String, core::String>("one", "two")));
|
||||
self::expectEquals(null, self::test2(null));
|
||||
}
|
||||
static method expectEquals(dynamic x, dynamic y) → dynamic {
|
||||
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
|
||||
throw "Expected ${x} to be equal to ${y}.";
|
||||
}
|
||||
}
|
||||
static method _#D#new#tearOff<X extends core::Object? = dynamic>(self::_#D#new#tearOff::X% x, self::_#D#new#tearOff::X% y) → self::C<self::_#D#new#tearOff::X%, self::_#D#new#tearOff::X%>
|
||||
return new self::C::•<self::_#D#new#tearOff::X%, self::_#D#new#tearOff::X%>(x, y);
|
|
@ -0,0 +1,70 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
typedef B = self::A;
|
||||
typedef D<X extends core::Object? = dynamic> = self::C<X%, X%>;
|
||||
class A extends core::Object {
|
||||
field core::int foo;
|
||||
constructor •(core::int foo) → self::A
|
||||
: self::A::foo = foo, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
|
||||
covariant-by-class field self::C::X% x;
|
||||
covariant-by-class field self::C::Y% y;
|
||||
constructor •(self::C::X% x, self::C::Y% y) → self::C<self::C::X%, self::C::Y%>
|
||||
: self::C::x = x, self::C::y = y, super core::Object::•()
|
||||
;
|
||||
}
|
||||
static method test1(dynamic x) → dynamic {
|
||||
final dynamic #t1 = x;
|
||||
final core::bool #t2 = true;
|
||||
final dynamic #t3 = #t1;
|
||||
if(#t3 is self::A) {
|
||||
final core::int #t4 = #t3{self::A}.{self::A::foo}{core::int};
|
||||
#t2 = false;
|
||||
{
|
||||
dynamic foo = #t4;
|
||||
{
|
||||
return foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(#t2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
static method test2(dynamic x) → dynamic {
|
||||
final dynamic #t5 = x;
|
||||
final core::bool #t6 = true;
|
||||
final dynamic #t7 = #t5;
|
||||
if(#t7 is self::C<core::String, core::String>) {
|
||||
final core::String #t8 = #t7{self::C<core::String, core::String>}.{self::C::x}{core::String};
|
||||
#t6 = false;
|
||||
{
|
||||
dynamic x = #t8;
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(#t6) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
static method main() → dynamic {
|
||||
self::expectEquals(0, self::test1(new self::A::•(0)));
|
||||
self::expectEquals(1, self::test1(new self::A::•(1)));
|
||||
self::expectEquals(null, self::test1(null));
|
||||
self::expectEquals("one", self::test2(new self::C::•<core::String, core::String>("one", "two")));
|
||||
self::expectEquals("one", self::test2(new self::C::•<core::String, core::String>("one", "two")));
|
||||
self::expectEquals(null, self::test2(null));
|
||||
}
|
||||
static method expectEquals(dynamic x, dynamic y) → dynamic {
|
||||
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
|
||||
throw "Expected ${x} to be equal to ${y}.";
|
||||
}
|
||||
}
|
||||
static method _#D#new#tearOff<X extends core::Object? = dynamic>(self::_#D#new#tearOff::X% x, self::_#D#new#tearOff::X% y) → self::C<self::_#D#new#tearOff::X%, self::_#D#new#tearOff::X%>
|
||||
return new self::C::•<self::_#D#new#tearOff::X%, self::_#D#new#tearOff::X%>(x, y);
|
|
@ -0,0 +1,27 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
typedef B = self::A;
|
||||
typedef D<X extends core::Object? = dynamic> = self::C<X%, X%>;
|
||||
class A extends core::Object {
|
||||
field core::int foo;
|
||||
constructor •(core::int foo) → self::A
|
||||
;
|
||||
}
|
||||
class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
|
||||
covariant-by-class field self::C::X% x;
|
||||
covariant-by-class field self::C::Y% y;
|
||||
constructor •(self::C::X% x, self::C::Y% y) → self::C<self::C::X%, self::C::Y%>
|
||||
;
|
||||
}
|
||||
static method test1(dynamic x) → dynamic
|
||||
;
|
||||
static method test2(dynamic x) → dynamic
|
||||
;
|
||||
static method main() → dynamic
|
||||
;
|
||||
static method expectEquals(dynamic x, dynamic y) → dynamic
|
||||
;
|
||||
static method _#D#new#tearOff<X extends core::Object? = dynamic>(self::_#D#new#tearOff::X% x, self::_#D#new#tearOff::X% y) → self::C<self::_#D#new#tearOff::X%, self::_#D#new#tearOff::X%>
|
||||
return new self::C::•<self::_#D#new#tearOff::X%, self::_#D#new#tearOff::X%>(x, y);
|
|
@ -0,0 +1,70 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
typedef B = self::A;
|
||||
typedef D<X extends core::Object? = dynamic> = self::C<X%, X%>;
|
||||
class A extends core::Object {
|
||||
field core::int foo;
|
||||
constructor •(core::int foo) → self::A
|
||||
: self::A::foo = foo, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
|
||||
covariant-by-class field self::C::X% x;
|
||||
covariant-by-class field self::C::Y% y;
|
||||
constructor •(self::C::X% x, self::C::Y% y) → self::C<self::C::X%, self::C::Y%>
|
||||
: self::C::x = x, self::C::y = y, super core::Object::•()
|
||||
;
|
||||
}
|
||||
static method test1(dynamic x) → dynamic {
|
||||
final dynamic #t1 = x;
|
||||
final core::bool #t2 = true;
|
||||
final dynamic #t3 = #t1;
|
||||
if(#t3 is self::A) {
|
||||
final core::int #t4 = #t3{self::A}.{self::A::foo}{core::int};
|
||||
#t2 = false;
|
||||
{
|
||||
dynamic foo = #t4;
|
||||
{
|
||||
return foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(#t2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
static method test2(dynamic x) → dynamic {
|
||||
final dynamic #t5 = x;
|
||||
final core::bool #t6 = true;
|
||||
final dynamic #t7 = #t5;
|
||||
if(#t7 is self::C<core::String, core::String>) {
|
||||
final core::String #t8 = #t7{self::C<core::String, core::String>}.{self::C::x}{core::String};
|
||||
#t6 = false;
|
||||
{
|
||||
dynamic x = #t8;
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(#t6) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
static method main() → dynamic {
|
||||
self::expectEquals(0, self::test1(new self::A::•(0)));
|
||||
self::expectEquals(1, self::test1(new self::A::•(1)));
|
||||
self::expectEquals(null, self::test1(null));
|
||||
self::expectEquals("one", self::test2(new self::C::•<core::String, core::String>("one", "two")));
|
||||
self::expectEquals("one", self::test2(new self::C::•<core::String, core::String>("one", "two")));
|
||||
self::expectEquals(null, self::test2(null));
|
||||
}
|
||||
static method expectEquals(dynamic x, dynamic y) → dynamic {
|
||||
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
|
||||
throw "Expected ${x} to be equal to ${y}.";
|
||||
}
|
||||
}
|
||||
static method _#D#new#tearOff<X extends core::Object? = dynamic>(self::_#D#new#tearOff::X% x, self::_#D#new#tearOff::X% y) → self::C<self::_#D#new#tearOff::X%, self::_#D#new#tearOff::X%>
|
||||
return new self::C::•<self::_#D#new#tearOff::X%, self::_#D#new#tearOff::X%>(x, y);
|
Loading…
Reference in a new issue