Skip to content

shopping-list silently double-counts ingredients when recipes reference each other #424

Description

@dubadub

When two recipes reference each other, cook shopping-list silently double-counts ingredients instead of detecting the cycle. There is no warning and the exit code is 0.

Reproduction

mkdir -p config
printf 'Make @./b{} and add @salt{1%%tsp}.\n' > a.cook
printf 'Make @./a{} and add @pepper{1%%tsp}.\n' > b.cook
printf '[spices]\nsalt\npepper\n' > config/aisle.conf

cook shopping-list a.cook
[spices]
salt   2 tsp
pepper 1 tsp

salt is declared once, in a.cook. It is counted twice because expanding a pulls in b, and expanding b pulls in a again.

Why it terminates but is still wrong

Reference expansion is bounded by depth rather than by cycle detection, so it does not hang — it just walks the cycle a fixed number of times and adds every ingredient it meets. The deeper the mutual references, the further the quantities drift from the truth.

A shopping list with silently wrong quantities is arguably worse than an error, because there is nothing to notice.

Suggested direction

Track the set of recipes already expanded along the current path and stop when one repeats — either erroring, or warning and expanding it once. The seen map that existed for this purpose was effectively inert, because entries were removed before each return.

Noticed while extracting shopping_list into a library crate. The extraction preserves the current behaviour exactly and pins it in a test (mutually_referencing_recipes_terminate), so changing it is a deliberate decision rather than an accident.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions