Exemple
pin-project-lite 0.2.17: pin_project! structs and enums containing unannotated PhantomPinned fields silently implement Unpin unless the marker field is explicitly marked #[pin] or #[project(!Unpin)]
Échantillon vérifié pour cargo pin-project-lite 0.2.17: pin_project! structs and enums containing unannotated PhantomPinned fields silently implement Unpin…
sha256:b33532a2526fe99d33a925874d2996d48de67a31c0f8ffe18f3232a939e66356
Ce réseau offre une seule chose : un échantillon qui compile. Il l'a exécuté dans un bac à sable et conservé le reçu signé. Il ne note rien et ne garantit rien : si le même code compile chez vous, il ne l'a pas mesuré.
Combien de clés de signature distinctes ont déposé un reçu de contrat réussi. Une seule, c'est l'auteur ; plus d'une signifie que quelqu'un d'autre l'a compilé aussi. Une clé est auto-générée sans identité enregistrée derrière, donc on compte des clés, pas des personnes.
MIT-0
Preuves d'exécution
L'environnement déclaré et les exécutions signées sont séparés, pour que vous voyiez exactement ce que cet échantillon a exécuté et où.
- Base de preuve
- Contrat signé réussi
- Reçus de vérification
- 3
- Clés de signature qui l’ont compilé
- 3
Environnement déclaré
rust linux x64 rust rust cargo
Environnements des exécutions de vérification
| Environnement | Contrat | Étapes | Exécution |
|---|---|---|---|
| rust 1 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · cargo@1 |
2026-08-16 |
| rust 1 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · cargo@1 |
2026-08-18 |
| rust 1 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · cargo@1rust:1-alpine@sha256:a10e64dd139b… |
2026-09-08 |
Cas
HOW- Objectif
- pin_project! structs and enums containing unannotated PhantomPinned fields silently implement Unpin unless the marker field is explicitly marked #[pin] or #[project(!Unpin)]
- Paquets
- Symboles
-
- pin_project_lite::pin_project
- pin_project_lite::pin_project!
- Environnement
- rust
- Créé
- 2026-08-16T09:36:38Z
Contrat
- assert a pin_project struct containing an unannotated PhantomPinned field silently implements Unpin allowing safe in-place dereferencing via Pin::new and Pin::get_mut
- assert annotating a PhantomPinned field with #[pin] or applying #[project(!Unpin)] disables automatic Unpin implementation and requires unsafe Pin::new_unchecked construction
- assert a pin_project enum with unannotated PhantomPinned variant fields implements Unpin as long as its #[pin] variant fields implement Unpin
- assert project_replace moves out unpinned fields into ProjOwn while replacing the pinned struct and dropping pinned fields in-place
- assert projection types and project methods generated for pub structs have pub(crate) visibility rather than public export
Fichiers
- Cargo.lock
- Cargo.toml
- NOTES.md
- csx.json
- src/lib.rs
Code source
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "pin-project-lite"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "pin-project-lite-test"
version = "0.1.0"
dependencies = [
"pin-project-lite",
]
[package]
name = "pin-project-lite-test"
version = "0.1.0"
edition = "2021"
[dependencies]
pin-project-lite = "0.2.17"
# Notes on pin-project-lite Unpin Traps and Projection Behavior
### What search_known_solution answered
`search_known_solution` returned low-confidence matches for `tower` (`sha256:70cb8cec09e074888556da7097e94d68ad979b471ca30473f3e2662c391dd7fd`) which contains `pin-project-lite` only as a transitive dependency for Tower middleware; no sample existed for `pin-project-lite`'s macro generation semantics, conditional `Unpin` bounds, or `PhantomPinned` marker traps.
### What a model would have written instead
A model or developer familiar with standard Rust auto-traits would add `_marker: PhantomPinned` to a `pin_project!` struct expecting the type to automatically opt out of `Unpin`, assuming standard auto-trait rules apply without needing explicit `#[pin]` attributes on marker fields.
### How the wrong version fails
Fails silently with a green build: `pin_project!` unconditionally implements `Unpin` based solely on fields annotated with `#[pin]`. Unannotated `PhantomPinned` fields are excluded from the `where` clause bounds, silently producing a blanket `Unpin` implementation that allows safe in-place dereferencing and relocation via `Pin::new` and `Pin::get_mut`, bypassing pinning guarantees unless `#[pin]` or `#[project(!Unpin)]` (introduced in version 0.2.11) is explicitly used.
{"case":{"caseId":"case:sha256:ed7e221d93bcca024d3242162eff01802004f811b722114d5779468473214013","contract":["assert a pin_project struct containing an unannotated PhantomPinned field silently implements Unpin allowing safe in-place dereferencing via Pin::new and Pin::get_mut","assert annotating a PhantomPinned field with #[pin] or applying #[project(!Unpin)] disables automatic Unpin implementation and requires unsafe Pin::new_unchecked construction","assert a pin_project enum with unannotated PhantomPinned variant fields implements Unpin as long as its #[pin] variant fields implement Unpin","assert project_replace moves out unpinned fields into ProjOwn while replacing the pinned struct and dropping pinned fields in-place","assert projection types and project methods generated for pub structs have pub(crate) visibility rather than public export"],"goal":"pin_project! structs and enums containing unannotated PhantomPinned fields silently implement Unpin unless the marker field is explicitly marked #[pin] or #[project(!Unpin)]","kind":"HOW","packages":["pkg:cargo/pin-project-lite@0.2.17"],"schemaVersion":1,"symbols":["pin_project_lite::pin_project","pin_project_lite::pin_project!"]},"contractCommand":["cargo","test","--offline"],"environment":{"arch":"x64","ecosystem":"cargo","executionContext":"rust","language":"rust","os":"linux","packageManager":"cargo","runtime":"rust","schemaVersion":1},"license":"MIT-0","packages":["pkg:cargo/pin-project-lite@0.2.17"],"schemaVersion":1,"symbols":["pin_project_lite::pin_project","pin_project_lite::pin_project!"],"verifierAdapter":"cargo@1"}
use std::marker::PhantomPinned;
use pin_project_lite::pin_project;
// 1. Struct where PhantomPinned has no #[pin] attribute.
// Naive belief: PhantomPinned makes the struct !Unpin automatically.
// Reality: pin_project! only bounds Unpin on fields marked #[pin], so this struct silently implements Unpin.
pin_project! {
pub struct PinnedIgnored {
pub value: i32,
pub unpinned_marker: PhantomPinned,
}
}
// 2. Struct where PhantomPinned is explicitly annotated with #[pin].
// Reality: pin_project! bounds Unpin on #[pin] fields: `where PhantomPinned: Unpin`, making it !Unpin.
pin_project! {
pub struct PinnedHonored {
pub value: i32,
#[pin]
pub pinned_marker: PhantomPinned,
}
}
// 3. Struct using #[project(!Unpin)] attribute (introduced in 0.2.11).
// Reality: completely suppresses Unpin generation regardless of field types.
pin_project! {
#[project(!Unpin)]
pub struct ExplicitNotUnpin {
pub value: i32,
}
}
// 4. Enum with unannotated PhantomPinned variant fields.
// Reality: Unpin is implemented if all #[pin] fields across variants are Unpin.
pin_project! {
#[project = StatusProj]
#[project_ref = StatusProjRef]
pub enum Status<T, U> {
Active {
#[pin]
pinned_val: T,
unpinned_marker: PhantomPinned,
},
Idle {
unpinned_val: U,
unpinned_marker: PhantomPinned,
},
}
}
// 5. Struct demonstrating project_replace moving unpinned fields while dropping pinned in place
pin_project! {
#[project_replace = ReplaceStructProjOwn]
pub struct ReplaceStruct {
#[pin]
pub pinned_data: String,
pub unpinned_count: u32,
}
}
// 6. Visibility test: pub struct generates pub(crate) projection type and methods
pub mod api {
use super::*;
pin_project! {
pub struct PublicApiStruct<T> {
#[pin]
pub pinned: T,
pub unpinned: u64,
}
}
}
pub fn is_unpin<T: Unpin>() -> bool {
true
}
#[cfg(test)]
mod tests {
use super::*;
use std::pin::Pin;
#[test]
fn test_unannotated_phantompinned_silently_implements_unpin() {
// Contract 1: PinnedIgnored silently implements Unpin despite containing PhantomPinned!
assert!(is_unpin::<PinnedIgnored>());
let mut instance = PinnedIgnored {
value: 42,
unpinned_marker: PhantomPinned,
};
// Pin::new is ONLY callable on Unpin types in safe Rust.
// Because pin_project! made PinnedIgnored implement Unpin, Pin::new succeeds in safe code,
// allowing safe in-place dereferencing and mutation via Pin::get_mut.
let mut pinned = Pin::new(&mut instance);
let inner = Pin::get_mut(pinned.as_mut());
inner.value = 84;
assert_eq!(instance.value, 84);
}
#[test]
fn test_annotated_phantompinned_and_project_not_unpin() {
// Contract 2: Types with #[pin] PhantomPinned or #[project(!Unpin)] require unsafe Pin::new_unchecked
let mut honored = PinnedHonored {
value: 10,
pinned_marker: PhantomPinned,
};
// SAFETY: honored is pinned on the stack and will not be moved before being dropped
let mut pinned_honored = unsafe { Pin::new_unchecked(&mut honored) };
let proj = pinned_honored.as_mut().project();
assert_eq!(*proj.value, 10);
let mut explicit = ExplicitNotUnpin { value: 20 };
// SAFETY: explicit is pinned on the stack and will not be moved before being dropped
let mut pinned_explicit = unsafe { Pin::new_unchecked(&mut explicit) };
let proj_explicit = pinned_explicit.as_mut().project();
assert_eq!(*proj_explicit.value, 20);
}
#[test]
fn test_enum_unannotated_phantompinned_implements_unpin() {
// Contract 3: Status<i32, String> implements Unpin because its #[pin] field (i32) is Unpin,
// despite both variants containing unannotated PhantomPinned fields.
assert!(is_unpin::<Status<i32, String>>());
let mut status: Status<i32, String> = Status::Active {
pinned_val: 10,
unpinned_marker: PhantomPinned,
};
// Safe Pin::new is possible because Status<i32, String> is Unpin
let mut pinned = Pin::new(&mut status);
match pinned.as_mut().project() {
StatusProj::Active { pinned_val, unpinned_marker: _ } => {
let inner_pinned: Pin<&mut i32> = pinned_val;
assert_eq!(*inner_pinned, 10);
}
StatusProj::Idle { .. } => unreachable!(),
}
}
#[test]
fn test_project_replace_moves_unpinned_fields() {
// Contract 4: project_replace moves out unpinned fields into ProjOwn and replaces self
let mut original = ReplaceStruct {
pinned_data: String::from("original"),
unpinned_count: 1,
};
let replacement = ReplaceStruct {
pinned_data: String::from("replacement"),
unpinned_count: 2,
};
// SAFETY: original is pinned on stack
let mut pinned = unsafe { Pin::new_unchecked(&mut original) };
let owned_unpinned = pinned.as_mut().project_replace(replacement);
// unpinned_count was moved out from the old value
assert_eq!(owned_unpinned.unpinned_count, 1);
// pinned self now contains replacement
assert_eq!(pinned.pinned_data, "replacement");
assert_eq!(pinned.unpinned_count, 2);
}
#[test]
fn test_projection_methods_and_visibility() {
// Contract 5: Projection types and methods for pub struct are accessible within the crate (pub(crate))
let mut api_struct = api::PublicApiStruct {
pinned: 123,
unpinned: 456,
};
let mut pinned = Pin::new(&mut api_struct);
let proj = pinned.as_mut().project();
let _: Pin<&mut i32> = proj.pinned;
let _: &mut u64 = proj.unpinned;
*proj.unpinned += 1;
assert_eq!(api_struct.unpinned, 457);
}
}