Pin

Scope of Pin and &mut in Rust

  • Several commenters note that &mut is “too powerful”: it allows moving via mem::swap, mem::replace, Option::take, etc.
  • Some argue that if moving through &mut were restricted (or those functions were unsafe), self‑referential values could be safe without Pin.
  • Others counter this would be a non‑starter: it would break large amounts of existing code and there are many move‑via‑reference patterns in the wild.

Move semantics, !Move, and alternative designs

  • Proposed alternative: a language‑level Move trait (analogous to Copy) or split traits for trivial vs custom moves, enabling self‑referential types and richer movement semantics.
  • Some see this as a cleaner long‑term design that could avoid Pin; others argue move constructors would be even more complex for users than Pin.
  • There is interest in “languages after Rust” that keep Rust’s safety but redesign moves, async, and comptime.

Async Rust, Pin, and ergonomics

  • Many see Pin as tightly tied to async/await and futures; some feel Rust’s async story is “half‑baked” and comparatively painful versus other languages.
  • Others insist that with macros (pin!, pin‑project) and idioms, Pin isn’t that hard in everyday async code.
  • A common pattern is “I add Pin where the compiler complains until it compiles,” reflecting weak intuition about when it’s needed.

Why Pin feels confusing

  • Pin alone doesn’t define what is allowed; its meaning depends on whether the inner type is Unpin and on custom APIs built around it.
  • Documentation is criticized as technically accurate but opaque, especially for Unpin and its double‑negative feel.
  • Users struggle with action‑at‑a‑distance: changes far from the error site can suddenly introduce Unpin constraints.
  • Suggestions include more practical, “systems‑engineering” docs and better teaching analogies (Velcro/smooth, magnets/non‑magnetic, stapling vs hooks).

Unpin and typestate

  • Clarified view:
    • Pin is a state of a pointer, not a property of the data.
    • For most types (those that are Unpin), Pin<T> is effectively a no‑op.
    • Only types that rely on their address (e.g., self‑referential, some futures) truly care about pinning.
  • Pinning vs non‑transitive pinning of fields (via projection) is acknowledged as necessary but confusing accidental complexity.

Use cases beyond async

  • Reported non‑async uses:
    • FFI where a C API gives a raw pointer that must not move.
    • OS or system types (e.g., mutex/futex implementations) whose docs require stable addresses across their lifetime.

Async vs threads and broader concurrency debate

  • One camp argues all async is a workaround for inefficient OS threads; “fix threads” and much complexity (including Pin) disappears.
  • Others respond that:
    • OS‑level fixes are unrealistic or outside language designers’ control.
    • Async offers benefits such as cancellation, fine‑grained control, and embedded/no‑alloc scenarios.
    • Thread APIs and context‑switch costs still limit simple “just use threads” answers.
  • Go’s model is cited both positively (no explicit async) and negatively (composability, context management, hidden overhead).

HN‑specific meta: titles and moderation

  • Many dislike the bare title “Pin” as uninformative or clickbaity; some want language tags like “[Rust] Pin”.
  • Others note HN guidelines favor original titles but are applied with varying strictness; debate centers on balancing fidelity vs clarity.