NativeAOT: non-ASCII identifiers collapse to underscores when mangled, producing duplicate symbols
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
### Description
`NativeAotNameMangler.SanitizeName` replaces every non-ASCII codepoint of an identifier with a single `_`. Identifiers that consist only of non-ASCII characters (e.g. Japanese type and method names) therefore collapse into runs of underscores, and different identifiers of the same length become identical after sanitization.
Uniqueness is only enforced per scope (types within a module, methods within a type), but the mangled name of a method is `__`. Because the separator is itself underscores, a type with an 8-character name and a 9-character method produces exactly the same symbol as a type with a 9-character name and an 8-character method (`_App___________________` in the repro below). Depending on the ILC version this surfaces as duplicate symbols at link time or as an `ArgumentException` in the object writer.
### Reproduction Steps
```csharp
namespace App
{
public sealed class ラベルを登録する // 8 characters
{
public string 実行して検分する() // 9 characters
{
try { return "a"; } catch (System.Exception) { return "b"; }
}
}
public sealed class 配置対象を選び出す // 9 characters
{
public string 実行して検分す() // 8 characters
{
try { return "c"; } catch (System.Exception) { return "d"; }
}
}
}
public static class Program
{
public static void Main() =>
System.Console.WriteLine(new App.ラベルを登録する().実行して検分する() + new App.配置対象を選び出す().実行して検分す());
}
```
```
dotnet publish -c Release -r osx-arm64 -p:PublishAot=true
```
(The `try/catch` is only there to make sure per-method symbols such as the EH info are emitted; the collision also affects the method symbols themselves.)
### Expected behavior
The program is compiled and prints `ac`.
### Actual behavior
ILCompiler 8.0.30 (macOS, `-ld_classic`):
```
:0: error: symbol '___ehinfo_aot_min3_App___________________' is already defined
:0: error: symbol '_aot_min3_App___________________' is already defined
:0: error: symbol '_fram0_aot_min3_App___________________' is already defined
:0: error: symbol '_lsda0_aot_min3_App___________________' is already defined
```
ILCompiler 10.0.11 (macOS, ios-arm64 shows the same):
```
EXEC : error : An item with the same key has already been added. Key: ___ehinfo_App___________________
System.ArgumentException: An item with the same key has already been added. Key: ___ehinfo_App___________________
```
A real-world assembly of ours (a domain model that uses Japanese identifiers throughout, ~19,000 lines) has 285 groups of members that sanitize to the same name and cannot be published with NativeAOT at all.
### Regression?
No — the sanitization has always replaced non-ASCII characters with `_`.
### Known Workarounds
Rename identifiers to ASCII (not acceptable for code bases that deliberately use business vocabulary as identifiers), or build ILC with a patched `SanitizeName`. A fix is proposed in the linked PR: encode non-ASCII codepoints as `_u` (similar to `\u` escapes), so that distinct identifiers stay distinct after sanitization.
### Configuration
- .NET SDK 10.0.400 / ILCompiler 10.0.11 and .NET SDK 8.0.420 / ILCompiler 8.0.30
- macOS 26 (arm64), targets `osx-arm64` and `ios-arm64`
- Xcode 26.6
### Other information
The same collapse affects type names, but `ComputeMangledTypeName` disambiguates those with a numeric suffix within a module, which hides the problem until method (or nested type / field) names are involved.
Contributor guide
Research direction
Start by locating NativeAotNameMangler.SanitizeName and read how its output is used by ComputeMangledTypeName and method symbol generation. Run the provided Japanese-identifier NativeAOT publish reproduction on the stated targets, then verify that distinct identifiers produce distinct symbols and the program prints "ac" without duplicate-symbol or duplicate-key errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 70/100