1 poin oleh GN⁺ 2024-07-22 | 1 komentar | Bagikan ke WhatsApp

Pin

  • Tipe Pin dan konsep pinning adalah komponen dasar dalam ekosistem async Rust
  • Namun, Pin adalah salah satu elemen yang sulit dipahami dan mudah disalahartikan
  • Artikel ini menjelaskan apa yang ingin dicapai Pin, bagaimana konsep ini muncul, dan apa masalah Pin saat ini

Requirements

  • Untuk mendukung referensi di fungsi async, perlu menyimpan referensi di dalam Future
  • Masalahnya, referensi tersebut bisa berupa referensi self-referential
  • Contoh kode:
    async fn foo<'a>(z: &'a mut i32) { ... }
    async fn bar(x: i32, y: i32) -> i32 {
        let mut z = x + y;
        foo(&mut z).await;
        z
    }
    
  • Status internal Bar adalah sebagai berikut:
    enum Bar {
        Start { x: i32, y: i32 },
        FirstAwait { z: i32, foo: Foo<'?> },
        Complete,
    }
    
  • Tujuan Pin adalah memanipulasi tipe self-referential dengan aman

Non-solutions: move constructors and offset pointers

  • Konstruktor pemindahan dan offset pointer tidak bekerja di Rust
  • Konstruktor pemindahan memperbaiki pointer saat pemindahan terjadi, tetapi hal ini tidak mungkin di Rust
  • Offset pointer tidak bekerja karena saat kompilasi tidak diketahui apakah suatu referensi bersifat self-referential atau tidak

The “pinned typestate”

  • Objek tidak selalu tidak bisa dipindahkan, tetapi harus menjadi tidak bisa dipindahkan mulai dari titik tertentu
  • Dalam model Ralf Jung, objek berpindah dari status "dimiliki" ke status "dibagikan", lalu ke status "terpin"
  • Setelah masuk ke status terpin, objek tidak lagi bisa dipindahkan

?Move

  • Sebelum Pin, pernah dicoba solusi berbasis trait baru bernama Move
  • Tipe yang tidak mengimplementasikan Move akan berpindah ke status terpin saat diambil referensinya
  • Namun, Move tidak menyediakan kompatibilitas mundur

Pin

  • Pin merancang jenis referensi baru yang membuat objek masuk ke status terpin
  • Pin diimplementasikan sebagai API library sehingga kompatibilitas mundur tetap terjaga
  • Trait otomatis Unpin ditambahkan agar sebagian besar tipe tidak perlu membedakan status terpin dan status biasa

The problems with Pin

  • Pin memiliki berbagai masalah dari sisi usability
  • Pin diimplementasikan sebagai tipe library sehingga banyak kemampuan yang dimiliki tipe referensi biasa hilang
  • Misalnya, &mut T tidak mengimplementasikan Copy, tetapi tetap bisa diberikan sebagai argumen beberapa kali
  • Pin tidak menyediakan kemudahan seperti ini
  • Banyak kebingungan muncul saat menggunakan Pin

In my next post…

  • Pin memungkinkan referensi arbitrer di fungsi async dikompilasi dengan aman
  • Namun, Pin menambah kompleksitas, dan artikel berikutnya akan membahas cara memperbaikinya

Ringkasan GN⁺

  • Pin adalah komponen penting dalam ekosistem async Rust
  • Masalah usability pada Pin berasal dari implementasinya sebagai tipe library
  • Cara untuk memperbaiki Pin akan dibahas di artikel berikutnya
  • Proyek dengan fungsi serupa antara lain pin-project-lite

1 komentar

 
GN⁺ 2024-07-22
Komentar Hacker News
  • Alasan Pin sulit dipahami adalah karena dokumentasi resminya tidak menjelaskannya dengan jelas

    • Dokumentasi menyatakan bahwa "Pin menjamin objek tidak akan pernah dipindahkan", tetapi ini sebenarnya tidak benar
    • Sebagian besar objek biasa adalah Unpin, jadi Pin biasanya tidak berperan apa-apa
    • Himpunan tipe T tempat Pin benar-benar bekerja sangat khusus dan hal ini tidak cukup ditekankan dalam dokumentasi
  • Pin sulit karena pada dirinya sendiri tidak punya makna

    • Dalam kasus Pin, bahasa maupun standard library tidak memberi tahu apa yang bisa dan tidak bisa dilakukan Pin
    • Sebaliknya, penyedia InnerType membuat metode dan API tambahan (yang secara internal tidak aman) agar objek yang di-pin bisa dimanipulasi
    • Satu-satunya tujuan Pin sendiri adalah menyediakan pointer dengan lebih sedikit "fungsi bawaan"
  • Kata "rust" seharusnya ditambahkan ke judul agar pembaca tahu artikel ini membahas apa

  • Istilah "value identity" tidak didefinisikan di mana pun dalam dokumentasi Mojo

    • Direkomendasikan ceramah Dave Abrahams "Value Semantics: Safety, Independence, Projection, & Future of Programming"
  • Pin adalah contoh bagus dari nama yang akurat secara teknis tetapi sulit dipahami

    • "Drop" punya makna yang lebih familier, tetapi "pinning" tidak demikian
    • immovable!(…) mungkin lebih baik, tetapi sulit memikirkan nama yang lebih bagus
    • Nama yang lebih deskriptif seperti prevent_moving!(…) dan trait PreventMove mungkin lebih baik
  • Dalam bahasa yang mirip Rust, jika ada move-constructors, kebutuhan akan Pin bisa hilang

    • Karena pengguna tidak akan punya cara untuk menghancurkan objek, maka juga tidak akan punya cara untuk memindahkannya
  • Objek bisa dipindahkan lewat referensi &mut menggunakan mem::swap/replace, tetapi kasus yang benar-benar membutuhkannya jarang

    • Akan bagus jika ada cara untuk memilih referensi-pindah
    • Menjadikan swap dan replace tidak aman mungkin bisa menyelesaikan masalah ini
  • WithoutBoats sedang melakukan diskusi aktif tentang topik iterator asinkron, poll, dan pin

    • Hampir tidak ada komunitas yang secara terbuka membahas detail bahasa sedalam ini, dan sangat menarik untuk mengikutinya
  • Pinning/!Move berguna untuk banyak hal selain async/await

    • Tetapi karena Rust tidak menanganinya dengan baik, jawaban yang biasa diberikan adalah "tulis ulang programnya dalam bahasa lain"