MLC112: Default wait() freezes while a frame-varying one-argument updater is active¶
qual reports MLC112 when a default Scene.wait() is provably
static while a one-argument updater that provably reads frame-varying
state (ValueTracker.get_value, random, wall-clock time, iterator
advancement) is active on a scene-family member. Manim decides whether a
wait re-renders via should_update_mobjects: only scene updaters,
stop_condition, always_update_mobjects, or a time-based family
updater (one whose signature names a dt parameter) make it dynamic. A
one-argument updater never does โ so the wait renders a single frozen
frame and the updater's visual change never appears.
- Default severity:
warning - Minimum confidence:
high - Implementation phase:
2 - Fix: passing
frozen_frame=Falseis suggested as an unsafe fix (declaring adtparameter is the idiomatic alternative)
Only Yes-certainty dataflow facts fire: the updater body must provably
read frame-varying state and provably not use dt, the registration must
happen on every path, the host must be provably in the scene family with
the updater still attached at the wait, and the wait must be provably
static with no literal frozen_frame argument. Any Maybe โ an
unresolvable callback body, a branch-dependent registration, a possible
removal โ stays silent.
Wrong¶
class Demo(Scene):
def construct(self):
tracker = ValueTracker(0)
dot = Dot()
dot.add_updater(lambda m: m.set_x(tracker.get_value()))
self.add(dot)
self.wait(2) # frozen frame: the tracker read never renders