// Copyright (c) 2012, 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.

/// This library defines individual world impacts.
///
/// We call these building blocks `uses`. Each `use` is a single impact of the
/// world. Some example uses are:
///
///  * an invocation of a top level function
///  * a call to the `foo()` method on an unknown class.
///  * an instantiation of class T
///
/// The different compiler stages combine these uses into `WorldImpact` objects,
/// which are later used to construct a closed-world understanding of the
/// program.
library dart2js.universe.use;

import '../common.dart';
import '../constants/values.dart';
import '../elements/types.dart';
import '../elements/entities.dart';
import '../inferrer/abstract_value_domain.dart';
import '../serialization/serialization_interfaces.dart';
import '../js_model/jrecord_field_interface.dart' show JRecordFieldInterface;
import '../util/util.dart' show equalElements, Hashing;
import 'call_structure.dart' show CallStructure;
import 'selector.dart' show Selector;
import 'strong_mode_constraint.dart' show StrongModeConstraintInterface;

enum DynamicUseKind {
  INVOKE,
  GET,
  SET,
}

/// The use of a dynamic property. [selector] defined the name and kind of the
/// property and [receiverConstraint] defines the known constraint for the
/// object on which the property is accessed.
class DynamicUse {
  static const String tag = 'dynamic-use';

  final Selector selector;
  final Object? receiverConstraint;
  final List<DartType>? _typeArguments;

  DynamicUse(this.selector, this.receiverConstraint, this._typeArguments)
      : assert(
            selector.callStructure.typeArgumentCount ==
                (_typeArguments?.length ?? 0),
            "Type argument count mismatch. Selector has "
            "${selector.callStructure.typeArgumentCount} but "
            "${_typeArguments?.length ?? 0} were passed.");

  DynamicUse withReceiverConstraint(Object otherReceiverConstraint) {
    if (otherReceiverConstraint == receiverConstraint) {
      return this;
    }
    return DynamicUse(selector, otherReceiverConstraint, _typeArguments);
  }

  factory DynamicUse.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    Selector selector = Selector.readFromDataSource(source);
    bool hasConstraint = source.readBool();
    Object? receiverConstraint;
    if (hasConstraint) {
      receiverConstraint = source.readAbstractValue();
    }
    List<DartType>? typeArguments = source.readDartTypesOrNull();
    source.end(tag);
    return DynamicUse(selector, receiverConstraint, typeArguments);
  }

  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    selector.writeToDataSink(sink);
    var constraint = receiverConstraint;
    sink.writeBool(constraint != null);
    if (constraint != null) {
      if (constraint is AbstractValue) {
        sink.writeAbstractValue(constraint);
      } else {
        throw UnsupportedError(
            "Unsupported receiver constraint: ${constraint}");
      }
    }
    sink.writeDartTypesOrNull(_typeArguments);
    sink.end(tag);
  }

  /// Short textual representation use for testing.
  String get shortText {
    StringBuffer sb = StringBuffer();
    if (receiverConstraint != null) {
      var constraint = receiverConstraint;
      if (constraint is StrongModeConstraintInterface) {
        if (constraint.isThis) {
          sb.write('this:');
        } else if (constraint.isExact) {
          sb.write('exact:');
        }
        sb.write(constraint.className);
      } else {
        sb.write(constraint);
      }
      sb.write('.');
    }
    sb.write(selector.name);
    if (typeArguments.isNotEmpty) {
      sb.write('<');
      sb.write(typeArguments.join(','));
      sb.write('>');
    }
    if (selector.isCall) {
      sb.write(selector.callStructure.shortText);
    } else if (selector.isSetter) {
      sb.write('=');
    }
    return sb.toString();
  }

  DynamicUseKind get kind {
    if (selector.isGetter) {
      return DynamicUseKind.GET;
    } else if (selector.isSetter) {
      return DynamicUseKind.SET;
    } else {
      return DynamicUseKind.INVOKE;
    }
  }

  List<DartType> get typeArguments => _typeArguments ?? const [];

  @override
  int get hashCode => Hashing.listHash(
      typeArguments, Hashing.objectsHash(selector, receiverConstraint));

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! DynamicUse) return false;
    return selector == other.selector &&
        receiverConstraint == other.receiverConstraint &&
        equalElements(typeArguments, other.typeArguments);
  }

  @override
  String toString() => '$selector,$receiverConstraint,$typeArguments';
}

enum StaticUseKind {
  STATIC_TEAR_OFF,
  SUPER_TEAR_OFF,
  SUPER_FIELD_SET,
  SUPER_GET,
  SUPER_SETTER_SET,
  SUPER_INVOKE,
  INSTANCE_FIELD_GET,
  INSTANCE_FIELD_SET,
  CLOSURE,
  CLOSURE_CALL,
  CALL_METHOD,
  CONSTRUCTOR_INVOKE,
  CONST_CONSTRUCTOR_INVOKE,
  DIRECT_INVOKE,
  INLINING,
  STATIC_INVOKE,
  STATIC_GET,
  STATIC_SET,
  FIELD_INIT,
  FIELD_CONSTANT_INIT,
}

/// Statically known use of an [Entity].
// TODO(johnniwinther): Create backend-specific implementations with better
// invariants.
class StaticUse {
  static const String tag = 'static-use';

  final Entity element;
  final StaticUseKind kind;
  @override
  final int hashCode;
  final InterfaceType? type;
  final CallStructure? callStructure;
  final ImportEntity? deferredImport;
  final ConstantValue? constant;
  final List<DartType>? typeArguments;

  StaticUse.internal(Entity element, this.kind,
      {this.type,
      this.callStructure,
      this.deferredImport,
      this.typeArguments,
      this.constant})
      : this.element = element,
        this.hashCode = Hashing.listHash([
          element,
          kind,
          type,
          Hashing.listHash(typeArguments),
          callStructure,
          deferredImport,
          constant
        ]);

  bool _checkGenericInvariants() {
    assert(
        (callStructure?.typeArgumentCount ?? 0) == (typeArguments?.length ?? 0),
        failedAt(
            element,
            "Type argument count mismatch. Call structure has "
            "${callStructure?.typeArgumentCount ?? 0} but "
            "${typeArguments?.length ?? 0} were passed in $this."));
    return true;
  }

  factory StaticUse.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    MemberEntity element = source.readMember();
    StaticUseKind kind = source.readEnum(StaticUseKind.values);
    InterfaceType? type = source.readDartTypeOrNull() as InterfaceType?;
    CallStructure? callStructure =
        source.readValueOrNull(() => CallStructure.readFromDataSource(source));
    ImportEntity? deferredImport = source.readImportOrNull();
    ConstantValue? constant = source.readConstantOrNull();
    List<DartType>? typeArguments = source.readDartTypesOrNull();
    source.end(tag);
    return StaticUse.internal(element, kind,
        type: type,
        callStructure: callStructure,
        deferredImport: deferredImport,
        constant: constant,
        typeArguments: typeArguments);
  }

  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeMember(element as MemberEntity);
    sink.writeEnum(kind);
    sink.writeDartTypeOrNull(type);
    sink.writeValueOrNull(
        callStructure, (CallStructure c) => c.writeToDataSink(sink));
    sink.writeImportOrNull(deferredImport);
    sink.writeConstantOrNull(constant);
    sink.writeDartTypesOrNull(typeArguments);
    sink.end(tag);
  }

  /// Short textual representation use for testing.
  String get shortText {
    StringBuffer sb = StringBuffer();
    switch (kind) {
      case StaticUseKind.INSTANCE_FIELD_SET:
      case StaticUseKind.SUPER_FIELD_SET:
      case StaticUseKind.SUPER_SETTER_SET:
      case StaticUseKind.STATIC_SET:
        sb.write('set:');
        break;
      case StaticUseKind.FIELD_INIT:
        sb.write('init:');
        break;
      case StaticUseKind.CLOSURE:
        sb.write('def:');
        break;
      default:
    }
    final member = element;
    if (member is MemberEntity) {
      if (member.enclosingClass != null) {
        sb.write(member.enclosingClass!.name);
        sb.write('.');
      }
    }
    if (member.name == null) {
      sb.write('<anonymous>');
    } else {
      sb.write(member.name);
    }
    if (typeArguments != null && typeArguments!.isNotEmpty) {
      sb.write('<');
      sb.write(typeArguments!.join(','));
      sb.write('>');
    }
    final callStructureLocal = callStructure;
    if (callStructureLocal != null) {
      sb.write('(');
      sb.write(callStructureLocal.positionalArgumentCount);
      if (callStructureLocal.namedArgumentCount > 0) {
        sb.write(',');
        sb.write(callStructureLocal.getOrderedNamedArguments().join(','));
      }
      sb.write(')');
    }
    if (deferredImport != null) {
      sb.write('{');
      sb.write(deferredImport!.name);
      sb.write('}');
    }
    if (constant != null) {
      sb.write('=');
      sb.write(constant!.toStructuredText(null));
    }
    return sb.toString();
  }

  /// Invocation of a static or top-level [element] with the given
  /// [callStructure].
  factory StaticUse.staticInvoke(
      FunctionEntity element, CallStructure callStructure,
      [List<DartType>? typeArguments, ImportEntity? deferredImport]) {
    assert(
        element.isStatic || element.isTopLevel,
        failedAt(
            element,
            "Static invoke element $element must be a top-level "
            "or static method."));
    assert(element.isFunction,
        failedAt(element, "Static get element $element must be a function."));
    assert(
        (callStructure as dynamic) != null, // TODO(48820): remove when sound
        failedAt(element,
            "Not CallStructure for static invocation of element $element."));
    StaticUse staticUse = StaticUse.internal(
        element, StaticUseKind.STATIC_INVOKE,
        callStructure: callStructure,
        typeArguments: typeArguments,
        deferredImport: deferredImport);
    assert(staticUse._checkGenericInvariants());
    return staticUse;
  }

  /// Closurization of a static or top-level function [element].
  factory StaticUse.staticTearOff(FunctionEntity element,
      [ImportEntity? deferredImport]) {
    assert(
        element.isStatic || element.isTopLevel,
        failedAt(
            element,
            "Static tear-off element $element must be a top-level "
            "or static method."));
    assert(element.isFunction,
        failedAt(element, "Static get element $element must be a function."));
    return StaticUse.internal(element, StaticUseKind.STATIC_TEAR_OFF,
        deferredImport: deferredImport);
  }

  /// Read access of a static or top-level field or getter [element].
  factory StaticUse.staticGet(MemberEntity element,
      [ImportEntity? deferredImport]) {
    assert(
        element.isStatic || element.isTopLevel,
        failedAt(
            element,
            "Static get element $element must be a top-level "
            "or static field or getter."));
    assert(
        element.isField || element.isGetter,
        failedAt(element,
            "Static get element $element must be a field or a getter."));
    return StaticUse.internal(element, StaticUseKind.STATIC_GET,
        deferredImport: deferredImport);
  }

  /// Write access of a static or top-level field or setter [element].
  factory StaticUse.staticSet(MemberEntity element,
      [ImportEntity? deferredImport]) {
    assert(
        element.isStatic || element.isTopLevel,
        failedAt(
            element,
            "Static set element $element "
            "must be a top-level or static method."));
    assert(
        (element.isField && element.isAssignable) || element.isSetter,
        failedAt(element,
            "Static set element $element must be a field or a setter."));
    return StaticUse.internal(element, StaticUseKind.STATIC_SET,
        deferredImport: deferredImport);
  }

  /// Invocation of the lazy initializer for a static or top-level field
  /// [element].
  factory StaticUse.staticInit(FieldEntity element) {
    assert(
        element.isStatic || element.isTopLevel,
        failedAt(
            element,
            "Static init element $element must be a top-level "
            "or static method."));
    assert(element.isField,
        failedAt(element, "Static init element $element must be a field."));
    return StaticUse.internal(element, StaticUseKind.FIELD_INIT);
  }

  /// Invocation of a super method [element] with the given [callStructure].
  factory StaticUse.superInvoke(
      FunctionEntity element, CallStructure callStructure,
      [List<DartType>? typeArguments]) {
    assert(
        element.isInstanceMember,
        failedAt(element,
            "Super invoke element $element must be an instance method."));
    assert(
        (callStructure as dynamic) != null, // TODO(48820): remove when sound
        failedAt(element,
            "Not CallStructure for super invocation of element $element."));
    StaticUse staticUse = StaticUse.internal(
        element, StaticUseKind.SUPER_INVOKE,
        callStructure: callStructure, typeArguments: typeArguments);
    assert(staticUse._checkGenericInvariants());
    return staticUse;
  }

  /// Read access of a super field or getter [element].
  factory StaticUse.superGet(MemberEntity element) {
    assert(
        element.isInstanceMember,
        failedAt(
            element, "Super get element $element must be an instance method."));
    assert(
        element.isField || element.isGetter,
        failedAt(element,
            "Super get element $element must be a field or a getter."));
    return StaticUse.internal(element, StaticUseKind.SUPER_GET);
  }

  /// Write access of a super field [element].
  factory StaticUse.superFieldSet(FieldEntity element) {
    assert(
        element.isInstanceMember,
        failedAt(
            element, "Super set element $element must be an instance method."));
    assert(element.isField,
        failedAt(element, "Super set element $element must be a field."));
    return StaticUse.internal(element, StaticUseKind.SUPER_FIELD_SET);
  }

  /// Write access of a super setter [element].
  factory StaticUse.superSetterSet(FunctionEntity element) {
    assert(
        element.isInstanceMember,
        failedAt(
            element, "Super set element $element must be an instance method."));
    assert(element.isSetter,
        failedAt(element, "Super set element $element must be a setter."));
    return StaticUse.internal(element, StaticUseKind.SUPER_SETTER_SET);
  }

  /// Closurization of a super method [element].
  factory StaticUse.superTearOff(FunctionEntity element) {
    assert(
        element.isInstanceMember && element.isFunction,
        failedAt(element,
            "Super invoke element $element must be an instance method."));
    return StaticUse.internal(element, StaticUseKind.SUPER_TEAR_OFF);
  }

  /// Invocation of a constructor [element] through a this or super
  /// constructor call with the given [callStructure].
  factory StaticUse.superConstructorInvoke(
      ConstructorEntity element, CallStructure callStructure) {
    assert(
        element.isGenerativeConstructor,
        failedAt(
            element,
            "Constructor invoke element $element must be a "
            "generative constructor."));
    assert(
        (callStructure as dynamic) != null, // TODO(48820): remove when sound
        failedAt(
            element,
            "Not CallStructure for super constructor invocation of element "
            "$element."));
    return StaticUse.internal(element, StaticUseKind.STATIC_INVOKE,
        callStructure: callStructure);
  }

  /// Invocation of a constructor (body) [element] through a this or super
  /// constructor call with the given [callStructure].
  factory StaticUse.constructorBodyInvoke(
      ConstructorBodyEntity element, CallStructure callStructure) {
    assert(
        (callStructure as dynamic) != null, // TODO(48820): remove when sound
        failedAt(
            element,
            "Not CallStructure for constructor body invocation of element "
            "$element."));
    return StaticUse.internal(element, StaticUseKind.STATIC_INVOKE,
        callStructure: callStructure);
  }

  /// Direct invocation of a generator (body) [element], as a static call or
  /// through a this or super constructor call.
  factory StaticUse.generatorBodyInvoke(FunctionEntity element) {
    return StaticUse.internal(element, StaticUseKind.STATIC_INVOKE,
        callStructure: CallStructure.NO_ARGS);
  }

  /// Direct invocation of a method [element] with the given [callStructure].
  factory StaticUse.directInvoke(FunctionEntity element,
      CallStructure callStructure, List<DartType> typeArguments) {
    assert(
        element.isInstanceMember,
        failedAt(element,
            "Direct invoke element $element must be an instance member."));
    assert(element.isFunction,
        failedAt(element, "Direct invoke element $element must be a method."));
    StaticUse staticUse = StaticUse.internal(
        element, StaticUseKind.DIRECT_INVOKE,
        callStructure: callStructure, typeArguments: typeArguments);
    assert(staticUse._checkGenericInvariants());
    return staticUse;
  }

  /// Direct read access of a field or getter [element].
  factory StaticUse.directGet(MemberEntity element) {
    assert(
        element.isInstanceMember,
        failedAt(element,
            "Direct get element $element must be an instance member."));
    assert(
        element.isField || element.isGetter,
        failedAt(element,
            "Direct get element $element must be a field or a getter."));
    return StaticUse.internal(element, StaticUseKind.STATIC_GET);
  }

  /// Direct write access of a field [element].
  factory StaticUse.directSet(FieldEntity element) {
    assert(
        element.isInstanceMember,
        failedAt(element,
            "Direct set element $element must be an instance member."));
    assert(element.isField,
        failedAt(element, "Direct set element $element must be a field."));
    return StaticUse.internal(element, StaticUseKind.STATIC_SET);
  }

  /// Constructor invocation of [element] with the given [callStructure].
  factory StaticUse.constructorInvoke(
      ConstructorEntity element, CallStructure callStructure) {
    assert(
        element.isConstructor,
        failedAt(element,
            "Constructor invocation element $element must be a constructor."));
    assert(
        (callStructure as dynamic) != null, // TODO(48820): remove when sound
        failedAt(
            element,
            "Not CallStructure for constructor invocation of element "
            "$element."));
    return StaticUse.internal(element, StaticUseKind.STATIC_INVOKE,
        callStructure: callStructure);
  }

  /// Constructor invocation of [element] with the given [callStructure] on
  /// [type].
  factory StaticUse.typedConstructorInvoke(
      ConstructorEntity element,
      CallStructure callStructure,
      InterfaceType type,
      ImportEntity deferredImport) {
    assert(
        (type as dynamic) != null, // TODO(48820): remove when sound
        failedAt(element, "No type provided for constructor invocation."));
    assert(
        element.isConstructor,
        failedAt(
            element,
            "Typed constructor invocation element $element "
            "must be a constructor."));
    return StaticUse.internal(element, StaticUseKind.CONSTRUCTOR_INVOKE,
        type: type,
        callStructure: callStructure,
        deferredImport: deferredImport);
  }

  /// Constant constructor invocation of [element] with the given
  /// [callStructure] on [type].
  factory StaticUse.constConstructorInvoke(
      ConstructorEntity element,
      CallStructure callStructure,
      InterfaceType type,
      ImportEntity deferredImport) {
    assert(
        (type as dynamic) != null, // TODO(48820): remove when sound
        failedAt(element, "No type provided for constructor invocation."));
    assert(
        element.isConstructor,
        failedAt(
            element,
            "Const constructor invocation element $element "
            "must be a constructor."));
    return StaticUse.internal(element, StaticUseKind.CONST_CONSTRUCTOR_INVOKE,
        type: type,
        callStructure: callStructure,
        deferredImport: deferredImport);
  }

  /// Initialization of an instance field [element].
  factory StaticUse.fieldInit(FieldEntity element) {
    assert(
        element.isInstanceMember,
        failedAt(
            element, "Field init element $element must be an instance field."));
    return StaticUse.internal(element, StaticUseKind.FIELD_INIT);
  }

  /// Constant initialization of an instance field [element].
  factory StaticUse.fieldConstantInit(
      FieldEntity element, ConstantValue constant) {
    assert(
        element.isInstanceMember,
        failedAt(
            element, "Field init element $element must be an instance field."));
    return StaticUse.internal(element, StaticUseKind.FIELD_CONSTANT_INIT,
        constant: constant);
  }

  /// Read access of an instance field or boxed field [element].
  factory StaticUse.fieldGet(FieldEntity element) {
    assert(
        element.isInstanceMember || element is JRecordFieldInterface,
        failedAt(element,
            "Field init element $element must be an instance or boxed field."));
    return StaticUse.internal(element, StaticUseKind.INSTANCE_FIELD_GET);
  }

  /// Write access of an instance field or boxed field [element].
  factory StaticUse.fieldSet(FieldEntity element) {
    assert(
        element.isInstanceMember || element is JRecordFieldInterface,
        failedAt(element,
            "Field init element $element must be an instance or boxed field."));
    return StaticUse.internal(element, StaticUseKind.INSTANCE_FIELD_SET);
  }

  /// Read of a local function [element].
  factory StaticUse.closure(Local element) {
    return StaticUse.internal(element, StaticUseKind.CLOSURE);
  }

  /// An invocation of a local function [element] with the provided
  /// [callStructure] and [typeArguments].
  factory StaticUse.closureCall(Local element, CallStructure callStructure,
      List<DartType> typeArguments) {
    StaticUse staticUse = StaticUse.internal(
        element, StaticUseKind.CLOSURE_CALL,
        callStructure: callStructure, typeArguments: typeArguments);
    assert(staticUse._checkGenericInvariants());
    return staticUse;
  }

  /// Read of a call [method] on a closureClass.
  factory StaticUse.callMethod(FunctionEntity method) {
    return StaticUse.internal(method, StaticUseKind.CALL_METHOD);
  }

  /// Implicit method/constructor invocation of [element] created by the
  /// backend.
  factory StaticUse.implicitInvoke(FunctionEntity element) {
    return StaticUse.internal(element, StaticUseKind.STATIC_INVOKE,
        callStructure: element.parameterStructure.callStructure);
  }

  /// Inlining of [element].
  factory StaticUse.constructorInlining(
      ConstructorEntity element, InterfaceType instanceType) {
    return StaticUse.internal(element, StaticUseKind.INLINING,
        type: instanceType);
  }

  /// Inlining of [element].
  factory StaticUse.methodInlining(
      FunctionEntity element, List<DartType> typeArguments) {
    return StaticUse.internal(element, StaticUseKind.INLINING,
        typeArguments: typeArguments);
  }

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    return other is StaticUse &&
        element == other.element &&
        kind == other.kind &&
        type == other.type &&
        callStructure == other.callStructure &&
        equalElements(typeArguments, other.typeArguments) &&
        deferredImport == other.deferredImport &&
        constant == other.constant;
  }

  @override
  String toString() =>
      'StaticUse($element,$kind,$type,$typeArguments,$callStructure)';
}

enum TypeUseKind {
  IS_CHECK,
  AS_CAST,
  CATCH_TYPE,
  TYPE_LITERAL,
  INSTANTIATION,
  NATIVE_INSTANTIATION,
  CONST_INSTANTIATION,
  CONSTRUCTOR_REFERENCE,
  IMPLICIT_CAST,
  PARAMETER_CHECK,
  RTI_VALUE,
  TYPE_ARGUMENT,
  NAMED_TYPE_VARIABLE_NEW_RTI,
  TYPE_VARIABLE_BOUND_CHECK,
}

/// Use of a [DartType].
class TypeUse {
  static const String tag = 'type-use';

  final DartType type;
  final TypeUseKind kind;
  @override
  final int hashCode;
  final ImportEntity? deferredImport;

  TypeUse.internal(DartType type, TypeUseKind kind, [this.deferredImport])
      : this.type = type,
        this.kind = kind,
        this.hashCode = Hashing.objectsHash(type, kind, deferredImport);

  factory TypeUse.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    DartType type = source.readDartType();
    TypeUseKind kind = source.readEnum(TypeUseKind.values);
    ImportEntity? deferredImport = source.readImportOrNull();
    source.end(tag);
    return TypeUse.internal(type, kind, deferredImport);
  }

  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeDartType(type);
    sink.writeEnum(kind);
    sink.writeImportOrNull(deferredImport);
    sink.end(tag);
  }

  /// Short textual representation use for testing.
  String get shortText {
    StringBuffer sb = StringBuffer();
    switch (kind) {
      case TypeUseKind.IS_CHECK:
        sb.write('is:');
        break;
      case TypeUseKind.AS_CAST:
        sb.write('as:');
        break;
      case TypeUseKind.CATCH_TYPE:
        sb.write('catch:');
        break;
      case TypeUseKind.TYPE_LITERAL:
        sb.write('lit:');
        break;
      case TypeUseKind.INSTANTIATION:
        sb.write('inst:');
        break;
      case TypeUseKind.CONST_INSTANTIATION:
        sb.write('const:');
        break;
      case TypeUseKind.CONSTRUCTOR_REFERENCE:
        sb.write('constructor:');
        break;
      case TypeUseKind.NATIVE_INSTANTIATION:
        sb.write('native:');
        break;
      case TypeUseKind.IMPLICIT_CAST:
        sb.write('impl:');
        break;
      case TypeUseKind.PARAMETER_CHECK:
        sb.write('param:');
        break;
      case TypeUseKind.RTI_VALUE:
        sb.write('rti:');
        break;
      case TypeUseKind.TYPE_ARGUMENT:
        sb.write('typeArg:');
        break;
      case TypeUseKind.NAMED_TYPE_VARIABLE_NEW_RTI:
        sb.write('named:');
        break;
      case TypeUseKind.TYPE_VARIABLE_BOUND_CHECK:
        sb.write('bound:');
        break;
    }
    sb.write(type);
    if (deferredImport != null) {
      sb.write('{');
      sb.write(deferredImport!.name);
      sb.write('}');
    }
    return sb.toString();
  }

  /// [type] used in an is check, like `e is T` or `e is! T`.
  factory TypeUse.isCheck(DartType type) {
    return TypeUse.internal(type, TypeUseKind.IS_CHECK);
  }

  /// [type] used in an as cast, like `e as T`.
  factory TypeUse.asCast(DartType type) {
    return TypeUse.internal(type, TypeUseKind.AS_CAST);
  }

  /// [type] used as a parameter type or field type in Dart 2, like `T` in:
  ///
  ///    method(T t) {}
  ///    T field;
  ///
  factory TypeUse.parameterCheck(DartType type) {
    return TypeUse.internal(type, TypeUseKind.PARAMETER_CHECK);
  }

  /// [type] used in an implicit cast in Dart 2, like `T` in
  ///
  ///    dynamic foo = new Object();
  ///    T bar = foo; // Implicitly `T bar = foo as T`.
  ///
  factory TypeUse.implicitCast(DartType type) {
    return TypeUse.internal(type, TypeUseKind.IMPLICIT_CAST);
  }

  /// [type] used in a on type catch clause, like `try {} on T catch (e) {}`.
  factory TypeUse.catchType(DartType type) {
    return TypeUse.internal(type, TypeUseKind.CATCH_TYPE);
  }

  /// [type] used as a type literal, like `foo() => T;`.
  factory TypeUse.typeLiteral(DartType type, ImportEntity deferredImport) {
    return TypeUse.internal(type, TypeUseKind.TYPE_LITERAL, deferredImport);
  }

  /// [type] used in an instantiation, like `new T();`.
  factory TypeUse.instantiation(InterfaceType type) {
    return TypeUse.internal(type, TypeUseKind.INSTANTIATION);
  }

  /// [type] used in a constant instantiation, like `const T();`.
  factory TypeUse.constInstantiation(
      InterfaceType type, ImportEntity deferredImport) {
    return TypeUse.internal(
        type, TypeUseKind.CONST_INSTANTIATION, deferredImport);
  }

  /// [type] used in a native instantiation.
  factory TypeUse.nativeInstantiation(InterfaceType type) {
    return TypeUse.internal(type, TypeUseKind.NATIVE_INSTANTIATION);
  }

  /// [type] used as a direct RTI value.
  factory TypeUse.constTypeLiteral(DartType type) {
    return TypeUse.internal(type, TypeUseKind.RTI_VALUE);
  }

  /// [type] constructor used, for example in a `instanceof` check.
  factory TypeUse.constructorReference(DartType type) {
    return TypeUse.internal(type, TypeUseKind.CONSTRUCTOR_REFERENCE);
  }

  /// [type] used directly as a type argument.
  ///
  /// The happens during optimization where a type variable can be replaced by
  /// an invariable type argument derived from a constant receiver.
  factory TypeUse.typeArgument(DartType type) {
    return TypeUse.internal(type, TypeUseKind.TYPE_ARGUMENT);
  }

  /// [type] used as a named type variable in a recipe.
  factory TypeUse.namedTypeVariableNewRti(TypeVariableType type) =>
      TypeUse.internal(type, TypeUseKind.NAMED_TYPE_VARIABLE_NEW_RTI);

  /// [type] used as a bound on a type variable.
  factory TypeUse.typeVariableBoundCheck(DartType type) =>
      TypeUse.internal(type, TypeUseKind.TYPE_VARIABLE_BOUND_CHECK);

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! TypeUse) return false;
    return type == other.type && kind == other.kind;
  }

  @override
  String toString() => 'TypeUse($type,$kind)';
}

/// Use of a [ConstantValue].
class ConstantUse {
  static const String tag = 'constant-use';

  final ConstantValue /*!*/ value;

  ConstantUse._(this.value);

  factory ConstantUse.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ConstantValue value = source.readConstant();
    source.end(tag);
    return ConstantUse._(value);
  }

  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeConstant(value);
    sink.end(tag);
  }

  /// Short textual representation use for testing.
  String get shortText {
    return value.toDartText(null);
  }

  /// Constant used as the initial value of a field.
  ConstantUse.init(ConstantValue /*!*/ value) : this._(value);

  /// Type constant used for registration of custom elements.
  ConstantUse.customElements(TypeConstantValue value) : this._(value);

  /// Constant literal used in code.
  ConstantUse.literal(ConstantValue value) : this._(value);

  /// Deferred constant used in code.
  ConstantUse.deferred(DeferredGlobalConstantValue value) : this._(value);

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! ConstantUse) return false;
    return value == other.value;
  }

  @override
  int get hashCode => value.hashCode;

  @override
  String toString() => 'ConstantUse(${value.toStructuredText(null)})';
}
