Aggiornamento per ruggine 1,0
A Rust 1.0 e successivamente il codice nell'esempio (quando uint
s sono sostituiti con un certo tipo esistente) non riesce con un altro errore:
% rustc test.rs
test.rs:23:9: 23:13 error: the trait `core::marker::Sync` is not implemented for the type `core::cell::UnsafeCell<usize>` [E0277]
test.rs:23 func(&r7)
^~~~
test.rs:23:9: 23:13 help: run `rustc --explain E0277` to see a detailed explanation
test.rs:23:9: 23:13 note: `core::cell::UnsafeCell<usize>` cannot be shared between threads safely
test.rs:23:9: 23:13 note: required because it appears within the type `core::cell::Cell<usize>`
test.rs:23:9: 23:13 note: required because it appears within the type `core::cell::BorrowRef<'_>`
test.rs:23:9: 23:13 note: required because it appears within the type `core::cell::Ref<'_, i32>`
test.rs:23:9: 23:13 note: required by `func`
Questo è un pò difficile - un altro tratto, Sync
, è apparso dal nulla.
Un tipo che implementa il tratto Send
(sebbene la sua documentazione sia certamente carente fin d'ora) è qualcosa che può essere trasferito oltre i limiti delle attività. La maggior parte dei tipi sono Send
, ma alcuni, come Rc
e Weak
, non sono Send
poiché le istanze di tali tipi potrebbero condividere lo stato mutabile non sincronizzato e pertanto non sono sicuri da utilizzare da più thread.
Nelle versioni precedenti di Ruggine Send
implicite 'static
, quindi i riferimenti non erano Send
. Da Rust 1.0, tuttavia, Send
non implica più 'static
, pertanto i riferimenti possono essere inviati attraverso i thread. Tuttavia, al fine di &T
essere Send
, T
deve essere Sync
: questo è richiesto dal seguente implementazione:
impl<'a, T> Send for &'a T where T: Sync + ?Sized
Ma nel nostro caso non stiamo richiedendo che &T
è Send
, abbiamo solo bisogno che T
è Send
, quindi non dovrebbe davvero importare, giusto?
No. In effetti, ci sono ancora riferimenti, anche noi non li vediamo subito. Ricorda che, per un tipo che deve essere Send
, ogni componente deve essere Send
, ovvero, ogni campo di una struttura e ogni parte di ogni variante enum di un enum deve essere Send
per questa struttura/enum da Send
. core::cell::Ref
internamente contains un'istanza di struct BorrowRef
, che a sua volta contains un riferimento a Cell<BorrowFlag>
. Ed ecco dove Sync
proviene da: in ordine o &Cell<BorrowFlag>
per essere Send
, Cell<BorrowFlag>
deve essere Sync
; tuttavia, non è e non può essere Sync
perché fornisce una mutabilità interna non sincronizzata. Questa è la vera causa dell'errore.
Ottima risposta, grazie, ora capisco! – user3762625