check_unit.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  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/check_unit.h"
  5. #include <string>
  6. #include <tuple>
  7. #include <utility>
  8. #include "llvm/ADT/IntrusiveRefCntPtr.h"
  9. #include "llvm/ADT/StringRef.h"
  10. #include "llvm/Support/VirtualFileSystem.h"
  11. #include "toolchain/base/kind_switch.h"
  12. #include "toolchain/base/pretty_stack_trace_function.h"
  13. #include "toolchain/check/diagnostic_helpers.h"
  14. #include "toolchain/check/generic.h"
  15. #include "toolchain/check/handle.h"
  16. #include "toolchain/check/impl.h"
  17. #include "toolchain/check/impl_lookup.h"
  18. #include "toolchain/check/import.h"
  19. #include "toolchain/check/import_cpp.h"
  20. #include "toolchain/check/import_ref.h"
  21. #include "toolchain/check/inst.h"
  22. #include "toolchain/check/node_id_traversal.h"
  23. #include "toolchain/check/type.h"
  24. #include "toolchain/check/type_structure.h"
  25. #include "toolchain/diagnostics/diagnostic.h"
  26. #include "toolchain/sem_ir/function.h"
  27. #include "toolchain/sem_ir/ids.h"
  28. #include "toolchain/sem_ir/import_ir.h"
  29. #include "toolchain/sem_ir/typed_insts.h"
  30. namespace Carbon::Check {
  31. // Returns the number of imported IRs, to assist in Context construction.
  32. static auto GetImportedIRCount(UnitAndImports* unit_and_imports) -> int {
  33. int count = 0;
  34. for (auto& package_imports : unit_and_imports->package_imports) {
  35. count += package_imports.imports.size();
  36. }
  37. if (!unit_and_imports->api_for_impl) {
  38. // Leave an empty slot for `ImportIRId::ApiForImpl`.
  39. ++count;
  40. }
  41. if (!unit_and_imports->cpp_import_names.empty()) {
  42. // Leave an empty slot for `ImportIRId::Cpp`.
  43. ++count;
  44. }
  45. return count;
  46. }
  47. CheckUnit::CheckUnit(
  48. UnitAndImports* unit_and_imports,
  49. llvm::ArrayRef<Parse::GetTreeAndSubtreesFn> tree_and_subtrees_getters,
  50. llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
  51. llvm::raw_ostream* vlog_stream)
  52. : unit_and_imports_(unit_and_imports),
  53. tree_and_subtrees_getter_(
  54. tree_and_subtrees_getters
  55. [unit_and_imports->unit->sem_ir->check_ir_id().index]),
  56. total_ir_count_(tree_and_subtrees_getters.size()),
  57. fs_(std::move(fs)),
  58. vlog_stream_(vlog_stream),
  59. emitter_(&unit_and_imports_->err_tracker, tree_and_subtrees_getters,
  60. unit_and_imports_->unit->sem_ir),
  61. context_(
  62. &emitter_, tree_and_subtrees_getter_, unit_and_imports_->unit->sem_ir,
  63. GetImportedIRCount(unit_and_imports), total_ir_count_, vlog_stream) {}
  64. auto CheckUnit::Run() -> void {
  65. Timings::ScopedTiming timing(unit_and_imports_->unit->timings, "check");
  66. // We can safely mark this as checked at the start.
  67. unit_and_imports_->is_checked = true;
  68. PrettyStackTraceFunction context_dumper(
  69. [&](llvm::raw_ostream& output) { context_.PrintForStackDump(output); });
  70. // Add a block for the file.
  71. context_.inst_block_stack().Push();
  72. InitPackageScopeAndImports();
  73. // Eagerly import the impls declared in the api file to prepare to redeclare
  74. // them.
  75. ImportImplsFromApiFile(context_);
  76. if (!ProcessNodeIds()) {
  77. context_.sem_ir().set_has_errors(true);
  78. return;
  79. }
  80. FinishRun();
  81. }
  82. auto CheckUnit::InitPackageScopeAndImports() -> void {
  83. // Importing makes many namespaces, so only canonicalize the type once.
  84. auto namespace_type_id =
  85. GetSingletonType(context_, SemIR::NamespaceType::TypeInstId);
  86. // Define the package scope, with an instruction for `package` expressions to
  87. // reference.
  88. auto package_scope_id = context_.name_scopes().Add(
  89. SemIR::Namespace::PackageInstId, SemIR::NameId::PackageNamespace,
  90. SemIR::NameScopeId::None);
  91. CARBON_CHECK(package_scope_id == SemIR::NameScopeId::Package);
  92. auto package_inst_id =
  93. AddInst<SemIR::Namespace>(context_, Parse::NodeId::None,
  94. {.type_id = namespace_type_id,
  95. .name_scope_id = SemIR::NameScopeId::Package,
  96. .import_id = SemIR::InstId::None});
  97. CARBON_CHECK(package_inst_id == SemIR::Namespace::PackageInstId);
  98. // Call `SetSpecialImportIRs()` to set `ImportIRId::ApiForImpl` and
  99. // `ImportIRId::Cpp` first, as required.
  100. if (unit_and_imports_->api_for_impl) {
  101. const auto& names = context_.parse_tree().packaging_decl()->names;
  102. auto import_decl_id = AddInst<SemIR::ImportDecl>(
  103. context_, names.node_id,
  104. {.package_id = SemIR::NameId::ForPackageName(names.package_id)});
  105. SetSpecialImportIRs(
  106. context_, {.decl_id = import_decl_id,
  107. .is_export = false,
  108. .sem_ir = unit_and_imports_->api_for_impl->unit->sem_ir});
  109. } else {
  110. SetSpecialImportIRs(context_,
  111. {.decl_id = SemIR::InstId::None, .sem_ir = nullptr});
  112. }
  113. // Add import instructions for everything directly imported. Implicit imports
  114. // are handled separately.
  115. for (auto& package_imports : unit_and_imports_->package_imports) {
  116. CARBON_CHECK(!package_imports.import_decl_id.has_value());
  117. package_imports.import_decl_id = AddInst<SemIR::ImportDecl>(
  118. context_, package_imports.node_id,
  119. {.package_id =
  120. SemIR::NameId::ForPackageName(package_imports.package_id)});
  121. }
  122. // Process the imports.
  123. if (unit_and_imports_->api_for_impl) {
  124. ImportApiFile(context_, namespace_type_id,
  125. *unit_and_imports_->api_for_impl->unit->sem_ir);
  126. }
  127. ImportCurrentPackage(package_inst_id, namespace_type_id);
  128. CARBON_CHECK(context_.scope_stack().PeekIndex() == ScopeIndex::Package);
  129. ImportOtherPackages(namespace_type_id);
  130. const auto& cpp_import_names = unit_and_imports_->cpp_import_names;
  131. if (!cpp_import_names.empty()) {
  132. auto* cpp_ast = unit_and_imports_->unit->cpp_ast;
  133. CARBON_CHECK(cpp_ast);
  134. CARBON_CHECK(!cpp_ast->get());
  135. *cpp_ast =
  136. ImportCppFiles(context_, unit_and_imports_->unit->sem_ir->filename(),
  137. cpp_import_names, fs_);
  138. }
  139. }
  140. auto CheckUnit::CollectDirectImports(
  141. llvm::SmallVector<SemIR::ImportIR>& results,
  142. llvm::MutableArrayRef<int> ir_to_result_index, SemIR::InstId import_decl_id,
  143. const PackageImports& imports, bool is_local) -> void {
  144. for (const auto& import : imports.imports) {
  145. const auto& direct_ir = *import.unit_info->unit->sem_ir;
  146. auto& index = ir_to_result_index[direct_ir.check_ir_id().index];
  147. if (index != -1) {
  148. // This should only happen when doing API imports for an implementation
  149. // file. Don't change the entry; is_export doesn't matter.
  150. continue;
  151. }
  152. index = results.size();
  153. results.push_back({.decl_id = import_decl_id,
  154. // Only tag exports in API files, ignoring the value in
  155. // implementation files.
  156. .is_export = is_local && import.names.is_export,
  157. .sem_ir = &direct_ir});
  158. }
  159. }
  160. auto CheckUnit::CollectTransitiveImports(SemIR::InstId import_decl_id,
  161. const PackageImports* local_imports,
  162. const PackageImports* api_imports)
  163. -> llvm::SmallVector<SemIR::ImportIR> {
  164. llvm::SmallVector<SemIR::ImportIR> results;
  165. // Track whether an IR was imported in full, including `export import`. This
  166. // distinguishes from IRs that are indirectly added without all names being
  167. // exported to this IR.
  168. llvm::SmallVector<int> ir_to_result_index(total_ir_count_, -1);
  169. // First add direct imports. This means that if an entity is imported both
  170. // directly and indirectly, the import path will reflect the direct import.
  171. if (local_imports) {
  172. CollectDirectImports(results, ir_to_result_index, import_decl_id,
  173. *local_imports,
  174. /*is_local=*/true);
  175. }
  176. if (api_imports) {
  177. CollectDirectImports(results, ir_to_result_index, import_decl_id,
  178. *api_imports,
  179. /*is_local=*/false);
  180. }
  181. // Loop through direct imports for any indirect exports. The underlying vector
  182. // is appended during iteration, so take the size first.
  183. const int direct_imports = results.size();
  184. for (int direct_index : llvm::seq(direct_imports)) {
  185. bool is_export = results[direct_index].is_export;
  186. for (const auto& indirect_ir :
  187. results[direct_index].sem_ir->import_irs().array_ref()) {
  188. if (!indirect_ir.is_export) {
  189. continue;
  190. }
  191. auto& indirect_index =
  192. ir_to_result_index[indirect_ir.sem_ir->check_ir_id().index];
  193. if (indirect_index == -1) {
  194. indirect_index = results.size();
  195. // TODO: In the case of a recursive `export import`, this only points at
  196. // the outermost import. May want something that better reflects the
  197. // recursion.
  198. results.push_back({.decl_id = results[direct_index].decl_id,
  199. .is_export = is_export,
  200. .sem_ir = indirect_ir.sem_ir});
  201. } else if (is_export) {
  202. results[indirect_index].is_export = true;
  203. }
  204. }
  205. }
  206. return results;
  207. }
  208. auto CheckUnit::ImportCurrentPackage(SemIR::InstId package_inst_id,
  209. SemIR::TypeId namespace_type_id) -> void {
  210. // Add imports from the current package.
  211. auto import_map_lookup =
  212. unit_and_imports_->package_imports_map.Lookup(PackageNameId::None);
  213. if (!import_map_lookup) {
  214. // Push the scope; there are no names to add.
  215. context_.scope_stack().PushForEntity(
  216. package_inst_id, SemIR::NameScopeId::Package, SemIR::SpecificId::None,
  217. /*lexical_lookup_has_load_error=*/false);
  218. return;
  219. }
  220. PackageImports& self_import =
  221. unit_and_imports_->package_imports[import_map_lookup.value()];
  222. if (self_import.has_load_error) {
  223. context_.name_scopes().Get(SemIR::NameScopeId::Package).set_has_error();
  224. }
  225. ImportLibrariesFromCurrentPackage(
  226. context_, namespace_type_id,
  227. CollectTransitiveImports(self_import.import_decl_id, &self_import,
  228. /*api_imports=*/nullptr));
  229. context_.scope_stack().PushForEntity(
  230. package_inst_id, SemIR::NameScopeId::Package, SemIR::SpecificId::None,
  231. context_.name_scopes().Get(SemIR::NameScopeId::Package).has_error());
  232. }
  233. auto CheckUnit::ImportOtherPackages(SemIR::TypeId namespace_type_id) -> void {
  234. // api_imports_list is initially the size of the current file's imports,
  235. // including for API files, for simplicity in iteration. It's only really used
  236. // when processing an implementation file, in order to combine the API file
  237. // imports.
  238. //
  239. // For packages imported by the API file, the PackageNameId is the package
  240. // name and the index is into the API's import list. Otherwise, the initial
  241. // {None, -1} state remains.
  242. llvm::SmallVector<std::pair<PackageNameId, int32_t>> api_imports_list;
  243. api_imports_list.resize(unit_and_imports_->package_imports.size(),
  244. {PackageNameId::None, -1});
  245. // When there's an API file, add the mapping to api_imports_list.
  246. if (unit_and_imports_->api_for_impl) {
  247. const auto& api_identifiers =
  248. unit_and_imports_->api_for_impl->unit->value_stores->identifiers();
  249. auto& impl_identifiers =
  250. unit_and_imports_->unit->value_stores->identifiers();
  251. for (auto [api_imports_index, api_imports] :
  252. llvm::enumerate(unit_and_imports_->api_for_impl->package_imports)) {
  253. // Skip the current package.
  254. if (!api_imports.package_id.has_value()) {
  255. continue;
  256. }
  257. // Translate the package ID from the API file to the implementation file.
  258. auto impl_package_id = api_imports.package_id;
  259. if (auto package_identifier_id = impl_package_id.AsIdentifierId();
  260. package_identifier_id.has_value()) {
  261. impl_package_id = PackageNameId::ForIdentifier(
  262. impl_identifiers.Add(api_identifiers.Get(package_identifier_id)));
  263. }
  264. if (auto lookup =
  265. unit_and_imports_->package_imports_map.Lookup(impl_package_id)) {
  266. // On a hit, replace the entry to unify the API and implementation
  267. // imports.
  268. api_imports_list[lookup.value()] = {impl_package_id, api_imports_index};
  269. } else {
  270. // On a miss, add the package as API-only.
  271. api_imports_list.push_back({impl_package_id, api_imports_index});
  272. }
  273. }
  274. }
  275. for (auto [i, api_imports_entry] : llvm::enumerate(api_imports_list)) {
  276. // These variables are updated after figuring out which imports are present.
  277. auto import_decl_id = SemIR::InstId::None;
  278. PackageNameId package_id = PackageNameId::None;
  279. bool has_load_error = false;
  280. // Identify the local package imports if present.
  281. PackageImports* local_imports = nullptr;
  282. if (i < unit_and_imports_->package_imports.size()) {
  283. local_imports = &unit_and_imports_->package_imports[i];
  284. if (!local_imports->package_id.has_value()) {
  285. // Skip the current package.
  286. continue;
  287. }
  288. import_decl_id = local_imports->import_decl_id;
  289. package_id = local_imports->package_id;
  290. has_load_error |= local_imports->has_load_error;
  291. }
  292. // Identify the API package imports if present.
  293. PackageImports* api_imports = nullptr;
  294. if (api_imports_entry.second != -1) {
  295. api_imports = &unit_and_imports_->api_for_impl
  296. ->package_imports[api_imports_entry.second];
  297. if (local_imports) {
  298. CARBON_CHECK(package_id == api_imports_entry.first);
  299. } else {
  300. auto import_ir_inst_id =
  301. context_.import_ir_insts().Add(SemIR::ImportIRInst(
  302. SemIR::ImportIRId::ApiForImpl, api_imports->import_decl_id));
  303. import_decl_id =
  304. AddInst(context_, MakeImportedLocIdAndInst<SemIR::ImportDecl>(
  305. context_, import_ir_inst_id,
  306. {.package_id = SemIR::NameId::ForPackageName(
  307. api_imports_entry.first)}));
  308. package_id = api_imports_entry.first;
  309. }
  310. has_load_error |= api_imports->has_load_error;
  311. }
  312. // Do the actual import.
  313. ImportLibrariesFromOtherPackage(
  314. context_, namespace_type_id, import_decl_id, package_id,
  315. CollectTransitiveImports(import_decl_id, local_imports, api_imports),
  316. has_load_error);
  317. }
  318. }
  319. // Loops over all nodes in the tree. On some errors, this may return early,
  320. // for example if an unrecoverable state is encountered.
  321. // NOLINTNEXTLINE(readability-function-size)
  322. auto CheckUnit::ProcessNodeIds() -> bool {
  323. NodeIdTraversal traversal(&context_, vlog_stream_);
  324. Parse::NodeId node_id = Parse::NodeId::None;
  325. // On crash, report which token we were handling.
  326. PrettyStackTraceFunction node_dumper([&](llvm::raw_ostream& output) {
  327. const auto& tree = tree_and_subtrees_getter_();
  328. auto converted = tree.NodeToDiagnosticLoc(node_id, /*token_only=*/false);
  329. converted.loc.FormatLocation(output);
  330. output << "checking " << context_.parse_tree().node_kind(node_id) << "\n";
  331. // Crash output has a tab indent; try to indent slightly past that.
  332. converted.loc.FormatSnippet(output, /*indent=*/10);
  333. });
  334. while (auto maybe_node_id = traversal.Next()) {
  335. node_id = *maybe_node_id;
  336. emitter_.AdvanceToken(context_.parse_tree().node_token(node_id));
  337. if (context_.parse_tree().node_has_error(node_id)) {
  338. context_.TODO(node_id, "handle invalid parse trees in `check`");
  339. return false;
  340. }
  341. bool result;
  342. auto parse_kind = context_.parse_tree().node_kind(node_id);
  343. switch (parse_kind) {
  344. #define CARBON_PARSE_NODE_KIND(Name) \
  345. case Parse::NodeKind::Name: { \
  346. result = HandleParseNode( \
  347. context_, context_.parse_tree().As<Parse::Name##Id>(node_id)); \
  348. break; \
  349. }
  350. #include "toolchain/parse/node_kind.def"
  351. }
  352. if (!result) {
  353. CARBON_CHECK(
  354. unit_and_imports_->err_tracker.seen_error(),
  355. "HandleParseNode for `{0}` returned false without diagnosing.",
  356. parse_kind);
  357. return false;
  358. }
  359. traversal.Handle(parse_kind);
  360. }
  361. return true;
  362. }
  363. auto CheckUnit::CheckRequiredDeclarations() -> void {
  364. for (const auto& function : context_.functions().array_ref()) {
  365. if (!function.first_owning_decl_id.has_value() &&
  366. function.extern_library_id == context_.sem_ir().library_id()) {
  367. auto function_import_id =
  368. context_.insts().GetImportSource(function.non_owning_decl_id);
  369. CARBON_CHECK(function_import_id.has_value());
  370. auto import_ir_id =
  371. context_.sem_ir().import_ir_insts().Get(function_import_id).ir_id();
  372. auto& import_ir = context_.import_irs().Get(import_ir_id);
  373. if (import_ir.sem_ir->package_id().has_value() !=
  374. context_.sem_ir().package_id().has_value()) {
  375. continue;
  376. }
  377. CARBON_DIAGNOSTIC(
  378. MissingOwningDeclarationInApi, Error,
  379. "owning declaration required for non-owning declaration");
  380. if (!import_ir.sem_ir->package_id().has_value() &&
  381. !context_.sem_ir().package_id().has_value()) {
  382. emitter_.Emit(function.non_owning_decl_id,
  383. MissingOwningDeclarationInApi);
  384. continue;
  385. }
  386. if (import_ir.sem_ir->identifiers().Get(
  387. import_ir.sem_ir->package_id().AsIdentifierId()) ==
  388. context_.sem_ir().identifiers().Get(
  389. context_.sem_ir().package_id().AsIdentifierId())) {
  390. emitter_.Emit(function.non_owning_decl_id,
  391. MissingOwningDeclarationInApi);
  392. }
  393. }
  394. }
  395. }
  396. auto CheckUnit::CheckRequiredDefinitions() -> void {
  397. CARBON_DIAGNOSTIC(MissingDefinitionInImpl, Error,
  398. "no definition found for declaration in impl file");
  399. // Note that more required definitions can be added during this loop.
  400. // NOLINTNEXTLINE(modernize-loop-convert)
  401. for (size_t i = 0; i != context_.definitions_required_by_decl().size(); ++i) {
  402. SemIR::InstId decl_inst_id = context_.definitions_required_by_decl()[i];
  403. SemIR::Inst decl_inst = context_.insts().Get(decl_inst_id);
  404. CARBON_KIND_SWITCH(context_.insts().Get(decl_inst_id)) {
  405. case CARBON_KIND(SemIR::ClassDecl class_decl): {
  406. if (!context_.classes().Get(class_decl.class_id).is_complete()) {
  407. emitter_.Emit(decl_inst_id, MissingDefinitionInImpl);
  408. }
  409. break;
  410. }
  411. case CARBON_KIND(SemIR::FunctionDecl function_decl): {
  412. if (context_.functions().Get(function_decl.function_id).definition_id ==
  413. SemIR::InstId::None) {
  414. emitter_.Emit(decl_inst_id, MissingDefinitionInImpl);
  415. }
  416. break;
  417. }
  418. case CARBON_KIND(SemIR::ImplDecl impl_decl): {
  419. auto& impl = context_.impls().Get(impl_decl.impl_id);
  420. if (!impl.is_complete()) {
  421. FillImplWitnessWithErrors(context_, impl);
  422. CARBON_DIAGNOSTIC(ImplMissingDefinition, Error,
  423. "impl declared but not defined");
  424. emitter_.Emit(decl_inst_id, ImplMissingDefinition);
  425. }
  426. break;
  427. }
  428. case SemIR::InterfaceDecl::Kind: {
  429. // TODO: Handle `interface` as well, once we can test it without
  430. // triggering
  431. // https://github.com/carbon-language/carbon-lang/issues/4071.
  432. CARBON_FATAL("TODO: Support interfaces in DiagnoseMissingDefinitions");
  433. }
  434. default: {
  435. CARBON_FATAL("Unexpected inst in definitions_required_by_decl: {0}",
  436. decl_inst);
  437. }
  438. }
  439. }
  440. // Note that more required definitions can be added during this loop.
  441. // NOLINTNEXTLINE(modernize-loop-convert)
  442. for (size_t i = 0; i != context_.definitions_required_by_use().size(); ++i) {
  443. // This is using the location for the use. We could track the
  444. // list of enclosing locations if this was used from a generic.
  445. auto [loc, specific_id] = context_.definitions_required_by_use()[i];
  446. if (!ResolveSpecificDefinition(context_, loc, specific_id)) {
  447. CARBON_DIAGNOSTIC(MissingGenericFunctionDefinition, Error,
  448. "use of undefined generic function");
  449. CARBON_DIAGNOSTIC(MissingGenericFunctionDefinitionHere, Note,
  450. "generic function declared here");
  451. auto generic_decl_id =
  452. context_.generics()
  453. .Get(context_.specifics().Get(specific_id).generic_id)
  454. .decl_id;
  455. emitter_.Build(loc, MissingGenericFunctionDefinition)
  456. .Note(generic_decl_id, MissingGenericFunctionDefinitionHere)
  457. .Emit();
  458. }
  459. }
  460. }
  461. auto CheckUnit::CheckPoisonedConcreteImplLookupQueries() -> void {
  462. // Impl lookup can generate instructions (via deduce) which we don't use, as
  463. // we're only generating diagnostics here, so we catch and discard them.
  464. context_.inst_block_stack().Push();
  465. auto poisoned_queries =
  466. std::exchange(context_.poisoned_concrete_impl_lookup_queries(), {});
  467. for (const auto& poison : poisoned_queries) {
  468. auto witness_result =
  469. EvalLookupSingleImplWitness(context_, poison.loc_id, poison.query,
  470. poison.non_canonical_query_self_inst_id,
  471. /*poison_concrete_results=*/false);
  472. CARBON_CHECK(witness_result.has_concrete_value());
  473. auto found_witness_id = witness_result.concrete_witness();
  474. if (found_witness_id != poison.impl_witness) {
  475. auto witness_to_impl_id = [&](SemIR::InstId witness_id) {
  476. auto table_id = context_.insts()
  477. .GetAs<SemIR::ImplWitness>(witness_id)
  478. .witness_table_id;
  479. return context_.insts()
  480. .GetAs<SemIR::ImplWitnessTable>(table_id)
  481. .impl_id;
  482. };
  483. // We can get the `Impl` from the resulting witness here, which is the
  484. // `Impl` that conflicts with the previous poison query.
  485. auto bad_impl_id = witness_to_impl_id(found_witness_id);
  486. const auto& bad_impl = context_.impls().Get(bad_impl_id);
  487. auto prev_impl_id = witness_to_impl_id(poison.impl_witness);
  488. const auto& prev_impl = context_.impls().Get(prev_impl_id);
  489. CARBON_DIAGNOSTIC(
  490. PoisonedImplLookupConcreteResult, Error,
  491. "found `impl` that would change the result of an earlier "
  492. "use of `{0} as {1}`",
  493. InstIdAsRawType, SpecificInterfaceIdAsRawType);
  494. auto builder =
  495. emitter_.Build(poison.loc_id, PoisonedImplLookupConcreteResult,
  496. poison.query.query_self_inst_id,
  497. poison.query.query_specific_interface_id);
  498. CARBON_DIAGNOSTIC(
  499. PoisonedImplLookupConcreteResultNoteBadImpl, Note,
  500. "the use would select the `impl` here but it was not found yet");
  501. builder.Note(bad_impl.first_decl_id(),
  502. PoisonedImplLookupConcreteResultNoteBadImpl);
  503. CARBON_DIAGNOSTIC(PoisonedImplLookupConcreteResultNotePreviousImpl, Note,
  504. "the use had selected the `impl` here");
  505. builder.Note(prev_impl.first_decl_id(),
  506. PoisonedImplLookupConcreteResultNotePreviousImpl);
  507. builder.Emit();
  508. }
  509. }
  510. context_.inst_block_stack().PopAndDiscard();
  511. }
  512. // Check for invalid overlap between impls, given the set of all impls for a
  513. // single interface.
  514. static auto CheckOverlappingImplsForInterface(
  515. Context& context,
  516. llvm::ArrayRef<std::pair<SemIR::ImplId, SemIR::SpecificInterface>>
  517. impls_and_interface) -> void {
  518. // Range over `SemIR::ImplId` only. It'd be nice to make this the function
  519. // parameter but we don't have a concept to express that outside the (banned)
  520. // std::ranges.
  521. auto impl_ids = llvm::map_range(
  522. impls_and_interface,
  523. [=](std::pair<SemIR::ImplId, SemIR::SpecificInterface> pair) {
  524. auto [impl_id, _] = pair;
  525. return impl_id;
  526. });
  527. // Avoid holding a reference into the ImplStore, as the diagnostic checks
  528. // below can invalidate the reference. We copy out the part of the `Impl` we
  529. // need.
  530. struct ImplInfo {
  531. bool is_final;
  532. SemIR::InstId witness_id;
  533. SemIR::TypeInstId self_id;
  534. SemIR::InstId latest_decl_id;
  535. SemIR::SpecificInterface interface;
  536. };
  537. auto get_impl_info = [&](SemIR::ImplId impl_id) -> ImplInfo {
  538. const auto& impl = context.impls().Get(impl_id);
  539. return {.is_final = impl.is_final,
  540. .witness_id = impl.witness_id,
  541. .self_id = impl.self_id,
  542. .latest_decl_id = impl.latest_decl_id(),
  543. .interface = impl.interface};
  544. };
  545. // TODO: We should revisit this and look for a way to do these checks in less
  546. // than quadratic time. From @zygoloid: Possibly by converting the set of
  547. // impls into a decision tree.
  548. for (auto [index_a, impl_a_id] : llvm::enumerate(impl_ids)) {
  549. auto impl_a = get_impl_info(impl_a_id);
  550. if (impl_a.witness_id == SemIR::ErrorInst::InstId) {
  551. continue;
  552. }
  553. auto type_structure =
  554. BuildTypeStructure(context, impl_a.self_id, impl_a.interface);
  555. for (auto impl_b_id : llvm::drop_begin(impl_ids, index_a + 1)) {
  556. auto impl_b = get_impl_info(impl_b_id);
  557. if (impl_b.witness_id == SemIR::ErrorInst::InstId) {
  558. continue;
  559. }
  560. // The type structure each non-final `impl` must differ from all other
  561. // non-final `impl` for the same interface visible from the file.
  562. if (!impl_a.is_final && !impl_b.is_final) {
  563. auto type_structure2 =
  564. BuildTypeStructure(context, impl_b.self_id, impl_b.interface);
  565. if (type_structure == type_structure2) {
  566. CARBON_DIAGNOSTIC(ImplNonFinalSameTypeStructure, Error,
  567. "found non-final `impl` with the same type "
  568. "structure as another non-final `impl`");
  569. auto builder = context.emitter().Build(impl_b.latest_decl_id,
  570. ImplNonFinalSameTypeStructure);
  571. CARBON_DIAGNOSTIC(ImplNonFinalSameTypeStructureNote, Note,
  572. "other `impl` here");
  573. builder.Note(impl_a.latest_decl_id,
  574. ImplNonFinalSameTypeStructureNote);
  575. builder.Emit();
  576. break;
  577. }
  578. } else {
  579. CARBON_CHECK(impl_a.is_final || impl_b.is_final);
  580. auto diagnose = [&](ImplInfo& query_impl, SemIR::ImplId final_impl_id,
  581. const ImplInfo& final_impl) -> bool {
  582. if (LookupMatchesImpl(
  583. context, SemIR::LocId(query_impl.latest_decl_id),
  584. context.constant_values().Get(query_impl.self_id),
  585. query_impl.interface, final_impl_id)) {
  586. CARBON_DIAGNOSTIC(ImplFinalOverlapsNonFinal, Error,
  587. "`impl` will never be used");
  588. auto builder = context.emitter().Build(query_impl.latest_decl_id,
  589. ImplFinalOverlapsNonFinal);
  590. CARBON_DIAGNOSTIC(
  591. ImplFinalOverlapsNonFinalNote, Note,
  592. "`final impl` declared here would always be used instead");
  593. builder.Note(final_impl.latest_decl_id,
  594. ImplFinalOverlapsNonFinalNote);
  595. builder.Emit();
  596. return true;
  597. }
  598. return false;
  599. };
  600. bool did_diagnose = false;
  601. if (impl_a.is_final) {
  602. did_diagnose = diagnose(impl_b, impl_a_id, impl_a);
  603. }
  604. if (impl_b.is_final && !did_diagnose) {
  605. diagnose(impl_a, impl_b_id, impl_b);
  606. }
  607. }
  608. }
  609. // TODO: The self + constraint of a `impl` must not match against (be
  610. // fully subsumed by) any final `impl` visible from the file. Do a
  611. // final-only query for all non-final impls?
  612. }
  613. }
  614. auto CheckUnit::CheckOverlappingImpls() -> void {
  615. // Collect all of the impls sorted into contiguous segments by their
  616. // interface. We only need to compare impls within each such segment.
  617. //
  618. // Don't hold Impl pointers here because the process of looking for
  619. // diagnostics may cause imports and may invalidate pointers into the
  620. // ImplStore.
  621. llvm::SmallVector<std::pair<SemIR::ImplId, SemIR::SpecificInterface>>
  622. impl_ids_by_interface(llvm::map_range(
  623. context_.impls().enumerate(),
  624. [](std::pair<SemIR::ImplId, const SemIR::Impl&> pair) {
  625. return std::make_pair(pair.first, pair.second.interface);
  626. }));
  627. llvm::stable_sort(
  628. impl_ids_by_interface,
  629. [](std::pair<SemIR::ImplId, SemIR::SpecificInterface> a,
  630. std::pair<SemIR::ImplId, const SemIR::SpecificInterface> b) {
  631. return a.second.interface_id.index < b.second.interface_id.index;
  632. });
  633. const auto* it = impl_ids_by_interface.begin();
  634. while (it != impl_ids_by_interface.end()) {
  635. const auto* segment_begin = it;
  636. do {
  637. ++it;
  638. } while (it != impl_ids_by_interface.end() &&
  639. it->second.interface_id == segment_begin->second.interface_id);
  640. const auto* segment_end = it;
  641. if (std::distance(segment_begin, segment_end) == 1) {
  642. // Only 1 interface in the segment; nothing to overlap with.
  643. continue;
  644. }
  645. CheckOverlappingImplsForInterface(
  646. context_, llvm::ArrayRef(segment_begin, segment_end));
  647. }
  648. }
  649. auto CheckUnit::FinishRun() -> void {
  650. CheckRequiredDeclarations();
  651. CheckRequiredDefinitions();
  652. CheckPoisonedConcreteImplLookupQueries();
  653. CheckOverlappingImpls();
  654. // Pop information for the file-level scope.
  655. context_.sem_ir().set_top_inst_block_id(context_.inst_block_stack().Pop());
  656. context_.scope_stack().Pop();
  657. // Finalizes the list of exports on the IR.
  658. context_.inst_blocks().ReplacePlaceholder(SemIR::InstBlockId::Exports,
  659. context_.exports());
  660. // Finalizes the ImportRef inst block.
  661. context_.inst_blocks().ReplacePlaceholder(SemIR::InstBlockId::ImportRefs,
  662. context_.import_ref_ids());
  663. // Finalizes __global_init.
  664. context_.global_init().Finalize();
  665. context_.sem_ir().set_has_errors(unit_and_imports_->err_tracker.seen_error());
  666. // Verify that Context cleanly finished.
  667. context_.VerifyOnFinish();
  668. }
  669. } // namespace Carbon::Check