//===-- Import.h - Representation of imports --------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains types used to represent information about imports
/// throughout the AST.
///
//===----------------------------------------------------------------------===//

#ifndef SWIFT_IMPORT_H
#define SWIFT_IMPORT_H

#include "swift/AST/Identifier.h"
#include "swift/Basic/Located.h"
#include "swift/Basic/OptionSet.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>

namespace swift {
class ASTContext;
class ModuleDecl;

// MARK: - Fundamental import enums

/// Describes what kind of name is being imported.
///
/// If the enumerators here are changed, make sure to update all diagnostics
/// using ImportKind as a select index.
enum class ImportKind : uint8_t {
  Module = 0,
  Type,
  Struct,
  Class,
  Enum,
  Protocol,
  Var,
  Func
};

inline bool isScopedImportKind(ImportKind importKind) {
  return importKind != ImportKind::Module;
}

/// Possible attributes for imports in source files.
enum class ImportFlags {
  /// The imported module is exposed to anyone who imports the parent module.
  Exported = 0x1,

  /// This source file has access to testable declarations in the imported
  /// module.
  Testable = 0x2,

  /// This source file has access to private declarations in the imported
  /// module.
  PrivateImport = 0x4,

  /// The imported module is an implementation detail of this file and should
  /// not be required to be present if the main module is ever imported
  /// elsewhere.
  ///
  /// Mutually exclusive with Exported.
  ImplementationOnly = 0x8,

  /// The module is imported to have access to named SPIs which is an
  /// implementation detail of this file.
  SPIAccessControl = 0x10,

  /// Used for DenseMap.
  Reserved = 0x80
};

/// \see ImportFlags
using ImportOptions = OptionSet<ImportFlags>;

// MARK: - Import Paths

namespace detail {
  using ImportPathElement = Located<Identifier>;
  using ImportPathRaw = llvm::ArrayRef<ImportPathElement>;

  template<typename Subclass>
  class ImportPathBase {
  public:
    using Element = ImportPathElement;
    using Raw = ImportPathRaw;

  protected:
    Raw raw;

    ImportPathBase(Raw raw) : raw(raw) { }

  public:
    const Raw &getRaw() const { return raw; }

    Raw::iterator begin() const {
      return raw.begin();
    }

    Raw::iterator end() const {
      return raw.end();
    }

    const Element &operator[](size_t i) const { return raw[i]; }
    bool empty() const { return raw.empty(); }
    size_t size() const { return raw.size(); }

    const Element &front() const { return raw.front(); }
    const Element &back() const { return raw.back(); }

    /// True if \c this and \c other are precisely equal, including SourceLocs.
    bool operator==(const Subclass &other) const {
      return raw == other.raw;
    }

    /// True if \c this and \c other contain the same identifiers in the same
    /// order, ignoring SourceLocs.
    bool isSameAs(const Subclass &other) const {
      return size() == other.size()
             && std::equal(this->begin(), this->end(), other.begin(),
                  [](const Element &l, const Element &r) -> bool {
                    return l.Item == r.Item;
                  }
                );
    }

    Subclass getTopLevelPath() const {
      assert(size() >= 1 && "nothing to take");
      return Subclass(raw.take_front());
    }

    Subclass getParentPath() const {
      assert(size() >= 0 && "nothing to take");
      return Subclass(raw.drop_back());
    }

    SourceRange getSourceRange() const {
      if (empty()) return SourceRange();
      return SourceRange(raw.front().Loc, raw.back().Loc);
    }

    void print(llvm::raw_ostream &os) const {
      llvm::interleave(*this,
                       [&](Element elem) { os << elem.Item.str(); },
                       [&]() { os << "."; });
    }

    void getString(SmallVectorImpl<char> &modulePathStr) const {
      llvm::raw_svector_ostream os(modulePathStr);
      print(os);
    }
  };

  // These shims avoid circularity between ASTContext.h and Import.h.
  ImportPathRaw ImportPathBuilder_copyToImpl(ASTContext &ctx,
                                             ImportPathRaw raw);
  Identifier ImportPathBuilder_getIdentifierImpl(ASTContext &ctx,
                                                 StringRef string);

  template<typename Subclass>
  class ImportPathBuilder {
    using Scratch = llvm::SmallVector<ImportPathElement, 4>;
    Scratch scratch;

  public:
    using value_type = Scratch::value_type;
    using reference = Scratch::reference;
    using iterator = Scratch::iterator;
    using const_iterator = Scratch::const_iterator;
    using difference_type = Scratch::difference_type;
    using size_type = Scratch::size_type;

    Subclass get() const {
      return Subclass(scratch);
    }

    Subclass copyTo(ASTContext &ctx) const {
      return Subclass(ImportPathBuilder_copyToImpl(ctx, scratch));
    }

    ImportPathBuilder() : scratch() { }
    ImportPathBuilder(const ImportPathElement &elem) : scratch() {
      scratch = { elem };
    }
    ImportPathBuilder(Identifier name, SourceLoc loc = SourceLoc())
        : ImportPathBuilder(ImportPathElement(name, loc)) { }

    template<typename Iterator>
    ImportPathBuilder(Iterator begin, Iterator end) : scratch(begin, end) { }

    template<typename Range>
    ImportPathBuilder(Range collection)
        : scratch(collection.begin(), collection.end()) { }

    /// Parses \p text into elements separated by \p separator, with identifiers
    /// from \p ctx and invalid SourceLocs.
    ///
    /// \warning This is not very robust; for instance, it doesn't check the
    /// validity of the identifiers.
    ImportPathBuilder(ASTContext &ctx, StringRef text, char separator)
        : scratch()
    {
      while (!text.empty()) {
        StringRef next;
        std::tie(next, text) = text.split(separator);
        push_back(ImportPathBuilder_getIdentifierImpl(ctx, next));
      }
    }

    void push_back(const ImportPathElement &elem) { scratch.push_back(elem); }
    void push_back(Identifier name, SourceLoc loc = SourceLoc()) {
      scratch.push_back({ name, loc });
    }

    void pop_back() { scratch.pop_back(); }

    bool empty() const { return scratch.empty(); }
    size_t size() const { return scratch.size(); }

    llvm::SmallVector<ImportPathElement, 4>::iterator begin() {
      return scratch.begin();
    }
    llvm::SmallVector<ImportPathElement, 4>::iterator end() {
      return scratch.end();
    }

    const ImportPathElement &front() const { return scratch.front(); }
    ImportPathElement &front() { return scratch.front(); }
    const ImportPathElement &back() const { return scratch.back(); }
    ImportPathElement &back() { return scratch.back(); }

    template<typename Iterator>
    void append(Iterator begin, Iterator end) {
      scratch.append(begin, end);
    }

    template<typename Range>
    void append(Range collection) {
      append(collection.begin(), collection.end());
    }
  };
}

/// @name ImportPathBase Comparison Operators
/// @{
template <typename Subclass>
inline bool operator<(const detail::ImportPathBase<Subclass> &LHS,
                      const detail::ImportPathBase<Subclass> &RHS) {
  using Element = typename detail::ImportPathBase<Subclass>::Element;
  auto Comparator = [](const Element &l, const Element &r) {
    return l.Item.compare(r.Item) < 0;
  };
  return std::lexicographical_compare(LHS.begin(), LHS.end(), RHS.begin(),
                                      RHS.end(), Comparator);
}
/// @}

/// An undifferentiated series of dotted identifiers in an \c import statement,
/// like \c Foo.Bar. Each identifier is packaged with its corresponding source
/// location.
///
/// The first element of an \c ImportPath is always a top-level module name. The
/// remaining elements could specify a scope (naming a declaration in the
/// module) or a chain of submodule names. \c ImportPath does not differentiate
/// between these cases; its \c getModule() and \c getAccess() methods take an
/// \c ImportKind parameter to decide how to divvy up these identifiers.
///
/// \c ImportPath is only used when analyzing the parsed representation of code.
/// Most code should use \c ImportPath::Module or \c ImportPath::Access, which
/// have semantic meaning.
///
/// \c ImportPath is essentially a wrapper around \c ArrayRef and does not own
/// its elements, so something else needs to manage their lifetime.
/// \c ImportDecl owns the memory backing \c ImportDecl::getImportPath().
class ImportPath : public detail::ImportPathBase<ImportPath> {
public:
  /// A single dotted name from an \c ImportPath, \c ImportPath::Module, or
  /// \c ImportPath::Access, with its source location.
  using Element = detail::ImportPathBase<ImportPath>::Element;

  /// The backing type for \c ImportPath, \c ImportPath::Module, and
  /// \c ImportPath::Access; namely, an \c ArrayRef of \c ImportPath::Elements.
  using Raw = detail::ImportPathBase<ImportPath>::Raw;

  /// A helper type which encapsulates a temporary vector and can produce an
  /// import path from it. In addition to the obvious use in a temporary
  /// variable, this type can be used mid-expression to produce an import path
  /// that is valid until the end of the expression.
  using Builder = detail::ImportPathBuilder<ImportPath>;

  /// Represents an access path--the portion of an \c ImportPath which describes
  /// the name of a declaration to scope the import to.
  ///
  /// \c ImportPath::Access is used in scoped imports to designate a specific
  /// declaration inside the module. The import will only* cover this
  /// declaration, and will import it with a higher "priority" than usual, so
  /// name lookup will prefer it over identically-named declarations visible
  /// through other imports.
  ///
  /// (* Not actually only--e.g. extensions will be imported too. The primary
  /// use case for scoped imports is actually to resolve name conflicts, not to
  /// reduce the set of visible declarations.)
  ///
  /// When \c ImportPath::Access is empty, this means the import covers all
  /// declarations in the module.
  ///
  /// Although in theory Swift could support scoped imports of nested
  /// declarations, in practice it currently only supports scoped imports of
  /// top-level declarations. Reflecting this, \c ImportPath::Access is backed
  /// by an \c ArrayRef, but it asserts that the access path has zero or one
  /// elements.
  ///
  /// \c ImportPath::Access is essentially a wrapper around \c ArrayRef and does
  /// not own its elements, so something else needs to manage their lifetime.
  /// \c ImportDecl owns the memory backing \c ImportDecl::getAccessPath().
  class Access : public detail::ImportPathBase<Access> {
  public:
    /// A helper type which encapsulates a temporary vector and can produce a
    /// scope path from it. In addition to the obvious use in a temporary
    /// variable, this type can be used mid-expression to produce a scope path
    /// that is valid until the end of the expression.
    using Builder = detail::ImportPathBuilder<Access>;

    Access(ImportPath::Raw raw) : ImportPathBase(raw) {
      assert(size() <= 1 && "nested scoped imports are not supported");
    }

    Access() : ImportPathBase({}) { }

    /// Returns \c true if the scope of this import includes \c name. An empty
    /// scope matches all names.
    bool matches(DeclName name) const {
      return empty() || DeclName(front().Item).matchesRef(name);
    }
  };

  /// Represents a module path--the portion of an \c ImportPath which describes
  /// the name of the module being imported, possibly including submodules.
  ///
  /// \c ImportPath::Module contains one or more identifiers. The first
  /// identiifer names a top-level module. The second and subsequent
  /// identifiers, if present, chain together to name a specific submodule to
  /// import. (Although Swift modules cannot currently contain submodules, Swift
  /// can import Clang submodules.)
  ///
  /// \c ImportPath::Module is essentially a wrapper around \c ArrayRef and
  /// does not own its elements, so something else needs to manage their
  /// lifetime. \c ImportDecl owns the memory backing
  /// \c ImportDecl::getModulePath().
  class Module : public detail::ImportPathBase<Module> {
  public:
    /// A helper type which encapsulates a temporary vector and can produce a
    /// module path from it. In addition to the obvious use in a temporary
    /// variable, this type can be used mid-expression to produce a module path
    /// that is valid until the end of the expression.
    using Builder = detail::ImportPathBuilder<Module>;

    Module(ImportPath::Raw raw) : ImportPathBase(raw) {
      assert(size() >= 1 && "must have a top-level module");
    }

    // Note: This type does not have a constructor which just takes an
    // `Identifier` because it would not be able to create a temporary
    // `ImportPath::Element` with a long enough lifetime to return. Use
    // `ImportPath::Module::Builder` to create a temporary module path.

    bool hasSubmodule() const {
      return size() != 1;
    }

    ImportPath::Raw getSubmodulePath() const {
      return getRaw().drop_front();
    }
  };

  ImportPath(Raw raw) : ImportPathBase(raw) {
    assert(raw.size() >= 1 && "ImportPath must contain a module name");
  }

  /// Extracts the portion of the \c ImportPath which represents a module name,
  /// including submodules if appropriate.
  Module getModulePath(bool isScoped) const {
    if (isScoped)
      return Module(getRaw().drop_back());

    return Module(getRaw());
  }

  /// Extracts the portion of the \c ImportPath which represents a scope for the
  /// import.
  Access getAccessPath(bool isScoped) const {
    if (isScoped) {
      assert(size() >= 2 && "scoped ImportPath must contain a decl name");
      return Access(getRaw().take_back());
    }

    return Access();
  }

  /// Extracts the portion of the \c ImportPath which represents a module name,
  /// including submodules, assuming the \c ImportDecl has the indicated
  /// \c importKind.
  Module getModulePath(ImportKind importKind) const {
    return getModulePath(isScopedImportKind(importKind));
  }

  /// Extracts the portion of the \c ImportPath which represents a scope for the
  /// import, assuming the \c ImportDecl has the indicated \c importKind.
  Access getAccessPath(ImportKind importKind) const {
    return getAccessPath(isScopedImportKind(importKind));
  }
};

// MARK: - Abstractions of imports

/// Convenience struct to keep track of an import path and whether or not it
/// is scoped.
class UnloadedImportedModule {
  // This is basically an ArrayRef with a bit stolen from the pointer.
  // FIXME: Extract an ArrayRefIntPair type from this.
  llvm::PointerIntPair<ImportPath::Raw::iterator, 1, bool> dataAndIsScoped;
  ImportPath::Raw::size_type length;

  ImportPath::Raw::iterator data() const {
    return dataAndIsScoped.getPointer();
  }

  bool isScoped() const {
    return dataAndIsScoped.getInt();
  }

  ImportPath::Raw getRaw() const {
    return ImportPath::Raw(data(), length);
  }

  UnloadedImportedModule(ImportPath::Raw raw, bool isScoped)
    : dataAndIsScoped(raw.data(), isScoped), length(raw.size()) { }

public:
  UnloadedImportedModule(ImportPath importPath, bool isScoped)
    : UnloadedImportedModule(importPath.getRaw(), isScoped) { }

  UnloadedImportedModule(ImportPath importPath, ImportKind importKind)
    : UnloadedImportedModule(importPath, isScopedImportKind(importKind)) { }

  ImportPath getImportPath() const {
    return ImportPath(getRaw());
  }

  ImportPath::Module getModulePath() const {
    return getImportPath().getModulePath(isScoped());
  }

  ImportPath::Access getAccessPath() const {
    return getImportPath().getAccessPath(isScoped());
  }

  friend bool operator==(const UnloadedImportedModule &lhs,
                         const UnloadedImportedModule &rhs) {
    return (lhs.getRaw() == rhs.getRaw()) &&
           (lhs.isScoped() == rhs.isScoped());
  }
};

/// Convenience struct to keep track of a module along with its access path.
struct alignas(uint64_t) ImportedModule {
  /// The access path from an import: `import Foo.Bar` -> `Foo.Bar`.
  ImportPath::Access accessPath;
  /// The actual module corresponding to the import.
  ///
  /// Invariant: The pointer is non-null.
  ModuleDecl *importedModule;

  ImportedModule(ImportPath::Access accessPath,
                 ModuleDecl *importedModule)
      : accessPath(accessPath), importedModule(importedModule) {
    assert(this->importedModule);
  }

  explicit ImportedModule(ModuleDecl *importedModule)
      : ImportedModule(ImportPath::Access(), importedModule) { }

  bool operator==(const ImportedModule &other) const {
    return (this->importedModule == other.importedModule) &&
           (this->accessPath == other.accessPath);
  }

  /// Uniques the items in \p imports, ignoring the source locations of the
  /// access paths.
  ///
  /// The order of items in \p imports is \e not preserved.
  static void removeDuplicates(SmallVectorImpl<ImportedModule> &imports);

  // Purely here to allow ImportedModule and UnloadedImportedModule to
  // substitute into the same templates.
  ImportPath::Access getAccessPath() const { return accessPath; }

  /// Arbitrarily orders ImportedModule records, for inclusion in sets and such.
  class Order {
  public:
    bool operator()(const ImportedModule &lhs,
                    const ImportedModule &rhs) const {
      if (lhs.importedModule != rhs.importedModule)
        return std::less<const ModuleDecl *>()(lhs.importedModule,
                                               rhs.importedModule);
      if (lhs.accessPath.getRaw().data() != rhs.accessPath.getRaw().data())
        return std::less<ImportPath::Raw::iterator>()(lhs.accessPath.begin(),
                                                   rhs.accessPath.begin());
      return lhs.accessPath.size() < rhs.accessPath.size();
    }
  };
};

/// Augments a type representing an import to also include information about the
/// import's attributes. This is usually used with either \c ImportedModule or
/// \c UnloadedImportedModule.
template<class ModuleInfo>
struct AttributedImport {
  /// Information about the module and access path being imported.
  ModuleInfo module;

  /// Flags indicating which attributes of this import are present.
  ImportOptions options;

  /// If this is a @_private import, the value of its 'sourceFile:' argument;
  /// otherwise, empty string.
  StringRef sourceFileArg;

  /// Names of explicitly imported SPI groups.
  ArrayRef<Identifier> spiGroups;

  AttributedImport(ModuleInfo module, ImportOptions options = ImportOptions(),
                   StringRef filename = {}, ArrayRef<Identifier> spiGroups = {})
      : module(module), options(options), sourceFileArg(filename),
        spiGroups(spiGroups) {
    assert(!(options.contains(ImportFlags::Exported) &&
             options.contains(ImportFlags::ImplementationOnly)) ||
           options.contains(ImportFlags::Reserved));
  }

  template<class OtherModuleInfo>
  AttributedImport(ModuleInfo module, AttributedImport<OtherModuleInfo> other)
    : AttributedImport(module, other.options, other.sourceFileArg,
                       other.spiGroups) { }

  friend bool operator==(const AttributedImport<ModuleInfo> &lhs,
                         const AttributedImport<ModuleInfo> &rhs) {
    return lhs.module == rhs.module &&
           lhs.options.toRaw() == rhs.options.toRaw() &&
           lhs.sourceFileArg == rhs.sourceFileArg &&
           lhs.spiGroups == rhs.spiGroups;
  }

  AttributedImport<ImportedModule> getLoaded(ModuleDecl *loadedModule) const {
    return { ImportedModule(module.getAccessPath(), loadedModule), *this };
  }
};

void simple_display(llvm::raw_ostream &out,
                    const ImportedModule &import);

void simple_display(llvm::raw_ostream &out,
                    const UnloadedImportedModule &import);

// This is a quasi-implementation detail of the template version below.
void simple_display(llvm::raw_ostream &out,
                    const AttributedImport<std::tuple<>> &import);

template<typename ModuleInfo>
void simple_display(llvm::raw_ostream &out,
                    const AttributedImport<ModuleInfo> &import) {
  // Print the module.
  simple_display(out, import.module);

  // Print the other details of the import, using the std::tuple<>
  // specialization.
  AttributedImport<std::tuple<>> importWithoutModule({}, import);
  simple_display(out, importWithoutModule);
}

// MARK: - Implicit imports

/// The kind of stdlib that should be imported.
enum class ImplicitStdlibKind {
  /// No standard library should be implicitly imported.
  None,

  /// The Builtin module should be implicitly imported.
  Builtin,

  /// The regular Swift standard library should be implicitly imported.
  Stdlib
};

/// Represents unprocessed options for implicit imports.
struct ImplicitImportInfo {
  /// The implicit stdlib to import.
  ImplicitStdlibKind StdlibKind;

  /// Whether we should attempt to import an underlying Clang half of this
  /// module.
  bool ShouldImportUnderlyingModule;

  /// The bridging header path for this module, empty if there is none.
  StringRef BridgingHeaderPath;

  /// The names of additional modules to be loaded and implicitly imported.
  SmallVector<AttributedImport<UnloadedImportedModule>, 4>
      AdditionalUnloadedImports;

  /// An additional list of already-loaded modules which should be implicitly
  /// imported.
  SmallVector<AttributedImport<ImportedModule>, 4>
      AdditionalImports;

  ImplicitImportInfo()
      : StdlibKind(ImplicitStdlibKind::None),
        ShouldImportUnderlyingModule(false) {}
};

/// Contains names of and pointers to modules that must be implicitly imported.
struct ImplicitImportList {
  ArrayRef<AttributedImport<ImportedModule>> imports;
  ArrayRef<AttributedImport<UnloadedImportedModule>> unloadedImports;

  friend bool operator==(const ImplicitImportList &lhs,
                         const ImplicitImportList &rhs) {
    return lhs.imports == rhs.imports
        && lhs.unloadedImports == rhs.unloadedImports;
  }
};

/// A list of modules to implicitly import.
void simple_display(llvm::raw_ostream &out,
                    const ImplicitImportList &importList);

}

// MARK: - DenseMapInfo

namespace llvm {

template<>
struct DenseMapInfo<swift::ImportOptions> {
  using ImportOptions = swift::ImportOptions;

  using UnsignedDMI = DenseMapInfo<uint8_t>;

  static inline ImportOptions getEmptyKey() {
    return ImportOptions(UnsignedDMI::getEmptyKey());
  }
  static inline ImportOptions getTombstoneKey() {
    return ImportOptions(UnsignedDMI::getTombstoneKey());
  }
  static inline unsigned getHashValue(ImportOptions options) {
    return UnsignedDMI::getHashValue(options.toRaw());
  }
  static bool isEqual(ImportOptions a, ImportOptions b) {
    return UnsignedDMI::isEqual(a.toRaw(), b.toRaw());
  }
};

template <>
class DenseMapInfo<swift::ImportedModule> {
  using ImportedModule = swift::ImportedModule;
  using ModuleDecl = swift::ModuleDecl;
public:
  static ImportedModule getEmptyKey() {
    return {{}, llvm::DenseMapInfo<ModuleDecl *>::getEmptyKey()};
  }
  static ImportedModule getTombstoneKey() {
    return {{}, llvm::DenseMapInfo<ModuleDecl *>::getTombstoneKey()};
  }

  static unsigned getHashValue(const ImportedModule &val) {
    auto pair = std::make_pair(val.accessPath.size(), val.importedModule);
    return llvm::DenseMapInfo<decltype(pair)>::getHashValue(pair);
  }

  static bool isEqual(const ImportedModule &lhs,
                      const ImportedModule &rhs) {
    return lhs.importedModule == rhs.importedModule &&
           lhs.accessPath.isSameAs(rhs.accessPath);
  }
};

template<typename ModuleInfo>
struct DenseMapInfo<swift::AttributedImport<ModuleInfo>> {
  using AttributedImport = swift::AttributedImport<ModuleInfo>;

  using ModuleInfoDMI = DenseMapInfo<ModuleInfo>;
  using ImportOptionsDMI = DenseMapInfo<swift::ImportOptions>;
  using StringRefDMI = DenseMapInfo<StringRef>;
  // We can't include spiGroups in the hash because ArrayRef<Identifier> is not
  // DenseMapInfo-able, but we do check that the spiGroups match in isEqual().

  static inline AttributedImport getEmptyKey() {
    return AttributedImport(ModuleInfoDMI::getEmptyKey(),
                            ImportOptionsDMI::getEmptyKey(),
                            StringRefDMI::getEmptyKey(),
                            {});
  }
  static inline AttributedImport getTombstoneKey() {
    return AttributedImport(ModuleInfoDMI::getTombstoneKey(),
                            ImportOptionsDMI::getTombstoneKey(),
                            StringRefDMI::getTombstoneKey(),
                            {});
  }
  static inline unsigned getHashValue(const AttributedImport &import) {
    return detail::combineHashValue(
        ModuleInfoDMI::getHashValue(import.module),
        detail::combineHashValue(
            ImportOptionsDMI::getHashValue(import.options),
            StringRefDMI::getHashValue(import.sourceFileArg)));
  }
  static bool isEqual(const AttributedImport &a,
                      const AttributedImport &b) {
    return ModuleInfoDMI::isEqual(a.module, b.module) &&
           ImportOptionsDMI::isEqual(a.options, b.options) &&
           StringRefDMI::isEqual(a.sourceFileArg, b.sourceFileArg) &&
           a.spiGroups == b.spiGroups;
  }
};
}

#endif
