CodeSampleX

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

  1. 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
  2. assert annotating a PhantomPinned field with #[pin] or applying #[project(!Unpin)] disables automatic Unpin implementation and requires unsafe Pin::new_unchecked construction
  3. assert a pin_project enum with unannotated PhantomPinned variant fields implements Unpin as long as its #[pin] variant fields implement Unpin
  4. assert project_replace moves out unpinned fields into ProjOwn while replacing the pinned struct and dropping pinned fields in-place
  5. 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

Télécharger l’artefact source (tar.gz)

Code source

Cargo.lock
# 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",
]
Cargo.toml
[package]
name = "pin-project-lite-test"
version = "0.1.0"
edition = "2021"

[dependencies]
pin-project-lite = "0.2.17"
NOTES.md
# 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.
csx.json
{"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"}
src/lib.rs
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);
    }
}

Seeder d'origine

csx-seed