Rust 无法将变量作为可变变量借用,因为在重构解析器时它也是作为不可变变量借用的

Rust 无法将变量作为可变变量借用,因为在重构解析器时它也是作为不可变变量借用的,rust,Rust,为了学习Rust,我开始研究一个简单的解析器。我让它工作了,但我使用了大量的错误做法,比如使用.clone()在结构中保存数据 今天我开始重构代码,使用对对象的引用,而不是克隆它们。在陷入这两个错误之前,我已经走了很长的路: error: cannot borrow 'm_list' as mutable because it is also borrowed as immutable [E0502] 及 读了关于错误的内容后,我很困惑。有人说这是Rust的借阅检查器中的一个bug,但我99%

为了学习Rust,我开始研究一个简单的解析器。我让它工作了,但我使用了大量的错误做法,比如使用
.clone()
在结构中保存数据

今天我开始重构代码,使用对对象的引用,而不是克隆它们。在陷入这两个错误之前,我已经走了很长的路:

error: cannot borrow 'm_list' as mutable because it is also borrowed as immutable [E0502]

读了关于错误的内容后,我很困惑。有人说这是Rust的借阅检查器中的一个bug,但我99%确定这是我的代码中的一个bug

出现错误的代码:

mod utypes;

use std::env;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::error::Error;

use utypes::*;

fn main() {    

    let args: Vec<_> = env::args().collect();

    let file = match File::open(&args[1]) {

        Ok(file) => file,
        Err(why) => panic!("IO Error on line: {}, cause: {}", line!(), Error::description(&why)),

    };
    let buffer = BufReader::new(file);

    let mut m_list: Vec<Materia> = Vec::new(); 
    let mut h_list: Vec<Hora> = Vec::new();
    let mut t_list: Vec<Turno> = Vec::new();

    for line in buffer.lines() {

        let l = line.unwrap();
        let spl_line: Vec<&str> = l.split(':').collect();

        if spl_line[0].starts_with('#') { continue; }

        match spl_line[0] {

            "mat" => { parse_mat(&mut m_list,spl_line) },
            "hra" => { parse_hra(&m_list,&mut h_list,spl_line) },
            "trn" => { parse_trn(&mut t_list,spl_line) },
            "tad" => { exec_tad(&h_list,&mut t_list,spl_line) },
            ""    => continue,
            _     => panic!("Unknown type identifier: {}.", spl_line[0]),

        }

    }

    for turno in t_list.iter() {

        println!("\nTurno: {}:\n", turno.nombre);
        for dia in turno.dias.iter() {

            print!("{:?}: ", dia.enum_id);
            for hora in dia.horas.iter() {

                print!("\n\t{} ", hora);

            }
            println!("");

        }

    }

    /*
    println!("\nDEBUG INFO:\n");
    println!("{:?}", m_list);
    println!("{:?}", h_list);
    println!("{:?}", t_list);
    */

}

fn get_trn( t_list: &Vec<Turno>, gid: u32 ) -> Option<usize> {

    for (i,trn) in t_list.iter().enumerate() {

        if trn.id == gid {

            return Some(i);

        }

    }

    None

}

fn get_hra ( h_list: &Vec<Hora>, gid: u32 ) -> Option<usize> {

    for (i,hra) in h_list.iter().enumerate() {

        if hra.id == gid {

            return Some(i);

        }

    }

    None

}

fn get_mat ( m_list: &Vec<Materia>, gid: u32 ) -> Option<usize> {

    for (i,mat) in m_list.iter().enumerate() {

        if mat.id == gid {

            return Some(i);

        }

    }

    None

}

fn parse_mat<'a> ( m_list: &'a mut Vec<Materia>, line: Vec<&str> ) {

    assert_eq!(4,line.len());

    let id: u32 = match line[1].parse::<u32>() {

        Ok(id)    => id,
        Err(_)    => panic!("Error parsing u32 at {}.", line!()),

    };   

    m_list.push(Materia::new(id,line[2].to_string(),line[3].to_string()));

    }

fn parse_hra<'a> ( m_list: &'a Vec<Materia>, h_list: &mut Vec<Hora<'a>>, line: Vec<&str> ) {

    assert_eq!(5,line.len());

    let id: u32 = match line[1].parse::<u32>() {

        Ok(id)    => id,
        Err(_)    => panic!("Error parsing u32 at {}.", line!()),

    };
    let start: u32 = match line[2].parse::<u32>() {

        Ok(start) => start,
        Err(_)    => panic!("Error parsing u32 at {}.", line!()),

    };
    let durat: u32 = match line[3].parse::<u32>() {

        Ok(durat) => durat,
        Err(_)    => panic!("Error parsing u32 at {}.", line!()),

    };
    let matid: u32 = match line[4].parse::<u32>() {

        Ok(matid) => matid,
        Err(_)    => panic!("Error parsing u32 at {}.", line!()),

    };
    let mat_i: usize = match get_mat(m_list,matid) {

        Some(x) => x,
        None      => panic!("Error matid not found in m_list!")

    };

    h_list.push(Hora::new(id,start,durat,&m_list[mat_i]));

}

fn parse_trn<'a> ( t_list: &mut Vec<Turno<'a>>, line: Vec<&str> ) {

    assert_eq!(3,line.len());

    let id: u32 = match line[1].parse::<u32>() {

        Ok(id) => id,
        Err(_) => panic!("Error parsing u32 at {}.", line!()),

    };

    t_list.push(Turno::new(id,line[2].to_string()));

}

fn exec_tad<'a> ( h_list: &'a Vec<Hora<'a>>, t_list: &mut Vec<Turno<'a>>, line: Vec<&str> ) {

    assert_eq!(4,line.len());

    let hid: u32 = match line[2].parse::<u32>(){

        Ok(hid) => hid,
        Err(_)  => panic!("Error parsing u32 at {}.", line!()),

    };
    let tid: u32 = match line[3].parse::<u32>(){

        Ok(tid) => tid,
        Err(_)  => panic!("Error parsing u32 at {}.", line!()),

    };

    let hra_i: usize = match get_hra(h_list,hid) {

        Some(x) => x,
        None    => panic!("Error matid not found in m_list!")

    };
    let trn_i: usize = match get_trn(t_list,tid) {

        Some(x) => x,
        None    => panic!("Error matid not found in m_list!")

    };

    match line[1] {

        "Dom" => t_list[trn_i].addhra(Dias::Dom,&h_list[hra_i]),
        "Lun" => t_list[trn_i].addhra(Dias::Lun,&h_list[hra_i]),
        "Mar" => t_list[trn_i].addhra(Dias::Mar,&h_list[hra_i]),
        "Mie" => t_list[trn_i].addhra(Dias::Mie,&h_list[hra_i]),
        "Jue" => t_list[trn_i].addhra(Dias::Jue,&h_list[hra_i]),
        "Vie" => t_list[trn_i].addhra(Dias::Vie,&h_list[hra_i]),
        "Sab" => t_list[trn_i].addhra(Dias::Sab,&h_list[hra_i]),
        _     => panic!("Unknown day error!") 

    }

}
我不是以英语为母语的人,所以我为我的错误感到抱歉


@aSpex评论是正确的

要解决此问题,可以用相应的索引替换
Hora
Dia
中的引用。就是

struct Hora {
    materia: usize; //index in m_list 
}

struct Dia {
    horas: Vec<usize>; //indices in h_list
}
struct Hora{
Material:usize;//m_列表中的索引
}
结构直径{
horas:Vec;//h_列表中的索引
}
您还可以使用字段
m_list
h_list
t_list
创建一个结构,以便将它们保持在一起


有关与使用
Rc
RefCell

的方法的比较,请包括错误代码的完整示例,包括用于parse_hra/parse_mat/parse_trn/exec_tad的存根方法&不删除main/use,使用函数
parse_hra
将对
m_list
中元素的引用存储在
h_list
中。因此,当
h\u列表
超出范围时,
m\u列表
借用结束。尝试使用
Rc
代替引用。
use std::fmt;

//Dias
#[derive(Debug)]
pub enum Dias {

    Dom,
    Lun,
    Mar,
    Mie,
    Jue,
    Vie,
    Sab,

}

//Materia

#[derive(Debug)]
pub struct Materia {

    pub id: u32,
    pub nombre: String,
    pub profesor: String,

}

impl Materia {

    pub fn new( i: u32, nom: String, prof: String ) -> Materia {

        Materia {

            id: i,
            nombre: nom,
            profesor: prof,


        }

    }
}

//Hora

#[derive(Debug,Clone)]
pub struct Hora<'a> {

    pub id: u32,
    pub comienzo: u32,
    pub duracion: u32,
    pub materia: &'a Materia,

}

impl<'a> Hora<'a> {

    pub fn new ( id: u32, com: u32, dur: u32, mat: &'a Materia ) -> Hora<'a> {

        Hora {

           id: id,
            comienzo: com,
            duracion: dur,
            materia: mat,

        }

    }

    pub fn fin ( &self ) -> u32 {

        self.comienzo + self.duracion

    }

    pub fn fmt_time ( tot: u32 ) -> String {

        let min = ( tot / 60 ) % 60;
        let hra = tot / 3600;

        format!("{:02}:{:02}", hra, min)

    }

}

impl<'a> fmt::Display for Hora<'a> {

    fn fmt( &self, f: &mut fmt::Formatter ) -> fmt::Result {

        write!(f, "[{}-{}, {}]", Hora::fmt_time(self.comienzo), Hora::fmt_time(self.fin()), self.materia.nombre)

    }

}

//Dia

#[derive(Debug)]
pub struct Dia<'a> {

    pub enum_id: Dias,
    pub nombre: String,
    pub horas: Vec<&'a Hora<'a>>,

}

impl<'a> Dia<'a> {

    pub fn new( ei: Dias, nom: String ) -> Dia<'a> {

        Dia {

            enum_id: ei,
            nombre: nom,
            horas: Vec::new(),

        }

    }

    pub fn addhra( &mut self, hra: &'a Hora<'a> ){

        self.horas.push(hra);

    }   

}

//Turno

#[derive(Debug)]
pub struct Turno<'a> {

    pub id: u32,
    pub nombre: String,
    pub dias: [Dia<'a>; 7],

}

impl<'a> Turno<'a> {

    pub fn new( i: u32, nom: String ) -> Turno<'a> {

        Turno {

            id: i,
            nombre: nom,
            dias: [

                    Dia::new(Dias::Dom,"Domingo"  .to_string()),
                    Dia::new(Dias::Lun,"Lunes"    .to_string()),
                    Dia::new(Dias::Mar,"Martes"   .to_string()),
                    Dia::new(Dias::Mie,"Miercoles".to_string()),
                    Dia::new(Dias::Jue,"Jueves"   .to_string()),
                    Dia::new(Dias::Vie,"Viernes"  .to_string()),
                    Dia::new(Dias::Sab,"Sabado"   .to_string())

                   ],

        }

    }

    pub fn addhra( &mut self, dia: Dias, hra: &'a Hora<'a> ) {

        match dia {

            Dias::Dom => self.dias[0].addhra(hra),
            Dias::Lun => self.dias[1].addhra(hra),
            Dias::Mar => self.dias[2].addhra(hra),
            Dias::Mie => self.dias[3].addhra(hra),
            Dias::Jue => self.dias[4].addhra(hra),
            Dias::Vie => self.dias[5].addhra(hra),
            Dias::Sab => self.dias[6].addhra(hra),

        }

    }

}
src/main.rs:36:39: 36:45 error: cannot borrow `m_list` as mutable because it is also borrowed as immutable [E0502]
src/main.rs:36             "mat" => { parse_mat(&mut m_list,spl_line) },
                                                 ^~~~~~
src/main.rs:37:35: 37:41 note: previous borrow of `m_list` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `m_list` until the borrow ends
src/main.rs:37             "hra" => { parse_hra(&m_list,&mut h_list,spl_line) },
                                             ^~~~~~
src/main.rs:71:2: 71:2 note: previous borrow ends here
src/main.rs:11 fn main() {    
           ...
src/main.rs:71 }
           ^
src/main.rs:37:47: 37:53 error: cannot borrow `h_list` as mutable because it is also borrowed as immutable [E0502]
src/main.rs:37             "hra" => { parse_hra(&m_list,&mut h_list,spl_line) },
                                                         ^~~~~~
src/main.rs:39:34: 39:40 note: previous borrow of `h_list` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `h_list` until the borrow ends
src/main.rs:39             "tad" => { exec_tad(&h_list,&mut t_list,spl_line) },
                                            ^~~~~~
src/main.rs:71:2: 71:2 note: previous borrow ends here
src/main.rs:11 fn main() {    
           ...
src/main.rs:71 }
           ^
struct Hora {
    materia: usize; //index in m_list 
}

struct Dia {
    horas: Vec<usize>; //indices in h_list
}