diff --git a/examples/deref_assign.rs b/examples/deref_assign.rs index aad858cc16bbd554ea620a225d1ea712129cd235..c915288c2867a519709259ad7dae7407561439f0 100644 --- a/examples/deref_assign.rs +++ b/examples/deref_assign.rs @@ -1,6 +1,6 @@ -fn main() -> i32 { +fn main() { let mut a = 7; let b = &mut a; *b = 9; - a + let c = a; } diff --git a/examples/deref_assign2.rs b/examples/deref_assign2.rs index 2d6189d2c98e2837a3790d441d3119ba3e70743d..53a1872cdf55a3827ffd761a6fc681dc96afd13e 100644 --- a/examples/deref_assign2.rs +++ b/examples/deref_assign2.rs @@ -1,7 +1,7 @@ -fn main() -> i32 { +fn main() { let mut a = 7; - let b = &a; - let c = &b; - **c = 9; - a + let mut b = &a; + let c = &mut b; + *(*c) = 9; + let d = a; } diff --git a/examples/ref_err4.rs b/examples/ref_err4.rs new file mode 100644 index 0000000000000000000000000000000000000000..2c105f44cba6e9cfe4ad4406c2f45ab42a567555 --- /dev/null +++ b/examples/ref_err4.rs @@ -0,0 +1,5 @@ +fn main() { + let mut a = 1; + let b = &a; + let mut c: &mut &i32 = &mut b; +} diff --git a/src/check.rs b/src/check.rs index 18c42be5f4caca3f1749045cf1bb52fd551807a4..0fe868dabb40c4e5a5db5b9eb9b84d98cb17d836 100644 --- a/src/check.rs +++ b/src/check.rs @@ -183,149 +183,6 @@ fn strip_mut(t: Type) -> Type { } } -// // walk the left hand expression in an assignment. -// // Ok(Type), the type of the left hand -// // Err(), illegal left hand -// fn left_expr_type(e: &Expr, to_type: Type, var_env: &mut VarEnv) -> Result<(), Error> { -// match e { -// Expr::Id(id) => { -// match var_env.get(id.clone()) { -// Some((true, Some(t))) => { -// match *t == to_type { -// true => Ok(()), // mutable, defined of same type -// false => Err("types differ".to_string()), -// } -// } -// Some((true, None)) => unimplemented!(), -// Some((false, _)) => Err("variable declared immutable".to_string()), -// None => Err("variable not in scope".to_string()), -// } -// } -// Expr::DeRef(ref_mut_e) => { -// let e: &Expr = &*ref_mut_e; -// trace!("DeRef({})", e); -// match e { -// Expr::RefMut(e) => left_expr_type(&*e, to_type, var_env), -// _ => Err("cannot deref left hand expression".to_string()), -// } -// // } -// // let ref_mut_id = left_expr_type(ref_mut_e, var_env)?; -// // trace!("left: RefMut({})", ref_mut_id); - -// // match var_env.get(ref_mut_id) { -// // Some(Val::Ref(id)) => { -// // println!("Ref id {}", id); -// // id.clone() -// // } -// // Some(Val::RefMut(id)) => { -// // println!("RefMut id {}", id); -// // id.clone() -// // } -// // _ => panic!("deref failed"), -// // } - -// // Ok(ref_mut_id) -// } - -// // let ev = eval_left_expr(e, m, fn_env); -// // println!("eval_left {:?}", ev); - -// // match m.get(ev) { -// // Some(Val::Ref(id)) => { -// // println!("Ref id {}", id); -// // id.clone() -// // } -// // Some(Val::RefMut(id)) => { -// // println!("RefMut id {}", id); -// // id.clone() -// // } -// // _ => panic!("deref failed"), -// // } -// _ => Err(format!("illegal left hand expression {}", e)), -// } -// } - -// walk the left hand expression in an assignment. -// Ok(Type), the type of the left hand -// Err(), illegal left hand -fn left_expr_type(e: &Expr, var_env: &mut VarEnv) -> Result<Id, Error> { - match e { - Expr::Id(id) => Ok(id.to_owned()), - // match var_env.get(id.clone()) { - // Some((true, Some(t))) => { - // match *t == to_type { - // true => Ok(()), // mutable, defined of same type - // false => Err("types differ".to_string()), - // } - // } - // Some((true, None)) => unimplemented!(), - // Some((false, _)) => Err("variable declared immutable".to_string()), - // None => Err("variable not in scope".to_string()), - // } - // } - Expr::DeRef(ref_mut_e) => { - trace!("DeRef({})", ref_mut_e); - let lh = left_expr_type(ref_mut_e, var_env)?; - trace!("DeRef({})", lh); - match var_env.get(lh) { - Some(t) => { - trace!("t {:?}", t); - panic!(); - } - // match *t == to_type { - // true => Ok(()), // mutable, defined of same type - // false => Err("types differ".to_string()), - // } - // } - // Some((true, None)) => unimplemented!(), - // Some((false, _)) => Err("variable declared immutable".to_string()), - None => Err("variable not in scope".to_string()), - } - } - - // match e { - // Expr::RefMut(e) => left_expr_type(&*e, to_type, var_env), - // _ => Err("cannot deref left hand expression".to_string()), - // } - // } - // println!("eval_left deref e {:?}", e); - - // let ev = eval_left_expr(e, m, fn_env); - // println!("eval_left {:?}", ev); - - // match m.get(ev) { - // Some(Val::Ref(id)) => { - // println!("Ref id {}", id); - // id.clone() - // } - // Some(Val::RefMut(id)) => { - // println!("RefMut id {}", id); - // id.clone() - // } - // _ => panic!("deref failed"), - // } - - // Ok(ref_mut_id) - // } - - // let ev = eval_left_expr(e, m, fn_env); - // println!("eval_left {:?}", ev); - - // match m.get(ev) { - // Some(Val::Ref(id)) => { - // println!("Ref id {}", id); - // id.clone() - // } - // Some(Val::RefMut(id)) => { - // println!("RefMut id {}", id); - // id.clone() - // } - // _ => panic!("deref failed"), - // } - _ => Err(format!("illegal left hand expression {}", e)), - } -} - pub fn check_stmts( stmts: &Stmts, fn_env: &FnEnv, @@ -369,13 +226,22 @@ pub fn check_stmts( } Assign(lh, e) => { - let expr_type = expr_type(&*e, fn_env, type_env, var_env)?; - trace!("expr_type = {}", expr_type); - trace!("v = {:?}", lh); + let e_type = expr_type(&*e, fn_env, type_env, var_env)?; + trace!("e_type = {}", e_type); + trace!("lh = {:?}", lh); - let id = left_expr_type(&*lh, var_env)?; - // var_env.update(id, expr_type)?; - Ok(Type::Unit) + let lh_type = expr_type(lh, fn_env, type_env, var_env)?; + trace!("lh_type {}", &lh_type); + + if match &lh_type { + Type::Mut(t) => **t == e_type, + + _ => Err(format!("assignment to immutable"))?, + } { + Ok(Type::Unit) + } else { + Err(format!("cannot assign {} = {}", &lh_type, e_type)) + } } While(e, block) => match expr_type(&*e, fn_env, type_env, var_env) { diff --git a/tests/test_check.rs b/tests/test_check.rs index 659152a951d52b193d05de1937e63c86c242e7b6..844b0b1395d6d8b47a3b8abb5a52e84cb206b7a2 100644 --- a/tests/test_check.rs +++ b/tests/test_check.rs @@ -144,3 +144,8 @@ fn check_ref_err2() { fn check_ref_err3() { assert!(check(&read_file::parse("examples/ref_err3.rs")).is_err()); } + +#[test] +fn check_ref_err4() { + assert!(check(&read_file::parse("examples/ref_err4.rs")).is_err()); +}