rust serde

rust - ¿Por qué no se implementa un rasgo para un tipo que claramente lo ha implementado?



serde (1)

El problema general es que el código tiene múltiples versiones de la caja, cada una de las cuales proporciona una versión diferente de los rasgos. El hecho de que Rust lo permita es algo bueno , pero los mensajes de error a su alrededor son confusos .

Su caja implementa Serialize desde la versión A pero la biblioteca está utilizando la versión B en una interfaz pública . Estos rasgos no son compatibles, por lo que cuando pasa su tipo de implementación de Serialize@A a la función que requiere Serialize@B , el compilador lo detiene.

Si bien su ejemplo trata sobre diferentes rasgos, también es posible que esto ocurra para los tipos que se han reexportado desde una caja.

El árbol de carga es muy útil para verificar que este sea su problema. Muestra todas sus dependencias y sus versiones. ¡Incluso tiene una bandera -d para mostrar dependencias duplicadas! Ese modo no se muestra aquí, pero es muy útil.

La solución general es restringir manualmente su versión de Serde en su Cargo.toml para que coincida con el resto de las dependencias:

serde = "0.9" serde_derive = "0.9" serde_json = "0.9"

Es posible que esto no siempre sea posible, en cuyo caso es posible que deba acosar a los propietarios de las cajas para actualizar sus dependencias.

Ejemplos trabajados

Cohete

[dependencies] chrono = "0.3.0" rocket = "0.2.8" rocket_codegen = "0.2.8" serde = "1.0.8" serde_derive = "1.0.8" serde_json = "1.0.2" mysql = "11.1.2" diesel = { version = "0.13.0", features = ["mysql","chrono"] } diesel_codegen = { version = "0.13.0", features = ["mysql"] } dotenv = "0.10.0" [dependencies.rocket_contrib] version = "*" default-features = false features = ["handlebars_templates"]

rocket_contrib 0.2.8 depende de Serde 0.9, pero ha sacado Serde 1.0. Este fragmento abreviado del cargo tree muestra el problema:

reproduction v0.1.0 (file:///private/tmp/reproduction) ├── rocket_contrib v0.2.8 │ ├── handlebars v0.25.3 │ │ └── serde_json v0.9.10 │ │ └── serde v0.9.15 │ ├── serde v0.9.15 (*) │ └── serde_json v0.9.10 (*) ├── serde v1.0.8 (*) ├── serde_derive v1.0.8 │ ├── serde_derive_internals v0.15.1 └── serde_json v1.0.2 (*)

La próxima versión 0.3 de Rocket debería permitir el uso de Serde 1.0.

Hierro / Bson / MongoDB

[dependencies] bodyparser = "0.5" bson = "0.8" iron = "0.5" jwt = "0.4" mongodb = "0.3" router = "0.5" rust-crypto = "0.2" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" time = "0.1"

bodyparser 0.5 depende de Serde 0.8, MongoDB ha sacado 0.9, pero la caja y BSON han sacado Serde 1.0. Este fragmento abreviado del cargo tree muestra el problema:

reproduction v0.1.0 (file:///private/tmp/reproduction) ├── bodyparser v0.5.0 │ ├── serde v0.8.23 │ └── serde_json v0.8.6 │ └── serde v0.8.23 (*) ├── bson v0.8.0 │ ├── serde v1.0.8 │ ├── serde_json v1.0.2 │ │ └── serde v1.0.8 (*) ├── mongodb v0.3.0 │ ├── textnonce v0.6.0 │ │ ├── serde v0.9.15 │ │ └── serde_derive v0.9.15 ├── serde v1.0.8 (*) ├── serde_derive v1.0.8 ├── serde_json v1.0.2 (*)

Bodyparser 0.7.0 debería ser compatible con Serde 1.0. El estado de textnonce es menos claro, pero esa dependencia podría ser privada , por lo que podría no importar en este caso.

Diesel / Chrono

chrono = "0.4.0" diesel = { version = "0.13.0", features = [ "chrono", "sqlite" ] } diesel_codegen = { version = "0.13.0", features = [ "sqlite" ] } dotenv = "0.9.0"

La versión actual de Chrono es 0.4.0, pero Diesel solo sabe cómo serializar Chrono 0.3.0.

reproduction v0.1.0 (file:///private/tmp/reproduction) ├── chrono v0.4.0 ├── diesel v0.13.0 │ ├── chrono v0.3.0

pez globo / rasgo de cifrado en bloque

[dependencies] blowfish = "0.2.1" block-cipher-trait = "0.3.0"

reproduction v0.1.0 (file:///private/tmp/reproduction) ├── block-cipher-trait v0.3.0 │── blowfish v0.2.1 ├── block-cipher-trait v0.2.0

conrod / piston2d-graphics

[dependencies] piston_window = "0.74.0" conrod = { version = "0.56.0", features = ["piston"] }

repro v0.1.0 (file:///private/tmp/repro) ├── conrod v0.56.0 │ ├── piston2d-graphics v0.23.0 └── piston_window v0.74.0 ├── piston2d-graphics v0.24.0 (*)

actix / futuros

[dependencies] actix-web = "0.6.10" futures = "0.2.1"

repro v0.1.0 (file:///private/tmp/repro) ├── actix-web v0.6.12 │ ├── actix v0.5.8 │ │ ├── futures v0.1.21 └── futures v0.2.1

¿Un futuro brillante?

RFC 1977 propone introducir la noción de dependencias públicas y privadas a Cargo. Si usa una caja que a su vez expone públicamente los tipos de otra caja, Cargo se aseguraría de que use una única versión unificada para la caja con los tipos comunes.

Estoy tratando de usar Diesel para consultar una base de datos MySQL y mostrar los resultados con una plantilla de Manillar con Rocket .

Tengo esto en models.rs

#[derive(Queryable, Serialize)] pub struct Post { pub id: i32, pub title: String, pub text: String, pub published: bool, }

cargo run genera esto:

--> src/main.rs:69:5 | 69 | Template::render("index", &results) | ^^^^^^^^^^^^^^^^ the trait `serde::ser::Serialize` is not implemented for `tasty::models::Post` | = note: required because of the requirements on the impl of `serde::ser::Serialize` for `std::vec::Vec<tasty::models::Post>` = note: required by `rocket_contrib::Template::render`

En mi Cargo.toml, tengo esto:

[dependencies] chrono = "0.3.0" rocket = "0.2.8" rocket_codegen = "0.2.8" serde = "1.0.8" serde_derive = "1.0.8" serde_json = "1.0.2" mysql = "11.1.2" diesel = { version = "0.13.0", features = ["mysql","chrono"] } diesel_codegen = { version = "0.13.0", features = ["mysql"] } dotenv = "0.10.0" [dependencies.rocket_contrib] version = "*" default-features = false features = ["handlebars_templates"]

He leído que Diesel no es compatible con Serialize en este momento, pero no estoy seguro.