Rust 在模式匹配中克隆不可克隆对象的可克隆元素
我正在从事一个项目,该项目使用带有自定义枚举值的Rust 在模式匹配中克隆不可克隆对象的可克隆元素,rust,borrow-checker,Rust,Borrow Checker,我正在从事一个项目,该项目使用带有自定义枚举值的BTreeMap。此枚举无法#[导出(克隆)],因为某些变量可能包含一个不能克隆的值。我的项目大致概述如下: enum Foo { // Bar has impl Clone, Baz does not. // Both Bar and Baz are from external crates, // so I cannot impl Clone on Baz. A(Result<Vec<Bar>,
BTreeMap
。此枚举
无法#[导出(克隆)]
,因为某些变量可能包含一个不能克隆的值。我的项目大致概述如下:
enum Foo {
// Bar has impl Clone, Baz does not.
// Both Bar and Baz are from external crates,
// so I cannot impl Clone on Baz.
A(Result<Vec<Bar>, Baz>),
B(Bar, Qux),
C,
}
struct Waldo {
map: BTreeMap<Bar, Foo>,
// Other variables...
}
理想情况下,我希望能够在离开if let
子句之前创建bar_vec
的克隆,这意味着不再借用self.map
。这是可能的,还是我必须重构代码的工作方式?我已经考虑过让analyze
返回Foo
枚举值而不是直接将其添加到映射中的选项,并让dou\u something
与返回值匹配,并在最后将其添加到映射中,但是我觉得我还是把这个问题发出来,看看是否可以做一些不那么痛苦的事情。如果您可以接受使用nightly compiler,那么您可以使用非词汇生存期
#![feature(nll)]
use std::collections::BTreeMap;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
struct Bar;
// I cannot impl Clone on Baz
struct Baz;
enum Foo {
A(Result<Vec<Bar>, Baz>),
B(Bar),
C,
}
struct Waldo {
map: BTreeMap<Bar, Foo>,
// Other variables...
}
impl Waldo {
fn do_something(&mut self, data: Bar) {
self.analyze(data.clone());
if let Some(&Foo::A(Ok(ref bar_vec))) = self.map.get(&data) {
let unique = bar_vec
.iter()
.filter(|b| !self.map.contains_key(b))
.cloned()
.collect::<Vec<Bar>>();
for new_item in unique.iter().cloned() {
self.map.insert(new_item, Foo::C);
}
for new_item in unique.into_iter() {
self.do_something(new_item);
}
}
}
fn analyze(&mut self, data: Bar) {
unimplemented!()
}
}
那么Qux呢?这是可克隆的吗?最简单的方法是在上游回购中修复这一点,如果可能:)@hellow-Qux可能是可克隆的,也可能不是可克隆的,就本例而言,我认为这与此无关。主要的一点是,当内部值为Ok
时,从Foo::A
中提取的项目会执行impl Clone
,但Foo
本身不能是Clone
d。请提供一个。您的代码包含两个与您的问题无关的错误。@red75prime我一定是因为睡眠不足。尽我所能减少我的项目。问题中的错误是什么?这或多或少是我期望的答案,不过为了理解,我确实有一个问题:在NLL示例中,如果我在for
循环之后使用bar_vec
做了其他事情,编译会失败吗(因为这扩展了借用的要求)?是的,借款持续到借款人最后一次使用。
#![feature(nll)]
use std::collections::BTreeMap;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
struct Bar;
// I cannot impl Clone on Baz
struct Baz;
enum Foo {
A(Result<Vec<Bar>, Baz>),
B(Bar),
C,
}
struct Waldo {
map: BTreeMap<Bar, Foo>,
// Other variables...
}
impl Waldo {
fn do_something(&mut self, data: Bar) {
self.analyze(data.clone());
if let Some(&Foo::A(Ok(ref bar_vec))) = self.map.get(&data) {
let unique = bar_vec
.iter()
.filter(|b| !self.map.contains_key(b))
.cloned()
.collect::<Vec<Bar>>();
for new_item in unique.iter().cloned() {
self.map.insert(new_item, Foo::C);
}
for new_item in unique.into_iter() {
self.do_something(new_item);
}
}
}
fn analyze(&mut self, data: Bar) {
unimplemented!()
}
}
fn do_something(&mut self, data: Bar) {
self.analyze(data.clone());
// This allows to access `unique` outside the scope
// where `self.map` is borrowed
let unique;
if let Some(&Foo::A(Ok(ref bar_vec))) = self.map.get(&data) {
unique = bar_vec
.iter()
.filter(|b| !self.map.contains_key(b)) // &Bar, sans those in map
.cloned()
.collect::<Vec<Bar>>();
} else {
// early return prevents the use of uninitialized `unique`
return;
}
for new_item in unique.iter().cloned() {
self.map.insert(new_item, Foo::C);
}
for new_item in unique.into_iter() {
self.do_something(new_item);
}
}