Uh oh!
There was an error while loading. Please reload this page.
NativeAOT: keep non-ASCII identifiers distinct when mangling names - #133230
NativeAOT: keep non-ASCII identifiers distinct when mangling names#133230t-tampo wants to merge 1 commit into
Conversation
SanitizeName replaced every non-ASCII codepoint with a single underscore, so identifiers made only of non-ASCII characters (e.g. Japanese type and method names) collapsed into runs of underscores. Since a method's mangled name is <type>__<method>, a type with an 8-character name and a 9-character method produced the same symbol as a type with a 9-character name and an 8-character method, and the linker or object writer rejected the duplicates. Encode non-ASCII codepoints as _u<hex> instead, similar to \u escapes, so distinct identifiers stay distinct. Add a regression test to the NativeAOT UnitTests smoke test.
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
t-tampo
commented
Sep 4, 2026
@dotnet-policy-service agree company="Sinfonia Inc." |
| // Everything else is replaced by underscore. | ||
| // TODO: We assume that there won't be collisions with our own or C++ built-in identifiers. | ||
| sb.Append('_'); |
There was a problem hiding this comment.
This can still be a problem for programs that only use ASCII. Here is a reproduction program that fails to compile with ILC on .NET 10.0.10 and I believe would still fail to compile with your change:
usingSystem.Runtime.CompilerServices;Foo._Bar();Foo_.Bar();classFoo{[MethodImpl(MethodImplOptions.NoInlining)]publicstaticvoid_Bar(){Console.WriteLine("_Bar");}}classFoo_{[MethodImpl(MethodImplOptions.NoInlining)]publicstaticvoidBar(){Console.WriteLine("Bar");}}I don't think this problem can be fully solved in this function. Probably it would be better handled by something that makes symbol names unique after mangling, similar to how identical method names in the same class are made unique.
| // example Japanese type and method names) collapse into runs of underscores. Because the | ||
| // mangled name of a method is "<type>__<method>", a type with an 8-character name and a | ||
| // 9-character method then produced exactly the same symbol as a type with a 9-character | ||
| // name and an 8-character method, and the linker rejected the duplicate symbols. |
There was a problem hiding this comment.
Nit: this whole comment describes what would happen before this change, not what the what the code currently does. It probably can be elided.
MichalPetryka
commented
Sep 5, 2026
Would it be better to instead append a short hash of the full function signature to the end of the name like Unity IL2CPP does? |
Fixes#133229
NativeAotNameMangler.SanitizeNamereplaced every non-ASCII codepoint with a single_. Identifiers that consist only of non-ASCII characters (for example Japanese type and method names) collapsed into runs of underscores, so different identifiers of the same length sanitized to the same string. Uniqueness is enforced per scope only, but a method's mangled name is<type>__<method>with an underscore separator, so a type with an 8-character name and a 9-character method produced exactly the same symbol as a type with a 9-character name and an 8-character method. The linker (ILC 8,symbol ... is already defined) or the object writer (ILC 10,An item with the same key has already been added. Key: ___ehinfo_...) then rejected the duplicates.This change encodes each non-ASCII codepoint as
_ufollowed by its hex value (4 digits, 6 for supplementary planes), similar to a\uescape, so that distinct identifiers stay distinct after sanitization.ラベルを登録するnow mangles to_u30e9_u30d9_u30eb_u3092_u767b_u9332_u3059_u308binstead of________. Malformed UTF-8 keeps the lead byte as the discriminator so the result stays deterministic. ASCII characters are handled exactly as before.I verified the fix with an ILC built from the 10.0 servicing branch (
v10.0.11+ this change): the minimal repro from the issue and a 19,000-line assembly with 285 colliding member groups both publish and run with NativeAOT onosx-arm64, and theios-arm64build that originally failed now links (the produced dSYM contains 10,266_uXXXXsymbols). Symbol names get longer for non-ASCII identifiers (7 bytes per BMP character), which seemed acceptable next to the alternative of not being able to compile at all; happy to switch to a hashed suffix if that is preferred.A regression test with the two colliding types is added to the NativeAOT
UnitTestssmoke test.