`post_processing_function` is documented as "a function name of the replacement
linear class that is called after processing", but the lookup targets the module
being replaced:
func = getattr(module, post_processing_function, None)
if func is not None:
func(module)
`module` at that point is still the original `torch.nn.Linear`, which never
carries the hook, so `getattr(..., None)` returns `None` and the block does
nothing. The parameter is a no-op for every caller.
replace_linear(model, MyLinear, post_processing_function="post_init")
-> fc replaced with MyLinear, post_init calls: []
Two things in three lines: the wrong object, and `func(module)` passing an extra
positional argument to what is already a bound method.
Look the hook up on `model._modules[name]` and call it with no argument. After:
-> fc and block[0] replaced, post_init calls: ['4x8', '8x16']
(lm_head skipped via skip_modules, as before)
A replacement class that does not define the method still passes through
untouched, so this cannot start raising for anyone.
post_processing_function is documented as
but the lookup targets the module being replaced:
module there is still the original torch.nn.Linear. It never carries the hook, so getattr(..., None) returns None and the block does nothing:
The parameter is a no-op for every caller, and silently so — the replacement itself works, only the hook is skipped.
Two problems in those three lines: the wrong object, and func(module) passing an extra positional argument to what getattr has already bound.
The change
Look the hook up on model._modules[name] (the instance just constructed) and call it with no argument.
After:
A replacement class that does not define the method still returns None from getattr and passes through, so this cannot start raising for existing callers. Nothing in the repo calls replace_linear with the hook, so the change is only visible to downstream users, for whom it goes from "silently ignored" to "runs".
Tests
New tests/test_utils.py:
Reverting only bitsandbytes/utils.py:
and with the change, 4 passed. ruff check and ruff format --check clean.