Skip to content

Some functions take ownership without using it #6

Open

Description

@cblanquera

Timing: Follow-up after trial/3 merges into main; defer implementation until then.

Review baseline: Local trial/3 at a094418baf6388e3eeca23821df481a7f0a8751c. This branch is not yet on the remote. Source locations below refer to that snapshot and should be rechecked after merge.

Problem

Some parameters are taken by value even though the function only reads them and builds separate output. This can unnecessarily consume caller-owned values or require allocations. Ownership can still be intentional for lifecycle, callback, trait, or API-contract reasons, so each candidate needs review.

Evidence

  • crates/framework/framework-ui/src/render.rs:220-232: escape_html(value: String) reads characters and allocates a different output buffer.
  • The helper is also supplied to Leptos's Title formatter; preserve any required callback signature rather than blindly changing it to &str.
  • The opt-in Clippy pass also identified other needless_pass_by_value candidates, including output planning and SQLite row decoding.

Acceptance criteria

  • Borrow inputs where ownership is unnecessary and the surrounding contract allows it.
  • Retain intentional consumption and required trait/framework signatures, using a thin adapter only where justified.
  • Preserve escaping, lifetimes, cancellation/cleanup, and public compatibility.
  • Rerun affected compilation/lints and meaningful behavior checks.

Code examples and suggested direction

Borrowing can coexist with a framework-required consuming callback:

fn escape_html_text(value: &str) -> String {
    let mut encoded = String::with_capacity(value.len());
    for character in value.chars() {
        match character {
            '&' => encoded.push_str("&"),
            '<' => encoded.push_str("&lt;"),
            '>' => encoded.push_str("&gt;"),
            '"' => encoded.push_str("&quot;"),
            '\'' => encoded.push_str("&#39;"),
            other => encoded.push(other),
        }
    }
    encoded
}

// Retain this adapter if Leptos requires Fn(String) -> String.
fn title_formatter(value: String) -> String {
    escape_html_text(&value)
}

The names above are suggestions. The adapter's ownership is intentional; it is not a reason to change a dependency's callback contract.

Activity

  1. cblanquera commented on Oct 26, 2026

    @cblanquera
    MemberAuthor

    Suggested investigation and fix notes

    Deferred until trial/3 is merged into main. Recheck the merged source and tests first. The snippets are examples/proposals, not an approved patch or a change to frozen contracts.

    1. Re-run targeted needless_pass_by_value diagnostics after merge and inspect each caller. Classify each case as unnecessary consumption, intentional one-shot ownership, or a fixed trait/framework signature.
    2. For HTML escaping, confirm the pinned Leptos Title formatter signature. Use a borrowed local implementation plus a consuming adapter only if it improves reuse/call-site allocations.
    3. Review OutputWorkspace::install_at(plan: OutputPlan, ...) separately: consuming a plan may encode one-shot ownership, even if the body only borrows it. Do not change this public/lifecycle contract based on a lint alone.
    4. For SQLite row decoding, consider whether taking the row intentionally establishes the native-row release point. A borrowed parameter can lengthen resource retention at its callers.
    5. Preserve straightforward lifetimes and existing public callers. Avoid replacing a simple owned value with widespread lifetime parameters for an unmeasured benefit.

    Example behavior checks for the proposed borrowed helper:

    assert_eq!(escape_html_text("A&B"), "A&amp;B");
    assert_eq!(escape_html_text("\"<tag>'"), "&quot;&lt;tag&gt;&#39;");
    assert_eq!(escape_html_text("café"), "café");
    assert_eq!(escape_html_text(""), "");

    Check native SSR separately with cargo test -p stackpress-framework-ui --features ssr --locked. Validate hydrate/CSR in their own supported target/feature configurations; do not combine mutually exclusive renderers. Record justified no-change candidates instead of mechanically changing ownership.

    Implementation workflow: After the merge, follow .agents/workflows/rust-programming.md: prove the affected behavior, complete the three test-verified review rounds, and record relevant formatting/lints/docs, feature/platform scope, and applicable development coverage. Preserve unrelated changes.

  2. cblanquera commented on Oct 26, 2026

    @cblanquera
    MemberAuthor

    Progress on trial/3 (merged as ff7a251): the server, CLI and transformer parts are now done, in addition to the earlier lib part. The SQL and UI-framework parts follow in a short final pass. Leaving open.

  3. cblanquera commented on Oct 26, 2026

    @cblanquera
    MemberAuthor

    Now complete across all crates on trial/3 (final pass 28b3826, merged as 7031282; earlier parts in 644795f and 407b4d6). Not yet on main, so leaving open.

    • SQL/framework parameters that were only read now borrow; framework-ui escape_html borrows &str, with a thin adapter kept for the Leptos Title callback signature.
    • Coordinator-verified on the combined code: fmt, Clippy -D warnings, Rustdoc -D warnings, cargo +1.96.0 check, 470 workspace tests and 867 doctests pass; the profile UI check passes for both in-memory and SQLite backends, with all 16 browser proofs.
  4. added 2 commits that reference this issue on Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions