Repository navigation
fix(cpp): an alias of a type written from the global scope names that global type - #2568
Merged
Merged
Conversation
… global type
protobuf's hpb declares `class Arena { … backend::Arena arena_; }`, where
`namespace backend = hpb::internal::backend::upb;` and that namespace says
`using Arena = ::upb::Arena;`. cppTypeName dropped the leading `::`, so the
alias's target was looked up as `upb::Arena` from the alias's own scope,
whose nearest `upb` is that very namespace: the alias named itself, the
lookup ended on no class, and `arena_.Fuse(other.arena_)` fell back to the
type's last name, linking `hpb::Arena::Fuse` (and `IsFused`, `RefArena`) to
itself instead of `upb::Arena::Fuse`.
TypeName now records a leading `::` (`global`), and a global name is looked
up from the global scope alone: when an alias's target is followed (follow,
and the scope expand looks the target up from and hands on), in a class's
base clause (baseClassesOf), and in cppAliasedTypeWritten, which #2532's
`auto` locals and chains walk alias by alias.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
colbymchenry
added a commit
that referenced
this pull request
Oct 15, 2026
…there, and a far lowercase outside type reaches no namesake (#2569) The two follow-ups #2567 and #2568 left open. A receiver declared with a leading `::` lost it: the declarator regex started a type at a letter, so `::upb::Arena& a` inside `namespace hpb` was looked up from `hpb` and found a namespace-local `hpb::upb::Arena`. The declared type now keeps a leading `::` where one can stand (not after a name, a template's arguments or a `)`, so `SkipList<Key, Comparator>::Iterator iter` is not read as `::Iterator`), and resolveCppAliasedType no longer takes a function-local `using Foo = Bar;` for `::Foo`. A lowercase outside type declared outside the calling function still used the last-name typed match: #2413's library rule skips such declarations, and #2567's namesake gate took capitalized types only. So a far `absl::flat_hash_set<int> seen` linked `seen.insert(v)` to the project's `util::flat_hash_set::insert`, and a far `std::string text` linked `text.clear()` to a global project `string` class. The gate now covers lowercase types, which are decided as when no class shares their name, and cppFindsOnlyNamesakes reads a `std::` name exactly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
This is the
hpb/arena.hfollow-up from #2567. protocolbuffers/protobuf's hpb declaresclass Arena { … backend::Arena arena_; }, where:namespace backend = hpb::internal::backend::upb;(inhpb/multibackend.h);namespace hpb::internal::backend::upb { using Arena = ::upb::Arena; }(inhpb/backend/types.h).So
arena_.Fuse(other.arena_)inhpb::Arena::Fuseshould reachupb::Arena::Fuse. On main,hpb::Arena::Fuse,IsFusedandRefArenaeach linked to themselves, at 0.9.Cause:
cppTypeNamedrops a leading::. Following the alias looked its target up asupb::Arenafrom the alias's own scope,hpb::internal::backend::upb, where the nearestupbis that namespace itself. The alias named itself, the lookup ended on no class, and the call fell back to the type's last name. That fallback prefers the call site's file, which here is the calling method.Fix:
TypeNamerecords a leading::(global), and a global name is looked up from the global scope alone in each place that resolves one:follow, and the scopeexpandlooks the target up from and hands on);baseClassesOf);cppAliasedTypeWritten, which fix(cpp): a call on anautovariable or a chained call reaches the class C++ finds, not a namesake #2532'sautolocals and chains walk alias by alias.cppClassNamedneeded nothing, since its callers already pass only the global scope for::names. A receiver's declared type never carries a leading::, because the declarator pattern starts at a letter, so nothing changes there.Validation
Tests:
__tests__/cpp-global-alias-target.test.ts, 4 tests, all failing on main:::upb::Arenabeside a namespace-localupb::Arena(main:hpb::upb::Arena::Fuse);autovariable typed through such an alias (main: the caller's file'shpb::Arena::Fuse);::lib::Optionsbeside a nestedapp::lib::Options(main:app::Inner::Run).All 42 C/C++ test files pass (396 tests). Full suite: 7,123 passed, 0 failed (82 skipped).
Mutations: each change, switched off, fails its own test.
globalnever setfollowlookup scopesautoexpand'sfollowglobalexpand's lookup scope::lib::OptionscppAliasedTypeWrittenautoSite-keyed A/B (main 00d7430 vs this branch, kit
%TEMP%\cgstd,diff-sites.mjs): leveldb, fmt, redis and rocksdb are byte-identical. protobuf has exactly 3 retargets, all right:hpb/arena.h:38arena_.Fuse:hpb::Arena::Fuse(itself) →upb::Arena::Fusehpb/arena.h:39arena_.IsFused:hpb::Arena::IsFused(itself) →upb::Arena::IsFusedhpb/arena.h:50arena_.RefArena:hpb::Arena::RefArena(itself) →upb::Arena::RefArenaCHANGELOG: #2399's
[Unreleased]alias bullet was extended rather than given a new one, since it isn't released yet.🤖 Generated with Claude Code