为什么惰性静态值声称不实现它明确实现的特征?
Why does a lazy-static value claim to not implement a trait that it clearly implements?
使用以下代码(尝试使用 reqwest
crate 发出 HTTP 请求),编译器说我的值 SID_URI
没有实现特征 PolyfillTryInto
。这里发生了什么? reqwest::Url
clearly implements the private trait reqwest::into_url::PolyfillTryInto
.
#[macro_use]
extern crate lazy_static;
extern crate reqwest;
static R_EMAIL: &str = "example@example.com";
static R_PASS: &str = "password";
static API_PUBKEY: &str = "99754106633f94d350db34d548d6091a";
static API_URI: &str = "https://example.com";
static AUTH_PATH: &str = "/api/v1";
lazy_static! {
static ref SID_URI: reqwest::Url = reqwest::Url::parse(&(API_URI.to_owned() + AUTH_PATH)).unwrap();
}
fn get_sid() -> Result<reqwest::Response, reqwest::Error> {
let client = reqwest::Client::new();
let params = [("ID", R_EMAIL), ("PW", R_PASS), ("KY", API_PUBKEY)];
let q = client.post(SID_URI).form(¶ms).send()?;
Ok(q)
}
fn main() {
assert!(get_sid().is_ok());
}
error[E0277]: the trait bound `SID_URI: reqwest::into_url::PolyfillTryInto` is not satisfied
--> src/main.rs:19:20
|
19 | let q = client.post(SID_URI).form(¶ms).send()?;
| ^^^^ the trait `reqwest::into_url::PolyfillTryInto` is not implemented for `SID_URI`
|
= note: required because of the requirements on the impl of `reqwest::IntoUrl` for `SID_URI`
编译器没有骗你,你只是跳过了错误消息的相关细节。这是一个独立的示例:
#[macro_use]
extern crate lazy_static;
struct Example;
trait ExampleTrait {}
impl ExampleTrait for Example {}
lazy_static! {
static ref EXAMPLE: Example = Example;
}
fn must_have_trait<T>(_: T)
where
T: ExampleTrait,
{
}
fn main() {
must_have_trait(EXAMPLE);
must_have_trait(42i32);
}
error[E0277]: the trait bound `EXAMPLE: ExampleTrait` is not satisfied
--> src/main.rs:19:5
|
19 | must_have_trait(EXAMPLE);
| ^^^^^^^^^^^^^^^ the trait `ExampleTrait` is not implemented for `EXAMPLE`
|
= note: required by `must_have_trait`
error[E0277]: the trait bound `i32: ExampleTrait` is not satisfied
--> src/main.rs:20:9
|
20 | must_have_trait(42i32);
| ^^^^^^^^^^^^^^^ the trait `ExampleTrait` is not implemented for `i32`
|
= note: required by `must_have_trait`
比较两条错误信息:
the trait bound `EXAMPLE: ExampleTrait` is not satisfied
the trait bound `i32: ExampleTrait` is not satisfied
第二个错误消息没有说 42
没有实现 ExampleTrait
,而是说 i32
缺少实现。此错误消息显示失败的 type,而不是值的名称!这意味着相同上下文中的 EXAMPLE
指的是一种类型。
Lazy-static 由 creating one-off types 工作,它包装您的值并提供线程安全的单一初始化保证:
For a given static ref NAME: TYPE = EXPR;
, the macro generates a unique type that implements Deref<TYPE>
and stores it in a static with name NAME
.
此包装类型不实现您的特征,只有包装类型实现。您将需要调用 Deref
然后可能重新引用它以获取 &Url
,假设对 Url
的引用实现了您的特征:
must_have_trait(&*EXAMPLE);
此外,使用裸静态变量会尝试将其移出静态位置(这将是一件非常糟糕的事情),因此您始终需要通过引用来使用它。
使用以下代码(尝试使用 reqwest
crate 发出 HTTP 请求),编译器说我的值 SID_URI
没有实现特征 PolyfillTryInto
。这里发生了什么? reqwest::Url
clearly implements the private trait reqwest::into_url::PolyfillTryInto
.
#[macro_use]
extern crate lazy_static;
extern crate reqwest;
static R_EMAIL: &str = "example@example.com";
static R_PASS: &str = "password";
static API_PUBKEY: &str = "99754106633f94d350db34d548d6091a";
static API_URI: &str = "https://example.com";
static AUTH_PATH: &str = "/api/v1";
lazy_static! {
static ref SID_URI: reqwest::Url = reqwest::Url::parse(&(API_URI.to_owned() + AUTH_PATH)).unwrap();
}
fn get_sid() -> Result<reqwest::Response, reqwest::Error> {
let client = reqwest::Client::new();
let params = [("ID", R_EMAIL), ("PW", R_PASS), ("KY", API_PUBKEY)];
let q = client.post(SID_URI).form(¶ms).send()?;
Ok(q)
}
fn main() {
assert!(get_sid().is_ok());
}
error[E0277]: the trait bound `SID_URI: reqwest::into_url::PolyfillTryInto` is not satisfied
--> src/main.rs:19:20
|
19 | let q = client.post(SID_URI).form(¶ms).send()?;
| ^^^^ the trait `reqwest::into_url::PolyfillTryInto` is not implemented for `SID_URI`
|
= note: required because of the requirements on the impl of `reqwest::IntoUrl` for `SID_URI`
编译器没有骗你,你只是跳过了错误消息的相关细节。这是一个独立的示例:
#[macro_use]
extern crate lazy_static;
struct Example;
trait ExampleTrait {}
impl ExampleTrait for Example {}
lazy_static! {
static ref EXAMPLE: Example = Example;
}
fn must_have_trait<T>(_: T)
where
T: ExampleTrait,
{
}
fn main() {
must_have_trait(EXAMPLE);
must_have_trait(42i32);
}
error[E0277]: the trait bound `EXAMPLE: ExampleTrait` is not satisfied
--> src/main.rs:19:5
|
19 | must_have_trait(EXAMPLE);
| ^^^^^^^^^^^^^^^ the trait `ExampleTrait` is not implemented for `EXAMPLE`
|
= note: required by `must_have_trait`
error[E0277]: the trait bound `i32: ExampleTrait` is not satisfied
--> src/main.rs:20:9
|
20 | must_have_trait(42i32);
| ^^^^^^^^^^^^^^^ the trait `ExampleTrait` is not implemented for `i32`
|
= note: required by `must_have_trait`
比较两条错误信息:
the trait bound `EXAMPLE: ExampleTrait` is not satisfied
the trait bound `i32: ExampleTrait` is not satisfied
第二个错误消息没有说 42
没有实现 ExampleTrait
,而是说 i32
缺少实现。此错误消息显示失败的 type,而不是值的名称!这意味着相同上下文中的 EXAMPLE
指的是一种类型。
Lazy-static 由 creating one-off types 工作,它包装您的值并提供线程安全的单一初始化保证:
For a given
static ref NAME: TYPE = EXPR;
, the macro generates a unique type that implementsDeref<TYPE>
and stores it in a static with nameNAME
.
此包装类型不实现您的特征,只有包装类型实现。您将需要调用 Deref
然后可能重新引用它以获取 &Url
,假设对 Url
的引用实现了您的特征:
must_have_trait(&*EXAMPLE);
此外,使用裸静态变量会尝试将其移出静态位置(这将是一件非常糟糕的事情),因此您始终需要通过引用来使用它。