check_unit.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  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 <iterator>
  6. #include <string>
  7. #include <tuple>
  8. #include <utility>
  9. #include "clang/Sema/Sema.h"
  10. #include "common/growing_range.h"
  11. #include "common/pretty_stack_trace_function.h"
  12. #include "llvm/ADT/IntrusiveRefCntPtr.h"
  13. #include "llvm/ADT/StringRef.h"
  14. #include "llvm/Support/VirtualFileSystem.h"
  15. #include "toolchain/base/fixed_size_value_store.h"
  16. #include "toolchain/base/kind_switch.h"
  17. #include "toolchain/check/cpp/generate_ast.h"
  18. #include "toolchain/check/cpp/import.h"
  19. #include "toolchain/check/diagnostic_helpers.h"
  20. #include "toolchain/check/generic.h"
  21. #include "toolchain/check/handle.h"
  22. #include "toolchain/check/impl.h"
  23. #include "toolchain/check/impl_lookup.h"
  24. #include "toolchain/check/impl_validation.h"
  25. #include "toolchain/check/import.h"
  26. #include "toolchain/check/import_ref.h"
  27. #include "toolchain/check/inst.h"
  28. #include "toolchain/check/node_id_traversal.h"
  29. #include "toolchain/check/type.h"
  30. #include "toolchain/check/type_structure.h"
  31. #include "toolchain/diagnostics/diagnostic.h"
  32. #include "toolchain/sem_ir/function.h"
  33. #include "toolchain/sem_ir/ids.h"
  34. #include "toolchain/sem_ir/import_ir.h"
  35. #include "toolchain/sem_ir/typed_insts.h"
  36. namespace Carbon::Check {
  37. // Returns the number of imported IRs, to assist in Context construction.
  38. static auto GetImportedIRCount(UnitAndImports* unit_and_imports) -> int {
  39. int count = 0;
  40. for (auto& package_imports : unit_and_imports->package_imports) {
  41. count += package_imports.imports.size();
  42. }
  43. if (!unit_and_imports->api_for_impl) {
  44. // Leave an empty slot for `ImportIRId::ApiForImpl`.
  45. ++count;
  46. }
  47. if (!unit_and_imports->cpp_imports.empty()) {
  48. // Leave an empty slot for `ImportIRId::Cpp`.
  49. ++count;
  50. }
  51. return count;
  52. }
  53. CheckUnit::CheckUnit(
  54. UnitAndImports* unit_and_imports,
  55. const Parse::GetTreeAndSubtreesStore* tree_and_subtrees_getters,
  56. llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
  57. llvm::LLVMContext* llvm_context,
  58. std::shared_ptr<clang::CompilerInvocation> clang_invocation,
  59. llvm::raw_ostream* vlog_stream)
  60. : unit_and_imports_(unit_and_imports),
  61. tree_and_subtrees_getter_(tree_and_subtrees_getters->Get(
  62. unit_and_imports->unit->sem_ir->check_ir_id())),
  63. fs_(std::move(fs)),
  64. llvm_context_(llvm_context),
  65. clang_invocation_(std::move(clang_invocation)),
  66. emitter_(&unit_and_imports_->err_tracker, tree_and_subtrees_getters,
  67. unit_and_imports_->unit->sem_ir),
  68. context_(&emitter_, tree_and_subtrees_getter_,
  69. unit_and_imports_->unit->sem_ir,
  70. GetImportedIRCount(unit_and_imports),
  71. unit_and_imports_->unit->total_ir_count, vlog_stream) {}
  72. auto CheckUnit::Run() -> void {
  73. Timings::ScopedTiming timing(unit_and_imports_->unit->timings, "check");
  74. // We can safely mark this as checked at the start.
  75. unit_and_imports_->is_checked = true;
  76. PrettyStackTraceFunction context_dumper(
  77. [&](llvm::raw_ostream& output) { context_.PrintForStackDump(output); });
  78. // Add a block for the file.
  79. context_.inst_block_stack().Push();
  80. InitPackageScopeAndImports();
  81. // Eagerly import the impls declared in the api file to prepare to redeclare
  82. // them.
  83. ImportImplsFromApiFile(context_);
  84. if (!ProcessNodeIds()) {
  85. context_.sem_ir().set_has_errors(true);
  86. return;
  87. }
  88. FinishRun();
  89. }
  90. auto CheckUnit::InitPackageScopeAndImports() -> void {
  91. // Importing makes many namespaces, so only canonicalize the type once.
  92. auto namespace_type_id =
  93. GetSingletonType(context_, SemIR::NamespaceType::TypeInstId);
  94. // Use the name of the package for the package scope.
  95. SemIR::NameId package_name_id = SemIR::NameId::MainPackage;
  96. const auto& packaging = context_.parse_tree().packaging_decl();
  97. if (packaging && packaging->names.package_id.has_value()) {
  98. package_name_id =
  99. SemIR::NameId::ForPackageName(packaging->names.package_id);
  100. }
  101. // Define the package scope, with an instruction for `package` expressions to
  102. // reference.
  103. auto package_scope_id =
  104. context_.name_scopes().Add(SemIR::Namespace::PackageInstId,
  105. package_name_id, SemIR::NameScopeId::None);
  106. CARBON_CHECK(package_scope_id == SemIR::NameScopeId::Package);
  107. auto package_inst_id =
  108. AddInst<SemIR::Namespace>(context_, Parse::NodeId::None,
  109. {.type_id = namespace_type_id,
  110. .name_scope_id = SemIR::NameScopeId::Package,
  111. .import_id = SemIR::InstId::None});
  112. CARBON_CHECK(package_inst_id == SemIR::Namespace::PackageInstId);
  113. // Call `SetSpecialImportIRs()` to set `ImportIRId::ApiForImpl` and
  114. // `ImportIRId::Cpp` first, as required.
  115. if (unit_and_imports_->api_for_impl) {
  116. const auto& names = packaging->names;
  117. auto import_decl_id = AddInst<SemIR::ImportDecl>(
  118. context_, names.node_id,
  119. {.package_id = SemIR::NameId::ForPackageName(names.package_id)});
  120. SetSpecialImportIRs(
  121. context_, {.decl_id = import_decl_id,
  122. .is_export = false,
  123. .sem_ir = unit_and_imports_->api_for_impl->unit->sem_ir});
  124. } else {
  125. SetSpecialImportIRs(context_,
  126. {.decl_id = SemIR::InstId::None, .sem_ir = nullptr});
  127. }
  128. // Add import instructions for everything directly imported. Implicit imports
  129. // are handled separately.
  130. for (auto& package_imports : unit_and_imports_->package_imports) {
  131. CARBON_CHECK(!package_imports.import_decl_id.has_value());
  132. package_imports.import_decl_id = AddInst<SemIR::ImportDecl>(
  133. context_, package_imports.node_id,
  134. {.package_id =
  135. SemIR::NameId::ForPackageName(package_imports.package_id)});
  136. }
  137. // Process the imports.
  138. if (unit_and_imports_->api_for_impl) {
  139. ImportApiFile(context_, namespace_type_id,
  140. *unit_and_imports_->api_for_impl->unit->sem_ir);
  141. }
  142. ImportCurrentPackage(package_inst_id, namespace_type_id);
  143. CARBON_CHECK(context_.scope_stack().PeekIndex() == ScopeIndex::Package);
  144. ImportOtherPackages(namespace_type_id);
  145. const auto& cpp_imports = unit_and_imports_->cpp_imports;
  146. if (!cpp_imports.empty()) {
  147. ImportCpp(context_, cpp_imports, fs_, llvm_context_, clang_invocation_);
  148. }
  149. }
  150. auto CheckUnit::CollectDirectImports(
  151. llvm::SmallVector<SemIR::ImportIR>& results,
  152. CheckIRIdToIntStore& ir_to_result_index, SemIR::InstId import_decl_id,
  153. const PackageImports& imports, bool is_local) -> void {
  154. for (const auto& import : imports.imports) {
  155. const auto& direct_ir = *import.unit_info->unit->sem_ir;
  156. auto& index = ir_to_result_index.Get(direct_ir.check_ir_id());
  157. if (index != -1) {
  158. // This should only happen when doing API imports for an implementation
  159. // file. Don't change the entry; is_export doesn't matter.
  160. continue;
  161. }
  162. index = results.size();
  163. results.push_back({.decl_id = import_decl_id,
  164. // Only tag exports in API files, ignoring the value in
  165. // implementation files.
  166. .is_export = is_local && import.names.is_export,
  167. .sem_ir = &direct_ir});
  168. }
  169. }
  170. auto CheckUnit::CollectTransitiveImports(SemIR::InstId import_decl_id,
  171. const PackageImports* local_imports,
  172. const PackageImports* api_imports)
  173. -> llvm::SmallVector<SemIR::ImportIR> {
  174. llvm::SmallVector<SemIR::ImportIR> results;
  175. // Track whether an IR was imported in full, including `export import`. This
  176. // distinguishes from IRs that are indirectly added without all names being
  177. // exported to this IR.
  178. auto ir_to_result_index = CheckIRIdToIntStore::MakeWithExplicitSize(
  179. unit_and_imports_->unit->total_ir_count, -1);
  180. // First add direct imports. This means that if an entity is imported both
  181. // directly and indirectly, the import path will reflect the direct import.
  182. if (local_imports) {
  183. CollectDirectImports(results, ir_to_result_index, import_decl_id,
  184. *local_imports,
  185. /*is_local=*/true);
  186. }
  187. if (api_imports) {
  188. CollectDirectImports(results, ir_to_result_index, import_decl_id,
  189. *api_imports,
  190. /*is_local=*/false);
  191. }
  192. // Loop through direct imports for any indirect exports. The underlying vector
  193. // is appended during iteration, so take the size first.
  194. const int direct_imports = results.size();
  195. for (int direct_index : llvm::seq(direct_imports)) {
  196. bool is_export = results[direct_index].is_export;
  197. for (const auto& indirect_ir :
  198. results[direct_index].sem_ir->import_irs().values()) {
  199. if (!indirect_ir.is_export) {
  200. continue;
  201. }
  202. auto& indirect_index =
  203. ir_to_result_index.Get(indirect_ir.sem_ir->check_ir_id());
  204. if (indirect_index == -1) {
  205. indirect_index = results.size();
  206. // TODO: In the case of a recursive `export import`, this only points at
  207. // the outermost import. May want something that better reflects the
  208. // recursion.
  209. results.push_back({.decl_id = results[direct_index].decl_id,
  210. .is_export = is_export,
  211. .sem_ir = indirect_ir.sem_ir});
  212. } else if (is_export) {
  213. results[indirect_index].is_export = true;
  214. }
  215. }
  216. }
  217. return results;
  218. }
  219. auto CheckUnit::ImportCurrentPackage(SemIR::InstId package_inst_id,
  220. SemIR::TypeId namespace_type_id) -> void {
  221. // Add imports from the current package.
  222. auto import_map_lookup =
  223. unit_and_imports_->package_imports_map.Lookup(PackageNameId::None);
  224. if (!import_map_lookup) {
  225. // Push the scope; there are no names to add.
  226. context_.scope_stack().PushForEntity(
  227. package_inst_id, SemIR::NameScopeId::Package, SemIR::SpecificId::None,
  228. /*lexical_lookup_has_load_error=*/false);
  229. return;
  230. }
  231. PackageImports& self_import =
  232. unit_and_imports_->package_imports[import_map_lookup.value()];
  233. if (self_import.has_load_error) {
  234. context_.name_scopes().Get(SemIR::NameScopeId::Package).set_has_error();
  235. }
  236. ImportLibrariesFromCurrentPackage(
  237. context_, namespace_type_id,
  238. CollectTransitiveImports(self_import.import_decl_id, &self_import,
  239. /*api_imports=*/nullptr));
  240. context_.scope_stack().PushForEntity(
  241. package_inst_id, SemIR::NameScopeId::Package, SemIR::SpecificId::None,
  242. context_.name_scopes().Get(SemIR::NameScopeId::Package).has_error());
  243. }
  244. auto CheckUnit::ImportOtherPackages(SemIR::TypeId namespace_type_id) -> void {
  245. // api_imports_list is initially the size of the current file's imports,
  246. // including for API files, for simplicity in iteration. It's only really used
  247. // when processing an implementation file, in order to combine the API file
  248. // imports.
  249. //
  250. // For packages imported by the API file, the PackageNameId is the package
  251. // name and the index is into the API's import list. Otherwise, the initial
  252. // {None, -1} state remains.
  253. llvm::SmallVector<std::pair<PackageNameId, int32_t>> api_imports_list;
  254. api_imports_list.resize(unit_and_imports_->package_imports.size(),
  255. {PackageNameId::None, -1});
  256. // When there's an API file, add the mapping to api_imports_list.
  257. if (unit_and_imports_->api_for_impl) {
  258. const auto& api_identifiers =
  259. unit_and_imports_->api_for_impl->unit->value_stores->identifiers();
  260. auto& impl_identifiers =
  261. unit_and_imports_->unit->value_stores->identifiers();
  262. for (auto [api_imports_index, api_imports] :
  263. llvm::enumerate(unit_and_imports_->api_for_impl->package_imports)) {
  264. // Skip the current package.
  265. if (!api_imports.package_id.has_value()) {
  266. continue;
  267. }
  268. // Translate the package ID from the API file to the implementation file.
  269. auto impl_package_id = api_imports.package_id;
  270. if (auto package_identifier_id = impl_package_id.AsIdentifierId();
  271. package_identifier_id.has_value()) {
  272. impl_package_id = PackageNameId::ForIdentifier(
  273. impl_identifiers.Add(api_identifiers.Get(package_identifier_id)));
  274. }
  275. if (auto lookup =
  276. unit_and_imports_->package_imports_map.Lookup(impl_package_id)) {
  277. // On a hit, replace the entry to unify the API and implementation
  278. // imports.
  279. api_imports_list[lookup.value()] = {impl_package_id, api_imports_index};
  280. } else {
  281. // On a miss, add the package as API-only.
  282. api_imports_list.push_back({impl_package_id, api_imports_index});
  283. }
  284. }
  285. }
  286. for (auto [i, api_imports_entry] : llvm::enumerate(api_imports_list)) {
  287. // These variables are updated after figuring out which imports are present.
  288. auto import_decl_id = SemIR::InstId::None;
  289. PackageNameId package_id = PackageNameId::None;
  290. bool has_load_error = false;
  291. // Identify the local package imports if present.
  292. PackageImports* local_imports = nullptr;
  293. if (i < unit_and_imports_->package_imports.size()) {
  294. local_imports = &unit_and_imports_->package_imports[i];
  295. if (!local_imports->package_id.has_value()) {
  296. // Skip the current package.
  297. continue;
  298. }
  299. import_decl_id = local_imports->import_decl_id;
  300. package_id = local_imports->package_id;
  301. has_load_error |= local_imports->has_load_error;
  302. }
  303. // Identify the API package imports if present.
  304. PackageImports* api_imports = nullptr;
  305. if (api_imports_entry.second != -1) {
  306. api_imports = &unit_and_imports_->api_for_impl
  307. ->package_imports[api_imports_entry.second];
  308. if (local_imports) {
  309. CARBON_CHECK(package_id == api_imports_entry.first);
  310. } else {
  311. auto import_ir_inst_id =
  312. context_.import_ir_insts().Add(SemIR::ImportIRInst(
  313. SemIR::ImportIRId::ApiForImpl, api_imports->import_decl_id));
  314. import_decl_id =
  315. AddInst(context_, MakeImportedLocIdAndInst<SemIR::ImportDecl>(
  316. context_, import_ir_inst_id,
  317. {.package_id = SemIR::NameId::ForPackageName(
  318. api_imports_entry.first)}));
  319. package_id = api_imports_entry.first;
  320. }
  321. has_load_error |= api_imports->has_load_error;
  322. }
  323. // Do the actual import.
  324. ImportLibrariesFromOtherPackage(
  325. context_, namespace_type_id, import_decl_id, package_id,
  326. CollectTransitiveImports(import_decl_id, local_imports, api_imports),
  327. has_load_error);
  328. }
  329. }
  330. // Loops over all nodes in the tree. On some errors, this may return early,
  331. // for example if an unrecoverable state is encountered.
  332. auto CheckUnit::ProcessNodeIds() -> bool {
  333. NodeIdTraversal traversal(&context_);
  334. Parse::NodeId node_id = Parse::NodeId::None;
  335. // On crash, report which token we were handling.
  336. PrettyStackTraceFunction node_dumper([&](llvm::raw_ostream& output) {
  337. const auto& tree = tree_and_subtrees_getter_();
  338. auto converted = tree.NodeToDiagnosticLoc(node_id, /*token_only=*/false);
  339. converted.loc.FormatLocation(output);
  340. output << "Checking " << context_.parse_tree().node_kind(node_id) << "\n";
  341. // Crash output has a tab indent; try to indent slightly past that.
  342. converted.loc.FormatSnippet(output, /*indent=*/10);
  343. });
  344. while (auto maybe_node_id = traversal.Next()) {
  345. node_id = *maybe_node_id;
  346. emitter_.AdvanceToken(context_.parse_tree().node_token(node_id));
  347. if (context_.parse_tree().node_has_error(node_id)) {
  348. context_.TODO(node_id, "handle invalid parse trees in `check`");
  349. return false;
  350. }
  351. bool result;
  352. auto parse_kind = context_.parse_tree().node_kind(node_id);
  353. switch (parse_kind) {
  354. #define CARBON_PARSE_NODE_KIND(Name) \
  355. case Parse::NodeKind::Name: { \
  356. result = HandleParseNode( \
  357. context_, context_.parse_tree().As<Parse::Name##Id>(node_id)); \
  358. break; \
  359. }
  360. #include "toolchain/parse/node_kind.def"
  361. }
  362. if (!result) {
  363. CARBON_CHECK(
  364. unit_and_imports_->err_tracker.seen_error(),
  365. "HandleParseNode for `{0}` returned false without diagnosing.",
  366. parse_kind);
  367. return false;
  368. }
  369. traversal.Handle(parse_kind);
  370. }
  371. return true;
  372. }
  373. auto CheckUnit::CheckRequiredDeclarations() -> void {
  374. for (const auto& function : context_.functions().values()) {
  375. if (!function.first_owning_decl_id.has_value() &&
  376. function.extern_library_id == context_.sem_ir().library_id()) {
  377. auto function_import_id =
  378. context_.insts().GetImportSource(function.non_owning_decl_id);
  379. CARBON_CHECK(function_import_id.has_value());
  380. auto import_ir_id =
  381. context_.sem_ir().import_ir_insts().Get(function_import_id).ir_id();
  382. auto& import_ir = context_.import_irs().Get(import_ir_id);
  383. if (import_ir.sem_ir->package_id().has_value() !=
  384. context_.sem_ir().package_id().has_value()) {
  385. continue;
  386. }
  387. CARBON_DIAGNOSTIC(
  388. MissingOwningDeclarationInApi, Error,
  389. "owning declaration required for non-owning declaration");
  390. if (!import_ir.sem_ir->package_id().has_value() &&
  391. !context_.sem_ir().package_id().has_value()) {
  392. emitter_.Emit(function.non_owning_decl_id,
  393. MissingOwningDeclarationInApi);
  394. continue;
  395. }
  396. if (import_ir.sem_ir->identifiers().Get(
  397. import_ir.sem_ir->package_id().AsIdentifierId()) ==
  398. context_.sem_ir().identifiers().Get(
  399. context_.sem_ir().package_id().AsIdentifierId())) {
  400. emitter_.Emit(function.non_owning_decl_id,
  401. MissingOwningDeclarationInApi);
  402. }
  403. }
  404. }
  405. }
  406. auto CheckUnit::CheckRequiredDefinitions() -> void {
  407. CARBON_DIAGNOSTIC(MissingDefinitionInImpl, Error,
  408. "no definition found for declaration in impl file");
  409. for (SemIR::InstId decl_inst_id : context_.definitions_required_by_decl()) {
  410. SemIR::Inst decl_inst = context_.insts().Get(decl_inst_id);
  411. CARBON_KIND_SWITCH(context_.insts().Get(decl_inst_id)) {
  412. case CARBON_KIND(SemIR::ClassDecl class_decl): {
  413. if (!context_.classes().Get(class_decl.class_id).is_complete()) {
  414. emitter_.Emit(decl_inst_id, MissingDefinitionInImpl);
  415. }
  416. break;
  417. }
  418. case CARBON_KIND(SemIR::FunctionDecl function_decl): {
  419. if (context_.functions().Get(function_decl.function_id).definition_id ==
  420. SemIR::InstId::None) {
  421. emitter_.Emit(decl_inst_id, MissingDefinitionInImpl);
  422. }
  423. break;
  424. }
  425. case CARBON_KIND(SemIR::ImplDecl impl_decl): {
  426. auto& impl = context_.impls().Get(impl_decl.impl_id);
  427. if (!impl.is_complete()) {
  428. FillImplWitnessWithErrors(context_, impl);
  429. CARBON_DIAGNOSTIC(ImplMissingDefinition, Error,
  430. "impl declared but not defined");
  431. emitter_.Emit(decl_inst_id, ImplMissingDefinition);
  432. }
  433. break;
  434. }
  435. case SemIR::InterfaceDecl::Kind: {
  436. // TODO: Handle `interface` as well, once we can test it without
  437. // triggering
  438. // https://github.com/carbon-language/carbon-lang/issues/4071.
  439. CARBON_FATAL("TODO: Support interfaces in DiagnoseMissingDefinitions");
  440. }
  441. default: {
  442. CARBON_FATAL("Unexpected inst in definitions_required_by_decl: {0}",
  443. decl_inst);
  444. }
  445. }
  446. }
  447. for (auto [loc, specific_id] :
  448. GrowingRange(context_.definitions_required_by_use())) {
  449. // This is using the location for the use. We could track the
  450. // list of enclosing locations if this was used from a generic.
  451. if (!ResolveSpecificDefinition(context_, loc, specific_id)) {
  452. CARBON_DIAGNOSTIC(MissingGenericFunctionDefinition, Error,
  453. "use of undefined generic function");
  454. CARBON_DIAGNOSTIC(MissingGenericFunctionDefinitionHere, Note,
  455. "generic function declared here");
  456. auto generic_decl_id =
  457. context_.generics()
  458. .Get(context_.specifics().Get(specific_id).generic_id)
  459. .decl_id;
  460. emitter_.Build(loc, MissingGenericFunctionDefinition)
  461. .Note(generic_decl_id, MissingGenericFunctionDefinitionHere)
  462. .Emit();
  463. }
  464. }
  465. }
  466. auto CheckUnit::CheckPoisonedConcreteImplLookupQueries() -> void {
  467. // Impl lookup can generate instructions (via deduce) which we don't use, as
  468. // we're only generating diagnostics here, so we catch and discard them.
  469. context_.inst_block_stack().Push();
  470. auto poisoned_queries =
  471. std::exchange(context_.poisoned_concrete_impl_lookup_queries(), {});
  472. for (const auto& poison : poisoned_queries) {
  473. auto witness_result = EvalLookupSingleImplWitness(
  474. context_, poison.loc_id, poison.query, poison.query.query_self_inst_id,
  475. EvalImplLookupMode::RecheckPoisonedLookup);
  476. CARBON_CHECK(witness_result.has_final_value());
  477. auto found_witness_id = witness_result.final_witness();
  478. if (found_witness_id == SemIR::ErrorInst::InstId) {
  479. // Errors may have been diagnosed with the impl used in the poisoned query
  480. // in the meantime (such as a missing definition).
  481. continue;
  482. }
  483. if (found_witness_id != poison.impl_witness) {
  484. auto witness_to_impl_id = [&](SemIR::InstId witness_id) {
  485. auto table_id = context_.insts()
  486. .GetAs<SemIR::ImplWitness>(witness_id)
  487. .witness_table_id;
  488. return context_.insts()
  489. .GetAs<SemIR::ImplWitnessTable>(table_id)
  490. .impl_id;
  491. };
  492. // We can get the `Impl` from the resulting witness here, which is the
  493. // `Impl` that conflicts with the previous poison query.
  494. auto bad_impl_id = witness_to_impl_id(found_witness_id);
  495. const auto& bad_impl = context_.impls().Get(bad_impl_id);
  496. auto prev_impl_id = witness_to_impl_id(poison.impl_witness);
  497. const auto& prev_impl = context_.impls().Get(prev_impl_id);
  498. CARBON_DIAGNOSTIC(
  499. PoisonedImplLookupConcreteResult, Error,
  500. "found `impl` that would change the result of an earlier "
  501. "use of `{0} as {1}`",
  502. InstIdAsRawType, SpecificInterfaceIdAsRawType);
  503. auto builder =
  504. emitter_.Build(poison.loc_id, PoisonedImplLookupConcreteResult,
  505. poison.query.query_self_inst_id,
  506. poison.query.query_specific_interface_id);
  507. CARBON_DIAGNOSTIC(
  508. PoisonedImplLookupConcreteResultNoteBadImpl, Note,
  509. "the use would select the `impl` here but it was not found yet");
  510. builder.Note(bad_impl.first_decl_id(),
  511. PoisonedImplLookupConcreteResultNoteBadImpl);
  512. CARBON_DIAGNOSTIC(PoisonedImplLookupConcreteResultNotePreviousImpl, Note,
  513. "the use had selected the `impl` here");
  514. builder.Note(prev_impl.first_decl_id(),
  515. PoisonedImplLookupConcreteResultNotePreviousImpl);
  516. builder.Emit();
  517. }
  518. }
  519. context_.inst_block_stack().PopAndDiscard();
  520. }
  521. auto CheckUnit::CheckImpls() -> void { ValidateImplsInFile(context_); }
  522. auto CheckUnit::FinishRun() -> void {
  523. CheckRequiredDeclarations();
  524. CheckRequiredDefinitions();
  525. CheckPoisonedConcreteImplLookupQueries();
  526. CheckImpls();
  527. // Finalizes the C++ portion of the compilation.
  528. FinishAst(context_);
  529. // Pop information for the file-level scope.
  530. context_.sem_ir().set_top_inst_block_id(context_.inst_block_stack().Pop());
  531. context_.scope_stack().Pop();
  532. // Finalizes the list of exports on the IR.
  533. context_.inst_blocks().ReplacePlaceholder(SemIR::InstBlockId::Exports,
  534. context_.exports());
  535. // Finalizes the ImportRef inst block.
  536. context_.inst_blocks().ReplacePlaceholder(SemIR::InstBlockId::Imports,
  537. context_.imports());
  538. // Finalizes __global_init.
  539. context_.global_init().Finalize();
  540. context_.sem_ir().set_has_errors(unit_and_imports_->err_tracker.seen_error());
  541. // Verify that Context cleanly finished.
  542. context_.VerifyOnFinish();
  543. }
  544. } // namespace Carbon::Check