Que signifie “la Taille n'est pas mis en œuvre”?
J'ai écrit le code suivant:
use std::io::{IoResult, Writer};
use std::io::stdio;
fn main() {
let h = |&: w: &mut Writer| -> IoResult<()> {
writeln!(w, "foo")
};
let _ = h.handle(&mut stdio::stdout());
}
trait Handler<W> where W: Writer {
fn handle(&self, &mut W) -> IoResult<()>;
}
impl<W, F> Handler<W> for F
where W: Writer, F: Fn(&mut W) -> IoResult<()> {
fn handle(&self, w: &mut W) -> IoResult<()> { (*self)(w) }
}
Et puis rustc
dans mon terminal:
$ rustc writer_handler.rs
writer_handler.rs:8:15: 8:43 error: the trait `core::marker::Sized` is not implemented for the type `std::io::Writer`
writer_handler.rs:8 let _ = h.handle(&mut stdio::stdout());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
writer_handler.rs:8:15: 8:43 error: the trait `core::marker::Sized` is not implemented for the type `std::io::Writer`
writer_handler.rs:8 let _ = h.handle(&mut stdio::stdout());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
Pourquoi est-ce Writer
nécessaires pour mettre en œuvre Sized
? Il me semble que le Sized
n'est pas nécessaire. Ce que je dois faire tout en gardant trait Handler
avoir cet argument générique?
À Rust 1.0, ce code semblable produit le même problème:
use std::io::{self, Write};
fn main() {
handle(&mut io::stdout());
}
fn handle(w: &mut Write) -> io::Result<()> {
handler(w)
}
fn handler<W>(w: &mut W) -> io::Result<()>
where
W: Write,
{
writeln!(w, "foo")
}
Avec l'erreur:
error[E0277]: the trait bound `std::io::Write: std::marker::Sized` is not satisfied
--> src/main.rs:8:5
|
8 | handler(w)
| ^^^^^^^ `std::io::Write` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `std::io::Write`
= note: required by `handler`
OriginalL'auteur k-ui | 2015-01-20
Vous devez vous connecter pour publier un commentaire.
La
Sized
trait est plutôt spécial, si spécial, que c'est un défaut lié sur les paramètres de type dans la plupart des situations. Il représente des valeurs qui ont une taille fixe connue au moment de la compilation, commeu8
(1 octet) ou&u32
(8 octets sur une plate-forme avec des pointeurs 64-bit), etc. Ces valeurs sont flexibles: ils peuvent être placés sur la pile et le déplacement sur le tas, et généralement passés par valeur, comme le compilateur sait de combien d'espace il doit partout où il passe.Types qui ne sont pas de taille sont beaucoup plus restreinte, et une valeur de type
Writer
n'est pas de taille: il représente, de façon abstraite, certains non spécifié type qui implémenteWriter
, avec aucune connaissance de ce que le type réel est. Depuis le type réel n'est pas connu, la taille ne peut pas être connu: certains grands types sontWriter
s, quelques petits types.Writer
est un exemple d'une caractéristique de l'objet, qui à l'heure actuelle, ne peut figurer dans le code exécuté derrière un pointeur. Des exemples communs incluent&Writer
,&mut Writer
, ouBox<Writer>
.C'est ce qui explique pourquoi
Sized
est la valeur par défaut: c'est souvent ce que l'on veut.En tout cas, pour ton code, c'est popping up parce que vous êtes à l'aide de
handle
avech
, qui est unFn(&mut Writer) -> IoResult<()>
. Si nous avons ce match contre leF: Fn(&mut W) -> IoResult<()>
type deHandle
est mis en œuvre pour nous trouver queW = Writer
, qui est, nous essayons d'utiliserhandle
avec le trait de l'objet&mut Writer
, pas un&mut W
pour certains type de bétonW
. C'est illégal parce que laW
paramètres à la fois le caractère et l'impl sont en défaut d'avoir unSized
lié, si nous remplacer manuellement avec?Sized
alors tout fonctionne bien:Et pour la Rouille 1.0 code:
J'ai aussi écrit un blog post sur
Taille
et trait des objets en général, qui a un peu plus de détails.Sized
pour une mise en œuvre parce que la rouille runtime besoin de savoir combien d'octets qu'il prend sur la pile d'appel. Donc, je vais éviter inconnue de taille types à l'aide du pointeur, dans ce cas&mut
... je ne comprends pas où sontSized
nécessaire dans mon code encore.Il n'est pas , comme le deuxième ensemble de code de travail démontre, c'est juste une question de valeurs par défaut: le compilateur est en défaut de mettre un
Sized
lié à ce paramètre de type, parce que c'est ce que le compilateur est défini à faire pour presque tous les paramètres de type.Oh. Je l'ai eu! Je suis désolé que je n'ai pas pleinement comprendre votre réponse: "l'impl sont en défaut d'avoir un
Sized
lié". Merci encore, dbaupp!OriginalL'auteur huon
Tout d'abord, notez que
h
est d'un type qui implémenteFn(&mut Writer) -> IoResult<()>
.h.handle
est appelé; cela dépend, ensuite, sur laHandler
de mise en œuvre oùW
estWriter
—note soigneusement: W estWriter
, sans apprêt type. Le&mut stdio::stdout()
va donc être exprimées à l'&mut Writer
trait de l'objet. Tout cela est très bien en théorie, mais quand ramené à la mise en œuvre tombe. Quand il s'agit de contraintes, ils sont à la taille par défaut, et il se plaint queWriter
, la valeur que vous essayez d'assigner pourW
, n'est pas de taille.Il existe deux solutions principales ici:
Passer à l'utilisation du béton type de l'écrivain sur
h
de sorte que vous avez à traiter avec une taille moyenne de type:Permis
W
être un sans apprêt type. Ce qui est acceptable comme vous ne l'utilisez à travers une référence&mut W
. Si vous souhaitez l'utiliser comme un nu-type, par exemple une méthode de prise deW
par valeur, il ne le ferait pas.Je recommande de soutenir un sans apprêt
W
même si vous ne les utiliser que dans ce cas il n'y a aucune raison qu'il besoins être de taille moyenne.OriginalL'auteur Chris Morgan