如何在不调用clone的情况下移出一个封装值中的多个值?

3

我有一个装箱的元组来避免递归。然而,当我对元组进行模式匹配时,我似乎无法获得两个元组值。为了说明我的问题,看一下以下代码

#[derive(Clone, PartialEq, Debug)]
enum Foo {
    Base,
    Branch(Box<(Foo, Foo)>),
}

fn do_something(f: Foo) -> Foo {
    match f {
        Foo::Base => Foo::Base,
        Foo::Branch(pair) => {
            let (f1, f2) = *pair;
            if f2 == Foo::Base {
                f1
            } else {
                f2
            }
        }
    }
}

fn main() {
    let f = Foo::Branch(Box::new((Foo::Base, Foo::Base)));
    println!("{:?}", do_something(f));
}

我遇到了这个错误:

error[E0382]: use of moved value: `pair`
  --> src/main.rs:11:22
   |
11 |             let (f1, f2) = *pair;
   |                  --  ^^ value used here after move
   |                  |
   |                  value moved here
   |
   = note: move occurs because `pair.0` has type `Foo`, which does not implement the `Copy` trait

我已经了解了关于包装语法的知识,但是如果可能的话,我想避免不稳定的功能。感觉唯一的答案就是将Branch重新定义为

Branch(Box<Foo>, Box<Foo>)

但是这似乎避免回答问题(尽管现在它主要是一个思想实验)。


3
根据所给答案,我认为这应该被视为rustc的一个bug。您可能需要提交一个bug报告,以便进行检查和修复。 - Matthieu M.
3个回答

3
非词法生命周期引入时,这个问题得到了解决。原始代码现在可以直接编译:
#[derive(Clone, PartialEq, Debug)]
enum Foo {
    Base,
    Branch(Box<(Foo, Foo)>),
}

fn do_something(f: Foo) -> Foo {
    match f {
        Foo::Base => Foo::Base,
        Foo::Branch(pair) => {
            let (f1, f2) = *pair;
            if f2 == Foo::Base {
                f1
            } else {
                f2
            }
        }
    }
}

fn main() {
    let f = Foo::Branch(Box::new((Foo::Base, Foo::Base)));
    println!("{:?}", do_something(f));
}

这个问题已经在问题16223中被追踪。


1

两步拆箱法如下:

fn do_something(f: Foo) -> Foo {
    match f {
        Foo::Base => Foo::Base,
        Foo::Branch(pair) => {
            let pair = *pair;
            let (f1, f2) = pair;
            if f2 == Foo::Base {
                f1
            } else {
                f2
            }
        }
    }
}

1

在花括号内包含也是可以的。

fn do_something(f: Foo) -> Foo {
    match f {
        Foo::Base => Foo::Base,
        Foo::Branch(pair) => {
            let (f1, f2) = { *pair };
            if f2 == Foo::Base {
                f1
            } else {
                f2
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接