Skip to content

Commit

Permalink
[analyzer] Refine types returned by TypeSystemImpl methods.
Browse files Browse the repository at this point in the history
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
#59763.

Change-Id: I24f27090bb2d07ae33be9c2c8d7908ef71a96929
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/404640
Reviewed-by: Konstantin Shcheglov <[email protected]>
Commit-Queue: Paul Berry <[email protected]>
  • Loading branch information
stereotype441 authored and Commit Queue committed Jan 15, 2025
1 parent 3417d1a commit 749de93
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 58 deletions.
24 changes: 10 additions & 14 deletions pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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) {
Expand Down
14 changes: 10 additions & 4 deletions pkg/analyzer/lib/src/dart/element/least_greatest_closure.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<TypeImpl?>`.
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<TypeImpl?>`.
return (type.accept(this) ?? type) as TypeImpl;
}

@override
Expand Down
31 changes: 14 additions & 17 deletions pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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) {
Expand Down
24 changes: 11 additions & 13 deletions pkg/analyzer/lib/src/dart/element/type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -575,7 +575,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
final InterfaceElementImpl2 element3;

@override
final List<DartType> typeArguments;
final List<TypeImpl> typeArguments;

@override
final NullabilitySuffix nullabilitySuffix;
Expand Down Expand Up @@ -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,
Expand All @@ -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,
);
Expand All @@ -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] {
Expand Down Expand Up @@ -1161,18 +1165,12 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {

@override
bool referencesAny(Set<TypeParameterElement> 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<TypeParameterElementImpl2> parameters) {
return typeArguments.any((argument) {
var argumentImpl = argument as TypeImpl;
return argumentImpl.referencesAny2(parameters);
});
return typeArguments.any((argument) => argument.referencesAny2(parameters));
}

@override
Expand Down
22 changes: 14 additions & 8 deletions pkg/analyzer/lib/src/dart/element/type_system.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<TypeParameterElementImpl2> typeParameters,
) {
Expand Down Expand Up @@ -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<T0, T1, ... Tn>` and a context type C,
Expand Down Expand Up @@ -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<TypeParameterElementImpl2> typeParameters,
) {
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,10 @@ class _Visitor extends SimpleAstVisitor<void> {
}) {
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(
Expand Down

0 comments on commit 749de93

Please sign in to comment.