import.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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. #include "toolchain/check/import.h"
  5. #include "common/check.h"
  6. #include "toolchain/check/context.h"
  7. #include "toolchain/parse/node_ids.h"
  8. #include "toolchain/sem_ir/file.h"
  9. #include "toolchain/sem_ir/ids.h"
  10. #include "toolchain/sem_ir/inst.h"
  11. #include "toolchain/sem_ir/typed_insts.h"
  12. #include "toolchain/sem_ir/value_stores.h"
  13. namespace Carbon::Check {
  14. // Returns name information for the entity, corresponding to IDs in the import
  15. // IR rather than the current IR. May return Invalid for a TODO.
  16. static auto GetImportName(const SemIR::File& import_sem_ir,
  17. SemIR::Inst import_inst)
  18. -> std::pair<SemIR::NameId, SemIR::NameScopeId> {
  19. switch (import_inst.kind()) {
  20. case SemIR::InstKind::BindName:
  21. case SemIR::InstKind::BindSymbolicName: {
  22. const auto& bind_name = import_sem_ir.bind_names().Get(
  23. import_inst.As<SemIR::AnyBindName>().bind_name_id);
  24. return {bind_name.name_id, bind_name.enclosing_scope_id};
  25. }
  26. case SemIR::InstKind::ClassDecl: {
  27. const auto& class_info = import_sem_ir.classes().Get(
  28. import_inst.As<SemIR::ClassDecl>().class_id);
  29. return {class_info.name_id, class_info.enclosing_scope_id};
  30. }
  31. case SemIR::InstKind::FunctionDecl: {
  32. const auto& function = import_sem_ir.functions().Get(
  33. import_inst.As<SemIR::FunctionDecl>().function_id);
  34. return {function.name_id, function.enclosing_scope_id};
  35. }
  36. case SemIR::InstKind::InterfaceDecl: {
  37. const auto& interface = import_sem_ir.interfaces().Get(
  38. import_inst.As<SemIR::InterfaceDecl>().interface_id);
  39. return {interface.name_id, interface.enclosing_scope_id};
  40. }
  41. case SemIR::InstKind::Namespace: {
  42. const auto& scope = import_sem_ir.name_scopes().Get(
  43. import_inst.As<SemIR::Namespace>().name_scope_id);
  44. return {scope.name_id, scope.enclosing_scope_id};
  45. }
  46. default:
  47. CARBON_FATAL() << "Unsupported export kind: " << import_inst;
  48. }
  49. }
  50. // Translate the name to the current IR. It will usually be an identifier, but
  51. // could also be a builtin name ID which is equivalent cross-IR.
  52. static auto CopyNameFromImportIR(Context& context,
  53. const SemIR::File& import_sem_ir,
  54. SemIR::NameId import_name_id) {
  55. if (auto import_identifier_id = import_name_id.AsIdentifierId();
  56. import_identifier_id.is_valid()) {
  57. auto name = import_sem_ir.identifiers().Get(import_identifier_id);
  58. return SemIR::NameId::ForIdentifier(context.identifiers().Add(name));
  59. }
  60. return import_name_id;
  61. }
  62. static auto CacheCopiedNamespace(
  63. llvm::DenseMap<SemIR::NameScopeId, SemIR::NameScopeId>& copied_namespaces,
  64. SemIR::NameScopeId import_scope_id, SemIR::NameScopeId to_scope_id)
  65. -> void {
  66. auto [it, success] = copied_namespaces.insert({import_scope_id, to_scope_id});
  67. CARBON_CHECK(success || it->second == to_scope_id)
  68. << "Copy result for namespace changed from " << import_scope_id << " to "
  69. << to_scope_id;
  70. }
  71. // Copies a namespace from the import IR, returning its ID. This may diagnose
  72. // name conflicts, but that won't change the result because namespaces supersede
  73. // other names in conflicts.
  74. static auto CopySingleNameScopeFromImportIR(
  75. Context& context,
  76. llvm::DenseMap<SemIR::NameScopeId, SemIR::NameScopeId>& copied_namespaces,
  77. SemIR::ImportIRId ir_id, SemIR::InstId import_inst_id,
  78. SemIR::NameScopeId import_scope_id, SemIR::NameScopeId enclosing_scope_id,
  79. SemIR::NameId name_id, SemIR::TypeId namespace_type_id)
  80. -> SemIR::NameScopeId {
  81. auto& scope = context.name_scopes().Get(enclosing_scope_id);
  82. auto [it, success] = scope.names.insert({name_id, SemIR::InstId::Invalid});
  83. if (!success) {
  84. if (auto namespace_inst =
  85. context.insts().TryGetAs<SemIR::Namespace>(it->second)) {
  86. // Namespaces are open, so we can append to the existing one even if it
  87. // comes from a different file.
  88. CacheCopiedNamespace(copied_namespaces, import_scope_id,
  89. namespace_inst->name_scope_id);
  90. return namespace_inst->name_scope_id;
  91. }
  92. }
  93. // Produce the namespace for the entry.
  94. auto ref_id = context.AddInst(SemIR::ImportRefUsed{
  95. .type_id = namespace_type_id, .ir_id = ir_id, .inst_id = import_inst_id});
  96. auto namespace_inst =
  97. SemIR::Namespace{namespace_type_id, SemIR::NameScopeId::Invalid, ref_id};
  98. // Use the invalid node because there's no node to associate with.
  99. auto namespace_id =
  100. context.AddPlaceholderInst({Parse::NodeId::Invalid, namespace_inst});
  101. namespace_inst.name_scope_id =
  102. context.name_scopes().Add(namespace_id, name_id, enclosing_scope_id);
  103. context.ReplaceInstBeforeConstantUse(
  104. namespace_id, {Parse::NodeId::Invalid, namespace_inst});
  105. // Diagnose if there's a name conflict, but still produce the namespace to
  106. // supersede the name conflict in order to avoid repeat diagnostics.
  107. if (!success) {
  108. context.DiagnoseDuplicateName(namespace_id, it->second);
  109. }
  110. it->second = namespace_id;
  111. CacheCopiedNamespace(copied_namespaces, import_scope_id,
  112. namespace_inst.name_scope_id);
  113. return namespace_inst.name_scope_id;
  114. }
  115. // Copies enclosing name scopes from the import IR. Handles the parent
  116. // traversal. Returns the NameScope corresponding to the copied
  117. // import_enclosing_scope_id.
  118. static auto CopyEnclosingNameScopesFromImportIR(
  119. Context& context, SemIR::TypeId namespace_type_id,
  120. const SemIR::File& import_sem_ir, SemIR::ImportIRId ir_id,
  121. SemIR::NameScopeId import_enclosing_scope_id,
  122. llvm::DenseMap<SemIR::NameScopeId, SemIR::NameScopeId>& copied_namespaces)
  123. -> SemIR::NameScopeId {
  124. // Package-level names don't need work.
  125. if (import_enclosing_scope_id == SemIR::NameScopeId::Package) {
  126. return import_enclosing_scope_id;
  127. }
  128. // The scope to add namespaces to. Note this may change while looking at
  129. // enclosing scopes, if we encounter a namespace that's already added.
  130. auto scope_cursor = SemIR::NameScopeId::Package;
  131. // Build a stack of enclosing namespace names, with innermost first.
  132. llvm::SmallVector<SemIR::NameScopeId> new_namespaces;
  133. while (import_enclosing_scope_id != SemIR::NameScopeId::Package) {
  134. // If the namespace was already copied, reuse the results.
  135. if (auto it = copied_namespaces.find(import_enclosing_scope_id);
  136. it != copied_namespaces.end()) {
  137. // We inject names at the provided scope, and don't need to keep
  138. // traversing parents.
  139. scope_cursor = it->second;
  140. break;
  141. }
  142. // The namespace hasn't been copied yet, so add it to our list.
  143. const auto& scope =
  144. import_sem_ir.name_scopes().Get(import_enclosing_scope_id);
  145. auto scope_inst =
  146. import_sem_ir.insts().GetAs<SemIR::Namespace>(scope.inst_id);
  147. new_namespaces.push_back(scope_inst.name_scope_id);
  148. import_enclosing_scope_id = scope.enclosing_scope_id;
  149. }
  150. // Add enclosing namespace names, starting with the outermost.
  151. for (auto import_scope_id : llvm::reverse(new_namespaces)) {
  152. auto import_scope = import_sem_ir.name_scopes().Get(import_scope_id);
  153. auto name_id =
  154. CopyNameFromImportIR(context, import_sem_ir, import_scope.name_id);
  155. scope_cursor = CopySingleNameScopeFromImportIR(
  156. context, copied_namespaces, ir_id, import_scope.inst_id,
  157. import_scope_id, scope_cursor, name_id, namespace_type_id);
  158. }
  159. return scope_cursor;
  160. }
  161. auto Import(Context& context, SemIR::TypeId namespace_type_id,
  162. const SemIR::File& import_sem_ir) -> void {
  163. auto ir_id = context.import_irs().Add(&import_sem_ir);
  164. for (const auto import_inst_id :
  165. import_sem_ir.inst_blocks().Get(SemIR::InstBlockId::Exports)) {
  166. auto import_inst = import_sem_ir.insts().Get(import_inst_id);
  167. auto [import_name_id, import_enclosing_scope_id] =
  168. GetImportName(import_sem_ir, import_inst);
  169. // TODO: This should only be invalid when GetImportName for an inst
  170. // isn't yet implemented. Long-term this should be removed.
  171. if (!import_name_id.is_valid()) {
  172. continue;
  173. }
  174. llvm::DenseMap<SemIR::NameScopeId, SemIR::NameScopeId> copied_namespaces;
  175. auto name_id = CopyNameFromImportIR(context, import_sem_ir, import_name_id);
  176. SemIR::NameScopeId enclosing_scope_id = CopyEnclosingNameScopesFromImportIR(
  177. context, namespace_type_id, import_sem_ir, ir_id,
  178. import_enclosing_scope_id, copied_namespaces);
  179. if (auto import_namespace_inst = import_inst.TryAs<SemIR::Namespace>()) {
  180. // Namespaces are always imported because they're essential for
  181. // qualifiers, and the type is simple.
  182. CopySingleNameScopeFromImportIR(
  183. context, copied_namespaces, ir_id, import_inst_id,
  184. import_namespace_inst->name_scope_id, enclosing_scope_id, name_id,
  185. namespace_type_id);
  186. } else {
  187. // Leave a placeholder that the inst comes from the other IR.
  188. auto target_id = context.AddPlaceholderInst(
  189. {SemIR::ImportRefUnused{.ir_id = ir_id, .inst_id = import_inst_id}});
  190. // TODO: When importing from other packages, the scope's names should
  191. // be changed to allow for ambiguous names. When importing from the
  192. // current package, as is currently being done, we should issue a
  193. // diagnostic on conflicts.
  194. auto [it, success] = context.name_scopes()
  195. .Get(enclosing_scope_id)
  196. .names.insert({name_id, target_id});
  197. if (!success) {
  198. context.DiagnoseDuplicateName(target_id, it->second);
  199. }
  200. }
  201. }
  202. }
  203. } // namespace Carbon::Check