| // Copyright (c) 2015, 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. |
| |
| library dart2js.abstract_value_domain; |
| |
| import '../common/metrics.dart'; |
| import '../constants/values.dart' show ConstantValue, PrimitiveConstantValue; |
| import '../elements/entities.dart'; |
| import '../elements/names.dart'; |
| import '../elements/types.dart' show DartType; |
| import '../serialization/serialization.dart'; |
| import '../universe/member_hierarchy.dart'; |
| import '../universe/record_shape.dart'; |
| import '../universe/selector.dart'; |
| |
| /// Abstract booleans used for reporting known and unknown truth values. |
| enum AbstractBool { |
| /// Used when the property is known _never_ to be true. |
| False, |
| |
| /// Used when the property is known _always_ to be true. |
| True, |
| |
| /// Used when the property might or might not be true. |
| Maybe, |
| ; |
| |
| bool get isDefinitelyTrue => this == True; |
| |
| bool get isPotentiallyTrue => this != False; |
| |
| bool get isDefinitelyFalse => this == False; |
| |
| bool get isPotentiallyFalse => this != True; |
| |
| static AbstractBool trueOrMaybe(bool value) => value ? True : Maybe; |
| |
| static AbstractBool trueOrFalse(bool value) => value ? True : False; |
| |
| static AbstractBool maybeOrFalse(bool value) => value ? Maybe : False; |
| |
| static AbstractBool strengthen(AbstractBool a, AbstractBool b) { |
| //TODO(coam): Assert arguments a and b are consistent |
| return a.isDefinitelyTrue ? True : (a.isDefinitelyFalse ? False : b); |
| } |
| |
| AbstractBool operator &(AbstractBool other) { |
| if (isDefinitelyTrue) return other; |
| if (other.isDefinitelyTrue) return this; |
| if (isDefinitelyFalse || other.isDefinitelyFalse) return False; |
| return Maybe; |
| } |
| |
| AbstractBool operator |(AbstractBool other) { |
| if (isDefinitelyFalse) return other; |
| if (other.isDefinitelyFalse) return this; |
| if (isDefinitelyTrue || other.isDefinitelyTrue) return True; |
| return Maybe; |
| } |
| |
| AbstractBool operator ~() { |
| if (isDefinitelyTrue) return AbstractBool.False; |
| if (isDefinitelyFalse) return AbstractBool.True; |
| return AbstractBool.Maybe; |
| } |
| } |
| |
| /// A value in an abstraction of runtime values. |
| abstract class AbstractValue {} |
| |
| /// A pair of an AbstractValue and a precision flag. See |
| /// [AbstractValueDomain.createFromStaticType] for semantics of [isPrecise]. |
| class AbstractValueWithPrecision { |
| final AbstractValue abstractValue; |
| final bool isPrecise; |
| |
| const AbstractValueWithPrecision(this.abstractValue, this.isPrecise); |
| |
| @override |
| String toString() => |
| 'AbstractValueWithPrecision($abstractValue, isPrecise: $isPrecise)'; |
| } |
| |
| /// A system that implements an abstraction over runtime values. |
| mixin AbstractValueDomain { |
| /// The [AbstractValue] that represents a type which has not yet been |
| /// computed. Type graph nodes may carry this type during construction of the |
| /// graph, but it should be replaced by a computed type by the time the graph |
| /// is queried. |
| AbstractValue get uncomputedType => emptyType; |
| |
| /// The [AbstractValue] that represents an unknown runtime value. This |
| /// includes values internal to the implementation, such as late sentinels. |
| AbstractValue get internalTopType; |
| |
| /// The [AbstractValue] that represents an unknown runtime Dart value. |
| AbstractValue get dynamicType; |
| |
| /// The [AbstractValue] that represents a non-null subtype of `Type` at |
| /// runtime. |
| AbstractValue get typeType; |
| |
| /// The [AbstractValue] that represents a non-null subtype of `Function` at |
| /// runtime. |
| AbstractValue get functionType; |
| |
| /// The [AbstractValue] that represents a non-null subtype of `Record` at |
| /// runtime. |
| AbstractValue get recordType; |
| |
| /// The [AbstractValue] that represents a non-null subtype of `bool` at |
| /// runtime. |
| AbstractValue get boolType; |
| |
| /// The [AbstractValue] that represents a non-null subtype of `int` at |
| /// runtime. |
| AbstractValue get intType; |
| |
| /// The [AbstractValue] that represents a non-null subtype of `double` at |
| /// runtime. |
| AbstractValue get numNotIntType; |
| |
| /// The [AbstractValue] that represents a non-null subtype of `num` at |
| /// runtime. |
| AbstractValue get numType; |
| |
| /// The [AbstractValue] that represents a non-null subtype of `String` at |
| /// runtime. |
| AbstractValue get stringType; |
| |
| /// The [AbstractValue] that represents a non-null subtype of `List` at |
| /// runtime. |
| AbstractValue get listType; |
| |
| /// The [AbstractValue] that represents a non-null subtype of `Set` at |
| /// runtime. |
| AbstractValue get setType; |
| |
| /// The [AbstractValue] that represents a non-null subtype of `Map` at |
| /// runtime. |
| AbstractValue get mapType; |
| |
| /// The [AbstractValue] that represents a non-null value at runtime. |
| AbstractValue get nonNullType; |
| |
| /// The [AbstractValue] that represents the `null` at runtime. |
| AbstractValue get nullType; |
| |
| /// The [AbstractValue] that represents a late sentinel value at runtime. |
| AbstractValue get lateSentinelType; |
| |
| /// The [AbstractValue] that represents a non-null growable JavaScript array |
| /// at runtime. |
| AbstractValue get growableListType; |
| |
| /// The [AbstractValue] that represents a non-null fixed size JavaScript array |
| /// at runtime. |
| AbstractValue get fixedListType; |
| |
| /// The [AbstractValue] that represents the union of [growableListType] and |
| /// [fixedListType], i.e. JavaScript arrays that may have their elements |
| /// assigned. |
| AbstractValue get mutableArrayType; |
| |
| /// The [AbstractValue] that represents a non-null 31-bit unsigned integer at |
| /// runtime. |
| AbstractValue get uint31Type; |
| |
| /// The [AbstractValue] that represents a non-null 32-bit unsigned integer at |
| /// runtime. |
| AbstractValue get uint32Type; |
| |
| /// The [AbstractValue] that represents a non-null unsigned integer at |
| /// runtime. |
| AbstractValue get positiveIntType; |
| |
| /// The [AbstractValue] that represents a non-null constant list literal at |
| /// runtime. |
| AbstractValue get constListType; |
| |
| /// The [AbstractValue] that represents a non-null constant set literal at |
| /// runtime. |
| AbstractValue get constSetType; |
| |
| /// The [AbstractValue] that represents a non-null constant map literal at |
| /// runtime. |
| AbstractValue get constMapType; |
| |
| /// The [AbstractValue] that represents the empty set of runtime values. |
| AbstractValue get emptyType; |
| |
| /// The [AbstractValue] that represents a non-null instance at runtime of the |
| /// `Iterable` class used for the `sync*` implementation. |
| AbstractValue get syncStarIterableType; |
| |
| /// The [AbstractValue] that represents a non-null instance at runtime of the |
| /// `Future` class used for the `async` implementation. |
| AbstractValue get asyncFutureType; |
| |
| /// The [AbstractValue] that represents a non-null instance at runtime of the |
| /// `Stream` class used for the `async*` implementation. |
| AbstractValue get asyncStarStreamType; |
| |
| /// Returns an [AbstractValue] and a precision flag. |
| /// |
| /// Creates an [AbstractValue] corresponding to an expression of the given |
| /// static [type] and [classRelation], and an `isPrecise` flag that is `true` |
| /// if the [AbstractValue] precisely represents the [type], or `false` if the |
| /// [AbstractValue] is an approximation. |
| /// |
| /// If `isPrecise` is `true`, then the abstract value is equivalent to [type]. |
| /// |
| /// If `isPrecise` is `false` then the abstract value contains all types in |
| /// [type] but might contain more. Two different Dart types can have the same |
| /// approximation, so care must be taken not to make subtype judgements from |
| /// imprecise abstract values. |
| /// |
| /// The type `T` where `T` is a type parameter would be modelled by an |
| /// imprecise abstract value type since we don't know how `T` is |
| /// instantiated. It might be approximated by the bound of `T`. `List<T>` |
| /// where `T` is a type parameter would be modelled as imprecise for the same |
| /// reason. |
| /// |
| /// If the abstract value domain does not track generic type parameters (e.g. |
| /// the current implementation of type-masks), then `List<int>` would need to |
| /// be modelled by an imprecise abstract value. `List<dynamic>` might be the |
| /// imprecise approximation. |
| /// |
| /// In the context of a run-time type check, an imprecise abstract value can |
| /// be used to compute an output type by narrowing the input type, but only a |
| /// precise abstract value could be used to remove the check on the basis of |
| /// the input's abstract type. The check can only be removed with additional |
| /// reasoning, for example, that a dominating check uses the same type |
| /// expression. |
| /// |
| /// [nullable] determines if the type in weak or legacy mode should be |
| /// interpreted as nullable. This is passed as `false` for is-tests and `true` |
| /// for as-checks and other contexts (e.g. parameter checks). |
| AbstractValueWithPrecision createFromStaticType(DartType type, |
| {required bool nullable}); |
| |
| /// Creates an [AbstractValue] for a non-null exact instance of [cls]. |
| AbstractValue createNonNullExact(ClassEntity cls); |
| |
| /// Creates an [AbstractValue] for a potentially null exact instance of [cls]. |
| AbstractValue createNullableExact(ClassEntity cls); |
| |
| /// Creates an [AbstractValue] for a non-null instance that extends [cls]. |
| AbstractValue createNonNullSubclass(ClassEntity cls); |
| |
| /// Creates an [AbstractValue] for a non-null instance that implements [cls]. |
| AbstractValue createNonNullSubtype(ClassEntity cls); |
| |
| /// Creates an [AbstractValue] for a potentially null instance that implements |
| /// [cls]. |
| AbstractValue createNullableSubtype(ClassEntity cls); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a native typed |
| /// array or `null` at runtime. |
| AbstractBool isTypedArray(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] could be a native |
| /// typed array at runtime. |
| AbstractBool couldBeTypedArray(covariant AbstractValue value); |
| |
| /// Returns the version of the abstract [value] that excludes `null`. |
| AbstractValue excludeNull(covariant AbstractValue value); |
| |
| /// Returns the version of the abstract [value] that includes `null`. |
| AbstractValue includeNull(covariant AbstractValue value); |
| |
| /// Returns the version of the abstract [value] that excludes the late |
| /// sentinel. |
| AbstractValue excludeLateSentinel(covariant AbstractValue value); |
| |
| /// Returns the version of the abstract [value] that includes the late |
| /// sentinel. |
| AbstractValue includeLateSentinel(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] contains |
| /// instances of [cls] at runtime. |
| AbstractBool containsType(covariant AbstractValue value, ClassEntity cls); |
| |
| /// Returns an [AbstractBool] that describes whether [value] only contains |
| /// subtypes of [cls] or `null` at runtime. |
| AbstractBool containsOnlyType(covariant AbstractValue value, ClassEntity cls); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is known to be an |
| /// instance of [cls] at runtime. |
| AbstractBool isInstanceOf(AbstractValue value, ClassEntity cls); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is empty set of |
| /// runtime values. |
| AbstractBool isEmpty(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a non-null |
| /// exact class at runtime. |
| AbstractBool isExact(covariant AbstractValue value); |
| |
| /// Returns the [ClassEntity] if this [value] is a non-null instance of an |
| /// exact class at runtime, and `null` otherwise. |
| ClassEntity? getExactClass(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is `null` at |
| /// runtime. |
| AbstractBool isNull(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a sentinel for |
| /// an uninitialized late variable at runtime. |
| AbstractBool isLateSentinel(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a JavaScript |
| /// bool, number, string, array or `null` at runtime. |
| AbstractBool isPrimitive(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a JavaScript |
| /// number at runtime. |
| AbstractBool isPrimitiveNumber(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a JavaScript |
| /// bool at runtime. |
| AbstractBool isPrimitiveBoolean(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a JavaScript |
| /// string, array, native HTML list or `null` at runtime. |
| AbstractBool isIndexablePrimitive(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a fixed-size |
| /// or constant JavaScript array or `null` at runtime. |
| AbstractBool isFixedArray(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a growable |
| /// JavaScript array or `null` at runtime. |
| AbstractBool isExtendableArray(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a mutable |
| /// JavaScript array or `null` at runtime. |
| AbstractBool isMutableArray(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a mutable |
| /// JavaScript array, native HTML list or `null` at runtime. |
| AbstractBool isMutableIndexable(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a JavaScript |
| /// array or `null` at runtime. |
| AbstractBool isArray(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a JavaScript |
| /// string at runtime. |
| AbstractBool isPrimitiveString(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is an interceptor |
| /// at runtime. |
| AbstractBool isInterceptor(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a non-null |
| /// integer value at runtime. |
| AbstractBool isInteger(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a non-null 32 |
| /// bit unsigned integer value at runtime. |
| AbstractBool isUInt32(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a non-null 31 |
| /// bit unsigned integer value at runtime. |
| AbstractBool isUInt31(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a non-null |
| /// unsigned integer value at runtime. |
| AbstractBool isPositiveInteger(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is an unsigned |
| /// integer value or `null` at runtime. |
| AbstractBool isPositiveIntegerOrNull(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is an integer |
| /// value or `null` at runtime. |
| AbstractBool isIntegerOrNull(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a non-null |
| /// JavaScript number at runtime. |
| AbstractBool isNumber(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a JavaScript |
| /// number or `null` at runtime. |
| AbstractBool isNumberOrNull(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a JavaScript |
| /// bool at runtime. |
| AbstractBool isBoolean(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a JavaScript |
| /// bool or `null` at runtime. |
| AbstractBool isBooleanOrNull(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a JavaScript |
| /// string at runtime. |
| AbstractBool isString(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] is a JavaScript |
| /// string or `null` at runtime. |
| AbstractBool isStringOrNull(covariant AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes whether [value] a JavaScript |
| /// primitive, possible `null`. |
| AbstractBool isPrimitiveOrNull(covariant AbstractValue value); |
| |
| /// Return an [AbstractBool] that describes whether [value] is a JavaScript |
| /// 'truthy' value at runtime. This is effectively symbolically evaluating the |
| /// abstract value as a JavaScript condition. |
| AbstractBool isTruthy(covariant AbstractValue value); |
| |
| /// Returns [AbstractValue] for the runtime values contained in either [a] or |
| /// [b]. |
| AbstractValue union(covariant AbstractValue a, covariant AbstractValue b); |
| |
| /// Returns [AbstractValue] for the runtime values contained in at least one |
| /// of [values]. |
| AbstractValue unionOfMany(Iterable<AbstractValue> values); |
| |
| /// Returns [AbstractValue] for the runtime values that [a] and [b] have in |
| /// common. |
| AbstractValue intersection( |
| covariant AbstractValue a, covariant AbstractValue b); |
| |
| /// Returns an [AbstractBool] that describes whether [a] and [b] have no |
| /// runtime values in common. |
| AbstractBool areDisjoint( |
| covariant AbstractValue a, covariant AbstractValue b); |
| |
| /// Returns an [AbstractBool] that describes whether [a] contains all non-null |
| /// runtime values. |
| AbstractBool containsAll(covariant AbstractValue a); |
| |
| /// Computes the [AbstractValue] corresponding to the constant [value]. |
| AbstractValue computeAbstractValueForConstant(ConstantValue value); |
| |
| /// Returns `true` if [value] represents a container value at runtime. |
| bool isContainer(covariant AbstractValue value); |
| |
| /// Creates a container value specialization of [originalValue] with the |
| /// inferred [element] runtime value and inferred runtime [length]. |
| /// |
| /// The [allocationNode] is used to identify this particular map allocation. |
| /// The [allocationElement] is used only for debugging. |
| AbstractValue createContainerValue( |
| AbstractValue? originalValue, |
| Object? allocationNode, |
| MemberEntity? allocationElement, |
| AbstractValue elementType, |
| int? length); |
| |
| /// Returns the element type of [value] if it represents a container value |
| /// at runtime. Returns [dynamicType] otherwise. |
| AbstractValue getContainerElementType(AbstractValue value); |
| |
| /// Return the known length of [value] if it represents a container value |
| /// at runtime. Returns `null` if the length is unknown or if [value] doesn't |
| /// represent a container value at runtime. |
| int? getContainerLength(AbstractValue value); |
| |
| /// Returns `true` if [value] represents a set value at runtime. |
| bool isSet(covariant AbstractValue value); |
| |
| /// Creates a set value specialization of [originalValue] with the inferred |
| /// [elementType] runtime value. |
| /// |
| /// The [allocationNode] is used to identify this particular set allocation. |
| /// The [allocationElement] is used only for debugging. |
| AbstractValue createSetValue( |
| AbstractValue? originalValue, |
| Object? allocationNode, |
| MemberEntity? allocationElement, |
| AbstractValue elementType); |
| |
| /// Returns the element type of [value] if it represents a set value at |
| /// runtime. Returns [dynamicType] otherwise. |
| AbstractValue getSetElementType(AbstractValue value); |
| |
| /// Returns `true` if [value] represents a map value at runtime. |
| bool isMap(covariant AbstractValue value); |
| |
| /// Creates a map value specialization of [originalValue] with the inferred |
| /// [key] and [value] runtime values. |
| /// |
| /// The [allocationNode] is used to identify this particular map allocation. |
| /// The [allocationElement] is used only for debugging. |
| AbstractValue createMapValue( |
| AbstractValue? originalValue, |
| Object? allocationNode, |
| MemberEntity? allocationElement, |
| AbstractValue key, |
| AbstractValue value); |
| |
| /// Returns the key type of [value] if it represents a map value at runtime. |
| /// Returns [dynamicType] otherwise. |
| AbstractValue getMapKeyType(AbstractValue value); |
| |
| /// Returns the value type of [value] if it represents a map value at runtime. |
| /// Returns [dynamicType] otherwise. |
| AbstractValue getMapValueType(AbstractValue value); |
| |
| /// Returns `true` if [value] represents a dictionary value, that is, a map |
| /// with strings as keys, at runtime. |
| bool isDictionary(covariant AbstractValue value); |
| |
| /// Creates a dictionary value specialization of [originalValue] with the |
| /// inferred [key] and [value] runtime values. |
| /// |
| /// The [allocationNode] is used to identify this particular map allocation. |
| /// The [allocationElement] is used only for debugging. |
| AbstractValue createDictionaryValue( |
| AbstractValue? originalValue, |
| Object? allocationNode, |
| MemberEntity? allocationElement, |
| AbstractValue key, |
| AbstractValue value, |
| Map<String, AbstractValue> mappings); |
| |
| /// Returns `true` if [value] is a dictionary value which contains [key] as |
| /// a key. |
| bool containsDictionaryKey(AbstractValue value, String key); |
| |
| /// Returns the value type for [key] in [value] if it represents a dictionary |
| /// value at runtime. Returns [dynamicType] otherwise. |
| AbstractValue getDictionaryValueForKey(AbstractValue value, String key); |
| |
| /// Creates a record value with the specified [shape] and the specified type |
| /// for each field in [types]. |
| AbstractValue createRecordValue(RecordShape shape, List<AbstractValue> types); |
| |
| /// Returns `true` if [value] represents a record value at runtime. |
| bool isRecord(covariant AbstractValue value); |
| |
| /// Returns `true` if [value] is a record type containing a field with name |
| /// [field]. |
| bool recordHasGetter(AbstractValue value, String field); |
| |
| /// Returns the value of the field record with name [field] in [value] if it |
| /// is a record type otherwise returns [dynamicType]. |
| AbstractValue getGetterTypeInRecord(AbstractValue value, String field); |
| |
| /// Returns `true` if [specialization] is a specialization of |
| /// [generalization]. |
| /// |
| /// Specializations are created through [createPrimitiveValue], |
| /// [createMapValue], [createDictionaryValue] and [createContainerValue]. |
| bool isSpecializationOf( |
| AbstractValue specialization, AbstractValue generalization); |
| |
| /// Returns the value of which [value] is a specialization. Return `null` if |
| /// [value] is not a specialization. |
| /// |
| /// Specializations are created through [createPrimitiveValue], |
| /// [createMapValue], [createDictionaryValue] and [createContainerValue]. |
| AbstractValue? getGeneralization(AbstractValue? value); |
| |
| /// Return the object identifying the allocation of [value] if it is an |
| /// allocation based specialization. Otherwise returns `null`. |
| /// |
| /// Allocation based specializations are created through [createMapValue], |
| /// [createDictionaryValue] and [createContainerValue] |
| Object? getAllocationNode(AbstractValue value); |
| |
| /// Return the allocation element of [value] if it is an allocation based |
| /// specialization. Otherwise returns `null`. |
| /// |
| /// Allocation based specializations are created through [createMapValue], |
| /// [createDictionaryValue] and [createContainerValue] |
| MemberEntity? getAllocationElement(AbstractValue value); |
| |
| /// Returns `true` if [value] a known primitive JavaScript value at runtime. |
| bool isPrimitiveValue(covariant AbstractValue value); |
| |
| /// Creates a primitive value specialization of [originalValue] with the |
| /// inferred primitive constant [value]. |
| AbstractValue createPrimitiveValue( |
| AbstractValue originalValue, PrimitiveConstantValue value); |
| |
| /// Returns the primitive JavaScript value of [value] if it represents a |
| /// primitive JavaScript value at runtime, value at runtime. Returns `null` |
| /// otherwise. |
| PrimitiveConstantValue? getPrimitiveValue(covariant AbstractValue value); |
| |
| /// Compute the type of all potential receivers of the set of live [members]. |
| AbstractValue computeReceiver(Iterable<MemberEntity> members); |
| |
| /// Returns an [AbstractBool] that describes whether [member] is a potential |
| /// target when being invoked on a [receiver]. [name] is used to ensure |
| /// library privacy is taken into account. |
| AbstractBool isTargetingMember( |
| AbstractValue receiver, MemberEntity member, Name name); |
| |
| /// Returns an [AbstractBool] that describes whether [selector] invoked on a |
| /// [receiver] can hit a [noSuchMethod]. |
| AbstractBool needsNoSuchMethodHandling( |
| AbstractValue receiver, Selector selector); |
| |
| /// Returns the [AbstractValue] for the [parameterType] of a native |
| /// method. May return `null`, for example, if [parameterType] is not modelled |
| /// precisely by an [AbstractValue]. |
| AbstractValue? getAbstractValueForNativeMethodParameterType(DartType type); |
| |
| /// Returns an [AbstractBool] that describes if the set of runtime values of |
| /// [subset] are known to all be in the set of runtime values of [superset]. |
| AbstractBool isIn(AbstractValue subset, AbstractValue superset); |
| |
| /// Returns the [MemberEntity] that is known to always be hit at runtime |
| /// [receiver]. |
| /// |
| /// Returns `null` if 0 or more than 1 member can be hit at runtime. |
| MemberEntity? locateSingleMember(AbstractValue receiver, Selector selector); |
| |
| /// Returns an [AbstractBool] that describes if [value] is known to be an |
| /// indexable JavaScript value at runtime. |
| AbstractBool isJsIndexable(covariant AbstractValue value); |
| |
| /// RReturns an [AbstractBool] that describes if [value] is known to be an |
| /// indexable or iterable JavaScript value at runtime. |
| /// |
| /// JavaScript arrays are both indexable and iterable whereas JavaScript |
| /// strings are indexable but not iterable. |
| AbstractBool isJsIndexableAndIterable(AbstractValue value); |
| |
| /// Returns an [AbstractBool] that describes if [value] is known to be a |
| /// JavaScript indexable of fixed length. |
| AbstractBool isFixedLengthJsIndexable(AbstractValue value); |
| |
| /// Returns compact a textual representation for [value] used for debugging. |
| String getCompactText(AbstractValue value); |
| |
| /// Returns a set of members that are ancestors of all possible targets for |
| /// a call targeting [selector] on an entity with type represented by |
| /// [receiver]. |
| Iterable<DynamicCallTarget> findRootsOfTargets(AbstractValue receiver, |
| Selector selector, MemberHierarchyBuilder memberHierarchyBuilder); |
| |
| /// Deserializes an [AbstractValue] for this domain from [source]. |
| AbstractValue readAbstractValueFromDataSource(DataSourceReader source); |
| |
| /// Serializes this [value] for this domain to [sink]. |
| void writeAbstractValueToDataSink(DataSinkWriter sink, AbstractValue? value); |
| |
| bool isInvalidRefinement(AbstractValue before, AbstractValue after); |
| |
| void finalizeMetrics() {} |
| |
| Metrics get metrics => Metrics.none(); |
| } |