What changed
parse() no longer returns sc_result by value: the caller provides the struct and parse() fills it in.
The old by-value return of this ~160KB struct made LLVM explode the inlined copies into a 166,188-instruction function, costing downstream projects many extra minutes on every --release build (nicolino: 29s debug vs 18.4 min release). With the new ABI, a minimal consumer's release build went from >9 minutes (aborted) to 6.7 seconds.
⚠️ Breaking — C ABI only
The Crystal API is unchanged:
require "shortcodes"
Shortcodes.parse("some {% foo %}text{% end %}") # same as beforeC consumers who vendor shortcodes.c/shortcodes.h must adapt their call sites:
sc_result result;
parse(input, len, &result);parse() now zeroes the result itself, which also makes the escaped and self_closing fields deterministic — they were previously only written when their parsing actions fired and read as whatever was on the stack.
📚 Documentation
New docs/compile-time-pitfall.md: the full case study — symptoms, profiling trail, IR before/after, the fix, a second pitfall (zero-initializing huge lib structs Crystal-side is also pathological for LLVM), pre/post timings, and guidance for shard authors.
Full Changelog: v0.4.1...v0.5.0