Skip to content

Reject extension reductions that return themselves or null - #578

Merged
dadhi merged 1 commit into
dadhi:masterfrom
jogibear9988:fix/reduction-progress
Nov 3, 2026
Merged

dadhi merged 1 commit into
dadhi:masterfrom
jogibear9988:fix/reduction-progress

Conversation

@jogibear9988

Copy link
Copy Markdown
Contributor

A custom Extension node whose Reduce() returns itself loops in the collector/emitter; a null reduction reaches a NullReferenceException. Guard both reduction sites and follow FEC's existing strict rejection contract: null/false, or NotSupportedExpressionException where the collection flags request it. Normal System fallback retains its validation exception.

Two local guards (8 inserted production lines); no new traversal, public API or closure changes. The deliberately broken test reducer is bounded, so the pre-fix test reports a failure rather than hanging.

This is an independent extraction from #558, based directly on master 4683482e929f98a528b12a1c7fee8e232ecc36c2. It has one commit and does not depend on either of the other standalone fixes. #558 and #559 are unchanged.

Validation

  • The new regressions fail against unmodified master and pass with this fix on .NET 8, .NET 10 and .NET Framework 4.7.2 (5 registered regression methods across the applicable input APIs).
  • Full Release solution build passes with zero warnings/errors.
  • Legacy native suites pass: 1,724 cases on .NET 10, 1,723 on .NET 8, and 1,607 on Framework.
  • The complete Framework runner passes 188 TestX + 1,607 legacy cases. en-US culture is used for existing English exception-message assertions.
  • On .NET 8/10, the full runner still fails ParityTests.Binary_operators_with_methods_and_nullable_operands_are_the_same_as_system for nullable MultiplyChecked in both input variants. The identical failures reproduce on unmodified master. No other fixture failures were observed; the legacy suites were invoked separately because this existing TestX failure gates the normal runner.

Performance checks

Measured against current master on Windows ARM64, SDK 10.0.301, .NET 8.0.28/10.0.9, Release; tiered compilation disabled and a fixed CPU affinity. Expression construction/conversion is outside the timed compilation. Only inputs that already compile correctly on master are compared.

For each input, compilation uses two opposite-load-order processes and nine alternating samples per side (about a 100 ms calibration target per pair). The table combines process medians geometrically. Invocation uses nine alternating samples.

All measured controls allocate the same managed bytes per compilation and zero bytes per invocation; decoded control IL is identical before/after. Compilation timing is mixed/noisy, including slower rows below. The identical-binary master/master control itself ranged from -9.9% to +6.0%. These measurements do not establish zero compilation slowdown, and no speedup claim is made. Runtime nanosecond differences are observations of identical emitted control IL.

Runtime Input Control Compile ns, master → fix Change Invoke ns, master → fix Compile B/op, both
net10.0 Standard add_control 1241.9 → 1260.7 +1.5% 1.82 → 1.81 872
net10.0 Standard runtime_type 1413.5 → 1368.2 -3.2% 1.80 → 1.88 928
net10.0 Standard reference_constant 1200.8 → 981.1 -18.3% 1.81 → 1.80 984
net10.0 Standard valid_extension 1257.3 → 1159.3 -7.8% 1.86 → 1.82 872
net10.0 Light add_control 999.0 → 1086.1 +8.7% 1.87 → 1.89 872
net10.0 Light runtime_type 858.7 → 873.6 +1.7% 1.81 → 1.81 928
net10.0 Light reference_constant 996.2 → 961.2 -3.5% 1.81 → 1.85 984
net8.0 Standard add_control 1142.3 → 1215.7 +6.4% 1.82 → 1.79 872
net8.0 Standard runtime_type 1123.6 → 1308.4 +16.4% 1.91 → 1.84 928
net8.0 Standard reference_constant 1080.4 → 1083.0 +0.2% 1.84 → 1.81 984
net8.0 Standard valid_extension 1226.2 → 1272.0 +3.7% 1.86 → 1.86 872
net8.0 Light add_control 1048.3 → 1042.8 -0.5% 1.86 → 1.82 872
net8.0 Light runtime_type 905.1 → 883.8 -2.4% 1.89 → 1.83 928
net8.0 Light reference_constant 949.5 → 927.1 -2.4% 1.88 → 1.80 984

Guard self/null reductions in both collection and emission. Keep strict null/exception contracts and ordinary valid reductions. Regression reducers are bounded so the pre-fix reproduction cannot hang.
@dadhi

dadhi commented Nov 3, 2026

Copy link
Copy Markdown
Owner

nice clean catch, thank you.

@dadhi
dadhi merged commit 7eaa947 into dadhi:master Nov 3, 2026
4 checks passed
@jogibear9988
jogibear9988 deleted the fix/reduction-progress branch November 3, 2026 21:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants