Repository navigation
code.co_names leaks a __doc__ entry #4505
Description
Activity
@DimitrisJim how difficult do you think this would be?
Ah, still not sure, sorry. There's some subtlety here since it only occurs with nested functions (maybe with anything nested that can take a docstring?).
You're of course welcome to look into it, especially if you'd like to see more of the compiler, and if stuck we'll figure something out :)
Sure! I'd love to get onto the compiler side. Do you have a recommendation for where I should look?
The reason why this happens is that cpython forwards
.__doc__to just the first element ofco_consts, which is either the docstring or None if there isn't one. We manually set.__doc__ = ...on the function object, but should probably switch to the other way of doing it.Reacted by Evan RittenhouseWhat Noa said, but in bytecode form, for a given function:
cmp = """ def foo(): ''' doc ''' pass """
What RustPython generates:
dis(cmp) 4 0 LoadConst (<code object foo at ??? file "<dis>", line 2>) 1 LoadConst ("foo") 2 MakeFunction ((empty)) 3 Duplicate 4 LoadConst (" doc ") 5 Rotate2 6 StoreAttr (0, __doc__) 7 StoreLocal (1, foo) 8 LoadConst (None) 9 ReturnValue Disassembly of <code object foo at ??? file "<dis>", line 2> 4 0 LoadConst (None) 1 ReturnValue
While for CPython:
dis(cmp) 2 0 LOAD_CONST 0 (<code object foo at 0x7fb1db4e03a0, file "<dis>", line 2>) 2 LOAD_CONST 1 ('foo') 4 MAKE_FUNCTION 0 6 STORE_NAME 0 (foo) 8 LOAD_CONST 2 (None) 10 RETURN_VALUE Disassembly of <code object foo at 0x7fb1db4e03a0, file "<dis>", line 2>: 4 0 LOAD_CONST 1 (None) 2 RETURN_VALUE
notice the missing instructions for
__doc__.The relevant file that handles this is
compiler/codegen/src/compile.rs. It needs some tweaking to stuff__doc__in the consts if it exists instead of generating the load and store for the__doc__.You could start for functions (
compile_function) and then the process should be similar to the other cases.Reacted by Evan Rittenhouse- added a commit that references this issue
on Dec 12, 2025 - added a commit that references this issue
on Dec 12, 2025
when it shouldn't.
I was able to repro this in cases where a nested function is defined, i.e:
In RustPython:
while in Python:
and also when compiling a module from a source string:
In RustPython:
while in Python:
not entirely sure how easy the fix might be.