diff --git a/examples/mut.rs b/examples/mut.rs
index a93ad514f1a2d99ec15ecb020564d501bc5698f9..ec2e14053f4a8740ff49f79be78c004f2d13d5b0 100644
--- a/examples/mut.rs
+++ b/examples/mut.rs
@@ -1,5 +1,5 @@
-fn main() -> i32 {
+fn main() {
     let mut a = 0;
     a = 2;
-    a
+    let b = a;
 }
diff --git a/examples/mut2.rs b/examples/mut2.rs
index 21669598482275164deae1278c391f309ca2646e..33fd4af8276b1200ed6b92eb5603385a39dcd51d 100644
--- a/examples/mut2.rs
+++ b/examples/mut2.rs
@@ -1,8 +1,8 @@
-fn main() -> i32 {
+fn main() {
     let mut a = 0;
     a = 2;
     let mut b = a; // copy semantics
     a = 3;
     b = b + 1;
-    a + b
+    let c = a + b;
 }
diff --git a/src/check.rs b/src/check.rs
index 1b169440030c1ce171971d696dddaba23240f9b5..18d567543835c534b225eeaad6d535c8e5f4a9bb 100644
--- a/src/check.rs
+++ b/src/check.rs
@@ -190,6 +190,41 @@ fn expr_type(
     }
 }
 
+fn lexpr_type<'a>(
+    e: &Expr,
+    fn_env: &FnEnv,
+    type_env: &TypeEnv,
+    var_env: &'a mut VarEnv,
+) -> Result<&'a mut Type, Error> {
+    use Expr::*;
+    trace!("expr_type {}", e);
+    trace!("var_env {:?}", var_env);
+
+    match e {
+        Id(id) => match var_env.get_mut(id.to_string()) {
+            Some(t) => Ok(t),
+            None => Err(format!("variable not found {}", id)),
+        },
+
+        DeRef(deref_e) => {
+            let t = lexpr_type(deref_e, fn_env, type_env, var_env)?;
+            trace!("deref_t {}", &t);
+
+            // strip mut
+            let t = match t {
+                Type::Mut(t) => t,
+                _ => t,
+            };
+            trace!("strip deref_t {}", t);
+            match t {
+                Type::Ref(dt) => Ok(dt),
+                _ => Err(format!("cannot deref {} of type {}", e, t)),
+            }
+        }
+        _ => Err(format!("Illegal left hand expression {}", e)),
+    }
+}
+
 fn strip_mut(t: Type) -> Type {
     match t {
         Type::Mut(t) => *t,
@@ -228,7 +263,8 @@ pub fn check_stmts(
                 let t: Type = match (ot, oe) {
                     (Some(t), Some(e)) => {
                         let e_type = expr_type(&*e, fn_env, type_env, var_env)?;
-                        match *t == e_type {
+                        let e_type = strip_mut(e_type);
+                        match strip_mut(t.clone()) == e_type {
                             true => t.clone(),
                             false => {
                                 trace!("e {}", e);
@@ -237,9 +273,9 @@ pub fn check_stmts(
                         }
                     }
                     (None, Some(e)) => {
-                        let et = expr_type(&*e, fn_env, type_env, var_env)?;
-                        match is_known(&et) {
-                            true => et,
+                        let e_type = strip_mut(expr_type(&*e, fn_env, type_env, var_env)?);
+                        match is_known(&e_type) {
+                            true => e_type,
                             _ => Err("reference to unknown type".to_string())?,
                         }
                     }
@@ -256,21 +292,28 @@ pub fn check_stmts(
             }
 
             Assign(lh, e) => {
+                trace!("assign");
+
                 let e_type = expr_type(&*e, fn_env, type_env, var_env)?;
-                trace!("e_type = {}", e_type);
-                trace!("lh = {:?}", lh);
+                trace!("e_type = {}", &e_type);
+                let e_type = strip_mut(e_type);
+                trace!("e_type stripped = {}", &e_type);
+
+                trace!("lh expr = {:?}", lh);
 
-                let lh_type = expr_type(lh, fn_env, type_env, var_env)?;
-                trace!("lh_type {}", &lh_type);
+                let lh_type = lexpr_type(lh, fn_env, type_env, var_env)?;
+                trace!("lh_type {}", lh_type);
 
-                if match &lh_type {
+                if match lh_type {
                     Type::Unknown => {
                         trace!("assign to unknown");
+                        *lh_type = e_type.clone();
                         true
                     }
                     Type::Mut(t) => match **t {
                         Type::Unknown => {
                             trace!("assign to `mut Unknown`");
+                            *t = Box::new(e_type.clone());
                             true
                         }
                         _ => **t == e_type,
diff --git a/tests/test_check.rs b/tests/test_check.rs
index d1209487f4d4d1e1d01863d9332d7e5602f9765e..6334148554f2942ae619d7e2a71c40ea61f5d876 100644
--- a/tests/test_check.rs
+++ b/tests/test_check.rs
@@ -21,6 +21,11 @@ fn check_assign2() {
     assert!(check(&read_file::parse("examples/assign2.rs")).is_ok());
 }
 
+#[test]
+fn check_assign3() {
+    assert!(check(&read_file::parse("examples/assign3.rs")).is_ok());
+}
+
 #[test]
 fn check_assign_err() {
     assert!(check(&read_file::parse("examples/assign_err.rs")).is_err());
@@ -154,3 +159,13 @@ fn check_ref_err3() {
 fn check_ref_err4() {
     assert!(check(&read_file::parse("examples/ref_err4.rs")).is_err());
 }
+
+#[test]
+fn check_scopes() {
+    assert!(check(&read_file::parse("examples/scopes.rs")).is_ok());
+}
+
+#[test]
+fn check_scopes_err() {
+    assert!(check(&read_file::parse("examples/scopes_err.rs")).is_err());
+}
diff --git a/tests/test_vm.rs b/tests/test_vm.rs
index 27086b6f8606e08a5be220f8124c5deb43406fb5..33d77295160878024b5784eb8dae75c171cdf049 100644
--- a/tests/test_vm.rs
+++ b/tests/test_vm.rs
@@ -35,6 +35,10 @@ fn scopes_test() {
     eval_prog("examples/scopes.rs");
 }
 
+#[test]
+fn scopes_err_test() {
+    eval_prog("examples/scopes_err.rs");
+}
 #[test]
 fn vm_test() {
     eval_prog("examples/vm.rs");