这是一个无效的Rust程序(Rust版本1.1),其中包含一个执行HTTP客户端请求的函数,只返回标题,删除响应中的所有其他字段.
extern crate hyper;
fn just_the_headers() -> Result<hyper::header::Headers, hyper::error::Error> {
let c = hyper::client::Client::new();
let result = c.get("http://www.example.com").send();
match result {
Err(e) => Err(e),
Ok(response) => Ok(response.headers),
}
}
fn main() {
println!("{:?}", just_the_headers());
}
Run Code Online (Sandbox Code Playgroud)
以下是编译器错误:
main.rs:8:28: 8:44 error: cannot move out of type `hyper::client::response::Response`, which defines the `Drop` trait
main.rs:8 Ok(response) => Ok(response.headers),
^~~~~~~~~~~~~~~~
error: aborting due to previous error
Run Code Online (Sandbox Code Playgroud)
我理解为什么借用检查器不接受这个程序 - 即,该drop函数将response在其headers成员被移动之后使用它.
我的问题是:我怎样才能解决这个问题并且仍然拥有安全的Rust代码?我知道我可以复制,通过clone(),像这样:
Ok(response) => Ok(response.headers.clone()), …Run Code Online (Sandbox Code Playgroud) 在mutagen中,我在代码中注入了各种突变.我想改变的一件事是模式
if let Ok(x) = y { .. }.然而,这构成了相当大的挑战,因为我无法知道其类型y- 用户可以使用一元Ok变体构建自己的枚举.我仍然可以机会性地改变它,因为我们实际上有一个Result错误类型实现的情况Default使用类似于以下简化的特征:
#![feature(specialization)]
pub trait Errorer {
fn err(self, mutate: bool) -> Self;
}
impl<X> Errorer for X {
default fn err(self, _mutate: bool) -> Self {
self
}
}
impl<T, E> Errorer for Result<T, E>
where
E: Default,
{
fn err(self, mutate: bool) -> Self {
if mutate {
Err(Default::default())
} else {
self
}
}
}
Run Code Online (Sandbox Code Playgroud)
唉,实现的错误并不多Default,所以这不太有用.即使是实现 …
我有一个结构,我想按值获取、变异然后返回。我还想改变它的泛型类型,因为我使用此状态静态地确保函数调用的正确顺序,以实现安全的 FFI(游乐场):
use core::marker::PhantomData;
struct State1 {}
struct State2 {}
struct Whatever {}
struct X<State> {
a: Whatever,
b: Whatever,
c: Whatever,
_d: PhantomData<State>,
}
impl<State> Drop for X<State> {
fn drop(&mut self) {}
}
fn f(x: X<State1>) -> X<State2> {
let X { a, b, c, _d } = x;
//mutate a, b and c
X {
a,
b,
c,
_d: PhantomData,
} // return new instance
}
Run Code Online (Sandbox Code Playgroud)
因为X实现了Drop,我得到:
use core::marker::PhantomData;
struct State1 …Run Code Online (Sandbox Code Playgroud) 我想在可变借入中替换一个值; 将其中的一部分移动到新值中:
enum Foo<T> {
Bar(T),
Baz(T),
}
impl<T> Foo<T> {
fn switch(&mut self) {
*self = match self {
&mut Foo::Bar(val) => Foo::Baz(val),
&mut Foo::Baz(val) => Foo::Bar(val),
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码不起作用,并且可以理解的是,将值移出会self破坏它的完整性.但由于之后立即删除了该值,我(如果不是编译器)可以保证它的安全性.
有没有办法实现这个目标?我觉得这是一个不安全代码的工作,但我不确定这是如何工作的.