Tipe apa yang valid untuk parameter `self` suatu metode?

Saya ingin membuat metode yang hanya berfungsi jika parameter self adalah Rc. Saya melihat bahwa saya dapat menggunakan Box, jadi saya pikir saya mungkin mencoba meniru cara kerjanya:

use std::rc::Rc;
use std::sync::Arc;

struct Bar;

impl Bar {
    fn consuming(self) {}
    fn reference(&self) {}
    fn mutable_reference(&mut self) {}
    fn boxed(self: Box<Bar>) {}
    fn ref_count(self: Rc<Bar>) {}
    fn atomic_ref_count(self: Arc<Bar>) {}
}

fn main() {}

Menghasilkan kesalahan ini:

error[E0308]: mismatched method receiver
  --> a.rs:11:18
   |
11 |     fn ref_count(self: Rc<Bar>) {}
   |                  ^^^^ expected struct `Bar`, found struct `std::rc::Rc`
   |
   = note: expected type `Bar`
   = note:    found type `std::rc::Rc<Bar>`

error[E0308]: mismatched method receiver
  --> a.rs:12:25
   |
12 |     fn atomic_ref_count(self: Arc<Bar>) {}
   |                         ^^^^ expected struct `Bar`, found struct `std::sync::Arc`
   |
   = note: expected type `Bar`
   = note:    found type `std::sync::Arc<Bar>`

Ini dengan Rust 1.15.1.


person Shepmaster    schedule 23.08.2014    source sumber


Jawaban (2)


Sebelum Rust 1.33, hanya ada empat penerima metode yang valid:

struct Foo;

impl Foo {
    fn by_val(self: Foo) {} // a.k.a. by_val(self)
    fn by_ref(self: &Foo) {} // a.k.a. by_ref(&self)
    fn by_mut_ref(self: &mut Foo) {} // a.k.a. by_mut_ref(&mut self)
    fn by_box(self: Box<Foo>) {} // no short form
}

fn main() {}

Awalnya, Rust tidak memiliki bentuk self eksplisit ini, hanya self, &self, &mut self dan ~self (nama lama Box). Hal ini diubah sehingga hanya nilai-nilai dan referensi-sampingan yang memiliki sintaks bawaan singkat, karena keduanya merupakan kasus umum, dan memiliki properti bahasa yang sangat penting, sementara semua penunjuk cerdas (termasuk Box) memerlukan bentuk eksplisit.

Mulai Rust 1.33, beberapa jenis tambahan yang dipilih tersedia untuk digunakan sebagai self:

  • Rc
  • Arc
  • Pin

Ini berarti contoh aslinya sekarang berfungsi:

use std::{rc::Rc, sync::Arc};

struct Bar;

impl Bar {
    fn consuming(self)                  { println!("self") }
    fn reference(&self)                 { println!("&self") }
    fn mut_reference(&mut self)         { println!("&mut self") }
    fn boxed(self: Box<Bar>)            { println!("Box") }
    fn ref_count(self: Rc<Bar>)         { println!("Rc") }
    fn atomic_ref_count(self: Arc<Bar>) { println!("Arc") }
}

fn main() {
    Bar.consuming();
    Bar.reference();
    Bar.mut_reference();
    Box::new(Bar).boxed();
    Rc::new(Bar).ref_count();
    Arc::new(Bar).atomic_ref_count();
}

Namun, penanganan impl belum sepenuhnya digeneralisasikan agar sesuai dengan sintaksisnya, sehingga tipe yang dibuat pengguna masih tidak berfungsi. Kemajuan dalam hal ini sedang dilakukan di bawah tanda fitur arbitrary_self_types dan diskusi sedang berlangsung di masalah pelacakan 44874.

(Sesuatu yang dinanti-nantikan!)

person huon    schedule 23.08.2014
comment
Jadi saya bisa berharap bahwa jenis perpustakaan lain selain Box akan didukung di masa mendatang? - person Shepmaster; 23.08.2014
comment
Ya, mendukung tipe pointer lain adalah motivasi utama untuk perubahan sintaksis. - person huon; 23.08.2014
comment
Kembali ke sini beberapa bulan kemudian; adakah perubahan yang Anda ketahui di area ini? Kode apa adanya gagal dikompilasi, jadi belum ada yang jelas. - person Shepmaster; 30.03.2016
comment
@Shepmaster lihat jawaban saya di bawah. - person jbg; 08.08.2018

Sekarang dimungkinkan untuk menggunakan tipe arbitrer untuk self, termasuk Arc<Self>, namun fitur tersebut dianggap tidak stabil sehingga memerlukan penambahan atribut peti:

#![feature(arbitrary_self_types)]

Penggunaan atribut peti feature memerlukan penggunaan Nightly Rust.

person jbg    schedule 08.08.2018
comment
Saya akan menambahkan bahwa terlepas dari namanya, tipe mandiri yang sewenang-wenang tidak sepenuhnya sewenang-wenang, tetapi harus (secara transitif) deref ke Self. Jadi self: Arc<Self> dan self: &Arc<Self> baik-baik saja, tetapi self: Vec<Self> tidak. (Tentu saja detailnya dapat berubah sebelum stabilisasi.) - person trentcl; 08.08.2018
comment
Jawaban ini sudah ketinggalan jaman sekarang. - person mcarton; 12.05.2020