check_unit.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_CHECK_CHECK_UNIT_H_
  5. #define CARBON_TOOLCHAIN_CHECK_CHECK_UNIT_H_
  6. #include "common/map.h"
  7. #include "llvm/ADT/SmallVector.h"
  8. #include "toolchain/check/check.h"
  9. #include "toolchain/check/context.h"
  10. #include "toolchain/parse/tree_node_diagnostic_converter.h"
  11. #include "toolchain/sem_ir/ids.h"
  12. namespace Carbon::Check {
  13. struct UnitAndImports;
  14. // A file's imports corresponding to a single package, for
  15. // `UnitAndImports::package_imports`.
  16. struct PackageImports {
  17. // A given import within the file, with its destination.
  18. struct Import {
  19. Parse::Tree::PackagingNames names;
  20. UnitAndImports* unit_info;
  21. };
  22. // Use the constructor so that the SmallVector is only constructed
  23. // as-needed.
  24. explicit PackageImports(IdentifierId package_id, Parse::ImportDeclId node_id)
  25. : package_id(package_id), node_id(node_id) {}
  26. // The identifier of the imported package.
  27. IdentifierId package_id;
  28. // The first `import` declaration in the file, which declared the package's
  29. // identifier (even if the import failed). Used for associating diagnostics
  30. // not specific to a single import.
  31. Parse::ImportDeclId node_id;
  32. // The associated `import` instruction. Only valid once a file is checked.
  33. SemIR::InstId import_decl_id = SemIR::InstId::Invalid;
  34. // Whether there's an import that failed to load.
  35. bool has_load_error = false;
  36. // The list of valid imports.
  37. llvm::SmallVector<Import> imports;
  38. };
  39. // Contains information accumulated while checking a `Unit` (primarily import
  40. // information), in addition to the `Unit` itself.
  41. struct UnitAndImports {
  42. explicit UnitAndImports(SemIR::CheckIRId check_ir_id, Unit& unit)
  43. : check_ir_id(check_ir_id),
  44. unit(&unit),
  45. err_tracker(*unit.consumer),
  46. emitter(*unit.node_converter, err_tracker) {}
  47. auto parse_tree() -> const Parse::Tree& { return unit->sem_ir->parse_tree(); }
  48. auto source() -> const SourceBuffer& {
  49. return parse_tree().tokens().source();
  50. }
  51. SemIR::CheckIRId check_ir_id;
  52. Unit* unit;
  53. // Emitter information.
  54. ErrorTrackingDiagnosticConsumer err_tracker;
  55. DiagnosticEmitter<Parse::NodeLoc> emitter;
  56. // List of the outgoing imports. If a package includes unavailable library
  57. // imports, it has an entry with has_load_error set. Invalid imports (for
  58. // example, `import Main;`) aren't added because they won't add identifiers to
  59. // name lookup.
  60. llvm::SmallVector<PackageImports> package_imports;
  61. // A map of the package names to the outgoing imports above.
  62. Map<IdentifierId, int32_t> package_imports_map;
  63. // The remaining number of imports which must be checked before this unit can
  64. // be processed.
  65. int32_t imports_remaining = 0;
  66. // A list of incoming imports. This will be empty for `impl` files, because
  67. // imports only touch `api` files.
  68. llvm::SmallVector<UnitAndImports*> incoming_imports;
  69. // The corresponding `api` unit if this is an `impl` file. The entry should
  70. // also be in the corresponding `PackageImports`.
  71. UnitAndImports* api_for_impl = nullptr;
  72. // Whether the unit has been checked.
  73. bool is_checked = false;
  74. };
  75. // Handles checking of a single unit. Requires that all dependencies have been
  76. // checked.
  77. //
  78. // This mainly splits out the single-unit logic from the higher level cross-unit
  79. // logic in check.cpp.
  80. class CheckUnit {
  81. public:
  82. explicit CheckUnit(UnitAndImports* unit_and_imports, int total_ir_count,
  83. llvm::raw_ostream* vlog_stream);
  84. // Produces and checks the IR for the provided unit.
  85. auto Run() -> void;
  86. private:
  87. // Add imports to the root block.
  88. auto InitPackageScopeAndImports() -> void;
  89. // Collects direct imports, for CollectTransitiveImports.
  90. auto CollectDirectImports(llvm::SmallVector<SemIR::ImportIR>& results,
  91. llvm::MutableArrayRef<int> ir_to_result_index,
  92. SemIR::InstId import_decl_id,
  93. const PackageImports& imports, bool is_local)
  94. -> void;
  95. // Collects transitive imports, handling deduplication. These will be unified
  96. // between local_imports and api_imports.
  97. auto CollectTransitiveImports(SemIR::InstId import_decl_id,
  98. const PackageImports* local_imports,
  99. const PackageImports* api_imports)
  100. -> llvm::SmallVector<SemIR::ImportIR>;
  101. // Imports the current package.
  102. auto ImportCurrentPackage(SemIR::InstId package_inst_id,
  103. SemIR::TypeId namespace_type_id) -> void;
  104. // Imports all other packages (excluding the current package).
  105. auto ImportOtherPackages(SemIR::TypeId namespace_type_id) -> void;
  106. // Checks that each required definition is available. If the definition can be
  107. // generated by resolving a specific, does so, otherwise emits a diagnostic
  108. // for each declaration in context.definitions_required() that doesn't have a
  109. // definition.
  110. auto CheckRequiredDefinitions() -> void;
  111. // Loops over all nodes in the tree. On some errors, this may return early,
  112. // for example if an unrecoverable state is encountered.
  113. // NOLINTNEXTLINE(readability-function-size)
  114. auto ProcessNodeIds() -> bool;
  115. UnitAndImports* unit_and_imports_;
  116. // The number of IRs being checked in total.
  117. int total_ir_count_;
  118. llvm::raw_ostream* vlog_stream_;
  119. Context::DiagnosticEmitter emitter_;
  120. Context context_;
  121. };
  122. } // namespace Carbon::Check
  123. #endif // CARBON_TOOLCHAIN_CHECK_CHECK_UNIT_H_