Skip to content

Allow non-'static opaque fields without lifetime unsoundness #1565

@fasterthanlime

Description

@fasterthanlime

Summary

The current soundness fix makes Opaque<T>: Facet require T: 'static. This closes the lifetime laundering hole in Poke::get_mut, but it also forbids borrowed opaque fields (#[facet(opaque)] on &'a T).

Goal

Allow non-'static opaque fields without reintroducing lifetime unsoundness.

Background

Possible direction

Introduce a lifetime-aware wrapper, e.g. Opaque<'a, T>, and only implement Facet<'a> for Opaque<'a, T>. Then have derive use Opaque<'ʄ, FieldTy> for #[facet(opaque)] fields. This ties the wrapper's lifetime to the Facet lifetime and blocks the laundering.

Considerations:

  • Requires macro changes to put in scope for opaque field shapes (may need conditional hoisting of __SHAPE_DATA).
  • API break: existing Opaque<T> usages may need migration or a new wrapper type for borrowed fields.

Open questions

  • Can we preserve the fast-path hoisted __SHAPE_DATA for types without opaque fields?
  • Should Opaque<T> remain for owned/'static data, with a separate OpaqueBorrow<'a, T> for borrowed data?

Metadata

Metadata

Assignees

No one assigned

    Labels

    ✨ enhancementNew feature or request🎺 soundnessUnsoundness in the code or design, we're doing UB / breaking invariants💥 breakingBreaking API changes📜 deriveRelated to the derive macro

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions