Skip to content

Commit 237bb3b

Browse files
stereotype441Commit Queue
authored andcommitted
[analyzer] Represent FutureOr<...> as FutureOrTypeImpl.
This change introduces the class `FutureOrTypeImpl` to represent the special types of the form `FutureOr<...>`, which were previously represented as ordinary instances of `InterfaceType`. This class mirrors the CFE's `FutureOrType` class. Adding it will facilitate further code sharing between the analyzer and the CFE, because it will allow code that's shared between the analyzer and CFE to use `is` tests to recognize `FutureOr` types. In a follow-up CL I intend to add a base class that is common to analyzer and CFE `FutureOrType` representations. Note that in https://dart-review.googlesource.com/c/sdk/+/396320, when I introduced the `NullTypeImpl` class, I took pains to find all the places in the analyzer that might call the `InterfaceTypeImpl` constructor, and updated them so that if the type they are creating is the `Null` type, they call the `NullTypeImpl` constructor instead. That was tractable for the type `Null`, since there's basically just a single `Null` type corresponding to a single declaration in `dart:core`. At first I tried doing a similar thing for `FutureOr`, but it proved to be a big pain, because `FutureOr` types get created all over the place. It was difficult to be confident that I'd updated all the necessary call sites. So instead I've put the necessary logic in the `InterfaceTypeImpl` constructor itself (by changing it into a factory constructor). This is a much lower risk approach and I'm much happier with it. In a follow-up CL I'll change the logic for `NullTypeImpl` to follow the same factory approach. Change-Id: I54c6998f991456199076faeac995e433cc88845d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/396523 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent b3ee890 commit 237bb3b

File tree

2 files changed

+72
-7
lines changed

2 files changed

+72
-7
lines changed

pkg/analyzer/lib/src/dart/element/type.dart

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,34 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
457457
}
458458
}
459459

460+
/// A concrete implementation of [DartType] representing types of the form
461+
/// `FutureOr<...>`.
462+
class FutureOrTypeImpl extends InterfaceTypeImpl {
463+
FutureOrTypeImpl(
464+
{required super.element,
465+
required super.typeArgument,
466+
required super.nullabilitySuffix,
467+
super.alias})
468+
: super._futureOr();
469+
470+
@override
471+
bool get isDartAsyncFutureOr => true;
472+
473+
DartType get typeArgument => typeArguments[0];
474+
475+
@override
476+
InterfaceTypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
477+
if (this.nullabilitySuffix == nullabilitySuffix) return this;
478+
479+
return FutureOrTypeImpl(
480+
element: element,
481+
typeArgument: typeArgument,
482+
nullabilitySuffix: nullabilitySuffix,
483+
alias: alias,
484+
);
485+
}
486+
}
487+
460488
class InstantiatedTypeAliasElementImpl implements InstantiatedTypeAliasElement {
461489
@override
462490
final TypeAliasElement element;
@@ -493,11 +521,33 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
493521
/// Cached [MethodElement]s - members or raw elements.
494522
List<MethodElement>? _methods;
495523

496-
InterfaceTypeImpl({
524+
factory InterfaceTypeImpl(
525+
{required InterfaceElement element,
526+
required List<DartType> typeArguments,
527+
required NullabilitySuffix nullabilitySuffix,
528+
InstantiatedTypeAliasElement? alias}) {
529+
if (element.name == 'FutureOr' && element.library.isDartAsync) {
530+
return FutureOrTypeImpl(
531+
element: element,
532+
typeArgument: typeArguments.isNotEmpty
533+
? typeArguments[0]
534+
: InvalidTypeImpl.instance,
535+
nullabilitySuffix: nullabilitySuffix,
536+
alias: alias);
537+
} else {
538+
return InterfaceTypeImpl._(
539+
element: element,
540+
typeArguments: typeArguments,
541+
nullabilitySuffix: nullabilitySuffix,
542+
alias: alias);
543+
}
544+
}
545+
546+
InterfaceTypeImpl._({
497547
required this.element,
498548
required this.typeArguments,
499549
required this.nullabilitySuffix,
500-
super.alias,
550+
required super.alias,
501551
}) {
502552
if (element.name == 'Null' && element.library.isDartCore) {
503553
throw ArgumentError('NullTypeImpl should be used for `Null`');
@@ -519,6 +569,16 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
519569
}
520570
}
521571

572+
InterfaceTypeImpl._futureOr(
573+
{required this.element,
574+
required DartType typeArgument,
575+
required this.nullabilitySuffix,
576+
super.alias})
577+
: typeArguments = [typeArgument] {
578+
assert(element.name == 'FutureOr' && element.library.isDartAsync);
579+
assert(this is FutureOrTypeImpl);
580+
}
581+
522582
InterfaceTypeImpl._null({required this.element, super.alias})
523583
: typeArguments = const [],
524584
nullabilitySuffix = NullabilitySuffix.none {
@@ -596,11 +656,6 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
596656
return element.name == "Future" && element.library.isDartAsync;
597657
}
598658

599-
@override
600-
bool get isDartAsyncFutureOr {
601-
return element.name == "FutureOr" && element.library.isDartAsync;
602-
}
603-
604659
@override
605660
bool get isDartAsyncStream {
606661
return element.name == "Stream" && element.library.isDartAsync;

pkg/analyzer/test/generated/non_error_resolver_test.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3082,6 +3082,16 @@ main() { lib1.f1(); lib.f2(); lib.f3(); }
30823082
''');
30833083
}
30843084

3085+
test_type_parameter_extends_futureOr_of_extension_type() async {
3086+
await assertNoErrorsInCode('''
3087+
import 'dart:async';
3088+
3089+
extension type E(int i) {}
3090+
3091+
void f<T extends FutureOr<E>>() {}
3092+
''');
3093+
}
3094+
30853095
test_typeArgument_boundToFunctionType() async {
30863096
await assertNoErrorsInCode('''
30873097
class A<T extends void Function(T)>{}

0 commit comments

Comments
 (0)