Komunitas pemrograman Rust sedang aktif membahas keterbatasan yang sudah lama ada dalam derive macro bahasa tersebut, khususnya terkait trait Clone
. Perdebatan ini berpusat pada apakah pendekatan Rust saat ini pada dasarnya cacat atau hanya merupakan trade-off yang wajar yang telah dipelajari pengembang untuk diatasi.
Masalah Inti dengan Perilaku Derive Saat Ini
Ketika Anda menggunakan #[derive(Clone)]
di Rust, compiler mengharuskan semua parameter generik untuk mengimplementasikan Clone
, bahkan ketika parameter tersebut mungkin tidak benar-benar perlu di-clone. Hal ini menciptakan pembatasan yang tidak perlu yang mencegah kode dari kompilasi dalam kasus di mana secara logis seharusnya berfungsi. Sebagai contoh, wrapper di sekitar Arc<T>
tidak dapat derive Clone
meskipun Arc<T>
itu sendiri dapat di-clone terlepas dari apakah T
mengimplementasikan Clone
.
Komunitas telah mengidentifikasi ini sebagai masalah yang luas yang tidak hanya mempengaruhi Clone
, tetapi juga trait lain yang dapat diturunkan seperti PartialEq
, Eq
, dan Debug
. Hal ini memaksa pengembang untuk menulis implementasi manual untuk apa yang seharusnya menjadi derivasi otomatis yang mudah.
Perilaku Derive Saat Ini vs Derive Sempurna
Aspek | Derive Saat Ini | Derive Sempurna |
---|---|---|
Batasan generik | Memerlukan semua parameter generik untuk mengimplementasikan trait | Hanya memerlukan tipe field untuk mengimplementasikan trait |
Contoh constraint | T: Clone untuk struct Wrapper<T>(Arc<T>) |
Arc<T>: Clone untuk struct Wrapper<T>(Arc<T>) |
Dampak Semver | Stabil - batasan tidak berubah dengan modifikasi field | Berpotensi merusak - batasan berubah dengan perubahan field privat |
Kompleksitas implementasi | Sederhana, dapat diprediksi | Memerlukan dukungan pencocokan trait siklis |
Tantangan Teknis di Balik Layar
Diskusi mengungkapkan bahwa ini bukan hanya kelalaian yang dapat diperbaiki dengan cepat. Menurut wawasan yang dibagikan dalam komunitas, mengimplementasikan perfect derive akan memerlukan perubahan signifikan pada sistem trait matching Rust. Compiler perlu menangani trait matching siklis, yang saat ini hanya berfungsi untuk auto trait seperti Send
.
Ada juga kekhawatiran kompatibilitas semver. Dengan perfect derive, mengubah tipe field private dapat merusak kode downstream dengan cara yang tidak terduga. Jika library berubah dari menyimpan Arc<T>
menjadi menyimpan T
secara langsung, trait bound akan berubah secara otomatis, berpotensi menyebabkan kegagalan kompilasi bagi pengguna library tersebut.
Perspektif Komunitas tentang Solusi
Komunitas Rust terbagi dalam cara mengatasi keterbatasan ini. Beberapa pengembang berargumen untuk mempertahankan sistem saat ini yang sederhana dan dapat diprediksi, memandang implementasi trait manual sebagai biaya yang dapat diterima untuk kejelasan. Yang lain mendorong solusi yang lebih canggih yang akan menganalisis persyaratan field aktual daripada batasan parameter generik menyeluruh.
Perangkat lunak yang elegan diukur dari jumlah baris kode yang tidak perlu Anda tulis.
Beberapa anggota komunitas telah menunjuk ke crate yang ada seperti derive_more
, derivative
, dan educe
sebagai solusi praktis. Solusi pihak ketiga ini sudah mengimplementasikan perilaku derive yang lebih cerdas, meskipun mereka menambahkan overhead dependensi ke proyek.
Solusi Alternatif yang Tersedia
- Crate derive_more: Fungsionalitas derive yang diperluas dengan bounds yang lebih fleksibel
- Crate derivative: Memungkinkan kontrol yang detail terhadap perilaku derive dengan atribut
- Crate educe: Menyediakan implementasi derive yang dapat disesuaikan
- Implementasi manual: Menulis implementasi trait secara manual ketika derive tidak mencukupi
- Proc macro kustom: Membuat macro derive khusus proyek dengan perilaku yang diinginkan
Jalan ke Depan
Sementara beberapa menyarankan ini dapat diatasi melalui RFC dan perubahan bahasa akhirnya, timeline untuk modifikasi semacam itu kemungkinan akan berlangsung beberapa tahun karena sifat perubahan yang merusak. Diskusi komunitas menyoroti ketegangan antara stabilitas bahasa dan kenyamanan pengembang.
Untuk saat ini, pengembang terus mengandalkan implementasi manual atau crate pihak ketiga ketika mereka menghadapi keterbatasan ini. Perdebatan ini menggarisbawahi bagaimana bahkan fitur bahasa yang tampaknya sederhana dapat melibatkan trade-off desain yang kompleks yang mempengaruhi baik kegunaan saat ini maupun evolusi bahasa jangka panjang.
Referensi: Why not?