为什么没有为明确实现的类型实现特征?
Why is a trait not implemented for a type that clearly has it implemented?
我正在尝试使用 Diesel to query a MySQL database and display the results with a Handlebars template with Rocket。
我在models.rs
中有这个
#[derive(Queryable, Serialize)]
pub struct Post {
pub id: i32,
pub title: String,
pub text: String,
pub published: bool,
}
cargo run
输出:
--> 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`
在我的 Cargo.toml 中,我有这个:
[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"]
我听说 Diesel 目前不支持 Serialize
,但我不确定。
普遍的问题是代码有多个版本的 crate,每个版本提供不同版本的 traits。事实上,Rust 允许这样做是一件 好事 ,but the error messages around it are confusing。
您的 crate 实现了版本 A 的 Serialize
,但库在 public 接口 中使用版本 B 。这些特征不兼容,因此当您将实现 Serialize@A
的类型传递给需要 Serialize@B
的函数时,编译器会阻止您。
虽然您的示例是关于不同特征的,但对于从箱子中重新导出的类型,也可能发生这种情况。
cargo tree
,从 Rust 1.44 开始可用,对于验证这是您的问题非常有用。它显示了您的所有依赖项及其版本。它甚至有一个 -d
标志来显示重复的依赖关系!该模式未在此处显示,但非常有用。
一般的解决方案是在 Cargo.toml 中手动限制您的 Serde 版本以匹配其余的依赖项:
serde = "0.9"
serde_derive = "0.9"
serde_json = "0.9"
这可能并不总是可行的,在这种情况下,您可能需要寻找 crate 所有者来升级他们的依赖项。
工作示例
火箭
[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 依赖于 Serde 0.9,但是你引入了 Serde 1.0。 cargo tree
中的这个删节片段显示了问题:
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 (*)
Rocket 的 upcoming version 0.3 应该允许使用 Serde 1.0。
铁/布森/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 依赖于 Serde 0.8,MongoDB 引入了 0.9,但是 crate 和 BSON 引入了 Serde 1.0。 cargo tree
中的这个删节片段显示了问题:
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 should support Serde 1.0. The state of textnonce 不太清楚,但该依赖项可能是 private 依赖项,因此在这种情况下可能无关紧要。
柴油/计时
chrono = "0.4.0"
diesel = { version = "0.13.0", features = [ "chrono", "sqlite" ] }
diesel_codegen = { version = "0.13.0", features = [ "sqlite" ] }
dotenv = "0.9.0"
当前的Chrono版本是0.4.0,但是Diesel只知道如何序列化Chrono 0.3.0。
reproduction v0.1.0 (file:///private/tmp/reproduction)
├── chrono v0.4.0
├── diesel v0.13.0
│ ├── chrono v0.3.0
河豚/块密码特征
[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
连杆/活塞2d图形
[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/期货
[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
光明的未来?
RFC 1977 提议向 Cargo 引入 public 和 private 依赖的概念。如果您使用的 crate 反过来 publicly 公开另一个 crate 的类型,Cargo 将确保您对具有通用类型的 crate 使用单一统一版本。
我正在尝试使用 Diesel to query a MySQL database and display the results with a Handlebars template with Rocket。
我在models.rs
中有这个#[derive(Queryable, Serialize)]
pub struct Post {
pub id: i32,
pub title: String,
pub text: String,
pub published: bool,
}
cargo run
输出:
--> 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`
在我的 Cargo.toml 中,我有这个:
[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"]
我听说 Diesel 目前不支持 Serialize
,但我不确定。
普遍的问题是代码有多个版本的 crate,每个版本提供不同版本的 traits。事实上,Rust 允许这样做是一件 好事 ,but the error messages around it are confusing。
您的 crate 实现了版本 A 的 Serialize
,但库在 public 接口 中使用版本 B 。这些特征不兼容,因此当您将实现 Serialize@A
的类型传递给需要 Serialize@B
的函数时,编译器会阻止您。
虽然您的示例是关于不同特征的,但对于从箱子中重新导出的类型,也可能发生这种情况。
cargo tree
,从 Rust 1.44 开始可用,对于验证这是您的问题非常有用。它显示了您的所有依赖项及其版本。它甚至有一个 -d
标志来显示重复的依赖关系!该模式未在此处显示,但非常有用。
一般的解决方案是在 Cargo.toml 中手动限制您的 Serde 版本以匹配其余的依赖项:
serde = "0.9"
serde_derive = "0.9"
serde_json = "0.9"
这可能并不总是可行的,在这种情况下,您可能需要寻找 crate 所有者来升级他们的依赖项。
工作示例
火箭
[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 依赖于 Serde 0.9,但是你引入了 Serde 1.0。 cargo tree
中的这个删节片段显示了问题:
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 (*)
Rocket 的 upcoming version 0.3 应该允许使用 Serde 1.0。
铁/布森/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 依赖于 Serde 0.8,MongoDB 引入了 0.9,但是 crate 和 BSON 引入了 Serde 1.0。 cargo tree
中的这个删节片段显示了问题:
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 should support Serde 1.0. The state of textnonce 不太清楚,但该依赖项可能是 private 依赖项,因此在这种情况下可能无关紧要。
柴油/计时
chrono = "0.4.0"
diesel = { version = "0.13.0", features = [ "chrono", "sqlite" ] }
diesel_codegen = { version = "0.13.0", features = [ "sqlite" ] }
dotenv = "0.9.0"
当前的Chrono版本是0.4.0,但是Diesel只知道如何序列化Chrono 0.3.0。
reproduction v0.1.0 (file:///private/tmp/reproduction)
├── chrono v0.4.0
├── diesel v0.13.0
│ ├── chrono v0.3.0
河豚/块密码特征
[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
连杆/活塞2d图形
[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/期货
[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
光明的未来?
RFC 1977 提议向 Cargo 引入 public 和 private 依赖的概念。如果您使用的 crate 反过来 publicly 公开另一个 crate 的类型,Cargo 将确保您对具有通用类型的 crate 使用单一统一版本。