2 votes

Puis-je empêcher la référence d'un type d'être créée ou utilisée?

Mon objectif principal est d'empêcher la référence d'un type défini par l'utilisateur d'être créée. Si c'est impossible, alors mon objectif secondaire est d'empêcher l'utilisation de cette référence.

J'ai une structure qui est supportée par une page de mémoire virtuelle. De temps en temps, cette page peut être remappée à une adresse différente, tandis que le contenu de la page reste inchangé. La remappage est effectué par le système d'exploitation, donc le code utilisateur n'est pas directement notifié quand cela se produit. Le système d'exploitation maintient un registre réservé qui pointe toujours vers la page remappable. Le code utilisateur doit suivre ce registre pour accéder à la structure. Il ne doit pas utiliser la référence (native Rust), car la référence devient obsolète après que le système d'exploitation remappe la page.

Par exemple, supposons que la struct remappable est définie comme Remappable. Des types de référence spéciaux, par exemple RefField1, sont définis pour chaque champ. volatile_deref() suivra le registre réservé pour lire le champ à la bonne adresse.

struct Remappable {
    f1: Field1,
    f2: Field2,
    /* ... */
}

impl Remappable {
    pub fn get_ref_f1(&self) -> RefField1 { /* ... */ }
    pub fn get_ref_f2(&self) -> RefField2 { /* ... */ }
}

impl RefField1 {
    pub fn volatile_deref(&self) -> Field1 {
        /* Apparemment une certaine assemblée en ligne tenant en compte l'atomicité (par rapport à l'adresse de la page remappable) de la lecture.
           Sur x86, cela peut être accompli à travers
           l'usage des registres de segment. */
    }
}

Je n'ai aucune idée de comment atteindre mon objectif principal, c'est-à-dire empêcher &Remappable d'être créé.

J'ai essayé naïvement d'atteindre mon objectif secondaire. J'ai fait ce qui suit, mais cela n'a pas fonctionné non plus.

use std::ops::Deref;

impl Deref for &Remappable {
    type Target = ();
    fn deref(&self) -> &Self::Target {
        panic!()
    }
}

C'est parce que cela donne une implémentation en conflit de Deref.

error[E0119]: implémentations en conflit du trait `std::ops::Deref` pour le type `&Remappable`
 --> src/main.rs:7:1
  |
7 | impl Deref for &Remappable {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: implémentation en conflit dans la crate `core` :
          - impl Deref for &T
            où T: ?Sized;

Y a-t-il un moyen d'atteindre un des objectifs ?

3voto

Kevin Reid Points 8806

Vous ne pouvez pas empêcher l'existence de références à un type. Au lieu de cela, afin de rendre ce que vous décrivez lisible pour le compilateur Rust, vous devez rendre le conteneur de ce type spécial. C'est-à-dire, étant donné que

le système d'exploitation maintient un registre réservé qui pointe toujours vers la page remappable

vous devriez avoir un type de données qui représente ce registre réservé (tout comme, par exemple, Box représente une allocation de mémoire sur le tas qu'il gère). Ce type de données est celui qui évite de mettre en œuvre Deref.

Pour illustration, une situation similaire apparaît avec le type Cell dans la bibliothèque standard de Rust — comme il offre une mutabilité interne, il ne peut pas renvoyer en toute sécurité des références à son contenu, donc chaque opération sur une Cell (sauf celles qui savent qu'elles ont un accès exclusif, ce qui ne s'applique pas à votre situation) doit copier les données dedans ou dehors plutôt que de renvoyer des références.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X