如何确保函数调用后不可变借用结束以启用可变借用?

Jar*_*rak 7 rust

我在使用 Rust 2018 时遇到了借用检查器问题,但找不到解决方案。基本上,我有一个函数接受对 vec 的可变引用,并且在其执行的第一部分将相同的 vec 作为不可变引用传递到另一个函数中。后一个函数返回一个新的拥有值 - 或者至少我打算这样做。对我来说,问题是编译器似乎认为函数调用的不可变借用持续到外部函数结束。

不幸的是,这不是一个简单地通过用大括号括起来就能解决的问题(无论如何都不应该这样,因为我使用的是 Rust 2018)。此外,虽然我发现了许多似乎涉及类似问题的问题(例如thisthisthisthis),但我无法找到任何其他直接解决此问题的内容。或者至少,我无法从中弄清楚我应该做什么。至关重要的是,大多数其他类似问题要么似乎涉及引用作为返回类型,要么只是非词汇生命周期之前的问题。

我在Rust Playground中创建了一个可执行的 MVE ,以及完整的程序,以防有帮助。我把代码贴在下面,供参考:

// This function was blatantly borrowed from a Stack Overflow post
// but unfortunately I lost track of which one.
fn compute_mean_of_vec<'g, T>(input_vec: &'g [T]) -> T
where
    T: Copy
        + num::Zero
        + std::ops::Add<T, Output = T>
        + std::ops::Div<T, Output = T>
        + num::FromPrimitive
        + std::iter::Sum<&'g T>,
{
    let sum: T = input_vec.iter().sum();
    sum / num::FromPrimitive::from_usize(input_vec.len()).unwrap()
}

fn normalise_cost_vec<'a, T>(cost_vec: &'a mut Vec<T>)
where
    T: std::ops::SubAssign
        + Copy
        + num::traits::identities::Zero
        + std::ops::Div<Output = T>
        + num::traits::cast::FromPrimitive
        + std::iter::Sum<&'a T>,
{
    let mean = compute_mean_of_vec(cost_vec);
    for c in cost_vec.iter_mut() {
        *c -= mean;
    }
}

fn main() {
    let mut my_vec = vec![5.0f32; 5];
    normalise_cost_vec(&mut my_vec);
    for e in my_vec.iter() {
        println!("{}", e);
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器产生的错误消息是:

// This function was blatantly borrowed from a Stack Overflow post
// but unfortunately I lost track of which one.
fn compute_mean_of_vec<'g, T>(input_vec: &'g [T]) -> T
where
    T: Copy
        + num::Zero
        + std::ops::Add<T, Output = T>
        + std::ops::Div<T, Output = T>
        + num::FromPrimitive
        + std::iter::Sum<&'g T>,
{
    let sum: T = input_vec.iter().sum();
    sum / num::FromPrimitive::from_usize(input_vec.len()).unwrap()
}

fn normalise_cost_vec<'a, T>(cost_vec: &'a mut Vec<T>)
where
    T: std::ops::SubAssign
        + Copy
        + num::traits::identities::Zero
        + std::ops::Div<Output = T>
        + num::traits::cast::FromPrimitive
        + std::iter::Sum<&'a T>,
{
    let mean = compute_mean_of_vec(cost_vec);
    for c in cost_vec.iter_mut() {
        *c -= mean;
    }
}

fn main() {
    let mut my_vec = vec![5.0f32; 5];
    normalise_cost_vec(&mut my_vec);
    for e in my_vec.iter() {
        println!("{}", e);
    }
}
Run Code Online (Sandbox Code Playgroud)

查看错误消息,在我看来,这两个函数指定的生命周期可能存在一些问题。我必须承认,我包含的内容几乎只是根据编译器和 Clippy 的建议放在那里,我并不完全理解它们。据我所知,编译器以某种方式认为调用中的不可变借用compute_mean_of_vec应该持续到调用的整个剩余部分normalise_cost_vec

我做错了什么,怎样才能让编译器满意?我想这与指定另一生有关,但尽管查看了这本书和许多在线资源,我仍无法找到正确的方法。

Pho*_*s15 3

问题似乎出在该Sum特征的生命周期参数上,这是一个不删除该特征的解决方案

fn compute_mean_of_vec<'g, T>(input_vec: &'g Vec<T>) -> T
where
    for<'x> T: Copy
        + num::Zero
        + std::ops::Add<T, Output = T>
        + std::ops::Div<T, Output = T>
        + num::FromPrimitive
        + std::iter::Sum<&'x T>,
{
    let sum: T = input_vec.iter().sum();
    sum / num::FromPrimitive::from_usize(input_vec.len()).unwrap()
}

fn normalise_cost_vec<'a, T>(cost_vec: &'a mut Vec<T>)
where
    for<'x> T: std::ops::SubAssign
        + Copy
        + num::traits::identities::Zero
        + std::ops::Div<Output = T>
        + num::traits::cast::FromPrimitive
        + std::iter::Sum<&'x T>,
{
    let mean = compute_mean_of_vec(cost_vec);
    for c in cost_vec.iter_mut() {
        *c -= mean;
    }
}

fn main() {
    let mut my_vec = vec![5.0f32; 5];
    normalise_cost_vec(&mut my_vec);
    for e in my_vec.iter() {
        println!("{}", e);
    }
}
Run Code Online (Sandbox Code Playgroud)

即,通过为 Trait 指定一个独立的生命周期参数Sum,该参数'g不会被假定为随整个函数一起携带。