mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
[cfe] Make IfNullJudgment an internal expression
Change-Id: I68c81e10692823e9fad552272167c0bf87144db4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/117942 Reviewed-by: Jens Johansen <jensj@google.com>
This commit is contained in:
parent
2777806901
commit
2b3541da57
26 changed files with 96 additions and 74 deletions
|
@ -108,6 +108,8 @@ import 'kernel_api.dart';
|
|||
|
||||
import 'kernel_ast_api.dart';
|
||||
|
||||
import 'kernel_shadow_ast.dart';
|
||||
|
||||
import 'kernel_builder.dart';
|
||||
|
||||
// TODO(ahe): Remove this and ensure all nodes have a location.
|
||||
|
@ -1517,16 +1519,7 @@ class BodyBuilder extends ScopeListener<JumpTarget>
|
|||
void doIfNull(Token token) {
|
||||
Expression b = popForValue();
|
||||
Expression a = popForValue();
|
||||
VariableDeclaration variable = new VariableDeclaration.forValue(a);
|
||||
push(new IfNullJudgment(
|
||||
variable,
|
||||
forest.createConditionalExpression(
|
||||
buildIsNull(new VariableGet(variable), offsetForToken(token), this),
|
||||
token,
|
||||
b,
|
||||
null,
|
||||
new VariableGet(variable)))
|
||||
..fileOffset = offsetForToken(token));
|
||||
push(new IfNullExpression(a, b)..fileOffset = offsetForToken(token));
|
||||
}
|
||||
|
||||
/// Handle `a?.b(...)`.
|
||||
|
|
|
@ -49,6 +49,8 @@ class InferenceVisitor
|
|||
return visitCompoundSuperIndexSet(node, typeContext);
|
||||
case InternalExpressionKind.DeferredCheck:
|
||||
return visitDeferredCheck(node, typeContext);
|
||||
case InternalExpressionKind.IfNull:
|
||||
return visitIfNull(node, typeContext);
|
||||
case InternalExpressionKind.IfNullIndexSet:
|
||||
return visitIfNullIndexSet(node, typeContext);
|
||||
case InternalExpressionKind.IfNullPropertySet:
|
||||
|
@ -684,13 +686,17 @@ class InferenceVisitor
|
|||
skipTypeArgumentInference: true);
|
||||
}
|
||||
|
||||
ExpressionInferenceResult visitIfNullJudgment(
|
||||
IfNullJudgment node, DartType typeContext) {
|
||||
ExpressionInferenceResult visitIfNull(
|
||||
IfNullExpression node, DartType typeContext) {
|
||||
// To infer `e0 ?? e1` in context K:
|
||||
// - Infer e0 in context K to get T0
|
||||
DartType lhsType =
|
||||
inferrer.inferExpression(node.left, typeContext, true).inferredType;
|
||||
node.variable.type = lhsType;
|
||||
|
||||
Member equalsMember = inferrer
|
||||
.findInterfaceMember(lhsType, equalsName, node.fileOffset)
|
||||
.member;
|
||||
|
||||
// - Let J = T0 if K is `?` else K.
|
||||
// - Infer e1 in context J to get T1
|
||||
DartType rhsType;
|
||||
|
@ -708,8 +714,15 @@ class InferenceVisitor
|
|||
// - Then the inferred type is T.
|
||||
DartType inferredType =
|
||||
inferrer.typeSchemaEnvironment.getStandardUpperBound(lhsType, rhsType);
|
||||
node.body.staticType = inferredType;
|
||||
return new ExpressionInferenceResult(inferredType);
|
||||
VariableDeclaration variable = createVariable(node.left, lhsType);
|
||||
MethodInvocation equalsNull = createEqualsNull(
|
||||
node.left.fileOffset, createVariableGet(variable), equalsMember);
|
||||
ConditionalExpression conditional = new ConditionalExpression(
|
||||
equalsNull, node.right, createVariableGet(variable), inferredType);
|
||||
Expression replacement = new Let(variable, conditional)
|
||||
..fileOffset = node.fileOffset;
|
||||
node.replaceWith(replacement);
|
||||
return new ExpressionInferenceResult(inferredType, replacement);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -89,7 +89,6 @@ export 'kernel_shadow_ast.dart'
|
|||
DeferredCheck,
|
||||
FactoryConstructorInvocationJudgment,
|
||||
FunctionDeclarationImpl,
|
||||
IfNullJudgment,
|
||||
InvalidSuperInitializerJudgment,
|
||||
LoadLibraryTearOff,
|
||||
MethodInvocationImpl,
|
||||
|
|
|
@ -188,6 +188,7 @@ enum InternalExpressionKind {
|
|||
CompoundPropertySet,
|
||||
CompoundSuperIndexSet,
|
||||
DeferredCheck,
|
||||
IfNull,
|
||||
IfNullIndexSet,
|
||||
IfNullPropertySet,
|
||||
IfNullSet,
|
||||
|
@ -495,29 +496,40 @@ class InvalidSuperInitializerJudgment extends LocalInitializer
|
|||
}
|
||||
}
|
||||
|
||||
/// Concrete shadow object representing an if-null expression.
|
||||
/// Internal expression representing an if-null expression.
|
||||
///
|
||||
/// An if-null expression of the form `a ?? b` is represented as the kernel
|
||||
/// expression:
|
||||
/// An if-null expression of the form `a ?? b` is encoded as:
|
||||
///
|
||||
/// let v = a in v == null ? b : v
|
||||
class IfNullJudgment extends Let implements ExpressionJudgment {
|
||||
IfNullJudgment(VariableDeclaration variable, Expression body)
|
||||
: super(variable, body);
|
||||
///
|
||||
class IfNullExpression extends InternalExpression {
|
||||
Expression left;
|
||||
Expression right;
|
||||
|
||||
IfNullExpression(this.left, this.right) {
|
||||
left?.parent = this;
|
||||
right?.parent = this;
|
||||
}
|
||||
|
||||
@override
|
||||
ConditionalExpression get body => super.body;
|
||||
|
||||
/// Returns the expression to the left of `??`.
|
||||
Expression get left => variable.initializer;
|
||||
|
||||
/// Returns the expression to the right of `??`.
|
||||
Expression get right => body.then;
|
||||
InternalExpressionKind get kind => InternalExpressionKind.IfNull;
|
||||
|
||||
@override
|
||||
ExpressionInferenceResult acceptInference(
|
||||
InferenceVisitor visitor, DartType typeContext) {
|
||||
return visitor.visitIfNullJudgment(this, typeContext);
|
||||
void visitChildren(Visitor<dynamic> v) {
|
||||
left?.accept(v);
|
||||
right?.accept(v);
|
||||
}
|
||||
|
||||
@override
|
||||
void transformChildren(Transformer v) {
|
||||
if (left != null) {
|
||||
left = left.accept<TreeNode>(v);
|
||||
left?.parent = this;
|
||||
}
|
||||
if (right != null) {
|
||||
right = right.accept<TreeNode>(v);
|
||||
right?.parent = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,6 @@ static method main() → dynamic {
|
|||
self::Foo::staticField.{core::num::==}(null) ?{core::int*} self::Foo::staticField = 5 : null;
|
||||
let final self::Foo* #t3 = foo in #t3.{core::Object::==}(null) ?{core::int*} null : #t3.{self::Foo::field}.{core::num::==}(null) ?{core::int*} #t3.{self::Foo::field} = 5 : null;
|
||||
self::Foo::staticField.{core::num::==}(null) ?{core::int*} self::Foo::staticField = 5 : null;
|
||||
core::int* intValue = let final core::int* #t4 = foo.{self::Foo::field} in #t4.==(null) ?{core::int*} 6 : #t4;
|
||||
core::num* numValue = let final core::int* #t5 = foo.{self::Foo::field} in #t5.==(null) ?{core::num*} 4.5 : #t5;
|
||||
core::int* intValue = let final core::int* #t4 = foo.{self::Foo::field} in #t4.{core::num::==}(null) ?{core::int*} 6 : #t4;
|
||||
core::num* numValue = let final core::int* #t5 = foo.{self::Foo::field} in #t5.{core::num::==}(null) ?{core::num*} 4.5 : #t5;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,6 @@ static method main() → dynamic {
|
|||
self::Foo::staticField.{core::num::==}(null) ?{core::int*} self::Foo::staticField = 5 : null;
|
||||
let final self::Foo* #t3 = foo in #t3.{core::Object::==}(null) ?{core::int*} null : #t3.{self::Foo::field}.{core::num::==}(null) ?{core::int*} #t3.{self::Foo::field} = 5 : null;
|
||||
self::Foo::staticField.{core::num::==}(null) ?{core::int*} self::Foo::staticField = 5 : null;
|
||||
core::int* intValue = let final core::int* #t4 = foo.{self::Foo::field} in #t4.==(null) ?{core::int*} 6 : #t4;
|
||||
core::num* numValue = let final core::int* #t5 = foo.{self::Foo::field} in #t5.==(null) ?{core::num*} 4.5 : #t5;
|
||||
core::int* intValue = let final core::int* #t4 = foo.{self::Foo::field} in #t4.{core::num::==}(null) ?{core::int*} 6 : #t4;
|
||||
core::num* numValue = let final core::int* #t5 = foo.{self::Foo::field} in #t5.{core::num::==}(null) ?{core::num*} 4.5 : #t5;
|
||||
}
|
||||
|
|
|
@ -9,20 +9,21 @@ void foo<E>(C<E> c, int cmp(E a, E b)) {}
|
|||
|
||||
class C<E> {
|
||||
void barA([int cmp(E a, E b)]) {
|
||||
/*@ typeArgs=C::E* */ foo(this, cmp ?? _default);
|
||||
/*@ typeArgs=C::E* */ foo(this, cmp /*@ target=Object::== */ ?? _default);
|
||||
}
|
||||
|
||||
void barB([int cmp(E a, E b)]) {
|
||||
/*@ typeArgs=C::E* */ foo(this, cmp ?? (_default as int Function(E, E)));
|
||||
/*@ typeArgs=C::E* */ foo(
|
||||
this, cmp /*@ target=Object::== */ ?? (_default as int Function(E, E)));
|
||||
}
|
||||
|
||||
void barC([int cmp(E a, E b)]) {
|
||||
int Function(E, E) v = _default;
|
||||
/*@ typeArgs=C::E* */ foo(this, cmp ?? v);
|
||||
/*@ typeArgs=C::E* */ foo(this, cmp /*@ target=Object::== */ ?? v);
|
||||
}
|
||||
|
||||
void barD([int cmp(E a, E b)]) {
|
||||
foo<E>(this, cmp ?? _default);
|
||||
foo<E>(this, cmp /*@ target=Object::== */ ?? _default);
|
||||
}
|
||||
|
||||
void barE([int cmp(E a, E b)]) {
|
||||
|
|
|
@ -7,17 +7,17 @@ class C<E extends core::Object* = dynamic> extends core::Object {
|
|||
: super core::Object::•()
|
||||
;
|
||||
method barA([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = cmp in #t1.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = cmp in #t1.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
|
||||
}
|
||||
method barB([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t2 = cmp in #t2.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} (#C2) as (self::C::E*, self::C::E*) →* core::int* : #t2);
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t2 = cmp in #t2.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} (#C2) as (self::C::E*, self::C::E*) →* core::int* : #t2);
|
||||
}
|
||||
method barC([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
|
||||
(self::C::E*, self::C::E*) →* core::int* v = #C2;
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t3 = cmp in #t3.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} v : #t3);
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t3 = cmp in #t3.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} v : #t3);
|
||||
}
|
||||
method barD([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t4 = cmp in #t4.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t4);
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t4 = cmp in #t4.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t4);
|
||||
}
|
||||
method barE([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
|
||||
self::foo<self::C::E*>(this, cmp.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : cmp);
|
||||
|
|
|
@ -7,17 +7,17 @@ class C<E extends core::Object* = dynamic> extends core::Object {
|
|||
: super core::Object::•()
|
||||
;
|
||||
method barA([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = cmp in #t1.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = cmp in #t1.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
|
||||
}
|
||||
method barB([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t2 = cmp in #t2.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} (#C2) as (self::C::E*, self::C::E*) →* core::int* : #t2);
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t2 = cmp in #t2.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} (#C2) as (self::C::E*, self::C::E*) →* core::int* : #t2);
|
||||
}
|
||||
method barC([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
|
||||
(self::C::E*, self::C::E*) →* core::int* v = #C2;
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t3 = cmp in #t3.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} v : #t3);
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t3 = cmp in #t3.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} v : #t3);
|
||||
}
|
||||
method barD([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t4 = cmp in #t4.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t4);
|
||||
self::foo<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t4 = cmp in #t4.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t4);
|
||||
}
|
||||
method barE([(self::C::E*, self::C::E*) →* core::int* cmp = #C1]) → void {
|
||||
self::foo<self::C::E*>(this, cmp.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : cmp);
|
||||
|
|
|
@ -12,7 +12,7 @@ void main() {
|
|||
var /*@ type=Iterable<List<String*>*>* */ i1 =
|
||||
l. /*@target=Iterable::map*/ /*@ typeArgs=List<String*>* */ map(
|
||||
/*@ returnType=List<String*>* */ (/*@ type=List<String*>* */ ll) =>
|
||||
ll ?? /*@ typeArgs=String* */ []);
|
||||
ll /*@ target=List::== */ ?? /*@ typeArgs=String* */ []);
|
||||
var /*@ type=Iterable<int*>* */ i2 =
|
||||
i1. /*@target=Iterable::map*/ /*@ typeArgs=int* */ map(
|
||||
/*@ returnType=int* */ (List<String> l) =>
|
||||
|
|
|
@ -4,7 +4,7 @@ import "dart:core" as core;
|
|||
|
||||
static method main() → void {
|
||||
core::List<core::List<core::String*>*>* l = <core::List<core::String*>*>[<core::String*>["hi", "world"]];
|
||||
core::Iterable<core::List<core::String*>*>* i1 = l.{core::Iterable::map}<core::List<core::String*>*>((core::List<core::String*>* ll) → core::List<core::String*>* => let final core::List<core::String*>* #t1 = ll in #t1.==(null) ?{core::List<core::String*>*} <core::String*>[] : #t1);
|
||||
core::Iterable<core::List<core::String*>*>* i1 = l.{core::Iterable::map}<core::List<core::String*>*>((core::List<core::String*>* ll) → core::List<core::String*>* => let final core::List<core::String*>* #t1 = ll in #t1.{core::List::==}(null) ?{core::List<core::String*>*} <core::String*>[] : #t1);
|
||||
core::Iterable<core::int*>* i2 = i1.{core::Iterable::map}<core::int*>((core::List<core::String*>* l) → core::int* => l.{core::List::length});
|
||||
core::print(i2);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import "dart:core" as core;
|
|||
|
||||
static method main() → void {
|
||||
core::List<core::List<core::String*>*>* l = <core::List<core::String*>*>[<core::String*>["hi", "world"]];
|
||||
core::Iterable<core::List<core::String*>*>* i1 = l.{core::Iterable::map}<core::List<core::String*>*>((core::List<core::String*>* ll) → core::List<core::String*>* => let final core::List<core::String*>* #t1 = ll in #t1.==(null) ?{core::List<core::String*>*} <core::String*>[] : #t1);
|
||||
core::Iterable<core::List<core::String*>*>* i1 = l.{core::Iterable::map}<core::List<core::String*>*>((core::List<core::String*>* ll) → core::List<core::String*>* => let final core::List<core::String*>* #t1 = ll in #t1.{core::List::==}(null) ?{core::List<core::String*>*} <core::String*>[] : #t1);
|
||||
core::Iterable<core::int*>* i2 = i1.{core::Iterable::map}<core::int*>((core::List<core::String*>* l) → core::int* => l.{core::List::length});
|
||||
core::print(i2);
|
||||
}
|
||||
|
|
|
@ -18,18 +18,20 @@ void test() {
|
|||
MyFuture<int> f;
|
||||
Future<int> t1 = f. /*@ typeArgs=int* */ /*@target=MyFuture::then*/ then(
|
||||
/*@ returnType=Future<int*>* */ (/*@ type=int* */ x) async =>
|
||||
x ?? await new Future<int>.value(3));
|
||||
x /*@ target=num::== */ ?? await new Future<int>.value(3));
|
||||
Future<int> t2 = f. /*@ typeArgs=int* */ /*@target=MyFuture::then*/ then(
|
||||
/*@ returnType=Future<int*>* */ (/*@ type=int* */ x) async {
|
||||
return /*info:DOWN_CAST_COMPOSITE*/ await x ?? new Future<int>.value(3);
|
||||
return /*info:DOWN_CAST_COMPOSITE*/ await x /*@ target=num::== */ ??
|
||||
new Future<int>.value(3);
|
||||
});
|
||||
Future<int> t5 = f. /*@ typeArgs=int* */ /*@target=MyFuture::then*/ then(
|
||||
/*error:INVALID_CAST_FUNCTION_EXPR*/
|
||||
/*@ returnType=FutureOr<int*>* */ (/*@ type=int* */ x) =>
|
||||
x ?? new Future<int>.value(3));
|
||||
x /*@ target=num::== */ ?? new Future<int>.value(3));
|
||||
Future<int> t6 = f. /*@ typeArgs=int* */ /*@target=MyFuture::then*/ then(
|
||||
/*@ returnType=FutureOr<int*>* */ (/*@ type=int* */ x) {
|
||||
return /*info:DOWN_CAST_COMPOSITE*/ x ?? new Future<int>.value(3);
|
||||
return /*info:DOWN_CAST_COMPOSITE*/ x /*@ target=num::== */ ??
|
||||
new Future<int>.value(3);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -25,13 +25,13 @@ class MyFuture<T extends core::Object* = dynamic> extends core::Object implement
|
|||
}
|
||||
static method test() → void {
|
||||
self::MyFuture<core::int*>* f;
|
||||
asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::Future<core::int*>* async => let final core::int* #t1 = x in #t1.==(null) ?{core::int*} await asy::Future::value<core::int*>(3) : #t1);
|
||||
asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::Future<core::int*>* async => let final core::int* #t1 = x in #t1.{core::num::==}(null) ?{core::int*} await asy::Future::value<core::int*>(3) : #t1);
|
||||
asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::Future<core::int*>* async {
|
||||
return (let final core::int* #t2 = await x in #t2.==(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t2) as{TypeError} asy::FutureOr<core::int*>*;
|
||||
return (let final core::int* #t2 = await x in #t2.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t2) as{TypeError} asy::FutureOr<core::int*>*;
|
||||
});
|
||||
asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::FutureOr<core::int*>* => (let final core::int* #t3 = x in #t3.==(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t3) as{TypeError} asy::FutureOr<core::int*>*);
|
||||
asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::FutureOr<core::int*>* => (let final core::int* #t3 = x in #t3.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t3) as{TypeError} asy::FutureOr<core::int*>*);
|
||||
asy::Future<core::int*>* t6 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::FutureOr<core::int*>* {
|
||||
return (let final core::int* #t4 = x in #t4.==(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t4) as{TypeError} asy::FutureOr<core::int*>*;
|
||||
return (let final core::int* #t4 = x in #t4.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t4) as{TypeError} asy::FutureOr<core::int*>*;
|
||||
});
|
||||
}
|
||||
static method main() → dynamic {}
|
||||
|
|
|
@ -40,7 +40,7 @@ static method test() → void {
|
|||
#L1:
|
||||
{
|
||||
final core::int* #t1 = x;
|
||||
if(#t1.==(null)) {
|
||||
if(#t1.{core::num::==}(null)) {
|
||||
[yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
|
||||
:async_temporary_0 = :result;
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ static method test() → void {
|
|||
#L2:
|
||||
{
|
||||
[yield] let dynamic #t3 = asy::_awaitHelper(x, :async_op_then, :async_op_error, :async_op) in null;
|
||||
:return_value = (let final core::int* #t4 = :result in #t4.==(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t4) as{TypeError} asy::FutureOr<core::int*>*;
|
||||
:return_value = (let final core::int* #t4 = :result in #t4.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t4) as{TypeError} asy::FutureOr<core::int*>*;
|
||||
break #L2;
|
||||
}
|
||||
asy::_completeOnAsyncReturn(:async_completer, :return_value);
|
||||
|
@ -91,9 +91,9 @@ static method test() → void {
|
|||
:async_completer.start(:async_op);
|
||||
return :async_completer.{asy::Completer::future};
|
||||
});
|
||||
asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::FutureOr<core::int*>* => (let final core::int* #t5 = x in #t5.==(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t5) as{TypeError} asy::FutureOr<core::int*>*);
|
||||
asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::FutureOr<core::int*>* => (let final core::int* #t5 = x in #t5.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t5) as{TypeError} asy::FutureOr<core::int*>*);
|
||||
asy::Future<core::int*>* t6 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::FutureOr<core::int*>* {
|
||||
return (let final core::int* #t6 = x in #t6.==(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t6) as{TypeError} asy::FutureOr<core::int*>*;
|
||||
return (let final core::int* #t6 = x in #t6.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t6) as{TypeError} asy::FutureOr<core::int*>*;
|
||||
});
|
||||
}
|
||||
static method main() → dynamic {}
|
||||
|
|
|
@ -7,7 +7,8 @@ library test;
|
|||
|
||||
abstract class C<E> {
|
||||
void sort([int compare(E a, E b)]) {
|
||||
/*@ typeArgs=C::E* */ sort2(this, compare ?? _compareAny);
|
||||
/*@ typeArgs=C::E* */ sort2(
|
||||
this, compare /*@ target=Object::== */ ?? _compareAny);
|
||||
}
|
||||
|
||||
static int _compareAny(a, b) {
|
||||
|
|
|
@ -7,7 +7,7 @@ abstract class C<E extends core::Object* = dynamic> extends core::Object {
|
|||
: super core::Object::•()
|
||||
;
|
||||
method sort([(self::C::E*, self::C::E*) →* core::int* compare = #C1]) → void {
|
||||
self::C::sort2<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = compare in #t1.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
|
||||
self::C::sort2<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = compare in #t1.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
|
||||
}
|
||||
static method _compareAny(dynamic a, dynamic b) → core::int* {
|
||||
throw "unimplemented";
|
||||
|
|
|
@ -7,7 +7,7 @@ abstract class C<E extends core::Object* = dynamic> extends core::Object {
|
|||
: super core::Object::•()
|
||||
;
|
||||
method sort([(self::C::E*, self::C::E*) →* core::int* compare = #C1]) → void {
|
||||
self::C::sort2<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = compare in #t1.==(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
|
||||
self::C::sort2<self::C::E*>(this, let final (self::C::E*, self::C::E*) →* core::int* #t1 = compare in #t1.{core::Object::==}(null) ?{(self::C::E*, self::C::E*) →* core::int*} #C2 : #t1);
|
||||
}
|
||||
static method _compareAny(dynamic a, dynamic b) → core::int* {
|
||||
throw "unimplemented";
|
||||
|
|
|
@ -7,6 +7,7 @@ library test;
|
|||
|
||||
main() {
|
||||
List<int> x;
|
||||
var /*@ type=List<int*>* */ y = x ?? /*@ typeArgs=int* */ [];
|
||||
var /*@ type=List<int*>* */ y =
|
||||
x /*@ target=List::== */ ?? /*@ typeArgs=int* */ [];
|
||||
List<int> z = y;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@ import "dart:core" as core;
|
|||
|
||||
static method main() → dynamic {
|
||||
core::List<core::int*>* x;
|
||||
core::List<core::int*>* y = let final core::List<core::int*>* #t1 = x in #t1.==(null) ?{core::List<core::int*>*} <core::int*>[] : #t1;
|
||||
core::List<core::int*>* y = let final core::List<core::int*>* #t1 = x in #t1.{core::List::==}(null) ?{core::List<core::int*>*} <core::int*>[] : #t1;
|
||||
core::List<core::int*>* z = y;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@ import "dart:core" as core;
|
|||
|
||||
static method main() → dynamic {
|
||||
core::List<core::int*>* x;
|
||||
core::List<core::int*>* y = let final core::List<core::int*>* #t1 = x in #t1.==(null) ?{core::List<core::int*>*} <core::int*>[] : #t1;
|
||||
core::List<core::int*>* y = let final core::List<core::int*>* #t1 = x in #t1.{core::List::==}(null) ?{core::List<core::int*>*} <core::int*>[] : #t1;
|
||||
core::List<core::int*>* z = y;
|
||||
}
|
||||
|
|
|
@ -7,5 +7,5 @@ library test;
|
|||
|
||||
main() {
|
||||
List<int> x;
|
||||
List<num> y = x ?? /*@ typeArgs=num* */ [];
|
||||
List<num> y = x /*@ target=List::== */ ?? /*@ typeArgs=num* */ [];
|
||||
}
|
||||
|
|
|
@ -4,5 +4,5 @@ import "dart:core" as core;
|
|||
|
||||
static method main() → dynamic {
|
||||
core::List<core::int*>* x;
|
||||
core::List<core::num*>* y = let final core::List<core::int*>* #t1 = x in #t1.==(null) ?{core::List<core::num*>*} <core::num*>[] : #t1;
|
||||
core::List<core::num*>* y = let final core::List<core::int*>* #t1 = x in #t1.{core::List::==}(null) ?{core::List<core::num*>*} <core::num*>[] : #t1;
|
||||
}
|
||||
|
|
|
@ -4,5 +4,5 @@ import "dart:core" as core;
|
|||
|
||||
static method main() → dynamic {
|
||||
core::List<core::int*>* x;
|
||||
core::List<core::num*>* y = let final core::List<core::int*>* #t1 = x in #t1.==(null) ?{core::List<core::num*>*} <core::num*>[] : #t1;
|
||||
core::List<core::num*>* y = let final core::List<core::int*>* #t1 = x in #t1.{core::List::==}(null) ?{core::List<core::num*>*} <core::num*>[] : #t1;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ static method main() → dynamic {
|
|||
self::test_nullable_function_type_formal_param(f: () → core::int => 2);
|
||||
}
|
||||
static method test_nullable_function_type_formal_param({() →? core::int f = #C1}) → core::int {
|
||||
return let final core::int #t1 = f.call() in #t1.==(null) ?{core::int*} 1.{core::int::unary-}() : #t1;
|
||||
return let final core::int #t1 = f.call() in #t1.{core::num::==}(null) ?{core::int*} 1.{core::int::unary-}() : #t1;
|
||||
}
|
||||
|
||||
constants {
|
||||
|
|
|
@ -33,7 +33,7 @@ static method main() → dynamic {
|
|||
self::test_nullable_function_type_formal_param(f: () → core::int => 2);
|
||||
}
|
||||
static method test_nullable_function_type_formal_param({() →? core::int f = #C1}) → core::int {
|
||||
return let final core::int #t1 = f.call() in #t1.==(null) ?{core::int*} 1.{core::int::unary-}() : #t1;
|
||||
return let final core::int #t1 = f.call() in #t1.{core::num::==}(null) ?{core::int*} 1.{core::int::unary-}() : #t1;
|
||||
}
|
||||
|
||||
constants {
|
||||
|
|
Loading…
Reference in a new issue