fix: [Python] consistent mangled names for generic abstract class members#4544
Merged
Conversation
…bers Abstract method stubs in a generic abstract class were produced from `memb.FullName` (which omits the backtick generic arity), while derived-class overrides were produced from the entity's `FullName` (which includes the arity). The two paths also used different sanitization: the stub path replaced `.` but not `` ` ``, while the override path replaced both. Result: Python's ABC refused to instantiate derived classes because the abstract method names (e.g. `TestRunner_get_Encode`) did not match the override names (`TestRunner_2_get_Encode`). Use `ent.FullName` plus `Fable.Py.Naming.cleanNameAsPyIdentifier` on both sides so the two mangled names match. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Python Type Checking Results (Pyright)
Excluded files with errors (4 files)These files have known type errors and are excluded from CI. Remove from
|
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.
Summary
Derived classes of generic abstract classes could not be instantiated in compiled Python due to mismatched mangled method names between the abstract stub and the override.
Root cause
Two different name-mangling paths:
Fable2Python.Bases.fs,InterfaceNaming.getMangledMemberName) derived the entity prefix frommemb.FullName, which from the F# compiler does not include the backtick generic arity. The code also replaced.with_but left backticks untouched.FSharp2Fable.Util.fs,getMangledAbstractMemberName) built the prefix from the entity's ownTryFullName, which does include the arity (e.g.`2), and downstream sanitization inPython.Prelude.sanitizeIdentForbiddenCharsreplaced both.and`with_.Result: for
TestRunner<'A, 'B>the abstract stub was namedTestRunner_get_Encodewhile the override was namedTestRunner_2_get_Encode. Python's ABC then refused to instantiate any derived class:Fix
getMangledMemberNamenow usesent.FullName(entity full name with arity) andFable.Py.Naming.cleanNameAsPyIdentifier, which replaces both.and`with_. This matches the mangled name that derived-class overrides produce.For non-generic abstract classes the output is unchanged.
Test plan
Generic abstract class can be instantiated through derived classintests/Python/TestType.fscovering an abstract method, an abstract property, and an abstract generic mapper.tests/Pythonsuite passes locally (2331 tests).🤖 Generated with Claude Code