On 2026-06-28 07:43, Thomas Morley wrote:
currently I'm looking at
https://gitlab.com/lilypond/lilypond/-/work_items/6946 "glissando and
line break issue".

The following analysis is from the LLM [Qwen 3.6](https://huggingface.co/Jundot/Qwen3.6-27B-oQ4-mtp). It seems reasonable to me -- a nice change from the usual! -- but I leave it to you to verify.
--
Dan

---

**Root cause confirmed.** The bug is in `Spanner_break_forbid_engraver`, specifically a combination of two issues:

### 1. `Grob::suicide()` clears interfaces (`grob.cc:338`)

```cpp
interfaces_ = SCM_EOL;
```

This destroys the grob's interface list, which is needed for dispatch lookup.

### 2. `acknowledge_grobs()` queries the grob's interfaces at dispatch time (`engraver-group.cc:146`)

```cpp
SCM ifaces = info.grob ()->interfaces ();
acklist = Engraver_dispatch_list::create (get_simple_trans_list (),
                                          ifaces, info.start_end ());
```

When the grob has been suicided, `interfaces()` returns `SCM_EOL`. The dispatch list creation iterates over an empty interface list, finds no acknowledgers, and returns `SCM_EOL`. The `acknowledge_end_unbreakable_spanner` callback is **never called**.

### 3. `Spanner_break_forbid_engraver` never cleans up dead grobs

The engraver stores raw `Spanner*` pointers in `running_spanners_`. The only removal path is `acknowledge_end_unbreakable_spanner` (line 49-56), which now never fires for suicided grobs. The pointer stays in the vector forever.

`pre_process_music()` (line 42-46) checks `running_spanners_.size()` — it's always > 0 — so `forbidBreak` is permanently set to `SCM_BOOL_T`.

---

Reply via email to