Skip to content

A defaulted scalar's .csg is byte-identical to a correct part's, so no .csg rule can decide #308 #332

Description

@CameronBrooks11

Epic #305. The uncovered remainder of #308, which PR #329 closed only in part.

What is wrong

#308's headline reproduction still passes at exit 0 on both pinned engines,
and PR #329 does not fix it. That PR guards Unable to convert, which
OpenSCAD prints for a vector- or **transform-**valued parameter it could
not convert. A scalar dimension taking undef is narrated by nothing at
all.

Measured under both engines the CI matrix pins — apt 2021.01 and the pinned
2026.08.01 snapshot — each source rendered with
openscad --export-format binstl -o out.stl p.scad, each o = undef:

source stderr, both engines
linear_extrude(o) square([40,30]); (nothing)
linear_extrude(height=o) square([40,30]); (nothing)
cube(o); (nothing)
cube(size=o); (nothing)
cylinder(h=o, d=10); (nothing)
sphere(o); (nothing)
circle(r=o); (nothing)
resize(o) cube(5); (nothing)
linear_extrude(o + 1) square([40,30]); WARNING: undefined operation (undefined + number)
cube(o + 1); WARNING: undefined operation (undefined + number)
cylinder(h = o + 1, d = 10); WARNING: undefined operation (undefined + number)

Every one of them exits 0 and exports a clean, watertight, single-solid mesh
built to a dimension nobody wrote down. #308's own example is the ninth row:
100 mm tall because a name was undefined, and no Unable to convert line
anywhere in stderr.

Why the obvious signals do not work

undefined operation cannot be used on the success path. It was tried in
PR #306 and reverted: holes = 4; echo("holes: " + holes); — + where
str() was meant — prints undefined operation (string + number) beside a
completely correct 272-facet part.

Nor can its operand types. The idea that (undefined + number) marks the
dimension case and (string + number) marks the echo case does not survive
contact with an optional parameter left at its undef default:

o = undef;
echo("holes: " + o);          // WARNING: undefined operation (string + undefined)
cube([40,30,6]);              // ... beside geometry that is exactly right

Both engines, measured. So undefined as an operand is not evidence that the
value reached geometry.

And the silent rows have no signal at all. For linear_extrude(undef)
there is no warning to key on, no exit code, and nothing in the export.

What this means

Any fix needs a channel other than stderr. partspec lint's tier 2 already
reads the .csg export, which is evaluated before any boolean runs and
is where a substituted default would be visible as a literal — that is the
most promising lead, but it is a lead and not a design, and lint exits 0
whatever it finds, so it is advisory by construction.

Until then this shape is uncovered, and
src/partspec/engines/openscad.py's _SUBSTITUTED_VALUE_MARKERS docstring
says so rather than implying #308 closed.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsilence-defectSilence read as success. Add the case to https://heibench.com/silence.html

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions