[PR #3240] [CLOSED] fix(native): retain Swift manglings the demangler accepts in type analysis #5666

Closed
opened 2026-10-31 01:08:27 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/3240
Author: @XiaoBinGan
Created: 10/14/2026
Status: ❌ Closed

Base: main ← Head: fix/swift-analysis-mangling-prefix


📝 Commits (2)

  • d1d16d3 fix(native): retain Swift manglings the demangler accepts in type analysis
  • 62494f1 Both findings are correct, and I reproduced both against the previous commit on this branch before changing anything.

📊 Changes

2 files changed (+61 additions, -3 deletions)

View changed files

📝 src/domain/symbolAnalysis.test.ts (+42 -0)
📝 src/domain/symbolAnalysis.ts (+19 -3)

📄 Description

Summary

categorizeSwiftTypes silently dropped Swift symbols whose mangling prefix the Swift demangler accepts but whose nominal category this decoder does not model, and reported no entry or limitation for them.

Problem and expected behavior

The module decides whether a name is a Swift symbol with:

classifySwiftSymbol(entry.name) === undefined ? [] : [entry.name]

classifySwiftSymbol answers a different question — whether it can decode a nominal category from the mangling — and its grammar only accepts _?($s|$S|_T0) plus visible _Tt… class names. So a name carrying $e, _$e or @__swiftmacro_, which #3089 and 17e3cf980 establish as names the demangler accepts, is treated as not a Swift symbol at all.

The module already has the right shape for unresolved identity: a $s mangling whose nominal cannot be decoded ($s9999999999999999999999BadVMa) is retained in unclassified with reason: "category_not_decoded" and its own limitation text. The prefixes above bypass that path entirely:

input (all Swift per the shared owner) before
$s4main7ServiceCMa classified classes
$s9999999999999999999999BadVMa retained in unclassified
$e4main7ServiceCMa dropped from total and unclassified
_$e4main7ServiceCMa dropped
@__swiftmacro_4main7ServiceCMa dropped

Expected: a name the demangler accepts is either categorized or retained as an unresolved Swift observation, never silently absent.

Change and scope

  • src/domain/symbolAnalysis.ts — a local isSwiftSymbolName predicate uses the shared isSwiftMangledSymbolName owner for the "is this Swift" decision, and keeps classifySwiftSymbol for category decoding alone. Both call sites (the per-procedure name set and the same-address alias map) use it. Visible runtime class names (_Tt…) remain an explicit disjunct here because, as the owner documents, they are metadata symbols rather than demangler manglings.
  • src/domain/symbolAnalysis.test.ts — regression test.

Additive only: no command, option, schema, or declared contract changes. Symbols that were already categorized keep their category.

Contract and boundary impact

total and other now include the previously dropped symbols, and they appear in unclassified with the existing category_not_decoded reason and the existing limitation wording, so a consumer can distinguish "not Swift" from "Swift, category undecoded". No category is invented for them and no decode status is upgraded.

Evidence and regression coverage

npm run test:focused -- src/domain/symbolAnalysis.test.ts src/domain/native/objcSwiftMetadata.test.ts src/native/parsers/demangle.test.ts tests/boundary/mcp/nativeDemangleMcp.test.ts → 4 files, 23 tests passed.

With/without on this exact base: reverting only src/domain/symbolAnalysis.ts and keeping the new test fails with expected [] to deeply equal [ '$e4main7ServiceCMa', …(2) ]; with the change the same test passes. npm run check:fast → 2 successful; npm run format:check → clean.

Unavailable coverage

Names are supplied by the caller, so this is exercised through the source module rather than a real Swift binary; no provider, demangler, or target execution was involved. Whether a given toolchain emits $e symbols into the symbol tables this analysis reads is not independently verified here — the change follows the prefix set the repository already treats as demangler-accepted.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/3240 **Author:** [@XiaoBinGan](https://github.com/XiaoBinGan) **Created:** 10/14/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/swift-analysis-mangling-prefix` --- ### 📝 Commits (2) - [`d1d16d3`](https://github.com/morluto/rea/commit/d1d16d3a618690c96b721e1121849fdcda5e95ed) fix(native): retain Swift manglings the demangler accepts in type analysis - [`62494f1`](https://github.com/morluto/rea/commit/62494f183fb5abcaed3b33697ece111e166843ed) Both findings are correct, and I reproduced both against the previous commit on this branch before changing anything. ### 📊 Changes **2 files changed** (+61 additions, -3 deletions) <details> <summary>View changed files</summary> 📝 `src/domain/symbolAnalysis.test.ts` (+42 -0) 📝 `src/domain/symbolAnalysis.ts` (+19 -3) </details> ### 📄 Description ## Summary `categorizeSwiftTypes` silently dropped Swift symbols whose mangling prefix the Swift demangler accepts but whose nominal category this decoder does not model, and reported no entry or limitation for them. ## Problem and expected behavior The module decides whether a name is a Swift symbol with: ```ts classifySwiftSymbol(entry.name) === undefined ? [] : [entry.name] ``` `classifySwiftSymbol` answers a different question — whether it can decode a nominal category from the mangling — and its grammar only accepts `_?($s|$S|_T0)` plus visible `_Tt…` class names. So a name carrying `$e`, `_$e` or `@__swiftmacro_`, which `#3089` and `17e3cf980` establish as names the demangler accepts, is treated as *not a Swift symbol at all*. The module already has the right shape for unresolved identity: a `$s` mangling whose nominal cannot be decoded (`$s9999999999999999999999BadVMa`) is retained in `unclassified` with `reason: "category_not_decoded"` and its own limitation text. The prefixes above bypass that path entirely: | input (all Swift per the shared owner) | before | |---|---| | `$s4main7ServiceCMa` | classified `classes` | | `$s9999999999999999999999BadVMa` | retained in `unclassified` | | `$e4main7ServiceCMa` | **dropped from `total` and `unclassified`** | | `_$e4main7ServiceCMa` | **dropped** | | `@__swiftmacro_4main7ServiceCMa` | **dropped** | Expected: a name the demangler accepts is either categorized or retained as an unresolved Swift observation, never silently absent. ## Change and scope - `src/domain/symbolAnalysis.ts` — a local `isSwiftSymbolName` predicate uses the shared `isSwiftMangledSymbolName` owner for the "is this Swift" decision, and keeps `classifySwiftSymbol` for category decoding alone. Both call sites (the per-procedure name set and the same-address alias map) use it. Visible runtime class names (`_Tt…`) remain an explicit disjunct here because, as the owner documents, they are metadata symbols rather than demangler manglings. - `src/domain/symbolAnalysis.test.ts` — regression test. Additive only: no command, option, schema, or declared contract changes. Symbols that were already categorized keep their category. ## Contract and boundary impact `total` and `other` now include the previously dropped symbols, and they appear in `unclassified` with the existing `category_not_decoded` reason and the existing limitation wording, so a consumer can distinguish "not Swift" from "Swift, category undecoded". No category is invented for them and no decode status is upgraded. ## Evidence and regression coverage `npm run test:focused -- src/domain/symbolAnalysis.test.ts src/domain/native/objcSwiftMetadata.test.ts src/native/parsers/demangle.test.ts tests/boundary/mcp/nativeDemangleMcp.test.ts` → 4 files, 23 tests passed. With/without on this exact base: reverting only `src/domain/symbolAnalysis.ts` and keeping the new test fails with `expected [] to deeply equal [ '$e4main7ServiceCMa', …(2) ]`; with the change the same test passes. `npm run check:fast` → 2 successful; `npm run format:check` → clean. ## Unavailable coverage Names are supplied by the caller, so this is exercised through the source module rather than a real Swift binary; no provider, demangler, or target execution was involved. Whether a given toolchain emits `$e` symbols into the symbol tables this analysis reads is not independently verified here — the change follows the prefix set the repository already treats as demangler-accepted. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:08:27 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#5666
No description provided.