From 749de9387f76346bd728f05ef2bc9f7a93144331 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Wed, 15 Jan 2025 10:05:48 -0800 Subject: [PATCH] [analyzer] Refine types returned by TypeSystemImpl methods. In the following methods in `TypeSystemImpl`, the return type is changed from `DartType` to `TypeImpl`: - `greatestClosure` - `greatestLowerBound` - `leastClosure` - `leastUpperBound` - `makeNullable` - `promoteToNonNull` This required adding a few casts to `TypeSystemImpl`, `LeastGreatestClosureHelper`, and `InterfaceTypeImpl`, which I believe I will be able to remove in future CLs. It also allowed removing some casts from `GreatestLowerBoundHelper`, `LeastUpperBoundHelper`, and `InterfaceTypeImpl`. This is part of a larger arc of work to change the analyzer's use of the shared code so that the type parameters it supplies are not part of the analyzer public API. See https://github.com/dart-lang/sdk/issues/59763. Change-Id: I24f27090bb2d07ae33be9c2c8d7908ef71a96929 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/404640 Reviewed-by: Konstantin Shcheglov Commit-Queue: Paul Berry --- .../dart/element/greatest_lower_bound.dart | 24 ++++++-------- .../dart/element/least_greatest_closure.dart | 14 ++++++--- .../src/dart/element/least_upper_bound.dart | 31 +++++++++---------- pkg/analyzer/lib/src/dart/element/type.dart | 24 +++++++------- .../lib/src/dart/element/type_system.dart | 22 ++++++++----- ...d_runtime_check_with_js_interop_types.dart | 4 +-- 6 files changed, 61 insertions(+), 58 deletions(-) diff --git a/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart b/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart index 70d4bb008e5a..78f59d87ae00 100644 --- a/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart +++ b/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart @@ -6,7 +6,6 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; -import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/element/extensions.dart'; import 'package:analyzer/src/dart/element/type.dart'; import 'package:analyzer/src/dart/element/type_provider.dart'; @@ -27,7 +26,7 @@ class GreatestLowerBoundHelper { /// /// https://github.com/dart-lang/language /// See `resources/type-system/upper-lower-bounds.md` - DartType getGreatestLowerBound(DartType T1, DartType T2) { + TypeImpl getGreatestLowerBound(TypeImpl T1, TypeImpl T2) { // DOWN(T, T) = T if (identical(T1, T2)) { return T1; @@ -103,11 +102,8 @@ class GreatestLowerBoundHelper { } } - var T1_impl = T1 as TypeImpl; - var T2_impl = T2 as TypeImpl; - - var T1_nullability = T1_impl.nullabilitySuffix; - var T2_nullability = T2_impl.nullabilitySuffix; + var T1_nullability = T1.nullabilitySuffix; + var T2_nullability = T2.nullabilitySuffix; // DOWN(Null, T2) if (T1_nullability == NullabilitySuffix.none && T1.isDartCoreNull) { @@ -153,7 +149,7 @@ class GreatestLowerBoundHelper { } // * NonNull(T2) if NonNull(T2) is non-nullable - var T2_nonNull = _typeSystem.promoteToNonNull(T2_impl); + var T2_nonNull = _typeSystem.promoteToNonNull(T2); if (_typeSystem.isNonNullable(T2_nonNull)) { return T2_nonNull; } @@ -170,7 +166,7 @@ class GreatestLowerBoundHelper { } // * NonNull(T1) if NonNull(T1) is non-nullable - var T1_nonNull = _typeSystem.promoteToNonNull(T1_impl); + var T1_nonNull = _typeSystem.promoteToNonNull(T1); if (_typeSystem.isNonNullable(T1_nonNull)) { return T1_nonNull; } @@ -184,12 +180,12 @@ class GreatestLowerBoundHelper { // DOWN(T1, T2?) = S where S is DOWN(T1, T2) if (T1_nullability != NullabilitySuffix.none || T2_nullability != NullabilitySuffix.none) { - var T1_none = T1_impl.withNullability(NullabilitySuffix.none); - var T2_none = T2_impl.withNullability(NullabilitySuffix.none); + var T1_none = T1.withNullability(NullabilitySuffix.none); + var T2_none = T2.withNullability(NullabilitySuffix.none); var S = getGreatestLowerBound(T1_none, T2_none); if (T1_nullability == NullabilitySuffix.question && T2_nullability == NullabilitySuffix.question) { - return (S as TypeImpl).withNullability(NullabilitySuffix.question); + return S.withNullability(NullabilitySuffix.question); } return S; } @@ -258,7 +254,7 @@ class GreatestLowerBoundHelper { /// /// https://github.com/dart-lang/language /// See `resources/type-system/upper-lower-bounds.md` - DartType _functionType(FunctionType f, FunctionType g) { + TypeImpl _functionType(FunctionTypeImpl f, FunctionTypeImpl g) { var fTypeFormals = f.typeFormals; var gTypeFormals = g.typeFormals; @@ -378,7 +374,7 @@ class GreatestLowerBoundHelper { ); } - DartType _recordType(RecordTypeImpl T1, RecordTypeImpl T2) { + TypeImpl _recordType(RecordTypeImpl T1, RecordTypeImpl T2) { var positional1 = T1.positionalFields; var positional2 = T2.positionalFields; if (positional1.length != positional2.length) { diff --git a/pkg/analyzer/lib/src/dart/element/least_greatest_closure.dart b/pkg/analyzer/lib/src/dart/element/least_greatest_closure.dart index f0bceb82d60e..b9419a945cf4 100644 --- a/pkg/analyzer/lib/src/dart/element/least_greatest_closure.dart +++ b/pkg/analyzer/lib/src/dart/element/least_greatest_closure.dart @@ -47,17 +47,23 @@ class LeastGreatestClosureHelper extends ReplacementVisitor { } /// Returns a supertype of [type] for all values of [eliminationTargets]. - DartType eliminateToGreatest(DartType type) { + TypeImpl eliminateToGreatest(DartType type) { _isCovariant = true; _isLeastClosure = false; - return type.accept(this) ?? type; + // TODO(paulberry): make this cast unnecessary by changing the type of + // `type` and by changing `ReplacementVisitor` to implement + // `TypeVisitor`. + return (type.accept(this) ?? type) as TypeImpl; } /// Returns a subtype of [type] for all values of [eliminationTargets]. - DartType eliminateToLeast(DartType type) { + TypeImpl eliminateToLeast(DartType type) { _isCovariant = true; _isLeastClosure = true; - return type.accept(this) ?? type; + // TODO(paulberry): make this cast unnecessary by changing the type of + // `type` and by changing `ReplacementVisitor` to implement + // `TypeVisitor`. + return (type.accept(this) ?? type) as TypeImpl; } @override diff --git a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart index 5f64449b8d56..898e4943ccf4 100644 --- a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart +++ b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart @@ -318,7 +318,7 @@ class LeastUpperBoundHelper { LeastUpperBoundHelper(this._typeSystem); - InterfaceType get _interfaceTypeFunctionNone { + InterfaceTypeImpl get _interfaceTypeFunctionNone { return _typeSystem.typeProvider.functionType.element3.instantiate( typeArguments: const [], nullabilitySuffix: NullabilitySuffix.none, @@ -329,7 +329,7 @@ class LeastUpperBoundHelper { /// /// https://github.com/dart-lang/language /// See `resources/type-system/upper-lower-bounds.md` - DartType getLeastUpperBound(DartType T1, DartType T2) { + TypeImpl getLeastUpperBound(TypeImpl T1, TypeImpl T2) { // UP(T, T) = T if (identical(T1, T2)) { return T1; @@ -439,11 +439,8 @@ class LeastUpperBoundHelper { } } - var T1_impl = T1 as TypeImpl; - var T2_impl = T2 as TypeImpl; - - var T1_nullability = T1_impl.nullabilitySuffix; - var T2_nullability = T2_impl.nullabilitySuffix; + var T1_nullability = T1.nullabilitySuffix; + var T2_nullability = T2.nullabilitySuffix; // UP(T1, T2) where NULL(T1) if (T1_isNull) { @@ -508,10 +505,10 @@ class LeastUpperBoundHelper { // UP(T1, T2?) = S? where S is UP(T1, T2) if (T1_nullability != NullabilitySuffix.none || T2_nullability != NullabilitySuffix.none) { - var T1_none = T1_impl.withNullability(NullabilitySuffix.none); - var T2_none = T2_impl.withNullability(NullabilitySuffix.none); + var T1_none = T1.withNullability(NullabilitySuffix.none); + var T2_none = T2.withNullability(NullabilitySuffix.none); var S = getLeastUpperBound(T1_none, T2_none); - return (S as TypeImpl).withNullability(NullabilitySuffix.question); + return S.withNullability(NullabilitySuffix.question); } assert(T1_nullability == NullabilitySuffix.none); @@ -622,7 +619,7 @@ class LeastUpperBoundHelper { /// /// https://github.com/dart-lang/language /// See `resources/type-system/upper-lower-bounds.md` - DartType _functionType(FunctionType f, FunctionType g) { + TypeImpl _functionType(FunctionTypeImpl f, FunctionTypeImpl g) { var fTypeFormals = f.typeParameters; var gTypeFormals = g.typeParameters; @@ -744,20 +741,20 @@ class LeastUpperBoundHelper { ); } - DartType? _futureOr(DartType T1, DartType T2) { - var T1_futureOr = T1 is InterfaceType && T1.isDartAsyncFutureOr + TypeImpl? _futureOr(TypeImpl T1, TypeImpl T2) { + var T1_futureOr = T1 is InterfaceTypeImpl && T1.isDartAsyncFutureOr ? T1.typeArguments[0] : null; - var T1_future = T1 is InterfaceType && T1.isDartAsyncFuture + var T1_future = T1 is InterfaceTypeImpl && T1.isDartAsyncFuture ? T1.typeArguments[0] : null; - var T2_futureOr = T2 is InterfaceType && T2.isDartAsyncFutureOr + var T2_futureOr = T2 is InterfaceTypeImpl && T2.isDartAsyncFutureOr ? T2.typeArguments[0] : null; - var T2_future = T2 is InterfaceType && T2.isDartAsyncFuture + var T2_future = T2 is InterfaceTypeImpl && T2.isDartAsyncFuture ? T2.typeArguments[0] : null; @@ -798,7 +795,7 @@ class LeastUpperBoundHelper { return _typeSystem.greatestLowerBound(a.type, b.type); } - DartType _recordType(RecordTypeImpl T1, RecordTypeImpl T2) { + TypeImpl _recordType(RecordTypeImpl T1, RecordTypeImpl T2) { var positional1 = T1.positionalFields; var positional2 = T2.positionalFields; if (positional1.length != positional2.length) { diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart index 05ef27234990..e05d8fb3e122 100644 --- a/pkg/analyzer/lib/src/dart/element/type.dart +++ b/pkg/analyzer/lib/src/dart/element/type.dart @@ -538,7 +538,7 @@ class FutureOrTypeImpl extends InterfaceTypeImpl { @override bool get isDartAsyncFutureOr => true; - DartType get typeArgument => typeArguments[0]; + TypeImpl get typeArgument => typeArguments[0]; @override InterfaceTypeImpl withNullability(NullabilitySuffix nullabilitySuffix) { @@ -575,7 +575,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { final InterfaceElementImpl2 element3; @override - final List typeArguments; + final List typeArguments; @override final NullabilitySuffix nullabilitySuffix; @@ -614,8 +614,10 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { if (element.name3 == 'FutureOr' && element.library2.isDartAsync) { return FutureOrTypeImpl( element3: element, + // TODO(paulberry): avoid this cast by changing the type of + // `typeArguments`. typeArgument: typeArguments.isNotEmpty - ? typeArguments[0] + ? typeArguments[0] as TypeImpl : InvalidTypeImpl.instance, nullabilitySuffix: nullabilitySuffix, alias: alias, @@ -626,9 +628,11 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { alias: alias, ); } else { + // TODO(paulberry): avoid this cast by changing the type of + // `typeArguments`. return InterfaceTypeImpl._( element3: element, - typeArguments: typeArguments, + typeArguments: typeArguments.cast(), nullabilitySuffix: nullabilitySuffix, alias: alias, ); @@ -644,7 +648,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { InterfaceTypeImpl._futureOr({ required this.element3, - required DartType typeArgument, + required TypeImpl typeArgument, required this.nullabilitySuffix, super.alias, }) : typeArguments = [typeArgument] { @@ -1161,18 +1165,12 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { @override bool referencesAny(Set parameters) { - return typeArguments.any((argument) { - var argumentImpl = argument as TypeImpl; - return argumentImpl.referencesAny(parameters); - }); + return typeArguments.any((argument) => argument.referencesAny(parameters)); } @override bool referencesAny2(Set parameters) { - return typeArguments.any((argument) { - var argumentImpl = argument as TypeImpl; - return argumentImpl.referencesAny2(parameters); - }); + return typeArguments.any((argument) => argument.referencesAny2(parameters)); } @override diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart index 3b6e7683bfe0..0ebeb45c1d20 100644 --- a/pkg/analyzer/lib/src/dart/element/type_system.dart +++ b/pkg/analyzer/lib/src/dart/element/type_system.dart @@ -598,7 +598,7 @@ class TypeSystemImpl implements TypeSystem { /// /// https://github.com/dart-lang/language /// See `resources/type-system/inference.md` - DartType greatestClosure( + TypeImpl greatestClosure( DartType type, List typeParameters, ) { @@ -638,8 +638,11 @@ class TypeSystemImpl implements TypeSystem { } @override - DartType greatestLowerBound(DartType T1, DartType T2) { - return _greatestLowerBoundHelper.getGreatestLowerBound(T1, T2); + TypeImpl greatestLowerBound(DartType T1, DartType T2) { + // TODO(paulberry): make these casts unnecessary by changing the type of + // `T1` and `T2`. + return _greatestLowerBoundHelper.getGreatestLowerBound( + T1 as TypeImpl, T2 as TypeImpl); } /// Given a generic function type `F` and a context type C, @@ -1380,7 +1383,7 @@ class TypeSystemImpl implements TypeSystem { /// /// https://github.com/dart-lang/language /// See `resources/type-system/inference.md` - DartType leastClosure( + TypeImpl leastClosure( DartType type, List typeParameters, ) { @@ -1419,13 +1422,16 @@ class TypeSystemImpl implements TypeSystem { } @override - DartType leastUpperBound(DartType T1, DartType T2) { - return _leastUpperBoundHelper.getLeastUpperBound(T1, T2); + TypeImpl leastUpperBound(DartType T1, DartType T2) { + // TODO(paulberry): make these casts unnecessary by changing the type of + // `T1` and `T2`. + return _leastUpperBoundHelper.getLeastUpperBound( + T1 as TypeImpl, T2 as TypeImpl); } /// Returns a nullable version of [type]. The result would be equivalent to /// the union `type | Null` (if we supported union types). - DartType makeNullable(DartType type) { + TypeImpl makeNullable(DartType type) { // TODO(paulberry): handle type parameter types return (type as TypeImpl).withNullability(NullabilitySuffix.question); } @@ -1485,7 +1491,7 @@ class TypeSystemImpl implements TypeSystem { /// Returns a non-nullable version of [type]. This is equivalent to the /// operation `NonNull` defined in the spec. @override - DartType promoteToNonNull(DartType type) { + TypeImpl promoteToNonNull(DartType type) { if (type.isDartCoreNull) return NeverTypeImpl.instance; if (type is TypeParameterTypeImpl) { diff --git a/pkg/linter/lib/src/rules/invalid_runtime_check_with_js_interop_types.dart b/pkg/linter/lib/src/rules/invalid_runtime_check_with_js_interop_types.dart index 3db8fdfd0db2..7bbc6a4e74f1 100644 --- a/pkg/linter/lib/src/rules/invalid_runtime_check_with_js_interop_types.dart +++ b/pkg/linter/lib/src/rules/invalid_runtime_check_with_js_interop_types.dart @@ -296,10 +296,10 @@ class _Visitor extends SimpleAstVisitor { }) { LintCode? lintCode; (DartType, DartType) eraseTypes(DartType left, DartType right) { - var erasedLeft = typeSystem.promoteToNonNull( + DartType erasedLeft = typeSystem.promoteToNonNull( eraseNonJsInteropTypes.perform(left), ); - var erasedRight = typeSystem.promoteToNonNull( + DartType erasedRight = typeSystem.promoteToNonNull( eraseNonJsInteropTypes.perform(right), ); var leftIsInteropType = _isJsInteropType(