diff --git a/toolchain/check/name_lookup.h b/toolchain/check/name_lookup.h index 4fc4ee435f89..5427c9e578d3 100644 --- a/toolchain/check/name_lookup.h +++ b/toolchain/check/name_lookup.h @@ -69,6 +69,8 @@ auto LookupUnqualifiedName(Context& context, Parse::NodeId node_id, // poisoned name will be treated as if it is not declared. Otherwise, this is // a lookup for a name being declared, so the name will not be poisoned, but // poison will be returned if it's already been looked up. +// +// If `name_id` is not an identifier, the name will not be poisoned. auto LookupNameInExactScope(Context& context, SemIR::LocId loc_id, SemIR::NameId name_id, SemIR::NameScopeId scope_id, SemIR::NameScope& scope, diff --git a/toolchain/sem_ir/name_scope.cpp b/toolchain/sem_ir/name_scope.cpp index c2b277a941d7..60741307c0a4 100644 --- a/toolchain/sem_ir/name_scope.cpp +++ b/toolchain/sem_ir/name_scope.cpp @@ -66,6 +66,10 @@ auto NameScope::LookupOrAdd(NameId name_id, InstId inst_id, auto NameScope::LookupOrPoison(LocId loc_id, NameId name_id) -> std::optional { + if (!name_id.AsIdentifierId().has_value()) { + return Lookup(name_id); + } + auto insert_result = name_map_.Insert(name_id, EntryId(names_.size())); if (insert_result.is_inserted()) { names_.push_back({.name_id = name_id, diff --git a/toolchain/sem_ir/name_scope.h b/toolchain/sem_ir/name_scope.h index 8c2d977f3dc8..efb4432c38fe 100644 --- a/toolchain/sem_ir/name_scope.h +++ b/toolchain/sem_ir/name_scope.h @@ -178,6 +178,8 @@ class NameScope : public Printable { // Searches for the given name. If found, including if a poisoned entry is // found, returns the corresponding EntryId. Otherwise, returns nullopt and + // poisons the name so it can't be declared later. Names that are not + // identifiers will not be poisoned. // poisons the name so it can't be declared later. auto LookupOrPoison(LocId loc_id, NameId name_id) -> std::optional; diff --git a/toolchain/sem_ir/name_scope_test.cpp b/toolchain/sem_ir/name_scope_test.cpp index 16c358ea90f3..204eb0e0554d 100644 --- a/toolchain/sem_ir/name_scope_test.cpp +++ b/toolchain/sem_ir/name_scope_test.cpp @@ -195,8 +195,9 @@ TEST(NameScope, Lookup) { EXPECT_EQ(name_scope.GetEntry(*lookup), entry3); NameId unknown_name_id(++id); - lookup = name_scope.Lookup(unknown_name_id); - EXPECT_EQ(lookup, std::nullopt); + EXPECT_EQ(name_scope.Lookup(unknown_name_id), std::nullopt); + // Check that this is different from LookupOrPoison() - doesn't get poisoned. + EXPECT_EQ(name_scope.Lookup(unknown_name_id), std::nullopt); } TEST(NameScope, LookupOrPoison) { @@ -222,24 +223,50 @@ TEST(NameScope, LookupOrPoison) { InstId(++id), AccessKind::Private)}; name_scope.AddRequired(entry3); - LocId poisoning_loc_id(++id); - auto lookup = name_scope.LookupOrPoison(poisoning_loc_id, entry1.name_id); + LocId poisoning_loc_id_known_entries(++id); + auto lookup = + name_scope.LookupOrPoison(poisoning_loc_id_known_entries, entry1.name_id); ASSERT_NE(lookup, std::nullopt); EXPECT_EQ(static_cast(name_scope).GetEntry(*lookup), entry1); EXPECT_EQ(static_cast(name_scope).GetEntry(*lookup), entry1); - lookup = name_scope.LookupOrPoison(poisoning_loc_id, entry2.name_id); + lookup = + name_scope.LookupOrPoison(poisoning_loc_id_known_entries, entry2.name_id); ASSERT_NE(lookup, std::nullopt); EXPECT_EQ(name_scope.GetEntry(*lookup), entry2); - lookup = name_scope.LookupOrPoison(poisoning_loc_id, entry3.name_id); + lookup = + name_scope.LookupOrPoison(poisoning_loc_id_known_entries, entry3.name_id); ASSERT_NE(lookup, std::nullopt); EXPECT_EQ(name_scope.GetEntry(*lookup), entry3); NameId unknown_name_id(++id); - lookup = name_scope.LookupOrPoison(poisoning_loc_id, unknown_name_id); - EXPECT_EQ(lookup, std::nullopt); + LocId poisoning_loc_id_unknown_entry(++id); + EXPECT_EQ(name_scope.LookupOrPoison(poisoning_loc_id_unknown_entry, + unknown_name_id), + std::nullopt); + // Check that this is different from Lookup() - does get poisoned. + lookup = name_scope.Lookup(unknown_name_id); + ASSERT_NE(lookup, std::nullopt); + EXPECT_EQ(name_scope.GetEntry(*lookup).result, + ScopeLookupResult::MakePoisoned(poisoning_loc_id_unknown_entry)); +} + +TEST(NameScope, LookupOrPoisonNotIdentifier) { + int id = 0; + + InstId scope_inst_id(++id); + NameId scope_name_id(++id); + NameScopeId parent_scope_id(++id); + NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id); + LocId poisoning_loc_id(++id); + + EXPECT_EQ(name_scope.LookupOrPoison(poisoning_loc_id, NameId::SelfType), + std::nullopt); + // Check that this is different from the identifier use case - doesn't get + // poisoned. + EXPECT_EQ(name_scope.Lookup(NameId::SelfType), std::nullopt); } TEST(NameScope, LookupOrAdd) {