Skip to content

Commit 47ec0ac

Browse files
kallentuCommit Queue
authored and
Commit Queue
committed
[cfe] Dot shorthands work with FutureOr.
This CL allows FutureOrs to work with dot shorthands. The static namespace denoted by `S` is also the namespace denoted by `FutureOr<S>`. Bug: #59758 Change-Id: Idac4c4e05dc8b9c13c2932bf6c98bc9918e5dad5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/414184 Commit-Queue: Kallen Tu <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
1 parent d5af13b commit 47ec0ac

9 files changed

+306
-1
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12177,6 +12177,13 @@ class InferenceVisitorImpl extends InferenceVisitorBase
1217712177
// Use the previously cached context type to determine the declaration
1217812178
// member that we're trying to find.
1217912179
DartType cachedContext = getDotShorthandContext().unwrapTypeSchemaView();
12180+
12181+
// The static namespace denoted by `S` is also the namespace denoted by
12182+
// `FutureOr<S>`.
12183+
while (cachedContext is FutureOrType) {
12184+
cachedContext = cachedContext.typeArgument;
12185+
}
12186+
1218012187
Member? member = findInterfaceMember(
1218112188
cachedContext, node.name, node.fileOffset,
1218212189
isSetter: false, isDotShorthand: true)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) 2025, 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+
import 'dart:async';
6+
7+
enum Color { red, blue, green }
8+
9+
void main() {
10+
FutureOr<Color> color = .blue;
11+
FutureOr<FutureOr<Color>> recursiveColor = .blue;
12+
const FutureOr<Color> constColor = .blue;
13+
switch (color) {
14+
case .blue:
15+
print('blue');
16+
case .red:
17+
print('red');
18+
case .green:
19+
print('green');
20+
case Future<Color>():
21+
print('Future in switch');
22+
}
23+
24+
var colorList = <FutureOr<Color>>[.blue, .green, .red];
25+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
library;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "dart:async" as asy;
5+
6+
import "dart:async";
7+
8+
class Color extends core::_Enum /*isEnum*/ {
9+
enum-element static const field self::Color red = #C3;
10+
enum-element static const field self::Color blue = #C6;
11+
enum-element static const field self::Color green = #C9;
12+
static const field core::List<self::Color> values = #C10;
13+
const synthetic constructor •(core::int #index, core::String #name) → self::Color
14+
: super core::_Enum::•(#index, #name)
15+
;
16+
method _enumToString() → core::String
17+
return "Color.${this.{core::_Enum::_name}{core::String}}";
18+
}
19+
static method main() → void {
20+
FutureOr<self::Color>color = #C6;
21+
FutureOr<FutureOr<self::Color>>recursiveColor = #C6;
22+
#L1:
23+
{
24+
final synthesized FutureOr<self::Color>#0#0 = color;
25+
{
26+
if(#C6 =={core::Object::==}{(core::Object) → core::bool} #0#0) {
27+
{
28+
core::print("blue");
29+
break #L1;
30+
}
31+
}
32+
}
33+
{
34+
if(#C3 =={core::Object::==}{(core::Object) → core::bool} #0#0) {
35+
{
36+
core::print("red");
37+
break #L1;
38+
}
39+
}
40+
}
41+
{
42+
if(#C9 =={core::Object::==}{(core::Object) → core::bool} #0#0) {
43+
{
44+
core::print("green");
45+
break #L1;
46+
}
47+
}
48+
}
49+
{
50+
if(#0#0 is asy::Future<self::Color>) {
51+
{
52+
core::print("Future in switch");
53+
}
54+
}
55+
}
56+
}
57+
core::List<FutureOr<self::Color>> colorList = <FutureOr<self::Color>>[#C6, #C9, #C3];
58+
}
59+
60+
constants {
61+
#C1 = 0
62+
#C2 = "red"
63+
#C3 = self::Color {index:#C1, _name:#C2}
64+
#C4 = 1
65+
#C5 = "blue"
66+
#C6 = self::Color {index:#C4, _name:#C5}
67+
#C7 = 2
68+
#C8 = "green"
69+
#C9 = self::Color {index:#C7, _name:#C8}
70+
#C10 = <self::Color>[#C3, #C6, #C9]
71+
}
72+
73+
74+
Constructor coverage from constants:
75+
org-dartlang-testcase:///futureor.dart:
76+
- Color. (from org-dartlang-testcase:///futureor.dart:7:6)
77+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart)
78+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
library;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "dart:async" as asy;
5+
6+
import "dart:async";
7+
8+
class Color extends core::_Enum /*isEnum*/ {
9+
enum-element static const field self::Color red = #C3;
10+
enum-element static const field self::Color blue = #C6;
11+
enum-element static const field self::Color green = #C9;
12+
static const field core::List<self::Color> values = #C10;
13+
const synthetic constructor •(core::int #index, core::String #name) → self::Color
14+
: super core::_Enum::•(#index, #name)
15+
;
16+
method _enumToString() → core::String
17+
return "Color.${this.{core::_Enum::_name}{core::String}}";
18+
}
19+
static method main() → void {
20+
FutureOr<self::Color>color = #C6;
21+
FutureOr<FutureOr<self::Color>>recursiveColor = #C6;
22+
#L1:
23+
{
24+
final synthesized FutureOr<self::Color>#0#0 = color;
25+
{
26+
if(#C6 =={core::Object::==}{(core::Object) → core::bool} #0#0) {
27+
{
28+
core::print("blue");
29+
break #L1;
30+
}
31+
}
32+
}
33+
{
34+
if(#C3 =={core::Object::==}{(core::Object) → core::bool} #0#0) {
35+
{
36+
core::print("red");
37+
break #L1;
38+
}
39+
}
40+
}
41+
{
42+
if(#C9 =={core::Object::==}{(core::Object) → core::bool} #0#0) {
43+
{
44+
core::print("green");
45+
break #L1;
46+
}
47+
}
48+
}
49+
{
50+
if(#0#0 is asy::Future<self::Color>) {
51+
{
52+
core::print("Future in switch");
53+
}
54+
}
55+
}
56+
}
57+
core::List<FutureOr<self::Color>> colorList = <FutureOr<self::Color>>[#C6, #C9, #C3];
58+
}
59+
60+
constants {
61+
#C1 = 0
62+
#C2 = "red"
63+
#C3 = self::Color {index:#C1, _name:#C2}
64+
#C4 = 1
65+
#C5 = "blue"
66+
#C6 = self::Color {index:#C4, _name:#C5}
67+
#C7 = 2
68+
#C8 = "green"
69+
#C9 = self::Color {index:#C7, _name:#C8}
70+
#C10 = <self::Color>[#C3, #C6, #C9]
71+
}
72+
73+
74+
Constructor coverage from constants:
75+
org-dartlang-testcase:///futureor.dart:
76+
- Color. (from org-dartlang-testcase:///futureor.dart:7:6)
77+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart)
78+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
library;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
import "dart:async";
6+
7+
class Color extends core::_Enum /*isEnum*/ {
8+
enum-element static const field self::Color red = const self::Color::•(0, "red");
9+
enum-element static const field self::Color blue = const self::Color::•(1, "blue");
10+
enum-element static const field self::Color green = const self::Color::•(2, "green");
11+
static const field core::List<self::Color> values = const <self::Color>[self::Color::red, self::Color::blue, self::Color::green];
12+
const synthetic constructor •(core::int #index, core::String #name) → self::Color
13+
: super core::_Enum::•(#index, #name)
14+
;
15+
method _enumToString() → core::String
16+
return "Color.${this.{core::_Enum::_name}{core::String}}";
17+
}
18+
static method main() → void
19+
;
20+
21+
22+
Extra constant evaluation status:
23+
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///futureor.dart:7:14 -> InstanceConstant(const Color{_Enum.index: 0, _Enum._name: "red"})
24+
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///futureor.dart:7:19 -> InstanceConstant(const Color{_Enum.index: 1, _Enum._name: "blue"})
25+
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///futureor.dart:7:25 -> InstanceConstant(const Color{_Enum.index: 2, _Enum._name: "green"})
26+
Evaluated: ListLiteral @ org-dartlang-testcase:///futureor.dart:7:6 -> ListConstant(const <Color>[const Color{_Enum.index: 0, _Enum._name: "red"}, const Color{_Enum.index: 1, _Enum._name: "blue"}, const Color{_Enum.index: 2, _Enum._name: "green"}])
27+
Extra constant evaluation: evaluated: 9, effectively constant: 4
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
library;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "dart:async" as asy;
5+
6+
import "dart:async";
7+
8+
class Color extends core::_Enum /*isEnum*/ {
9+
enum-element static const field self::Color red = #C3;
10+
enum-element static const field self::Color blue = #C6;
11+
enum-element static const field self::Color green = #C9;
12+
static const field core::List<self::Color> values = #C10;
13+
const synthetic constructor •(core::int #index, core::String #name) → self::Color
14+
: super core::_Enum::•(#index, #name)
15+
;
16+
method _enumToString() → core::String
17+
return "Color.${this.{core::_Enum::_name}{core::String}}";
18+
}
19+
static method main() → void {
20+
FutureOr<self::Color>color = #C6;
21+
FutureOr<FutureOr<self::Color>>recursiveColor = #C6;
22+
#L1:
23+
{
24+
final synthesized FutureOr<self::Color>#0#0 = color;
25+
{
26+
if(#C6 =={core::Object::==}{(core::Object) → core::bool} #0#0) {
27+
{
28+
core::print("blue");
29+
break #L1;
30+
}
31+
}
32+
}
33+
{
34+
if(#C3 =={core::Object::==}{(core::Object) → core::bool} #0#0) {
35+
{
36+
core::print("red");
37+
break #L1;
38+
}
39+
}
40+
}
41+
{
42+
if(#C9 =={core::Object::==}{(core::Object) → core::bool} #0#0) {
43+
{
44+
core::print("green");
45+
break #L1;
46+
}
47+
}
48+
}
49+
{
50+
if(#0#0 is asy::Future<self::Color>) {
51+
{
52+
core::print("Future in switch");
53+
}
54+
}
55+
}
56+
}
57+
core::List<FutureOr<self::Color>> colorList = core::_GrowableList::_literal3<FutureOr<self::Color>>(#C6, #C9, #C3);
58+
}
59+
60+
constants {
61+
#C1 = 0
62+
#C2 = "red"
63+
#C3 = self::Color {index:#C1, _name:#C2}
64+
#C4 = 1
65+
#C5 = "blue"
66+
#C6 = self::Color {index:#C4, _name:#C5}
67+
#C7 = 2
68+
#C8 = "green"
69+
#C9 = self::Color {index:#C7, _name:#C8}
70+
#C10 = <self::Color>[#C3, #C6, #C9]
71+
}
72+
73+
74+
Constructor coverage from constants:
75+
org-dartlang-testcase:///futureor.dart:
76+
- Color. (from org-dartlang-testcase:///futureor.dart:7:6)
77+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart)
78+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import 'dart:async';
2+
3+
enum Color { red, blue, green }
4+
5+
void main() {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import 'dart:async';
2+
3+
enum Color { red, blue, green }
4+
5+
void main() {}

tests/language/dot_shorthands/simple/simple_identifier_future_or_test.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ void main() {
5555
print('red');
5656
case .green:
5757
print('green');
58+
case Future<Color>():
59+
print('Future in switch');
5860
}
5961

6062
var colorList = <FutureOr<Color>>[.blue, .green, .red];
@@ -100,7 +102,7 @@ void main() {
100102
var nullableIntegerMixinList = <FutureOr<IntegerExt?>>[.one, .two, .one];
101103

102104
var integerMixinContextPositional = IntegerMixinFutureOrContext(.mixinOne, .mixinTwo);
103-
var integerMixinContextNamed = IntegerMixinFutureOrContext.named(integer: .mixinOne, nullableInteger: .mixinTwotwo);
105+
var integerMixinContextNamed = IntegerMixinFutureOrContext.named(integer: .mixinOne, nullableInteger: .mixinTwo);
104106
var integerMixinContextOptional = IntegerMixinFutureOrContext.optional(.mixinOne, .mixinTwo);
105107
}
106108

0 commit comments

Comments
 (0)