mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:39:49 +00:00
[cfe] Implement dispatchPatternSchema
Part of https://github.com/dart-lang/sdk/issues/49749 Change-Id: I9fa3ad41501422990d47bc637d46cbd22fdb54fb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/277004 Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
parent
638ca5cfd4
commit
ecef1a0137
|
@ -9606,11 +9606,63 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
}
|
||||
|
||||
@override
|
||||
DartType dispatchPatternSchema(TreeNode node) {
|
||||
// The front end's representation of a switch cases currently doesn't have
|
||||
// any support for patterns; each case is represented as an expression. So
|
||||
// analyze it as a constant pattern.
|
||||
return analyzeConstantPatternSchema();
|
||||
DartType dispatchPatternSchema(Node node) {
|
||||
if (node is AndPattern) {
|
||||
return analyzeLogicalAndPatternSchema(node.left, node.right);
|
||||
} else if (node is AssignedVariablePattern) {
|
||||
return analyzeAssignedVariablePatternSchema(node.variable);
|
||||
} else if (node is CastPattern) {
|
||||
return analyzeCastPatternSchema();
|
||||
} else if (node is ConstantPattern) {
|
||||
return analyzeConstantPatternSchema();
|
||||
} else if (node is ListPattern) {
|
||||
return analyzeListPatternSchema(
|
||||
elementType: node.typeArgument, elements: node.patterns);
|
||||
} else if (node is MapPattern) {
|
||||
return analyzeMapPatternSchema(
|
||||
typeArguments: node.keyType != null && node.valueType != null
|
||||
? new MapPatternTypeArguments<DartType>(
|
||||
keyType: node.keyType!, valueType: node.valueType!)
|
||||
: null,
|
||||
elements: node.entries);
|
||||
} else if (node is NamedPattern) {
|
||||
return dispatchPatternSchema(node.pattern);
|
||||
} else if (node is NullAssertPattern) {
|
||||
return analyzeNullCheckOrAssertPatternSchema(node.pattern,
|
||||
isAssert: true);
|
||||
} else if (node is NullCheckPattern) {
|
||||
return analyzeNullCheckOrAssertPatternSchema(node.pattern,
|
||||
isAssert: false);
|
||||
} else if (node is ObjectPattern) {
|
||||
return analyzeObjectPatternSchema(node.type);
|
||||
} else if (node is OrPattern) {
|
||||
return analyzeLogicalOrPatternSchema(node.left, node.right);
|
||||
} else if (node is RecordPattern) {
|
||||
return analyzeRecordPatternSchema(
|
||||
fields: <RecordPatternField<TreeNode, Pattern>>[
|
||||
for (Pattern element in node.patterns)
|
||||
if (element is NamedPattern)
|
||||
new RecordPatternField<TreeNode, Pattern>(
|
||||
node: element, name: element.name, pattern: element.pattern)
|
||||
else
|
||||
new RecordPatternField<TreeNode, Pattern>(
|
||||
node: element, name: null, pattern: element)
|
||||
]);
|
||||
} else if (node is RelationalPattern) {
|
||||
return analyzeRelationalPatternSchema();
|
||||
} else if (node is RestPattern) {
|
||||
// This pattern can't appear on it's own.
|
||||
return const InvalidType();
|
||||
} else if (node is VariablePattern) {
|
||||
return analyzeDeclaredVariablePatternSchema(node.type);
|
||||
} else if (node is WildcardPattern) {
|
||||
return analyzeDeclaredVariablePatternSchema(node.type);
|
||||
} else if (node is InvalidPattern) {
|
||||
return const InvalidType();
|
||||
} else {
|
||||
return problems.unhandled("${node.runtimeType}", "dispatchPatternSchema",
|
||||
node is TreeNode ? node.fileOffset : TreeNode.noOffset, helper.uri);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -517,7 +517,8 @@ class OperationsCfe
|
|||
|
||||
@override
|
||||
DartType glb(DartType type1, DartType type2) {
|
||||
throw new UnimplementedError('TODO(paulberry)');
|
||||
return typeEnvironment.getStandardLowerBound(type1, type2,
|
||||
isNonNullableByDefault: true);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -546,7 +547,7 @@ class OperationsCfe
|
|||
|
||||
@override
|
||||
DartType makeNullable(DartType type) {
|
||||
throw new UnimplementedError('TODO(paulberry)');
|
||||
return type.withDeclaredNullability(Nullability.nullable);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -600,8 +601,18 @@ class OperationsCfe
|
|||
|
||||
@override
|
||||
DartType? matchIterableType(DartType type) {
|
||||
// TODO(scheglov): implement matchIterableType
|
||||
throw new UnimplementedError('TODO(scheglov)');
|
||||
if (type is! InterfaceType) {
|
||||
return null;
|
||||
} else {
|
||||
InterfaceType? interfaceType = typeEnvironment.getTypeAsInstanceOf(type,
|
||||
typeEnvironment.coreTypes.iterableClass, typeEnvironment.coreTypes,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
if (interfaceType == null) {
|
||||
return null;
|
||||
} else {
|
||||
return interfaceType.typeArguments.single;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
// 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 {
|
||||
int get foo => 0;
|
||||
}
|
||||
|
||||
List<T> foo<T>(void Function(T) f) => throw 0;
|
||||
|
||||
test1() {
|
||||
var <A>[var x] = foo((a) => a.foo);
|
||||
}
|
||||
|
||||
test2() {
|
||||
var [var x, ...y] = foo((e) => e);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
get foo() → core::int
|
||||
return 0;
|
||||
}
|
||||
static method foo<T extends core::Object? = dynamic>((self::foo::T%) → void f) → core::List<self::foo::T%>
|
||||
return throw 0;
|
||||
static method test1() → dynamic {
|
||||
self::A x;
|
||||
{
|
||||
final dynamic #0#0 = self::foo<self::A>((self::A a) → void => a.{self::A::foo}{core::int});
|
||||
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)))
|
||||
throw new _in::ReachabilityError::•();
|
||||
}
|
||||
}
|
||||
static method test2() → dynamic {
|
||||
core::Object? x;
|
||||
core::List<core::Object?> y;
|
||||
{
|
||||
final dynamic #0#0 = self::foo<core::Object?>((core::Object? e) → void => e);
|
||||
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)))
|
||||
throw new _in::ReachabilityError::•();
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 1
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
get foo() → core::int
|
||||
return 0;
|
||||
}
|
||||
static method foo<T extends core::Object? = dynamic>((self::foo::T%) → void f) → core::List<self::foo::T%>
|
||||
return throw 0;
|
||||
static method test1() → dynamic {
|
||||
self::A x;
|
||||
{
|
||||
final dynamic #0#0 = self::foo<self::A>((self::A a) → void => a.{self::A::foo}{core::int});
|
||||
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)))
|
||||
throw new _in::ReachabilityError::•();
|
||||
}
|
||||
}
|
||||
static method test2() → dynamic {
|
||||
core::Object? x;
|
||||
core::List<core::Object?> y;
|
||||
{
|
||||
final dynamic #0#0 = self::foo<core::Object?>((core::Object? e) → void => e);
|
||||
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)))
|
||||
throw new _in::ReachabilityError::•();
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 1
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
class A {
|
||||
int get foo => 0;
|
||||
}
|
||||
|
||||
List<T> foo<T>(void Function(T) f) => throw 0;
|
||||
test1() {}
|
||||
test2() {}
|
|
@ -0,0 +1,8 @@
|
|||
List<T> foo<T>(void Function(T) f) => throw 0;
|
||||
|
||||
class A {
|
||||
int get foo => 0;
|
||||
}
|
||||
|
||||
test1() {}
|
||||
test2() {}
|
|
@ -0,0 +1,35 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
get foo() → core::int
|
||||
return 0;
|
||||
}
|
||||
static method foo<T extends core::Object? = dynamic>((self::foo::T%) → void f) → core::List<self::foo::T%>
|
||||
return throw 0;
|
||||
static method test1() → dynamic {
|
||||
self::A x;
|
||||
{
|
||||
final dynamic #0#0 = self::foo<self::A>((self::A a) → void => a.{self::A::foo}{core::int});
|
||||
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)))
|
||||
throw new _in::ReachabilityError::•();
|
||||
}
|
||||
}
|
||||
static method test2() → dynamic {
|
||||
core::Object? x;
|
||||
core::List<core::Object?> y;
|
||||
{
|
||||
final dynamic #0#0 = self::foo<core::Object?>((core::Object? e) → void => e);
|
||||
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)))
|
||||
throw new _in::ReachabilityError::•();
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 1
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
get foo() → core::int
|
||||
return 0;
|
||||
}
|
||||
static method foo<T extends core::Object? = dynamic>((self::foo::T%) → void f) → core::List<self::foo::T%>
|
||||
return throw 0;
|
||||
static method test1() → dynamic {
|
||||
self::A x;
|
||||
{
|
||||
final dynamic #0#0 = self::foo<self::A>((self::A a) → void => a.{self::A::foo}{core::int});
|
||||
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)))
|
||||
throw new _in::ReachabilityError::•();
|
||||
}
|
||||
}
|
||||
static method test2() → dynamic {
|
||||
core::Object? x;
|
||||
core::List<core::Object?> y;
|
||||
{
|
||||
final dynamic #0#0 = self::foo<core::Object?>((core::Object? e) → void => e);
|
||||
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)))
|
||||
throw new _in::ReachabilityError::•();
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 1
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
;
|
||||
get foo() → core::int
|
||||
;
|
||||
}
|
||||
static method foo<T extends core::Object? = dynamic>((self::foo::T%) → void f) → core::List<self::foo::T%>
|
||||
;
|
||||
static method test1() → dynamic
|
||||
;
|
||||
static method test2() → dynamic
|
||||
;
|
|
@ -0,0 +1,35 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
get foo() → core::int
|
||||
return 0;
|
||||
}
|
||||
static method foo<T extends core::Object? = dynamic>((self::foo::T%) → void f) → core::List<self::foo::T%>
|
||||
return throw 0;
|
||||
static method test1() → dynamic {
|
||||
self::A x;
|
||||
{
|
||||
final dynamic #0#0 = self::foo<self::A>((self::A a) → void => a.{self::A::foo}{core::int});
|
||||
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)))
|
||||
throw new _in::ReachabilityError::•();
|
||||
}
|
||||
}
|
||||
static method test2() → dynamic {
|
||||
core::Object? x;
|
||||
core::List<core::Object?> y;
|
||||
{
|
||||
final dynamic #0#0 = self::foo<core::Object?>((core::Object? e) → void => e);
|
||||
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)))
|
||||
throw new _in::ReachabilityError::•();
|
||||
}
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 1
|
||||
}
|
Loading…
Reference in a new issue