You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust所有权、借用与生命周期问题:编译报错求助

Rust所有权、借用与生命周期问题:编译错误解决

编译错误信息

error[E0597]: `particle` does not live long enough
  --> src\main.rs:80:20
   |
78 |     let mut particle = Particle::new(Vector3::ZERO, 20.0, 0.95);
   |         ------------ binding `particle` declared here
79 |
80 |     simulation.add(&mut particle);
   |     ---------------^^^^^^^^^^^^^-
   |     |              |
   |     |              borrowed value does not live long enough
   |     argument requires that `particle` is borrowed for `'static`
...
97 | }
   | - `particle` dropped here while still borrowed
error[E0505]: cannot move out of `particle` because it is borrowed
--> src\main.rs:82:24
|
78 |     let mut particle = Particle::new(Vector3::ZERO, 20.0, 0.95);
|         ------------ binding `particle` declared here
79 |
80 |     simulation.add(&mut particle);
|     -----------------------------
|     |              |
|     |              borrow of `particle` occurs here
|     argument requires that `particle` is borrowed for `'static`
81 |
82 |     window.render_loop(move |mut frame_input| {
|                        ^^^^^^^^^^^^^^^^^^^^^^ move out of `particle` occurs here
...
86 |         particle.apply_force(Vector3 { x: 0.0, y: -G, z: 0.0 } * particle.mass);
|         -------- move occurs due to use in closure

相关代码

main.rs

let window = Window::new(WindowSettings {
    title: String::from("test"),
    max_size: Some((1600, 900)),

    ..Default::default()
}).unwrap();

let mut particle = Particle::new(Vector3::ZERO, 20.0, 0.95);
let mut simulation = ParticleSimulation::new();

simulation.add(&mut particle);

window.render_loop(move |mut frame_input| {
    particle.apply_force(Vector3 { x: 0.0, y: -G, z: 0.0 } * particle.mass);
    simulation.update(0.001 * frame_input.elapsed_time);

    FrameOutput::default()
});

particle.rs

pub struct Particle {
    pub position: Vector3,

    velocity: Vector3,
    force: Vector3,

    damping: f64,
    pub mass: f64,
    pub inverse_mass: f64
}

impl Particle {
    pub fn new(position: Vector3, mass: f64, damping: f64) -> Particle {
        Particle {
            position,

            velocity: Vector3::ZERO,
            force: Vector3::ZERO,

            damping,
            mass,
            inverse_mass: 1.0 / mass,
        }
    }

    pub fn apply_force(&mut self, force: Vector3) {
        self.force += force;
    }

    pub fn update(&mut self, delta_time: f64) {
        assert!(delta_time >= 0.0, "negative delta_time");

        self.position += self.velocity * delta_time;

        let acceleration = self.force * self.inverse_mass;

        self.velocity += acceleration * delta_time;
        self.velocity *= self.damping.powf(delta_time);

        self.force = Vector3::ZERO;
    }
}

pub struct ParticleSimulation<'a> {
    particles: Vec<&'a mut Particle>,
}

impl<'a> ParticleSimulation<'a> {
    pub fn new() -> Self {
        ParticleSimulation {
            particles: Vec::new(),
        }
    }

    pub fn add(&mut self, particle: &'a mut Particle) {
        self.particles.push(particle)
    }

    pub fn update(&mut self, delta_time: f64) {
        for particle in self.particles.iter_mut() {
            particle.update(delta_time);
        }
    }
}

问题根源与解决方案

问题分析

  1. 生命周期不匹配:ParticleSimulation存储的是&mut Particle可变引用,但window.render_loop的闭包会被长期持有(直到窗口关闭),要求捕获的变量生命周期为'static,而栈上创建的particle生命周期仅到main函数结束,无法满足要求。
  2. 借用冲突:simulation持有particle的可变引用后,又将particle移动到闭包中,违反了Rust的核心规则:一个值不能同时存在可变引用和被移动。

修改方案

让ParticleSimulation直接持有Particle的所有权,而非引用,彻底规避生命周期和借用问题:

修改后的particle.rs

pub struct Particle {
    pub position: Vector3,

    velocity: Vector3,
    force: Vector3,

    damping: f64,
    pub mass: f64,
    pub inverse_mass: f64
}

impl Particle {
    pub fn new(position: Vector3, mass: f64, damping: f64) -> Particle {
        Particle {
            position,

            velocity: Vector3::ZERO,
            force: Vector3::ZERO,

            damping,
            mass,
            inverse_mass: 1.0 / mass,
        }
    }

    pub fn apply_force(&mut self, force: Vector3) {
        self.force += force;
    }

    pub fn update(&mut self, delta_time: f64) {
        assert!(delta_time >= 0.0, "negative delta_time");

        self.position += self.velocity * delta_time;

        let acceleration = self.force * self.inverse_mass;

        self.velocity += acceleration * delta_time;
        self.velocity *= self.damping.powf(delta_time);

        self.force = Vector3::ZERO;
    }
}

// 移除生命周期参数,直接持有Particle所有权
pub struct ParticleSimulation {
    particles: Vec<Particle>,
}

impl ParticleSimulation {
    pub fn new() -> Self {
        ParticleSimulation {
            particles: Vec::new(),
        }
    }

    // 接收Particle并转移所有权
    pub fn add(&mut self, particle: Particle) {
        self.particles.push(particle)
    }

    pub fn update(&mut self, delta_time: f64) {
        for particle in self.particles.iter_mut() {
            particle.update(delta_time);
        }
    }

    // 添加方法用于获取粒子的可变引用,方便在闭包中施加力
    pub fn get_particle_mut(&mut self, index: usize) -> Option<&mut Particle> {
        self.particles.get_mut(index)
    }
}

修改后的main.rs

let window = Window::new(WindowSettings {
    title: String::from("test"),
    max_size: Some((1600, 900)),

    ..Default::default()
}).unwrap();

let particle = Particle::new(Vector3::ZERO, 20.0, 0.95);
let mut simulation = ParticleSimulation::new();

// 将粒子所有权转移给simulation
simulation.add(particle);

// 将simulation移动到闭包中
window.render_loop(move |mut frame_input| {
    // 通过simulation获取粒子可变引用并施加力
    if let Some(particle) = simulation.get_particle_mut(0) {
        particle.apply_force(Vector3 { x: 0.0, y: -G, z: 0.0 } * particle.mass);
    }
    simulation.update(0.001 * frame_input.elapsed_time);

    FrameOutput::default()
});

说明

  • 移除ParticleSimulation的生命周期参数,让它直接持有Particle的所有权,消除了引用带来的生命周期约束。
  • 通过get_particle_mut方法在闭包中获取粒子的可变引用,既保证了对粒子的修改,又符合Rust的借用规则。
  • 将simulation整体移动到闭包中,确保其生命周期与窗口渲染循环一致。

内容的提问来源于stack exchange,提问作者Keys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 04:59:51