Sto tentando di scrivere binding Rust per una libreria di raccolta C (Judy Arrays [1]) che fornisce solo spazio per memorizzare un valore di larghezza del puntatore. La mia azienda ha una discreta quantità di codice esistente che utilizza questo spazio per memorizzare direttamente valori non puntatore come interi di larghezza del puntatore e piccole strutture. Mi piacerebbe che i miei binding Rust consentissero l'accesso sicuro al tipo a tali raccolte utilizzando i generici, ma sto avendo problemi a far funzionare correttamente la semantica del puntatore.Generici di puntatori tramite `mem :: transmute()`
La funzione mem::transmute()
sembra uno strumento potenziale per implementare il comportamento desiderato, ma il tentativo di utilizzarlo su un'istanza di un tipo parametrizzato genera un errore di compilazione confuso.
Esempio:
pub struct Example<T> {
v: usize,
t: PhantomData<T>,
}
impl<T> Example<T> {
pub fn new() -> Example<T> {
Example { v: 0, t: PhantomData }
}
pub fn insert(&mut self, val: T) {
unsafe {
self.v = mem::transmute(val);
}
}
}
errore risultante:
src/lib.rs:95:22: 95:36 error: cannot transmute to or from a type that contains type parameters in its interior [E0139]
src/lib.rs:95 self.v = mem::transmute(val);
^~~~~~~~~~~~~~
Significa questo tipo costituito solo di un parametro "contiene parametri di tipo al suo interno" e quindi transmute()
semplicemente non funzionerà Qui? Qualche suggerimento sul modo giusto di farlo?
(Related question, nel tentativo di ottenere lo stesso risultato, ma non necessariamente via mem::transmute()
.)
[1] Sono a conoscenza del progetto esistente rust-judy
, ma non supporta il puntatore-stashing voglio e sto scrivendo questi nuovi attacchi in gran parte come un esercizio di apprendimento comunque.
Modificato alla prima domanda; creerà nuovo e link per il secondo. – llasram
Una domanda interessante! È quasi come se si volesse scrivere "dove sizeof (T) == sizeof (usize)". – Shepmaster
@Shepmaster: Questo sarebbe complicato, perché il collegamento tra la clausola 'where' e' transmute' sarebbe leggermente difficile da stabilire (specialmente se è possibile utilizzare vincoli più generali, come con '<=' and '> ='). D'altra parte, mi ha ricordato: [RFC: Coercible e HasPrefix per Zero Cost Conversions] (https://github.com/rust-lang/rfcs/issues/270); il vincolo potrebbe essere applicabile per un 'Transmable dove mem :: size_of :: () == mem :: size_of :: ()' e quindi 'transmute' da' T' a 'usize' richiederebbe' T: Transmutable '=> perfettamente decidibile. –