Skip to content

Commit ecef1a0

Browse files
chloestefantsovaCommit Queue
authored and
Commit Queue
committed
[cfe] Implement dispatchPatternSchema
Part of #49749 Change-Id: I9fa3ad41501422990d47bc637d46cbd22fdb54fb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/277004 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Chloe Stefantsova <[email protected]>
1 parent 638ca5c commit ecef1a0

11 files changed

+295
-9
lines changed

pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart

+57-5
Original file line numberDiff line numberDiff line change
@@ -9606,11 +9606,63 @@ class InferenceVisitorImpl extends InferenceVisitorBase
96069606
}
96079607

96089608
@override
9609-
DartType dispatchPatternSchema(TreeNode node) {
9610-
// The front end's representation of a switch cases currently doesn't have
9611-
// any support for patterns; each case is represented as an expression. So
9612-
// analyze it as a constant pattern.
9613-
return analyzeConstantPatternSchema();
9609+
DartType dispatchPatternSchema(Node node) {
9610+
if (node is AndPattern) {
9611+
return analyzeLogicalAndPatternSchema(node.left, node.right);
9612+
} else if (node is AssignedVariablePattern) {
9613+
return analyzeAssignedVariablePatternSchema(node.variable);
9614+
} else if (node is CastPattern) {
9615+
return analyzeCastPatternSchema();
9616+
} else if (node is ConstantPattern) {
9617+
return analyzeConstantPatternSchema();
9618+
} else if (node is ListPattern) {
9619+
return analyzeListPatternSchema(
9620+
elementType: node.typeArgument, elements: node.patterns);
9621+
} else if (node is MapPattern) {
9622+
return analyzeMapPatternSchema(
9623+
typeArguments: node.keyType != null && node.valueType != null
9624+
? new MapPatternTypeArguments<DartType>(
9625+
keyType: node.keyType!, valueType: node.valueType!)
9626+
: null,
9627+
elements: node.entries);
9628+
} else if (node is NamedPattern) {
9629+
return dispatchPatternSchema(node.pattern);
9630+
} else if (node is NullAssertPattern) {
9631+
return analyzeNullCheckOrAssertPatternSchema(node.pattern,
9632+
isAssert: true);
9633+
} else if (node is NullCheckPattern) {
9634+
return analyzeNullCheckOrAssertPatternSchema(node.pattern,
9635+
isAssert: false);
9636+
} else if (node is ObjectPattern) {
9637+
return analyzeObjectPatternSchema(node.type);
9638+
} else if (node is OrPattern) {
9639+
return analyzeLogicalOrPatternSchema(node.left, node.right);
9640+
} else if (node is RecordPattern) {
9641+
return analyzeRecordPatternSchema(
9642+
fields: <RecordPatternField<TreeNode, Pattern>>[
9643+
for (Pattern element in node.patterns)
9644+
if (element is NamedPattern)
9645+
new RecordPatternField<TreeNode, Pattern>(
9646+
node: element, name: element.name, pattern: element.pattern)
9647+
else
9648+
new RecordPatternField<TreeNode, Pattern>(
9649+
node: element, name: null, pattern: element)
9650+
]);
9651+
} else if (node is RelationalPattern) {
9652+
return analyzeRelationalPatternSchema();
9653+
} else if (node is RestPattern) {
9654+
// This pattern can't appear on it's own.
9655+
return const InvalidType();
9656+
} else if (node is VariablePattern) {
9657+
return analyzeDeclaredVariablePatternSchema(node.type);
9658+
} else if (node is WildcardPattern) {
9659+
return analyzeDeclaredVariablePatternSchema(node.type);
9660+
} else if (node is InvalidPattern) {
9661+
return const InvalidType();
9662+
} else {
9663+
return problems.unhandled("${node.runtimeType}", "dispatchPatternSchema",
9664+
node is TreeNode ? node.fileOffset : TreeNode.noOffset, helper.uri);
9665+
}
96149666
}
96159667

96169668
@override

pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart

+15-4
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,8 @@ class OperationsCfe
517517

518518
@override
519519
DartType glb(DartType type1, DartType type2) {
520-
throw new UnimplementedError('TODO(paulberry)');
520+
return typeEnvironment.getStandardLowerBound(type1, type2,
521+
isNonNullableByDefault: true);
521522
}
522523

523524
@override
@@ -546,7 +547,7 @@ class OperationsCfe
546547

547548
@override
548549
DartType makeNullable(DartType type) {
549-
throw new UnimplementedError('TODO(paulberry)');
550+
return type.withDeclaredNullability(Nullability.nullable);
550551
}
551552

552553
@override
@@ -600,8 +601,18 @@ class OperationsCfe
600601

601602
@override
602603
DartType? matchIterableType(DartType type) {
603-
// TODO(scheglov): implement matchIterableType
604-
throw new UnimplementedError('TODO(scheglov)');
604+
if (type is! InterfaceType) {
605+
return null;
606+
} else {
607+
InterfaceType? interfaceType = typeEnvironment.getTypeAsInstanceOf(type,
608+
typeEnvironment.coreTypes.iterableClass, typeEnvironment.coreTypes,
609+
isNonNullableByDefault: isNonNullableByDefault);
610+
if (interfaceType == null) {
611+
return null;
612+
} else {
613+
return interfaceType.typeArguments.single;
614+
}
615+
}
605616
}
606617
}
607618

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
class A {
6+
int get foo => 0;
7+
}
8+
9+
List<T> foo<T>(void Function(T) f) => throw 0;
10+
11+
test1() {
12+
var <A>[var x] = foo((a) => a.foo);
13+
}
14+
15+
test2() {
16+
var [var x, ...y] = foo((e) => e);
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "dart:_internal" as _in;
5+
6+
class A extends core::Object {
7+
synthetic constructor •() → self::A
8+
: super core::Object::•()
9+
;
10+
get foo() → core::int
11+
return 0;
12+
}
13+
static method foo<T extends core::Object? = dynamic>((self::foo::T%) → void f) → core::List<self::foo::T%>
14+
return throw 0;
15+
static method test1() → dynamic {
16+
self::A x;
17+
{
18+
final dynamic #0#0 = self::foo<self::A>((self::A a) → void => a.{self::A::foo}{core::int});
19+
if(!(#0#0{core::List<self::A>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t1 = x = #0#0{core::List<self::A>}.{core::List::[]}(0){(core::int) → self::A} in true)))
20+
throw new _in::ReachabilityError::•();
21+
}
22+
}
23+
static method test2() → dynamic {
24+
core::Object? x;
25+
core::List<core::Object?> y;
26+
{
27+
final dynamic #0#0 = self::foo<core::Object?>((core::Object? e) → void => e);
28+
if(!(#0#0{core::List<core::Object?>}.{core::List::length}{core::int}.{core::num::>=}(#C1){(core::num) → core::bool} && (let final dynamic #t2 = x = #0#0{core::List<core::Object?>}.{core::List::[]}(0){(core::int) → core::Object?} in true) && (let final dynamic #t3 = y = #0#0{core::List<core::Object?>}.{core::List::sublist}(1){(core::int, [core::int?]) → core::List<core::Object?>} in true)))
29+
throw new _in::ReachabilityError::•();
30+
}
31+
}
32+
33+
constants {
34+
#C1 = 1
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "dart:_internal" as _in;
5+
6+
class A extends core::Object {
7+
synthetic constructor •() → self::A
8+
: super core::Object::•()
9+
;
10+
get foo() → core::int
11+
return 0;
12+
}
13+
static method foo<T extends core::Object? = dynamic>((self::foo::T%) → void f) → core::List<self::foo::T%>
14+
return throw 0;
15+
static method test1() → dynamic {
16+
self::A x;
17+
{
18+
final dynamic #0#0 = self::foo<self::A>((self::A a) → void => a.{self::A::foo}{core::int});
19+
if(!(#0#0{core::List<self::A>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final self::A #t1 = x = #0#0{core::List<self::A>}.{core::List::[]}(0){(core::int) → self::A} in true)))
20+
throw new _in::ReachabilityError::•();
21+
}
22+
}
23+
static method test2() → dynamic {
24+
core::Object? x;
25+
core::List<core::Object?> y;
26+
{
27+
final dynamic #0#0 = self::foo<core::Object?>((core::Object? e) → void => e);
28+
if(!(#0#0{core::List<core::Object?>}.{core::List::length}{core::int}.{core::num::>=}(#C1){(core::num) → core::bool} && (let final core::Object? #t2 = x = #0#0{core::List<core::Object?>}.{core::List::[]}(0){(core::int) → core::Object?} in true) && (let final core::List<core::Object?> #t3 = y = #0#0{core::List<core::Object?>}.{core::List::sublist}(1){(core::int, [core::int?]) → core::List<core::Object?>} in true)))
29+
throw new _in::ReachabilityError::•();
30+
}
31+
}
32+
33+
constants {
34+
#C1 = 1
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class A {
2+
int get foo => 0;
3+
}
4+
5+
List<T> foo<T>(void Function(T) f) => throw 0;
6+
test1() {}
7+
test2() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
List<T> foo<T>(void Function(T) f) => throw 0;
2+
3+
class A {
4+
int get foo => 0;
5+
}
6+
7+
test1() {}
8+
test2() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "dart:_internal" as _in;
5+
6+
class A extends core::Object {
7+
synthetic constructor •() → self::A
8+
: super core::Object::•()
9+
;
10+
get foo() → core::int
11+
return 0;
12+
}
13+
static method foo<T extends core::Object? = dynamic>((self::foo::T%) → void f) → core::List<self::foo::T%>
14+
return throw 0;
15+
static method test1() → dynamic {
16+
self::A x;
17+
{
18+
final dynamic #0#0 = self::foo<self::A>((self::A a) → void => a.{self::A::foo}{core::int});
19+
if(!(#0#0{core::List<self::A>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t1 = x = #0#0{core::List<self::A>}.{core::List::[]}(0){(core::int) → self::A} in true)))
20+
throw new _in::ReachabilityError::•();
21+
}
22+
}
23+
static method test2() → dynamic {
24+
core::Object? x;
25+
core::List<core::Object?> y;
26+
{
27+
final dynamic #0#0 = self::foo<core::Object?>((core::Object? e) → void => e);
28+
if(!(#0#0{core::List<core::Object?>}.{core::List::length}{core::int}.{core::num::>=}(#C1){(core::num) → core::bool} && (let final dynamic #t2 = x = #0#0{core::List<core::Object?>}.{core::List::[]}(0){(core::int) → core::Object?} in true) && (let final dynamic #t3 = y = #0#0{core::List<core::Object?>}.{core::List::sublist}(1){(core::int, [core::int?]) → core::List<core::Object?>} in true)))
29+
throw new _in::ReachabilityError::•();
30+
}
31+
}
32+
33+
constants {
34+
#C1 = 1
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "dart:_internal" as _in;
5+
6+
class A extends core::Object {
7+
synthetic constructor •() → self::A
8+
: super core::Object::•()
9+
;
10+
get foo() → core::int
11+
return 0;
12+
}
13+
static method foo<T extends core::Object? = dynamic>((self::foo::T%) → void f) → core::List<self::foo::T%>
14+
return throw 0;
15+
static method test1() → dynamic {
16+
self::A x;
17+
{
18+
final dynamic #0#0 = self::foo<self::A>((self::A a) → void => a.{self::A::foo}{core::int});
19+
if(!(#0#0{core::List<self::A>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t1 = x = #0#0{core::List<self::A>}.{core::List::[]}(0){(core::int) → self::A} in true)))
20+
throw new _in::ReachabilityError::•();
21+
}
22+
}
23+
static method test2() → dynamic {
24+
core::Object? x;
25+
core::List<core::Object?> y;
26+
{
27+
final dynamic #0#0 = self::foo<core::Object?>((core::Object? e) → void => e);
28+
if(!(#0#0{core::List<core::Object?>}.{core::List::length}{core::int}.{core::num::>=}(#C1){(core::num) → core::bool} && (let final dynamic #t2 = x = #0#0{core::List<core::Object?>}.{core::List::[]}(0){(core::int) → core::Object?} in true) && (let final dynamic #t3 = y = #0#0{core::List<core::Object?>}.{core::List::sublist}(1){(core::int, [core::int?]) → core::List<core::Object?>} in true)))
29+
throw new _in::ReachabilityError::•();
30+
}
31+
}
32+
33+
constants {
34+
#C1 = 1
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
class A extends core::Object {
6+
synthetic constructor •() → self::A
7+
;
8+
get foo() → core::int
9+
;
10+
}
11+
static method foo<T extends core::Object? = dynamic>((self::foo::T%) → void f) → core::List<self::foo::T%>
12+
;
13+
static method test1() → dynamic
14+
;
15+
static method test2() → dynamic
16+
;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "dart:_internal" as _in;
5+
6+
class A extends core::Object {
7+
synthetic constructor •() → self::A
8+
: super core::Object::•()
9+
;
10+
get foo() → core::int
11+
return 0;
12+
}
13+
static method foo<T extends core::Object? = dynamic>((self::foo::T%) → void f) → core::List<self::foo::T%>
14+
return throw 0;
15+
static method test1() → dynamic {
16+
self::A x;
17+
{
18+
final dynamic #0#0 = self::foo<self::A>((self::A a) → void => a.{self::A::foo}{core::int});
19+
if(!(#0#0{core::List<self::A>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final self::A #t1 = x = #0#0{core::List<self::A>}.{core::List::[]}(0){(core::int) → self::A} in true)))
20+
throw new _in::ReachabilityError::•();
21+
}
22+
}
23+
static method test2() → dynamic {
24+
core::Object? x;
25+
core::List<core::Object?> y;
26+
{
27+
final dynamic #0#0 = self::foo<core::Object?>((core::Object? e) → void => e);
28+
if(!(#0#0{core::List<core::Object?>}.{core::List::length}{core::int}.{core::num::>=}(#C1){(core::num) → core::bool} && (let final core::Object? #t2 = x = #0#0{core::List<core::Object?>}.{core::List::[]}(0){(core::int) → core::Object?} in true) && (let final core::List<core::Object?> #t3 = y = #0#0{core::List<core::Object?>}.{core::List::sublist}(1){(core::int, [core::int?]) → core::List<core::Object?>} in true)))
29+
throw new _in::ReachabilityError::•();
30+
}
31+
}
32+
33+
constants {
34+
#C1 = 1
35+
}

0 commit comments

Comments
 (0)