name_lookup.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  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/name_lookup.h"
  5. #include <optional>
  6. #include "common/raw_string_ostream.h"
  7. #include "toolchain/check/cpp/import.h"
  8. #include "toolchain/check/facet_type.h"
  9. #include "toolchain/check/generic.h"
  10. #include "toolchain/check/import.h"
  11. #include "toolchain/check/import_ref.h"
  12. #include "toolchain/check/inst.h"
  13. #include "toolchain/check/member_access.h"
  14. #include "toolchain/check/subst.h"
  15. #include "toolchain/check/type.h"
  16. #include "toolchain/check/type_completion.h"
  17. #include "toolchain/diagnostics/format_providers.h"
  18. #include "toolchain/sem_ir/generic.h"
  19. #include "toolchain/sem_ir/ids.h"
  20. #include "toolchain/sem_ir/name_scope.h"
  21. namespace Carbon::Check {
  22. auto AddNameToLookup(Context& context, SemIR::NameId name_id,
  23. SemIR::InstId target_id, ScopeIndex scope_index) -> void {
  24. if (auto existing = context.scope_stack().LookupOrAddName(name_id, target_id,
  25. scope_index);
  26. existing.has_value()) {
  27. // TODO: Add coverage to this use case and use the location of the name
  28. // instead of the target.
  29. DiagnoseDuplicateName(context, name_id, SemIR::LocId(target_id),
  30. SemIR::LocId(existing));
  31. }
  32. }
  33. auto LookupNameInDecl(Context& context, SemIR::LocId loc_id,
  34. SemIR::NameId name_id, SemIR::NameScopeId scope_id,
  35. ScopeIndex scope_index) -> SemIR::ScopeLookupResult {
  36. if (!scope_id.has_value()) {
  37. // Look for a name in the specified scope or a scope nested within it only.
  38. // There are two cases where the name would be in an outer scope:
  39. //
  40. // - The name is the sole component of the declared name:
  41. //
  42. // class A;
  43. // fn F() {
  44. // class A;
  45. // }
  46. //
  47. // In this case, the inner A is not the same class as the outer A, so
  48. // lookup should not find the outer A.
  49. //
  50. // - The name is a qualifier of some larger declared name:
  51. //
  52. // class A { class B; }
  53. // fn F() {
  54. // class A.B {}
  55. // }
  56. //
  57. // In this case, we're not in the correct scope to define a member of
  58. // class A, so we should reject, and we achieve this by not finding the
  59. // name A from the outer scope.
  60. //
  61. // There is also one case where the name would be in an inner scope:
  62. //
  63. // - The name is redeclared by a parameter of the same entity:
  64. //
  65. // fn F() {
  66. // class C(C:! type);
  67. // }
  68. //
  69. // In this case, the class C is not a redeclaration of its parameter, but
  70. // we find the parameter in order to diagnose a redeclaration error.
  71. return SemIR::ScopeLookupResult::MakeWrappedLookupResult(
  72. context.scope_stack().LookupInLexicalScopesWithin(name_id, scope_index),
  73. SemIR::AccessKind::Public);
  74. } else {
  75. // We do not look into `extend`ed scopes here. A qualified name in a
  76. // declaration must specify the exact scope in which the name was originally
  77. // introduced:
  78. //
  79. // base class A { fn F(); }
  80. // class B { extend base: A; }
  81. //
  82. // // Error, no `F` in `B`.
  83. // fn B.F() {}
  84. return LookupNameInExactScope(context, loc_id, name_id, scope_id,
  85. context.name_scopes().Get(scope_id),
  86. /*is_being_declared=*/true);
  87. }
  88. }
  89. auto LookupUnqualifiedName(Context& context, SemIR::LocId loc_id,
  90. SemIR::NameId name_id, bool required)
  91. -> LookupResult {
  92. // TODO: Check for shadowed lookup results.
  93. // Find the results from ancestor lexical scopes. These will be combined with
  94. // results from non-lexical scopes such as namespaces and classes.
  95. auto [lexical_result, non_lexical_scopes] =
  96. context.scope_stack().LookupInLexicalScopes(name_id);
  97. // Walk the non-lexical scopes and perform lookups into each of them.
  98. for (auto [index, lookup_scope_id, specific_id] :
  99. llvm::reverse(non_lexical_scopes)) {
  100. if (auto non_lexical_result = LookupQualifiedName(
  101. context, loc_id, name_id,
  102. LookupScope{.name_scope_id = lookup_scope_id,
  103. .specific_id = specific_id,
  104. .self_const_id = SemIR::ConstantId::None},
  105. /*required=*/false);
  106. non_lexical_result.scope_result.is_found()) {
  107. // In an interface definition, replace associated entity `M` with
  108. // `Self.M` (where the `Self` is the `Self` of the interface).
  109. const auto& scope = context.name_scopes().Get(lookup_scope_id);
  110. if (scope.is_interface_definition()) {
  111. SemIR::InstId target_inst_id =
  112. non_lexical_result.scope_result.target_inst_id();
  113. if (auto assoc_type =
  114. context.types().TryGetAs<SemIR::AssociatedEntityType>(
  115. SemIR::GetTypeOfInstInSpecific(
  116. context.sem_ir(), non_lexical_result.specific_id,
  117. target_inst_id))) {
  118. auto interface_decl =
  119. context.insts().GetAs<SemIR::InterfaceDecl>(scope.inst_id());
  120. const auto& interface =
  121. context.interfaces().Get(interface_decl.interface_id);
  122. SemIR::InstId result_inst_id = GetAssociatedValue(
  123. context, loc_id, interface.self_param_id,
  124. SemIR::GetConstantValueInSpecific(context.sem_ir(),
  125. non_lexical_result.specific_id,
  126. target_inst_id),
  127. assoc_type->GetSpecificInterface());
  128. non_lexical_result = {
  129. .specific_id = SemIR::SpecificId::None,
  130. .scope_result = SemIR::ScopeLookupResult::MakeFound(
  131. result_inst_id,
  132. non_lexical_result.scope_result.access_kind())};
  133. }
  134. }
  135. return non_lexical_result;
  136. }
  137. }
  138. if (lexical_result == SemIR::InstId::InitTombstone) {
  139. CARBON_DIAGNOSTIC(UsedBeforeInitialization, Error,
  140. "`{0}` used before initialization", SemIR::NameId);
  141. context.emitter().Emit(loc_id, UsedBeforeInitialization, name_id);
  142. return {.specific_id = SemIR::SpecificId::None,
  143. .scope_result = SemIR::ScopeLookupResult::MakeError()};
  144. }
  145. if (lexical_result.has_value()) {
  146. // A lexical scope never needs an associated specific. If there's a
  147. // lexically enclosing generic, then it also encloses the point of use of
  148. // the name.
  149. return {.specific_id = SemIR::SpecificId::None,
  150. .scope_result = SemIR::ScopeLookupResult::MakeFound(
  151. lexical_result, SemIR::AccessKind::Public)};
  152. }
  153. // We didn't find anything at all.
  154. if (required) {
  155. DiagnoseNameNotFound(context, loc_id, name_id);
  156. }
  157. // TODO: Should this return MakeNotFound if `required` is false, so that
  158. // `is_found()` would be false?
  159. return {.specific_id = SemIR::SpecificId::None,
  160. .scope_result = SemIR::ScopeLookupResult::MakeError()};
  161. }
  162. auto LookupNameInExactScope(Context& context, SemIR::LocId loc_id,
  163. SemIR::NameId name_id, SemIR::NameScopeId scope_id,
  164. SemIR::NameScope& scope, bool is_being_declared)
  165. -> SemIR::ScopeLookupResult {
  166. if (auto entry_id = is_being_declared
  167. ? scope.Lookup(name_id)
  168. : scope.LookupOrPoison(loc_id, name_id)) {
  169. auto lookup_result = scope.GetEntry(*entry_id).result;
  170. if (!lookup_result.is_poisoned()) {
  171. LoadImportRef(context, lookup_result.target_inst_id());
  172. }
  173. return lookup_result;
  174. }
  175. if (!scope.import_ir_scopes().empty()) {
  176. // TODO: Enforce other access modifiers for imports.
  177. return SemIR::ScopeLookupResult::MakeWrappedLookupResult(
  178. ImportNameFromOtherPackage(context, loc_id, scope_id,
  179. scope.import_ir_scopes(), name_id),
  180. SemIR::AccessKind::Public);
  181. }
  182. if (scope.is_cpp_scope()) {
  183. return ImportNameFromCpp(context, loc_id, scope_id, name_id);
  184. }
  185. return SemIR::ScopeLookupResult::MakeNotFound();
  186. }
  187. // Prints diagnostics on invalid qualified name access.
  188. static auto DiagnoseInvalidQualifiedNameAccess(
  189. Context& context, SemIR::LocId loc_id, SemIR::LocId member_loc_id,
  190. SemIR::NameId name_id, SemIR::AccessKind access_kind, bool is_parent_access,
  191. AccessInfo access_info) -> void {
  192. auto class_type = context.insts().TryGetAs<SemIR::ClassType>(
  193. context.constant_values().GetInstId(access_info.constant_id));
  194. if (!class_type) {
  195. return;
  196. }
  197. // TODO: Support scoped entities other than just classes.
  198. const auto& class_info = context.classes().Get(class_type->class_id);
  199. auto parent_type_id = class_info.self_type_id;
  200. if (access_kind == SemIR::AccessKind::Private && is_parent_access) {
  201. if (auto base_type_id =
  202. class_info.GetBaseType(context.sem_ir(), class_type->specific_id);
  203. base_type_id.has_value()) {
  204. parent_type_id = base_type_id;
  205. } else if (auto adapted_type_id = class_info.GetAdaptedType(
  206. context.sem_ir(), class_type->specific_id);
  207. adapted_type_id.has_value()) {
  208. parent_type_id = adapted_type_id;
  209. } else {
  210. CARBON_FATAL("Expected parent for parent access");
  211. }
  212. }
  213. CARBON_DIAGNOSTIC(
  214. ClassInvalidMemberAccess, Error,
  215. "cannot access {0:private|protected} member `{1}` of type {2}",
  216. Diagnostics::BoolAsSelect, SemIR::NameId, SemIR::TypeId);
  217. CARBON_DIAGNOSTIC(ClassMemberDeclaration, Note, "declared here");
  218. context.emitter()
  219. .Build(loc_id, ClassInvalidMemberAccess,
  220. access_kind == SemIR::AccessKind::Private, name_id, parent_type_id)
  221. .Note(member_loc_id, ClassMemberDeclaration)
  222. .Emit();
  223. }
  224. // Returns whether the access is prohibited by the access modifiers.
  225. static auto IsAccessProhibited(std::optional<AccessInfo> access_info,
  226. SemIR::AccessKind access_kind,
  227. bool is_parent_access) -> bool {
  228. if (!access_info) {
  229. return false;
  230. }
  231. switch (access_kind) {
  232. case SemIR::AccessKind::Public:
  233. return false;
  234. case SemIR::AccessKind::Protected:
  235. return access_info->highest_allowed_access == SemIR::AccessKind::Public;
  236. case SemIR::AccessKind::Private:
  237. return access_info->highest_allowed_access !=
  238. SemIR::AccessKind::Private ||
  239. is_parent_access;
  240. }
  241. }
  242. auto CheckAccess(Context& context, SemIR::LocId loc_id,
  243. SemIR::LocId member_loc_id, SemIR::NameId name_id,
  244. SemIR::AccessKind access_kind, bool is_parent_access,
  245. AccessInfo access_info) -> void {
  246. if (IsAccessProhibited(access_info, access_kind, is_parent_access)) {
  247. DiagnoseInvalidQualifiedNameAccess(context, loc_id, member_loc_id, name_id,
  248. access_kind, is_parent_access,
  249. access_info);
  250. }
  251. }
  252. // Information regarding a prohibited access.
  253. struct ProhibitedAccessInfo {
  254. // The resulting inst of the lookup.
  255. SemIR::InstId scope_result_id;
  256. // The access kind of the lookup.
  257. SemIR::AccessKind access_kind;
  258. // If the lookup is from an extended scope. For example, if this is a base
  259. // class member access from a class that extends it.
  260. bool is_parent_access;
  261. };
  262. auto AppendLookupScopesForConstant(Context& context, SemIR::LocId loc_id,
  263. SemIR::ConstantId lookup_const_id,
  264. SemIR::ConstantId self_type_const_id,
  265. llvm::SmallVector<LookupScope>* scopes)
  266. -> bool {
  267. auto lookup_inst_id = context.constant_values().GetInstId(lookup_const_id);
  268. auto lookup = context.insts().Get(lookup_inst_id);
  269. if (auto ns = lookup.TryAs<SemIR::Namespace>()) {
  270. scopes->push_back(LookupScope{.name_scope_id = ns->name_scope_id,
  271. .specific_id = SemIR::SpecificId::None,
  272. .self_const_id = SemIR::ConstantId::None});
  273. return true;
  274. }
  275. if (auto class_ty = lookup.TryAs<SemIR::ClassType>()) {
  276. // TODO: Allow name lookup into classes that are being defined even if they
  277. // are not complete.
  278. RequireCompleteType(
  279. context, context.types().GetTypeIdForTypeConstantId(lookup_const_id),
  280. loc_id, [&] {
  281. CARBON_DIAGNOSTIC(QualifiedExprInIncompleteClassScope, Error,
  282. "member access into incomplete class {0}",
  283. InstIdAsType);
  284. return context.emitter().Build(
  285. loc_id, QualifiedExprInIncompleteClassScope, lookup_inst_id);
  286. });
  287. auto& class_info = context.classes().Get(class_ty->class_id);
  288. scopes->push_back(LookupScope{.name_scope_id = class_info.scope_id,
  289. .specific_id = class_ty->specific_id,
  290. .self_const_id = self_type_const_id});
  291. return true;
  292. }
  293. if (auto facet_type = lookup.TryAs<SemIR::FacetType>()) {
  294. // TODO: Allow name lookup into facet types that are being defined even if
  295. // they are not complete.
  296. if (RequireCompleteType(
  297. context,
  298. context.types().GetTypeIdForTypeConstantId(lookup_const_id), loc_id,
  299. [&] {
  300. CARBON_DIAGNOSTIC(QualifiedExprInIncompleteFacetTypeScope, Error,
  301. "member access into incomplete facet type {0}",
  302. InstIdAsType);
  303. return context.emitter().Build(
  304. loc_id, QualifiedExprInIncompleteFacetTypeScope,
  305. lookup_inst_id);
  306. })) {
  307. auto facet_type_info =
  308. context.facet_types().Get(facet_type->facet_type_id);
  309. // Name lookup into "extend" constraints but not "self impls" constraints.
  310. for (const auto& extend : facet_type_info.extend_constraints) {
  311. auto& interface = context.interfaces().Get(extend.interface_id);
  312. scopes->push_back({.name_scope_id = interface.scope_id,
  313. .specific_id = extend.specific_id,
  314. .self_const_id = self_type_const_id});
  315. }
  316. for (const auto& extend : facet_type_info.extend_named_constraints) {
  317. auto& constraint =
  318. context.named_constraints().Get(extend.named_constraint_id);
  319. scopes->push_back({.name_scope_id = constraint.scope_id,
  320. .specific_id = extend.specific_id,
  321. .self_const_id = self_type_const_id});
  322. }
  323. } else {
  324. // Lookup into this scope should fail without producing an error since
  325. // `RequireCompleteFacetType` has already issued a diagnostic.
  326. scopes->push_back(LookupScope{.name_scope_id = SemIR::NameScopeId::None,
  327. .specific_id = SemIR::SpecificId::None,
  328. .self_const_id = SemIR::ConstantId::None});
  329. }
  330. return true;
  331. }
  332. if (lookup_const_id == SemIR::ErrorInst::ConstantId) {
  333. // Lookup into this scope should fail without producing an error.
  334. scopes->push_back(LookupScope{.name_scope_id = SemIR::NameScopeId::None,
  335. .specific_id = SemIR::SpecificId::None,
  336. .self_const_id = SemIR::ConstantId::None});
  337. return true;
  338. }
  339. // TODO: Per the design, if `base_id` is any kind of type, then lookup should
  340. // treat it as a name scope, even if it doesn't have members. For example,
  341. // `(i32*).X` should fail because there's no name `X` in `i32*`, not because
  342. // there's no name `X` in `type`.
  343. return false;
  344. }
  345. // Prints a diagnostic for a missing qualified name.
  346. static auto DiagnoseMemberNameNotFound(
  347. Context& context, SemIR::LocId loc_id, SemIR::NameId name_id,
  348. llvm::ArrayRef<LookupScope> lookup_scopes) -> void {
  349. if (lookup_scopes.size() == 1 &&
  350. lookup_scopes.front().name_scope_id.has_value()) {
  351. if (auto specific_id = lookup_scopes.front().specific_id;
  352. specific_id.has_value()) {
  353. CARBON_DIAGNOSTIC(MemberNameNotFoundInSpecificScope, Error,
  354. "member name `{0}` not found in {1}", SemIR::NameId,
  355. SemIR::SpecificId);
  356. context.emitter().Emit(loc_id, MemberNameNotFoundInSpecificScope, name_id,
  357. specific_id);
  358. } else {
  359. auto scope_inst_id = context.name_scopes()
  360. .Get(lookup_scopes.front().name_scope_id)
  361. .inst_id();
  362. CARBON_DIAGNOSTIC(MemberNameNotFoundInInstScope, Error,
  363. "member name `{0}` not found in {1}", SemIR::NameId,
  364. InstIdAsType);
  365. context.emitter().Emit(loc_id, MemberNameNotFoundInInstScope, name_id,
  366. scope_inst_id);
  367. }
  368. return;
  369. }
  370. CARBON_DIAGNOSTIC(MemberNameNotFound, Error, "member name `{0}` not found",
  371. SemIR::NameId);
  372. context.emitter().Emit(loc_id, MemberNameNotFound, name_id);
  373. }
  374. auto LookupQualifiedName(Context& context, SemIR::LocId loc_id,
  375. SemIR::NameId name_id,
  376. llvm::ArrayRef<LookupScope> lookup_scopes,
  377. bool required, std::optional<AccessInfo> access_info)
  378. -> LookupResult {
  379. llvm::SmallVector<LookupScope> scopes(lookup_scopes);
  380. // TODO: Support reporting of multiple prohibited access.
  381. llvm::SmallVector<ProhibitedAccessInfo> prohibited_accesses;
  382. LookupResult result = {
  383. .specific_id = SemIR::SpecificId::None,
  384. .scope_result = SemIR::ScopeLookupResult::MakeNotFound()};
  385. auto parent_const_id = SemIR::ConstantId::None;
  386. bool has_error = false;
  387. bool is_parent_access = false;
  388. // Walk this scope and, if nothing is found here, the scopes it extends.
  389. while (!scopes.empty()) {
  390. auto [scope_id, specific_id, self_const_id] = scopes.pop_back_val();
  391. if (!scope_id.has_value()) {
  392. has_error = true;
  393. continue;
  394. }
  395. auto& name_scope = context.name_scopes().Get(scope_id);
  396. has_error |= name_scope.has_error();
  397. const SemIR::ScopeLookupResult scope_result =
  398. LookupNameInExactScope(context, loc_id, name_id, scope_id, name_scope);
  399. SemIR::AccessKind access_kind = scope_result.access_kind();
  400. if (is_parent_access && scope_result.is_found() &&
  401. !access_info.has_value()) {
  402. access_info =
  403. AccessInfo{.constant_id = parent_const_id,
  404. .highest_allowed_access = SemIR::AccessKind::Protected};
  405. }
  406. auto is_access_prohibited =
  407. IsAccessProhibited(access_info, access_kind, is_parent_access);
  408. // Keep track of prohibited accesses, this will be useful for reporting
  409. // multiple prohibited accesses if we can't find a suitable lookup.
  410. if (is_access_prohibited) {
  411. prohibited_accesses.push_back({
  412. .scope_result_id = scope_result.target_inst_id(),
  413. .access_kind = access_kind,
  414. .is_parent_access = is_parent_access,
  415. });
  416. }
  417. if (!scope_result.is_found() || is_access_prohibited) {
  418. // If nothing is found in this scope or if we encountered an invalid
  419. // access, look in its extended scopes.
  420. const auto& extended = name_scope.extended_scopes();
  421. scopes.reserve(scopes.size() + extended.size());
  422. for (auto [extended_id, inner_self_id] : llvm::reverse(extended)) {
  423. // Substitute into the constant describing the extended scope to
  424. // determine its corresponding specific.
  425. CARBON_CHECK(extended_id.has_value());
  426. LoadImportRef(context, extended_id);
  427. SemIR::ConstantId const_id = GetConstantValueInSpecific(
  428. context.sem_ir(), specific_id, extended_id);
  429. // Apply self_const_id to the extended_id, replacing inner_self_id
  430. // inside.
  431. //
  432. // TODO: We do this by substituting a `Self` value that the extended
  433. // scope provides us with the self type/facet of the name lookup. But
  434. // we'd like to avoid using substitution, and do this through the
  435. // generic system with a specific and/or eval. Ideally it's somehow done
  436. // as part of the `GetConstantValueInSpecific` call above, but with
  437. // providing the additional information of the self type/facet of the
  438. // name lookup. Further thoughts here:
  439. // https://discord.com/channels/655572317891461132/941071822756143115/1463277684082737214
  440. if (inner_self_id.has_value() && self_const_id.has_value()) {
  441. LoadImportRef(context, inner_self_id);
  442. auto inner_self_binding =
  443. context.insts().GetAs<SemIR::SymbolicBinding>(
  444. context.constant_values().GetConstantInstId(inner_self_id));
  445. auto entity_id = inner_self_binding.entity_name_id;
  446. auto bind_index = context.entity_names().Get(entity_id).bind_index();
  447. auto facet_value = SemIR::ConstantId::None;
  448. if (auto self_type_id =
  449. context.types().TryGetTypeIdForTypeConstantId(self_const_id);
  450. self_type_id.has_value()) {
  451. // The self for member lookup is a type, we need a facet value to
  452. // replace `Self`.
  453. facet_value = GetConstantFacetValueForType(
  454. context, context.types().GetInstId(self_type_id));
  455. } else {
  456. // The self for member lookup is a facet value, use it as is to
  457. // replace `Self`.
  458. facet_value = self_const_id;
  459. }
  460. llvm::SmallVector<Substitution> substitutions = {
  461. {.bind_id = bind_index, .replacement_id = facet_value}};
  462. const_id = SubstConstant(context, loc_id, const_id, substitutions);
  463. }
  464. if (!AppendLookupScopesForConstant(context, loc_id, const_id,
  465. self_const_id, &scopes)) {
  466. // TODO: Handle case where we have a symbolic type and instead should
  467. // look in its type.
  468. }
  469. }
  470. is_parent_access |= !extended.empty();
  471. parent_const_id = context.constant_values().Get(name_scope.inst_id());
  472. continue;
  473. }
  474. // If this is our second lookup result, diagnose an ambiguity.
  475. if (result.scope_result.is_found()) {
  476. CARBON_DIAGNOSTIC(
  477. NameAmbiguousDueToExtend, Error,
  478. "ambiguous use of name `{0}` found in multiple extended scopes",
  479. SemIR::NameId);
  480. context.emitter().Emit(loc_id, NameAmbiguousDueToExtend, name_id);
  481. // TODO: Add notes pointing to the scopes.
  482. return {.specific_id = SemIR::SpecificId::None,
  483. .scope_result = SemIR::ScopeLookupResult::MakeError()};
  484. }
  485. result.scope_result = scope_result;
  486. result.specific_id = specific_id;
  487. }
  488. if ((!prohibited_accesses.empty() || required) &&
  489. !result.scope_result.is_found()) {
  490. if (!has_error) {
  491. if (prohibited_accesses.empty()) {
  492. DiagnoseMemberNameNotFound(context, loc_id, name_id, lookup_scopes);
  493. } else {
  494. // TODO: We should report multiple prohibited accesses in case we don't
  495. // find a valid lookup. Reporting the last one should suffice for now.
  496. auto [scope_result_id, access_kind, is_parent_access] =
  497. prohibited_accesses.back();
  498. // Note, `access_info` is guaranteed to have a value here, since
  499. // `prohibited_accesses` is non-empty.
  500. DiagnoseInvalidQualifiedNameAccess(
  501. context, loc_id, SemIR::LocId(scope_result_id), name_id,
  502. access_kind, is_parent_access, *access_info);
  503. }
  504. }
  505. CARBON_CHECK(!result.scope_result.is_poisoned());
  506. return {.specific_id = SemIR::SpecificId::None,
  507. .scope_result = SemIR::ScopeLookupResult::MakeError()};
  508. }
  509. return result;
  510. }
  511. // Returns a `Core.<qualifiers>` name for diagnostics.
  512. static auto GetCoreQualifiedName(llvm::ArrayRef<CoreIdentifier> qualifiers)
  513. -> std::string {
  514. RawStringOstream str;
  515. str << "Core";
  516. for (auto qualifier : qualifiers) {
  517. str << "." << qualifier;
  518. }
  519. return str.TakeStr();
  520. }
  521. // Returns the scope of the Core package, or `None` if it's not found.
  522. //
  523. // TODO: Consider tracking the Core package in SemIR so we don't need to use
  524. // name lookup to find it.
  525. static auto GetCorePackage(Context& context, SemIR::LocId loc_id,
  526. llvm::ArrayRef<CoreIdentifier> qualifiers)
  527. -> SemIR::NameScopeId {
  528. if (context.name_scopes().IsCorePackage(SemIR::NameScopeId::Package)) {
  529. return SemIR::NameScopeId::Package;
  530. }
  531. // Look up `package.Core`.
  532. auto core_scope_result = LookupNameInExactScope(
  533. context, loc_id, SemIR::NameId::Core, SemIR::NameScopeId::Package,
  534. context.name_scopes().Get(SemIR::NameScopeId::Package));
  535. if (core_scope_result.is_found()) {
  536. // We expect it to be a namespace.
  537. if (auto namespace_inst = context.insts().TryGetAs<SemIR::Namespace>(
  538. core_scope_result.target_inst_id())) {
  539. // TODO: Decide whether to allow the case where `Core` is not a package.
  540. return namespace_inst->name_scope_id;
  541. }
  542. }
  543. CARBON_DIAGNOSTIC(
  544. CoreNotFound, Error,
  545. "`{0}` implicitly referenced here, but package `Core` not found",
  546. std::string);
  547. context.emitter().Emit(loc_id, CoreNotFound,
  548. GetCoreQualifiedName(qualifiers));
  549. return SemIR::NameScopeId::None;
  550. }
  551. auto LookupNameInCore(Context& context, SemIR::LocId loc_id,
  552. llvm::ArrayRef<CoreIdentifier> qualifiers)
  553. -> SemIR::InstId {
  554. CARBON_CHECK(!qualifiers.empty());
  555. auto core_package_id = GetCorePackage(context, loc_id, qualifiers);
  556. if (!core_package_id.has_value()) {
  557. return SemIR::ErrorInst::InstId;
  558. }
  559. auto inst_id = SemIR::InstId::None;
  560. for (auto qualifier : qualifiers) {
  561. auto name_id = context.core_identifiers().AddNameId(qualifier);
  562. auto scope_id = SemIR::NameScopeId::None;
  563. if (inst_id.has_value()) {
  564. auto namespace_inst = context.insts().TryGetAs<SemIR::Namespace>(inst_id);
  565. if (namespace_inst) {
  566. scope_id = namespace_inst->name_scope_id;
  567. }
  568. } else {
  569. scope_id = core_package_id;
  570. }
  571. auto scope_result =
  572. scope_id.has_value()
  573. ? LookupNameInExactScope(context, loc_id, name_id, scope_id,
  574. context.name_scopes().Get(scope_id))
  575. : SemIR::ScopeLookupResult::MakeNotFound();
  576. if (!scope_result.is_found()) {
  577. CARBON_DIAGNOSTIC(CoreNameNotFound, Error,
  578. "name `{0}` implicitly referenced here, but not found",
  579. std::string);
  580. context.emitter().Emit(loc_id, CoreNameNotFound,
  581. GetCoreQualifiedName(qualifiers));
  582. return SemIR::ErrorInst::InstId;
  583. }
  584. // Look through import_refs and aliases.
  585. inst_id = context.constant_values().GetConstantInstId(
  586. scope_result.target_inst_id());
  587. }
  588. return inst_id;
  589. }
  590. auto DiagnoseDuplicateName(Context& context, SemIR::NameId name_id,
  591. SemIR::LocId dup_def, SemIR::LocId prev_def)
  592. -> void {
  593. CARBON_DIAGNOSTIC(NameDeclDuplicate, Error,
  594. "duplicate name `{0}` being declared in the same scope",
  595. SemIR::NameId);
  596. CARBON_DIAGNOSTIC(NameDeclPrevious, Note, "name is previously declared here");
  597. context.emitter()
  598. .Build(dup_def, NameDeclDuplicate, name_id)
  599. .Note(prev_def, NameDeclPrevious)
  600. .Emit();
  601. }
  602. auto DiagnosePoisonedName(Context& context, SemIR::NameId name_id,
  603. SemIR::LocId poisoning_loc_id,
  604. SemIR::LocId decl_name_loc_id) -> void {
  605. CARBON_CHECK(poisoning_loc_id.has_value(),
  606. "Trying to diagnose poisoned name with no poisoning location");
  607. CARBON_DIAGNOSTIC(NameUseBeforeDecl, Error,
  608. "name `{0}` used before it was declared", SemIR::NameId);
  609. CARBON_DIAGNOSTIC(NameUseBeforeDeclNote, Note, "declared here");
  610. context.emitter()
  611. .Build(poisoning_loc_id, NameUseBeforeDecl, name_id)
  612. .Note(decl_name_loc_id, NameUseBeforeDeclNote)
  613. .Emit();
  614. }
  615. auto DiagnoseNameNotFound(Context& context, SemIR::LocId loc_id,
  616. SemIR::NameId name_id) -> void {
  617. CARBON_DIAGNOSTIC(NameNotFound, Error, "name `{0}` not found", SemIR::NameId);
  618. context.emitter().Emit(loc_id, NameNotFound, name_id);
  619. }
  620. } // namespace Carbon::Check