You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
NonPerfAssumption constructed with missing fields in wrapRunPoolType (fields become undefined) #353
Locationapp/Main.hs:149-156 (wrapRunPoolType), type in src/Assumptions.hs:136-148
Cause Each equation builds AP.NonPerfAssumption{AP.interest = mRates} and omits 11 fields (stopRunBy, projectedExpense, callWhen, revolving, inspectOn, buildFinancialReport, pricing, fireTrigger, makeWholeWhen, issueBondSchedule, refinance). Haskell initializes omitted record fields to undefined; accessing any of them throws.
Evidence (GHC 9.12.3, -Wall)8 × -Wmissing-fields at app/Main.hs:149-156, listing exactly those fields.
Impact Any pool-run path that reads a non-interest field (e.g. revolving) crashes with Prelude.undefined.
Suggested fix Populate all fields (use Nothing for the optionals), e.g. via a total defaultNonPerfAssumption value.
src/Assumptions.hs:156-174: added total constructors defaultNonPerfAssumption (all 12 fields explicitly Nothing) and nonPerfWithRates mRates (record-update over the default), both exported.
app/Main.hs:156-164: all 8 wrapRunPoolType equations now build the assumption via AP.nonPerfWithRates mRates; the partial AP.NonPerfAssumption{AP.interest = mRates} syntax is gone.
Same class of bug fixed for RunContext: D.defaultRunContext added in src/Deal/DealBase.hs:219-220, replacing all-undefined RunContext {} uses.
Hastructure.cabal: -Werror=missing-fields enabled on library, executable and test suite, so future partial record construction fails the build.
Regression tests: nonPerfAssumptionTest in test/UT/DealTest.hs:521-539 forces show on every field of the defaults, so any residual undefined throws.
Risk / perf / API
Behaviour-preserving: the pre-fix code only set interest, so pool-run cashflows are unchanged; Nothing is the documented meaning of the other optionals.
Negligible cost (one record per pool run, same allocation as before).
No request/response JSON or API change; only additive library exports.
Verification (GHC 9.12.3)
cabal build lib:Hastructure exe:Hastructure-exe passes with -Werror=missing-fields.
cabal test Hastructure-test --test-options="-p NonPerfAssumption": 5/5 tests pass.
Activity
yellowbean commentedon Oct 20, 2026
Fixed by 5193636 (merged in 8cfe4b7 / Sep26 #322), released in 0.52.14.
What changed
src/Assumptions.hs:156-174: added total constructorsdefaultNonPerfAssumption(all 12 fields explicitlyNothing) andnonPerfWithRates mRates(record-update over the default), both exported.app/Main.hs:156-164: all 8wrapRunPoolTypeequations now build the assumption viaAP.nonPerfWithRates mRates; the partialAP.NonPerfAssumption{AP.interest = mRates}syntax is gone.RunContext:D.defaultRunContextadded insrc/Deal/DealBase.hs:219-220, replacing all-undefinedRunContext {}uses.Hastructure.cabal:-Werror=missing-fieldsenabled on library, executable and test suite, so future partial record construction fails the build.nonPerfAssumptionTestintest/UT/DealTest.hs:521-539forcesshowon every field of the defaults, so any residualundefinedthrows.Risk / perf / API
interest, so pool-run cashflows are unchanged;Nothingis the documented meaning of the other optionals.Verification (GHC 9.12.3)
cabal build lib:Hastructure exe:Hastructure-exepasses with-Werror=missing-fields.cabal test Hastructure-test --test-options="-p NonPerfAssumption": 5/5 tests pass.