首页 > 解决方案 > Rust:将借来的结构传递给借来的枚举?

问题描述

我正在尝试将借来的结构传递给借来的枚举。

#[derive(Copy, Clone)]
pub struct CustomerData {
    // Many fields about customers
}

#[derive(Copy, Clone)]
pub struct EmployeeData {
    // Many fields about employees
}

pub enum Person {
    Customer(CustomerData),
    Employee(EmployeeData)
}

fn do_something_with_customer(customer: &CustomerData) {
    let person = &Person::Customer(customer);

    // This would work, but this can be a large struct.
    // let person = &Person::Customer(customer.clone());

    general_method(person);
}

fn do_something_with_employee(employee: &EmployeeData) {
    let person = &Person::Employee(employee);

    // This would work, but this can be a large struct.
    // let person = &Person::Employee(employee.clone());

    general_method(person);
}

fn general_method(person: &Person) {

}

fn main() {
    let person = Person::Customer(CustomerData { });

    match &person {
        Person::Customer(data) => {
            do_something_with_customer(data);
        }
        Person::Employee(data) => {
            do_something_with_employee(data);
        }
    }
}

编译给了我结果:

error[E0308]: mismatched types
  --> src/main.rs:19:36
   |
19 |     let person = &Person::Customer(customer);
   |                                    ^^^^^^^^
   |                                    |
   |                                    expected struct `CustomerData`, found reference
   |                                    help: consider dereferencing the borrow: `*customer`
   |
   = note: expected type `CustomerData`
              found type `&CustomerData`

error[E0308]: mismatched types
  --> src/main.rs:28:36
   |
28 |     let person = &Person::Employee(employee);
   |                                    ^^^^^^^^
   |                                    |
   |                                    expected struct `EmployeeData`, found reference
   |                                    help: consider dereferencing the borrow: `*employee`
   |
   = note: expected type `EmployeeData`
              found type `&EmployeeData`

我知道 Rust 编译器不允许我这样做,但我觉得我应该能够这样做,考虑到我将结构传递给的枚举也是借用的。

这种情况是否有模式/解决方法?也许使用Rc类型?我不想在这种情况下乱扔我的代码。

use std::rc::Rc;

#[derive(Copy, Clone)]
pub struct CustomerData {
    // Many fields about customers
}

#[derive(Copy, Clone)]
pub struct EmployeeData {
    // Many fields about employees
}

pub enum Person {
    Customer(Rc<CustomerData>),
    Employee(Rc<EmployeeData>)
}

fn do_something_with_customer(customer: Rc<CustomerData>) {
    let person = &Person::Customer(customer);

    // This would work, but this can be a large struct.
    // let person = &Person::Customer(customer.clone());

    general_method(person);
}

fn do_something_with_employee(employee: Rc<EmployeeData>) {
    let person = &Person::Employee(employee);

    // This would work, but this can be a large struct.
    // let person = &Person::Employee(employee.clone());

    general_method(person);
}

fn general_method(person: &Person) {

}

fn main() {
    let person = Person::Customer(Rc::new(CustomerData { }));

    match &person {
        Person::Customer(data) => {
            do_something_with_customer(data.clone());
        }
        Person::Employee(data) => {
            do_something_with_employee(data.clone());
        }
    }
}

标签: enumsrustborrow-checker

解决方案


您错误地识别了问题,并且编译器在其错误注释上很准确。

您像这样定义了您的枚举:

pub enum Person {
    Customer(CustomerData),
    Employee(EmployeeData)
}

但是你决定你的枚举成员应该是Person::Customer(&CustomerData)

fn do_something_with_customer(customer: &CustomerData) {
    let person = &Person::Customer(customer);

引用不可传递。因为&CustomerData是引用并不意味着整个枚举都是对真实数据的引用(即&Person::Customer(CustomerData))。

有两种方法可以解决它;显而易见的是看是否CustomerData实现Copy。如果是这样,您可以取消引用(因此隐式复制):

fn do_something_with_customer(customer: &CustomerData) {
    let person = Person::Customer(*customer);

(这是编译器建议的,所以我很确定你的类型实现了Copy

另一个选项是#[derive(Clone)]在类型上并调用customer.clone(). 同样,以额外分配为代价。

如果您真的想要枚举中的引用,则需要将枚举定义更改为:

pub enum Person<'a> {
    Customer(&'a CustomerData),
    Employee(&'a EmployeeData)
}

并处理对象属性现在是引用的事实,以及相关的所有问题。


推荐阅读