name_scope_test.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  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/sem_ir/name_scope.h"
  5. #include <gmock/gmock.h>
  6. #include <gtest/gtest.h>
  7. namespace Carbon::SemIR {
  8. namespace {
  9. using ::testing::ElementsAre;
  10. using ::testing::Pair;
  11. TEST(ScopeLookupResult, MakeWrappedLookupResultUsingExistingInstId) {
  12. InstId inst_id(1);
  13. auto result = ScopeLookupResult::MakeWrappedLookupResult(
  14. inst_id, AccessKind::Protected);
  15. EXPECT_FALSE(result.is_poisoned());
  16. EXPECT_TRUE(result.is_found());
  17. EXPECT_EQ(result.target_inst_id(), inst_id);
  18. EXPECT_EQ(result.access_kind(), AccessKind::Protected);
  19. }
  20. TEST(ScopeLookupResult, MakeWrappedLookupResultUsingNoneInstId) {
  21. auto result = ScopeLookupResult::MakeWrappedLookupResult(
  22. InstId::None, AccessKind::Protected);
  23. EXPECT_FALSE(result.is_poisoned());
  24. EXPECT_FALSE(result.is_found());
  25. EXPECT_DEATH(result.target_inst_id(), "is_found");
  26. EXPECT_EQ(result.access_kind(), AccessKind::Protected);
  27. }
  28. TEST(ScopeLookupResult, MakeWrappedLookupResultUsingErrorInst) {
  29. auto result = ScopeLookupResult::MakeWrappedLookupResult(
  30. ErrorInst::SingletonInstId, AccessKind::Private);
  31. EXPECT_FALSE(result.is_poisoned());
  32. EXPECT_TRUE(result.is_found());
  33. EXPECT_EQ(result.target_inst_id(), ErrorInst::SingletonInstId);
  34. EXPECT_EQ(result.access_kind(), AccessKind::Private);
  35. }
  36. TEST(ScopeLookupResult, MakeFoundExisting) {
  37. InstId inst_id(1);
  38. auto result = ScopeLookupResult::MakeFound(inst_id, AccessKind::Protected);
  39. EXPECT_FALSE(result.is_poisoned());
  40. EXPECT_TRUE(result.is_found());
  41. EXPECT_EQ(result.target_inst_id(), inst_id);
  42. EXPECT_EQ(result.access_kind(), AccessKind::Protected);
  43. }
  44. TEST(ScopeLookupResult, MakeFoundNone) {
  45. EXPECT_DEATH(
  46. ScopeLookupResult::MakeFound(InstId::None, AccessKind::Protected),
  47. "has_value");
  48. }
  49. TEST(ScopeLookupResult, MakeNotFound) {
  50. auto result = ScopeLookupResult::MakeNotFound();
  51. EXPECT_FALSE(result.is_poisoned());
  52. EXPECT_FALSE(result.is_found());
  53. EXPECT_DEATH(result.target_inst_id(), "is_found");
  54. EXPECT_EQ(result.access_kind(), AccessKind::Public);
  55. }
  56. TEST(ScopeLookupResult, MakePoisoned) {
  57. auto result = ScopeLookupResult::MakePoisoned();
  58. EXPECT_TRUE(result.is_poisoned());
  59. EXPECT_FALSE(result.is_found());
  60. EXPECT_DEATH(result.target_inst_id(), "is_found");
  61. EXPECT_EQ(result.access_kind(), AccessKind::Public);
  62. }
  63. TEST(ScopeLookupResult, MakeError) {
  64. auto result = ScopeLookupResult::MakeError();
  65. EXPECT_FALSE(result.is_poisoned());
  66. EXPECT_TRUE(result.is_found());
  67. EXPECT_EQ(result.target_inst_id(), ErrorInst::SingletonInstId);
  68. EXPECT_EQ(result.access_kind(), AccessKind::Public);
  69. }
  70. TEST(NameScope, Empty) {
  71. int id = 0;
  72. InstId scope_inst_id(++id);
  73. NameId scope_name_id(++id);
  74. NameScopeId parent_scope_id(++id);
  75. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  76. EXPECT_THAT(name_scope.entries(), ElementsAre());
  77. EXPECT_THAT(name_scope.extended_scopes(), ElementsAre());
  78. EXPECT_EQ(name_scope.inst_id(), scope_inst_id);
  79. EXPECT_EQ(name_scope.name_id(), scope_name_id);
  80. EXPECT_EQ(name_scope.parent_scope_id(), parent_scope_id);
  81. EXPECT_FALSE(name_scope.has_error());
  82. EXPECT_FALSE(name_scope.is_closed_import());
  83. EXPECT_FALSE(name_scope.is_imported_package());
  84. EXPECT_THAT(name_scope.import_ir_scopes(), ElementsAre());
  85. }
  86. TEST(NameScope, Lookup) {
  87. int id = 0;
  88. InstId scope_inst_id(++id);
  89. NameId scope_name_id(++id);
  90. NameScopeId parent_scope_id(++id);
  91. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  92. NameScope::Entry entry1 = {
  93. .name_id = NameId(++id),
  94. .result = ScopeLookupResult::MakeFound(InstId(++id), AccessKind::Public)};
  95. name_scope.AddRequired(entry1);
  96. NameScope::Entry entry2 = {.name_id = NameId(++id),
  97. .result = ScopeLookupResult::MakeFound(
  98. InstId(++id), AccessKind::Protected)};
  99. name_scope.AddRequired(entry2);
  100. NameScope::Entry entry3 = {.name_id = NameId(++id),
  101. .result = ScopeLookupResult::MakeFound(
  102. InstId(++id), AccessKind::Private)};
  103. name_scope.AddRequired(entry3);
  104. auto lookup = name_scope.Lookup(entry1.name_id);
  105. ASSERT_NE(lookup, std::nullopt);
  106. EXPECT_EQ(static_cast<NameScope&>(name_scope).GetEntry(*lookup), entry1);
  107. EXPECT_EQ(static_cast<const NameScope&>(name_scope).GetEntry(*lookup),
  108. entry1);
  109. lookup = name_scope.Lookup(entry2.name_id);
  110. ASSERT_NE(lookup, std::nullopt);
  111. EXPECT_EQ(name_scope.GetEntry(*lookup), entry2);
  112. lookup = name_scope.Lookup(entry3.name_id);
  113. ASSERT_NE(lookup, std::nullopt);
  114. EXPECT_EQ(name_scope.GetEntry(*lookup), entry3);
  115. NameId unknown_name_id(++id);
  116. lookup = name_scope.Lookup(unknown_name_id);
  117. EXPECT_EQ(lookup, std::nullopt);
  118. }
  119. TEST(NameScope, LookupOrPoison) {
  120. int id = 0;
  121. InstId scope_inst_id(++id);
  122. NameId scope_name_id(++id);
  123. NameScopeId parent_scope_id(++id);
  124. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  125. NameScope::Entry entry1 = {
  126. .name_id = NameId(++id),
  127. .result = ScopeLookupResult::MakeFound(InstId(++id), AccessKind::Public)};
  128. name_scope.AddRequired(entry1);
  129. NameScope::Entry entry2 = {.name_id = NameId(++id),
  130. .result = ScopeLookupResult::MakeFound(
  131. InstId(++id), AccessKind::Protected)};
  132. name_scope.AddRequired(entry2);
  133. NameScope::Entry entry3 = {.name_id = NameId(++id),
  134. .result = ScopeLookupResult::MakeFound(
  135. InstId(++id), AccessKind::Private)};
  136. name_scope.AddRequired(entry3);
  137. auto lookup = name_scope.LookupOrPoison(entry1.name_id);
  138. ASSERT_NE(lookup, std::nullopt);
  139. EXPECT_EQ(static_cast<NameScope&>(name_scope).GetEntry(*lookup), entry1);
  140. EXPECT_EQ(static_cast<const NameScope&>(name_scope).GetEntry(*lookup),
  141. entry1);
  142. lookup = name_scope.LookupOrPoison(entry2.name_id);
  143. ASSERT_NE(lookup, std::nullopt);
  144. EXPECT_EQ(name_scope.GetEntry(*lookup), entry2);
  145. lookup = name_scope.LookupOrPoison(entry3.name_id);
  146. ASSERT_NE(lookup, std::nullopt);
  147. EXPECT_EQ(name_scope.GetEntry(*lookup), entry3);
  148. NameId unknown_name_id(++id);
  149. lookup = name_scope.LookupOrPoison(unknown_name_id);
  150. EXPECT_EQ(lookup, std::nullopt);
  151. }
  152. TEST(NameScope, LookupOrAdd) {
  153. int id = 0;
  154. InstId scope_inst_id(++id);
  155. NameId scope_name_id(++id);
  156. NameScopeId parent_scope_id(++id);
  157. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  158. NameScope::Entry entry1 = {
  159. .name_id = NameId(++id),
  160. .result = ScopeLookupResult::MakeFound(InstId(++id), AccessKind::Public)};
  161. {
  162. auto [added, entry_id] =
  163. name_scope.LookupOrAdd(entry1.name_id, entry1.result.target_inst_id(),
  164. entry1.result.access_kind());
  165. EXPECT_TRUE(added);
  166. EXPECT_EQ(name_scope.GetEntry(entry_id), entry1);
  167. }
  168. NameScope::Entry entry2 = {.name_id = NameId(++id),
  169. .result = ScopeLookupResult::MakeFound(
  170. InstId(++id), AccessKind::Protected)};
  171. {
  172. auto [added, entry_id] =
  173. name_scope.LookupOrAdd(entry2.name_id, entry2.result.target_inst_id(),
  174. entry2.result.access_kind());
  175. EXPECT_TRUE(added);
  176. EXPECT_EQ(name_scope.GetEntry(entry_id), entry2);
  177. }
  178. NameScope::Entry entry3 = {.name_id = NameId(++id),
  179. .result = ScopeLookupResult::MakeFound(
  180. InstId(++id), AccessKind::Private)};
  181. {
  182. auto [added, entry_id] =
  183. name_scope.LookupOrAdd(entry3.name_id, entry3.result.target_inst_id(),
  184. entry3.result.access_kind());
  185. EXPECT_TRUE(added);
  186. EXPECT_EQ(name_scope.GetEntry(entry_id), entry3);
  187. }
  188. {
  189. auto [added, entry_id] =
  190. name_scope.LookupOrAdd(entry1.name_id, entry1.result.target_inst_id(),
  191. entry1.result.access_kind());
  192. EXPECT_FALSE(added);
  193. EXPECT_EQ(name_scope.GetEntry(entry_id), entry1);
  194. }
  195. {
  196. auto [added, entry_id] =
  197. name_scope.LookupOrAdd(entry2.name_id, entry2.result.target_inst_id(),
  198. entry2.result.access_kind());
  199. EXPECT_FALSE(added);
  200. EXPECT_EQ(name_scope.GetEntry(entry_id), entry2);
  201. }
  202. {
  203. auto [added, entry_id] =
  204. name_scope.LookupOrAdd(entry3.name_id, entry3.result.target_inst_id(),
  205. entry3.result.access_kind());
  206. EXPECT_FALSE(added);
  207. EXPECT_EQ(name_scope.GetEntry(entry_id), entry3);
  208. }
  209. }
  210. TEST(NameScope, Poison) {
  211. int id = 0;
  212. InstId scope_inst_id(++id);
  213. NameId scope_name_id(++id);
  214. NameScopeId parent_scope_id(++id);
  215. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  216. NameId poison1(++id);
  217. EXPECT_EQ(name_scope.LookupOrPoison(poison1), std::nullopt);
  218. EXPECT_THAT(
  219. name_scope.entries(),
  220. ElementsAre(NameScope::Entry(
  221. {.name_id = poison1, .result = ScopeLookupResult::MakePoisoned()})));
  222. NameId poison2(++id);
  223. EXPECT_EQ(name_scope.LookupOrPoison(poison2), std::nullopt);
  224. EXPECT_THAT(
  225. name_scope.entries(),
  226. ElementsAre(
  227. NameScope::Entry({.name_id = poison1,
  228. .result = ScopeLookupResult::MakePoisoned()}),
  229. NameScope::Entry({.name_id = poison2,
  230. .result = ScopeLookupResult::MakePoisoned()})));
  231. auto lookup = name_scope.Lookup(poison1);
  232. ASSERT_NE(lookup, std::nullopt);
  233. EXPECT_THAT(name_scope.GetEntry(*lookup),
  234. NameScope::Entry({.name_id = poison1,
  235. .result = ScopeLookupResult::MakePoisoned()}));
  236. }
  237. TEST(NameScope, AddRequiredAfterPoison) {
  238. int id = 0;
  239. InstId scope_inst_id(++id);
  240. NameId scope_name_id(++id);
  241. NameScopeId parent_scope_id(++id);
  242. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  243. NameId name_id(++id);
  244. InstId inst_id(++id);
  245. EXPECT_EQ(name_scope.LookupOrPoison(name_id), std::nullopt);
  246. EXPECT_THAT(
  247. name_scope.entries(),
  248. ElementsAre(NameScope::Entry(
  249. {.name_id = name_id, .result = ScopeLookupResult::MakePoisoned()})));
  250. NameScope::Entry entry = {
  251. .name_id = name_id,
  252. .result = ScopeLookupResult::MakeFound(inst_id, AccessKind::Private)};
  253. name_scope.AddRequired(entry);
  254. auto lookup = name_scope.LookupOrPoison(name_id);
  255. ASSERT_NE(lookup, std::nullopt);
  256. EXPECT_EQ(name_scope.GetEntry(*lookup),
  257. NameScope::Entry({.name_id = name_id,
  258. .result = ScopeLookupResult::MakeFound(
  259. inst_id, AccessKind::Private)}));
  260. }
  261. TEST(NameScope, ExtendedScopes) {
  262. int id = 0;
  263. InstId scope_inst_id(++id);
  264. NameId scope_name_id(++id);
  265. NameScopeId parent_scope_id = NameScopeId::Package;
  266. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  267. EXPECT_THAT(name_scope.extended_scopes(), ElementsAre());
  268. InstId extended_scope1(++id);
  269. name_scope.AddExtendedScope(extended_scope1);
  270. EXPECT_THAT(name_scope.extended_scopes(), ElementsAre(extended_scope1));
  271. InstId extended_scope2(++id);
  272. name_scope.AddExtendedScope(extended_scope2);
  273. EXPECT_THAT(name_scope.extended_scopes(),
  274. ElementsAre(extended_scope1, extended_scope2));
  275. }
  276. TEST(NameScope, HasError) {
  277. int id = 0;
  278. InstId scope_inst_id(++id);
  279. NameId scope_name_id(++id);
  280. NameScopeId parent_scope_id(++id);
  281. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  282. EXPECT_FALSE(name_scope.has_error());
  283. name_scope.set_has_error();
  284. EXPECT_TRUE(name_scope.has_error());
  285. name_scope.set_has_error();
  286. EXPECT_TRUE(name_scope.has_error());
  287. }
  288. TEST(NameScope, IsClosedImport) {
  289. int id = 0;
  290. InstId scope_inst_id(++id);
  291. NameId scope_name_id(++id);
  292. NameScopeId parent_scope_id(++id);
  293. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  294. EXPECT_FALSE(name_scope.is_closed_import());
  295. name_scope.set_is_closed_import(true);
  296. EXPECT_TRUE(name_scope.is_closed_import());
  297. name_scope.set_is_closed_import(false);
  298. EXPECT_FALSE(name_scope.is_closed_import());
  299. }
  300. TEST(NameScope, IsImportedPackageParentNonPackageScope) {
  301. int id = 0;
  302. InstId scope_inst_id(++id);
  303. NameId scope_name_id(++id);
  304. NameScopeId parent_scope_id(++id);
  305. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  306. EXPECT_FALSE(name_scope.is_imported_package());
  307. name_scope.set_is_closed_import(true);
  308. EXPECT_FALSE(name_scope.is_imported_package());
  309. name_scope.set_is_closed_import(false);
  310. EXPECT_FALSE(name_scope.is_imported_package());
  311. }
  312. TEST(NameScope, IsImportedPackageParentPackageScope) {
  313. int id = 0;
  314. InstId scope_inst_id(++id);
  315. NameId scope_name_id(++id);
  316. NameScopeId parent_scope_id = NameScopeId::Package;
  317. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  318. EXPECT_FALSE(name_scope.is_imported_package());
  319. name_scope.set_is_closed_import(true);
  320. EXPECT_TRUE(name_scope.is_imported_package());
  321. name_scope.set_is_closed_import(false);
  322. EXPECT_FALSE(name_scope.is_imported_package());
  323. }
  324. TEST(NameScope, ImportIRScopes) {
  325. int id = 0;
  326. InstId scope_inst_id(++id);
  327. NameId scope_name_id(++id);
  328. NameScopeId parent_scope_id = NameScopeId::Package;
  329. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  330. EXPECT_THAT(name_scope.import_ir_scopes(), ElementsAre());
  331. ImportIRId import_ir_id1(++id);
  332. NameScopeId import_name_scope_id1(++id);
  333. name_scope.AddImportIRScope({import_ir_id1, import_name_scope_id1});
  334. EXPECT_THAT(name_scope.import_ir_scopes(),
  335. ElementsAre(Pair(import_ir_id1, import_name_scope_id1)));
  336. ImportIRId import_ir_id2(++id);
  337. NameScopeId import_name_scope_id2(++id);
  338. name_scope.AddImportIRScope({import_ir_id2, import_name_scope_id2});
  339. EXPECT_THAT(name_scope.import_ir_scopes(),
  340. ElementsAre(Pair(import_ir_id1, import_name_scope_id1),
  341. Pair(import_ir_id2, import_name_scope_id2)));
  342. }
  343. } // namespace
  344. } // namespace Carbon::SemIR