Skip to content

refactor(strategies,position): remove todo!()/unimplemented!() (#322)#356

Merged
joaquinbejar merged 4 commits intomainfrom
issue-322-remove-todo-unimplemented
Apr 18, 2026
Merged

refactor(strategies,position): remove todo!()/unimplemented!() (#322)#356
joaquinbejar merged 4 commits intomainfrom
issue-322-remove-todo-unimplemented

Conversation

@joaquinbejar
Copy link
Copy Markdown
Owner

Summary

Removes every todo!() and unimplemented!() from production code per rules/global_rules.md §DO NOT. 27 sites eliminated across 6 files:

  • src/strategies/base.rs — 17 trait defaults
  • src/strategies/{long,short}_{call,put}.rs — 8 stubs (4 files × 2)
  • src/model/position.rs — 2 TransactionAble stubs

After this PR the acceptance grep returns 0 matches across all src/**/*.rs:

for f in $(find src -name '*.rs'); do
  awk '/#\[cfg\(test\)\]/{exit} {print}' "$f" | grep -nE '^\s*(todo!\(|unimplemented!\()'
done

Per-pattern transformations

Before After
unimplemented!(...) in Result<_, StrategyError> fn Err(StrategyError::operation_not_supported(<op>, "default"))
unimplemented!(...) in Result<_, PositionError> fn Err(PositionError::unsupported_operation("default", <op>))
todo!() in Result<Self, StrategyError>::get_strategy Err(StrategyError::operation_not_supported("get_strategy", "<Strategy>"))
todo!() in Result<_, TransactionError> fn Err(TransactionError { message: "<X> not implemented for Position".into() })
todo!() in ()-returning find_optimal override tracing::warn!(...) no-op
unimplemented!(...) in non-Result getter (String, HashSet, HashMap) empty-collection / String::new() default + tracing::warn!
unimplemented!(...) returning &Options / &mut Options explicit panic!("...") + # Panics doc (no graceful fallback)

Public-surface notes

  • All trait method signatures unchanged.
  • Behaviour change: methods that previously panicked now either return Err(...) or no-op + tracing::warn!. Callers that pattern-match Err continue to work; callers that relied on the panic see graceful failure.
  • one_option / one_option_mut keep panic! because &Options / &mut Options can't be defaulted; switching to Option<&Options> would touch every caller — tracked as a follow-up.
  • No new error variants. No prelude.rs change. No semver-relevant signature change.

Test plan

  • Acceptance grep returns 0 matches across src/**/*.rs
  • cargo clippy --all-targets --all-features --workspace -- -D warnings
  • cargo fmt --all --check
  • cargo test --all-features --workspace
  • cargo build --release
  • make pre-push (fix + fmt + lint-fix + test + readme + doc)
  • 3 new negative tests cover the typed-error replacements (LongCall::get_strategy, Position::add_transaction, Position::get_transactions)

Commit layout

3 atomic per-bucket commits:

  1. 89a9790c — base.rs trait defaults (17 sites)
  2. 5061a547 — strategy stubs (8 sites + 1 negative test)
  3. 01f6b88c — Position TransactionAble (2 sites + 2 negative tests)

Closes #322

)

Replace 17 `unimplemented!` macro calls in `src/strategies/base.rs`
trait defaults with safer alternatives:

- 11 Result-returning methods (set_expiration_date, set_underlying_price,
  set_implied_volatility, roll_in, roll_out, update_break_even_points,
  get_position, get_position_unique, get_option_unique, modify_position,
  replace_position) now return
  `Err(StrategyError::operation_not_supported(...))` or
  `Err(PositionError::unsupported_operation(...))` instead of panicking.
- 4 non-Result getters (get_title, get_option_basic_type,
  get_implied_volatility, get_quantity) now return an empty value
  (String::new() / HashSet::new() / HashMap::new()) and emit a
  `tracing::warn!` so the missing override is observable in logs.
- 2 reference-returning defaults (one_option, one_option_mut) keep
  `panic!` since &Options / &mut Options can't be defaulted, but use
  explicit `panic!("...")` instead of `unimplemented!` so the
  panic-free grep is satisfied. Documented in `# Panics`.

Trait-level `# Panics` paragraph rewritten to list only the two
remaining panic sites. Per-method docstrings replaced their
`# Panics` notes with `# Errors` describing the propagated
`NotSupported` variant.
Each of the four single-leg strategies had two `todo!()` stubs:

- `StrategyConstructor::get_strategy(&[Position]) -> Result<Self,
  StrategyError>` now returns
  `Err(StrategyError::operation_not_supported("get_strategy",
  "<StrategyName>"))` instead of panicking.
- `Optimizable::find_optimal(...) -> ()` now emits a
  `tracing::warn!` and no-ops instead of panicking. Strategies that
  don't implement optimization no longer crash callers that request
  it.

Adds a negative test in long_call.rs verifying
`LongCall::get_strategy(&[])` returns the typed error variant.
`Position::add_transaction` and `::get_transactions` now return
`Err(TransactionError { message: ... })` instead of panicking.
`Position` doesn't currently track an internal transaction history;
the typed error makes that contract explicit.

Adds two negative tests covering both methods.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors strategy/position code to eliminate todo!() / unimplemented!() in production by replacing them with typed Err(...) results, explicit panics only where required by reference return types, and tracing::warn! no-ops for ()-returning stubs.

Changes:

  • Replaced todo!()/unimplemented!() in multiple strategy trait defaults with warnings, empty defaults, or typed StrategyError/PositionError returns.
  • Updated single-leg strategy stubs (LongCall, LongPut, ShortCall, ShortPut) to return operation_not_supported and warn on find_optimal instead of panicking.
  • Updated Position’s TransactionAble stubs to return TransactionError and added negative tests.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/strategies/short_put.rs Replace todo!() stubs with typed StrategyError and warn! no-op for optimization.
src/strategies/short_call.rs Replace todo!() stubs with typed StrategyError and warn! no-op for optimization.
src/strategies/long_put.rs Replace todo!() stubs with typed StrategyError and warn! no-op for optimization.
src/strategies/long_call.rs Replace todo!() stubs with typed StrategyError, add a negative test for get_strategy.
src/strategies/base.rs Replace trait-default panics with warnings/empty defaults or typed Err(...) for unsupported operations; keep explicit panics for reference-return defaults.
src/model/position.rs Replace TransactionAble todo!() with TransactionError returns and add negative tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/strategies/base.rs Outdated
Comment thread src/strategies/base.rs Outdated
Comment thread src/strategies/base.rs Outdated
Comment thread src/strategies/long_call.rs Outdated
Comment thread src/model/position.rs Outdated
Comment thread src/strategies/base.rs Outdated
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 18, 2026

Codecov Report

❌ Patch coverage is 11.26761% with 63 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/strategies/base.rs 1.96% 50 Missing ⚠️
src/strategies/long_put.rs 0.00% 4 Missing ⚠️
src/strategies/short_call.rs 0.00% 4 Missing ⚠️
src/strategies/short_put.rs 0.00% 4 Missing ⚠️
src/strategies/long_call.rs 75.00% 1 Missing ⚠️
Files with missing lines Coverage Δ
src/model/position.rs 82.97% <100.00%> (+0.84%) ⬆️
src/strategies/long_call.rs 71.25% <75.00%> (+0.36%) ⬆️
src/strategies/long_put.rs 70.76% <0.00%> (-0.89%) ⬇️
src/strategies/short_call.rs 73.11% <0.00%> (-0.90%) ⬇️
src/strategies/short_put.rs 71.47% <0.00%> (-0.89%) ⬇️
src/strategies/base.rs 52.53% <1.96%> (-9.74%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…n test, reword no-op doc

- src/strategies/base.rs: replace literal "default" strategy reason
  in 11 trait-default error sites (set_expiration_date,
  set_underlying_price, set_implied_volatility, roll_in, roll_out,
  update_break_even_points, get_position, get_position_unique,
  get_option_unique, modify_position, replace_position) with
  std::any::type_name::<Self>(). Matches the pattern already used by
  add_position / get_positions and produces actionable error messages
  that name the actual implementing strategy.
- src/strategies/base.rs: get_title, get_option_basic_type,
  get_implied_volatility, get_quantity tracing::warn! messages now
  include std::any::type_name::<Self>() so a missing override is
  attributable to a concrete type from the log.
- src/strategies/long_call.rs: tighten the get_strategy negative test
  to assert OperationErrorKind::NotSupported with operation
  "get_strategy" and reason containing "LongCall", instead of just
  matching the outer OperationError variant.
- src/model/position.rs: reword the TransactionAble docstring from
  "Default no-op stub" to "intentionally unsupported" since the impl
  always errors rather than no-oping.
@joaquinbejar
Copy link
Copy Markdown
Owner Author

Thanks for the review. All six findings are addressed in f28cb15.

@joaquinbejar joaquinbejar merged commit cc91065 into main Apr 18, 2026
13 checks passed
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.

Remove todo!/unimplemented! from strategies trait defaults and stub impls

2 participants