diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs
index dc44a52..91656ec 100644
--- a/nac3core/src/codegen/expr.rs
+++ b/nac3core/src/codegen/expr.rs
@@ -610,7 +610,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
                 if let ExprKind::Name { id, .. } = &func.as_ref().node {
                     // TODO: handle primitive casts and function pointers
                     let fun =
-                        self.resolver.lock().get_identifier_def(&id).expect("Unknown identifier");
+                        self.resolver.get_identifier_def(&id).expect("Unknown identifier");
                     let mut params =
                         args.iter().map(|arg| (None, self.gen_expr(arg).unwrap())).collect_vec();
                     let kw_iter = keywords.iter().map(|kw| {
diff --git a/nac3core/src/codegen/mod.rs b/nac3core/src/codegen/mod.rs
index 79c9699..ccedbe5 100644
--- a/nac3core/src/codegen/mod.rs
+++ b/nac3core/src/codegen/mod.rs
@@ -38,7 +38,7 @@ pub struct CodeGenContext<'ctx, 'a> {
     pub module: Module<'ctx>,
     pub top_level: &'a TopLevelContext,
     pub unifier: Unifier,
-    pub resolver: Arc<Mutex<Box<dyn SymbolResolver + Send + Sync>>>,
+    pub resolver: Arc<Box<dyn SymbolResolver + Send + Sync>>,
     pub var_assignment: HashMap<String, PointerValue<'ctx>>,
     pub type_cache: HashMap<Type, BasicTypeEnum<'ctx>>,
     pub primitives: PrimitiveStore,
@@ -190,7 +190,7 @@ pub struct CodeGenTask {
     pub body: Vec<Stmt<Option<Type>>>,
     pub calls: HashMap<CodeLocation, CallId>,
     pub unifier: (SharedUnifier, PrimitiveStore),
-    pub resolver: Arc<Mutex<Box<dyn SymbolResolver + Send + Sync>>>,
+    pub resolver: Arc<Box<dyn SymbolResolver + Send + Sync>>,
 }
 
 fn get_llvm_type<'ctx>(
diff --git a/nac3core/src/codegen/test.rs b/nac3core/src/codegen/test.rs
index dd61ae1..4d6d99e 100644
--- a/nac3core/src/codegen/test.rs
+++ b/nac3core/src/codegen/test.rs
@@ -43,10 +43,6 @@ impl SymbolResolver for Resolver {
     fn get_identifier_def(&self, id: &str) -> Option<DefinitionId> {
         self.id_to_def.read().get(id).cloned()
     }
-
-    fn add_id_def(&mut self, _: String, _: DefinitionId) {
-        unimplemented!()
-    }
 }
 
 #[test]
@@ -70,11 +66,11 @@ fn test_primitives() {
     //     class_names: Default::default(),
     // }) as Mutex<dyn SymbolResolver + Send + Sync>);
 
-    let resolver = Arc::new(Mutex::new(Box::new(Resolver {
+    let resolver = Arc::new(Box::new(Resolver {
         id_to_type: HashMap::new(),
         id_to_def: RwLock::new(HashMap::new()),
         class_names: Default::default(),
-    }) as Box<dyn SymbolResolver + Send + Sync>));
+    }) as Box<dyn SymbolResolver + Send + Sync>);
 
     let threads = ["test"];
     let signature = FunSignature {
@@ -236,7 +232,7 @@ fn test_simple_call() {
         class_names: Default::default(),
     });
     resolver.add_id_def("foo".to_string(), DefinitionId(foo_id));
-    let resolver = Arc::new(Mutex::new(resolver as Box<dyn SymbolResolver + Send + Sync>));
+    let resolver = Arc::new(resolver as Box<dyn SymbolResolver + Send + Sync>);
 
     if let TopLevelDef::Function { resolver: r, .. } =
         &mut *top_level.definitions.read()[foo_id].write()
diff --git a/nac3core/src/symbol_resolver.rs b/nac3core/src/symbol_resolver.rs
index a015d25..e28e2c7 100644
--- a/nac3core/src/symbol_resolver.rs
+++ b/nac3core/src/symbol_resolver.rs
@@ -35,7 +35,6 @@ pub trait SymbolResolver {
     fn get_identifier_def(&self, str: &str) -> Option<DefinitionId>;
     fn get_symbol_value(&self, str: &str) -> Option<SymbolValue>;
     fn get_symbol_location(&self, str: &str) -> Option<Location>;
-    fn add_id_def(&mut self, id: String, def_id: DefinitionId);
     // handle function call etc.
 }
 
diff --git a/nac3core/src/toplevel/helper.rs b/nac3core/src/toplevel/helper.rs
index ffdea0b..73325ad 100644
--- a/nac3core/src/toplevel/helper.rs
+++ b/nac3core/src/toplevel/helper.rs
@@ -87,7 +87,7 @@ impl TopLevelComposer {
     /// when first regitering, the type_vars, fields, methods, ancestors are invalid
     pub fn make_top_level_class_def(
         index: usize,
-        resolver: Option<Arc<Mutex<Box<dyn SymbolResolver + Send + Sync>>>>,
+        resolver: Option<Arc<Box<dyn SymbolResolver + Send + Sync>>>,
         name: &str,
     ) -> TopLevelDef {
         TopLevelDef::Class {
@@ -105,7 +105,7 @@ impl TopLevelComposer {
     pub fn make_top_level_function_def(
         name: String,
         ty: Type,
-        resolver: Option<Arc<Mutex<Box<dyn SymbolResolver + Send + Sync>>>>,
+        resolver: Option<Arc<Box<dyn SymbolResolver + Send + Sync>>>,
     ) -> TopLevelDef {
         TopLevelDef::Function {
             name,
diff --git a/nac3core/src/toplevel/mod.rs b/nac3core/src/toplevel/mod.rs
index e254feb..2cae756 100644
--- a/nac3core/src/toplevel/mod.rs
+++ b/nac3core/src/toplevel/mod.rs
@@ -1,11 +1,4 @@
-use std::{
-    borrow::BorrowMut,
-    collections::{HashMap, HashSet},
-    fmt::Debug,
-    iter::FromIterator,
-    ops::{Deref, DerefMut},
-    sync::Arc,
-};
+use std::{borrow::BorrowMut, collections::{HashMap, HashSet}, fmt::Debug, iter::FromIterator, ops::{Deref, DerefMut}, sync::Arc};
 
 use super::typecheck::type_inferencer::PrimitiveStore;
 use super::typecheck::typedef::{FunSignature, FuncArg, SharedUnifier, Type, TypeEnum, Unifier};
@@ -50,7 +43,7 @@ pub enum TopLevelDef {
         // ancestor classes, including itself.
         ancestors: Vec<TypeAnnotation>,
         // symbol resolver of the module defined the class, none if it is built-in type
-        resolver: Option<Arc<Mutex<Box<dyn SymbolResolver + Send + Sync>>>>,
+        resolver: Option<Arc<Box<dyn SymbolResolver + Send + Sync>>>,
     },
     Function {
         // prefix for symbol, should be unique globally, and not ending with numbers
@@ -71,7 +64,7 @@ pub enum TopLevelDef {
         /// rigid type variables that would be substituted when the function is instantiated.
         instance_to_stmt: HashMap<String, FunInstance>,
         // symbol resolver of the module defined the class
-        resolver: Option<Arc<Mutex<Box<dyn SymbolResolver + Send + Sync>>>>,
+        resolver: Option<Arc<Box<dyn SymbolResolver + Send + Sync>>>,
     },
     Initializer {
         class_id: DefinitionId,
@@ -162,7 +155,7 @@ impl TopLevelComposer {
     pub fn register_top_level(
         &mut self,
         ast: ast::Stmt<()>,
-        resolver: Option<Arc<Mutex<Box<dyn SymbolResolver + Send + Sync>>>>,
+        resolver: Option<Arc<Box<dyn SymbolResolver + Send + Sync>>>,
     ) -> Result<(String, DefinitionId), String> {
         let defined_class_name = &mut self.defined_class_name;
         let defined_class_method_name = &mut self.defined_class_method_name;
@@ -374,7 +367,7 @@ impl TopLevelComposer {
                         let type_vars = type_var_list
                             .into_iter()
                             .map(|e| {
-                                class_resolver.lock().parse_type_annotation(
+                                class_resolver.parse_type_annotation(
                                     &temp_def_list,
                                     unifier,
                                     primitives_store,
@@ -463,7 +456,7 @@ impl TopLevelComposer {
                 // the function parse_ast_to make sure that no type var occured in
                 // bast_ty if it is a CustomClassKind
                 let base_ty = parse_ast_to_type_annotation_kinds(
-                    class_resolver,
+                    class_resolver.as_ref(),
                     &temp_def_list,
                     unifier,
                     &self.primitives_ty,
@@ -550,6 +543,8 @@ impl TopLevelComposer {
             }
         }
 
+        println!("type_var_to_concrete_def1: {:?}", type_var_to_concrete_def);
+
         // handle the inheritanced methods and fields
         let mut current_ancestor_depth: usize = 2;
         loop {
@@ -584,11 +579,41 @@ impl TopLevelComposer {
             }
         }
 
+        // println!("type_var_to_concrete_def2: {:?}", type_var_to_concrete_def);
+
         // unification of previously assigned typevar
+        println!("type_var_to_concrete_def3: {:?}\n", type_var_to_concrete_def);
+        let mut ddddd: Vec<(Type, Type)> = Vec::new();
         for (ty, def) in type_var_to_concrete_def {
+            println!(
+                "{:?}_{} -> {:?}\n",
+                ty,
+                unifier.stringify(ty, 
+                    &mut |id| format!("class{}", id),
+                    &mut |id| format!("tvar{}", id)
+                ),
+                def
+            );
             let target_ty =
                 get_type_from_type_annotation_kinds(&temp_def_list, unifier, primitives, &def)?;
             unifier.unify(ty, target_ty)?;
+            ddddd.push((ty, target_ty));
+        }
+        
+        for (ty, tar_ty) in ddddd {
+            println!(
+                "{:?}_{} -> {:?}_{}",
+                ty,
+                unifier.stringify(ty, 
+                    &mut |id| format!("class{}", id),
+                    &mut |id| format!("tvar{}", id)
+                ),
+                tar_ty,
+                unifier.stringify(tar_ty, 
+                    &mut |id| format!("class{}", id),
+                    &mut |id| format!("tvar{}", id)
+                ),
+            )
         }
 
         Ok(())
@@ -649,7 +674,7 @@ impl TopLevelComposer {
                                     .as_ref();
 
                                 let type_annotation = parse_ast_to_type_annotation_kinds(
-                                    resolver,
+                                    resolver.as_ref(),
                                     temp_def_list.as_slice(),
                                     unifier,
                                     primitives_store,
@@ -695,7 +720,7 @@ impl TopLevelComposer {
                             let return_ty_annotation = {
                                 let return_annotation = returns.as_ref();
                                 parse_ast_to_type_annotation_kinds(
-                                    resolver,
+                                    resolver.as_ref(),
                                     &temp_def_list,
                                     unifier,
                                     primitives_store,
@@ -848,7 +873,7 @@ impl TopLevelComposer {
                                     .ok_or_else(|| "type annotation needed".to_string())?
                                     .as_ref();
                                 parse_ast_to_type_annotation_kinds(
-                                    class_resolver,
+                                    class_resolver.as_ref(),
                                     temp_def_list,
                                     unifier,
                                     primitives,
@@ -908,7 +933,7 @@ impl TopLevelComposer {
                         if let Some(result) = returns {
                             let result = result.as_ref();
                             let annotation = parse_ast_to_type_annotation_kinds(
-                                class_resolver,
+                                class_resolver.as_ref(),
                                 temp_def_list,
                                 unifier,
                                 primitives,
@@ -986,7 +1011,7 @@ impl TopLevelComposer {
                                         class_fields_def.push((attr.to_string(), dummy_field_type));
 
                                         let annotation = parse_ast_to_type_annotation_kinds(
-                                            class_resolver,
+                                            class_resolver.as_ref(),
                                             &temp_def_list,
                                             unifier,
                                             primitives,
diff --git a/nac3core/src/toplevel/test.rs b/nac3core/src/toplevel/test.rs
index e48e94c..4337ef9 100644
--- a/nac3core/src/toplevel/test.rs
+++ b/nac3core/src/toplevel/test.rs
@@ -15,15 +15,23 @@ use test_case::test_case;
 
 use super::*;
 
-struct Resolver {
-    id_to_type: HashMap<String, Type>,
-    id_to_def: HashMap<String, DefinitionId>,
-    class_names: HashMap<String, Type>,
+struct ResolverInternal {
+    id_to_type: Mutex<HashMap<String, Type>>,
+    id_to_def: Mutex<HashMap<String, DefinitionId>>,
+    class_names: Mutex<HashMap<String, Type>>,
 }
 
+impl ResolverInternal {
+    fn add_id_def(&self, id: String, def: DefinitionId) {
+        self.id_to_def.lock().insert(id, def);
+    }
+}
+
+struct Resolver(Arc<ResolverInternal>);
+
 impl SymbolResolver for Resolver {
     fn get_symbol_type(&self, _: &mut Unifier, _: &PrimitiveStore, str: &str) -> Option<Type> {
-        self.id_to_type.get(str).cloned()
+        self.0.id_to_type.lock().get(str).cloned()
     }
 
     fn get_symbol_value(&self, _: &str) -> Option<SymbolValue> {
@@ -35,12 +43,9 @@ impl SymbolResolver for Resolver {
     }
 
     fn get_identifier_def(&self, id: &str) -> Option<DefinitionId> {
-        self.id_to_def.get(id).cloned()
+        self.0.id_to_def.lock().get(id).cloned()
     }
 
-    fn add_id_def(&mut self, id: String, def: DefinitionId) {
-        self.id_to_def.insert(id, def);
-    }
 }
 
 #[test_case(
@@ -72,7 +77,8 @@ impl SymbolResolver for Resolver {
                     self.c: int32 = 4
                     self.a: bool = True
         "}
-    ]
+    ];
+    "register"
 )]
 fn test_simple_register(source: Vec<&str>) {
     let mut composer = TopLevelComposer::new();
@@ -109,23 +115,25 @@ fn test_simple_register(source: Vec<&str>) {
         "fun",
         "foo",
         "f"
-    ]
+    ];
+    "function compose"
 )]
 fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&str>) {
     let mut composer = TopLevelComposer::new();
 
-    let resolver = Arc::new(Mutex::new(Box::new(Resolver {
+    let internal_resolver = Arc::new(ResolverInternal {
         id_to_def: Default::default(),
         id_to_type: Default::default(),
         class_names: Default::default(),
-    }) as Box<dyn SymbolResolver + Send + Sync>));
+    });
+    let resolver = Arc::new(Box::new(Resolver(internal_resolver.clone())) as Box<dyn SymbolResolver + Send + Sync>);
 
     for s in source {
         let ast = parse_program(s).unwrap();
         let ast = ast[0].clone();
 
         let (id, def_id) = composer.register_top_level(ast, Some(resolver.clone())).unwrap();
-        resolver.lock().add_id_def(id, def_id);
+        internal_resolver.add_id_def(id, def_id);
     }
 
     composer.start_analysis().unwrap();
@@ -245,7 +253,19 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
         sig: \"fn[[a=5], 4]\",
         var_id: []
         }"},
-    ]
+    ];
+    "simple class compose"
+)]
+#[test_case(
+    vec![
+        indoc! {"
+            class Generic_A(Generic[T, V]):
+                def __init__():
+                    pass
+        "}
+    ],
+    vec![];
+    "generic class"
 )]
 fn test_simple_class_analyze(source: Vec<&str>, res: Vec<&str>) {
     let mut composer = TopLevelComposer::new();
@@ -254,23 +274,24 @@ fn test_simple_class_analyze(source: Vec<&str>, res: Vec<&str>) {
     let tvar_v = composer
         .unifier
         .get_fresh_var_with_range(&[composer.primitives_ty.bool, composer.primitives_ty.int32]);
-    println!("t: {}", tvar_t.1);
-    println!("v: {}\n", tvar_v.1);
+    println!("t: {}, {:?}", tvar_t.1, tvar_t.0);
+    println!("v: {}, {:?}\n", tvar_v.1, tvar_v.0);
 
-    let resolver = Arc::new(Mutex::new(Box::new(Resolver {
+    let internal_resolver = Arc::new(ResolverInternal {
         id_to_def: Default::default(),
-        id_to_type: vec![("T".to_string(), tvar_t.0), ("V".to_string(), tvar_v.0)]
-            .into_iter()
-            .collect(),
+        id_to_type: Mutex::new(vec![("T".to_string(), tvar_t.0), ("V".to_string(), tvar_v.0)]
+        .into_iter()
+        .collect()),
         class_names: Default::default(),
-    }) as Box<dyn SymbolResolver + Send + Sync>));
+    });
+    let resolver = Arc::new(Box::new(Resolver(internal_resolver.clone())) as Box<dyn SymbolResolver + Send + Sync>);
 
     for s in source {
         let ast = parse_program(s).unwrap();
         let ast = ast[0].clone();
 
         let (id, def_id) = composer.register_top_level(ast, Some(resolver.clone())).unwrap();
-        resolver.lock().add_id_def(id, def_id);
+        internal_resolver.add_id_def(id, def_id);
     }
 
     composer.start_analysis().unwrap();
@@ -278,15 +299,15 @@ fn test_simple_class_analyze(source: Vec<&str>, res: Vec<&str>) {
     // skip 5 to skip primitives
     for (i, (def, _)) in composer.definition_ast_list.iter().skip(5).enumerate() {
         let def = &*def.read();
-        println!(
-            "{}: {}\n",
-            i + 5,
-            def.to_string(
-                composer.unifier.borrow_mut(),
-                &mut |id| format!("class{}", id),
-                &mut |id| format!("tvar{}", id)
-            )
-        );
+        // println!(
+        //     "{}: {}\n",
+        //     i + 5,
+        //     def.to_string(
+        //         composer.unifier.borrow_mut(),
+        //         &mut |id| format!("class{}", id),
+        //         &mut |id| format!("tvar{}", id)
+        //     )
+        // );
         // assert_eq!(
         //     format!(
         //         "{}: {}",
diff --git a/nac3core/src/toplevel/type_annotation.rs b/nac3core/src/toplevel/type_annotation.rs
index 3834505..291937f 100644
--- a/nac3core/src/toplevel/type_annotation.rs
+++ b/nac3core/src/toplevel/type_annotation.rs
@@ -1,3 +1,5 @@
+use std::cell::RefCell;
+
 use crate::typecheck::typedef::TypeVarMeta;
 
 use super::*;
@@ -19,7 +21,7 @@ pub enum TypeAnnotation {
 }
 
 pub fn parse_ast_to_type_annotation_kinds<T>(
-    resolver: &Mutex<Box<dyn SymbolResolver + Send + Sync>>,
+    resolver: &(dyn SymbolResolver + Send + Sync),
     top_level_defs: &[Arc<RwLock<TopLevelDef>>],
     unifier: &mut Unifier,
     primitives: &PrimitiveStore,
@@ -36,7 +38,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
                 if let Some(obj_id) = {
                     // write this way because the lock in the if/let construct lives
                     // for the whole if let construct
-                    let id = resolver.lock().get_identifier_def(x);
+                    let id = resolver.get_identifier_def(x);
                     id
                 } {
                     let def = top_level_defs[obj_id.0].read();
@@ -53,7 +55,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
                         Err("function cannot be used as a type".into())
                     }
                 } else if let Some(ty) = {
-                    let ty = resolver.lock().get_symbol_type(unifier, primitives, id);
+                    let ty = resolver.get_symbol_type(unifier, primitives, id);
                     ty
                 } {
                     if let TypeEnum::TVar { .. } = unifier.get_ty(ty).as_ref() {
@@ -128,7 +130,6 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
                     return Err("keywords cannot be class name".into());
                 }
                 let obj_id = resolver
-                    .lock()
                     .get_identifier_def(id)
                     .ok_or_else(|| "unknown class name".to_string())?;
                 let def = top_level_defs[obj_id.0].read();
@@ -237,9 +238,22 @@ pub fn get_type_from_type_annotation_kinds(
                         let subst_ty = unifier.subst(*ty, &subst).unwrap_or(*ty);
                         (name.clone(), subst_ty)
                     }));
+
+                    println!("tobj_fields: {:?}", tobj_fields);
+                    println!("{:?}: {}\n", 
+                        tobj_fields.get("__init__").unwrap(),
+                        unifier.stringify(
+                            *tobj_fields.get("__init__").unwrap(), 
+                            &mut |id| format!("class{}", id),
+                            &mut |id| format!("tvar{}", id)
+                        )
+                    );
+                    
                     Ok(unifier.add_ty(TypeEnum::TObj {
                         obj_id: *id,
-                        fields: tobj_fields.into(),
+                        //fields: RefCell::new(tobj_fields),
+                        fields: RefCell::new(HashMap::new()),
+                        // fields: Default::default(),
                         params: subst.into(),
                     }))
                 }
diff --git a/nac3core/src/typecheck/function_check.rs b/nac3core/src/typecheck/function_check.rs
index 4988a3d..0330661 100644
--- a/nac3core/src/typecheck/function_check.rs
+++ b/nac3core/src/typecheck/function_check.rs
@@ -57,7 +57,7 @@ impl<'a> Inferencer<'a> {
         match &expr.node {
             ExprKind::Name { id, .. } => {
                 if !defined_identifiers.contains(id) {
-                    if self.function_data.resolver.lock().get_identifier_def(id).is_some() {
+                    if self.function_data.resolver.get_identifier_def(id).is_some() {
                         defined_identifiers.insert(id.clone());
                     } else {
                         return Err(format!(
diff --git a/nac3core/src/typecheck/type_inferencer/mod.rs b/nac3core/src/typecheck/type_inferencer/mod.rs
index 68a3d4d..57e19b0 100644
--- a/nac3core/src/typecheck/type_inferencer/mod.rs
+++ b/nac3core/src/typecheck/type_inferencer/mod.rs
@@ -39,7 +39,7 @@ pub struct PrimitiveStore {
 }
 
 pub struct FunctionData {
-    pub resolver: Arc<Mutex<Box<dyn SymbolResolver + Send + Sync>>>,
+    pub resolver: Arc<Box<dyn SymbolResolver + Send + Sync>>,
     pub return_type: Option<Type>,
     pub bound_variables: Vec<Type>,
 }
@@ -89,7 +89,7 @@ impl<'a> fold::Fold<()> for Inferencer<'a> {
                     ));
                 };
                 let top_level_defs = self.top_level.definitions.read();
-                let annotation_type = self.function_data.resolver.lock().parse_type_annotation(
+                let annotation_type = self.function_data.resolver.parse_type_annotation(
                     top_level_defs.as_slice(),
                     self.unifier,
                     &self.primitives,
@@ -164,7 +164,7 @@ impl<'a> fold::Fold<()> for Inferencer<'a> {
             ast::ExprKind::Constant { value, .. } => Some(self.infer_constant(value)?),
             ast::ExprKind::Name { id, .. } => {
                 if !self.defined_identifiers.contains(id) {
-                    if self.function_data.resolver.lock().get_identifier_def(id.as_str()).is_some()
+                    if self.function_data.resolver.get_identifier_def(id.as_str()).is_some()
                     {
                         self.defined_identifiers.insert(id.clone());
                     } else {
@@ -405,7 +405,7 @@ impl<'a> Inferencer<'a> {
                     let arg0 = self.fold_expr(args.remove(0))?;
                     let ty = if let Some(arg) = args.pop() {
                         let top_level_defs = self.top_level.definitions.read();
-                        self.function_data.resolver.lock().parse_type_annotation(
+                        self.function_data.resolver.parse_type_annotation(
                             top_level_defs.as_slice(),
                             self.unifier,
                             self.primitives,
@@ -483,10 +483,9 @@ impl<'a> Inferencer<'a> {
         if let Some(ty) = self.variable_mapping.get(id) {
             Ok(*ty)
         } else {
-            let resolver = self.function_data.resolver.lock();
             let variable_mapping = &mut self.variable_mapping;
             let unifier = &mut self.unifier;
-            Ok(resolver.get_symbol_type(unifier, self.primitives, id).unwrap_or_else(|| {
+            Ok(self.function_data.resolver.get_symbol_type(unifier, self.primitives, id).unwrap_or_else(|| {
                 let ty = unifier.get_fresh_var().0;
                 variable_mapping.insert(id.to_string(), ty);
                 ty
diff --git a/nac3core/src/typecheck/type_inferencer/test.rs b/nac3core/src/typecheck/type_inferencer/test.rs
index 3a507bd..bf1c372 100644
--- a/nac3core/src/typecheck/type_inferencer/test.rs
+++ b/nac3core/src/typecheck/type_inferencer/test.rs
@@ -33,10 +33,6 @@ impl SymbolResolver for Resolver {
     fn get_identifier_def(&self, id: &str) -> Option<DefinitionId> {
         self.id_to_def.get(id).cloned()
     }
-
-    fn add_id_def(&mut self, _: String, _: DefinitionId) {
-        unimplemented!()
-    }
 }
 
 struct TestEnvironment {
@@ -96,11 +92,11 @@ impl TestEnvironment {
         let mut identifier_mapping = HashMap::new();
         identifier_mapping.insert("None".into(), none);
 
-        let resolver = Arc::new(Mutex::new(Box::new(Resolver {
+        let resolver = Arc::new(Box::new(Resolver {
             id_to_type: identifier_mapping.clone(),
             id_to_def: Default::default(),
             class_names: Default::default(),
-        }) as Box<dyn SymbolResolver + Send + Sync>));
+        }) as Box<dyn SymbolResolver + Send + Sync>);
 
         TestEnvironment {
             top_level: TopLevelContext {
@@ -279,7 +275,7 @@ impl TestEnvironment {
             unifiers: Default::default(),
         };
 
-        let resolver = Arc::new(Mutex::new(Box::new(Resolver {
+        let resolver = Arc::new(Box::new(Resolver {
             id_to_type: identifier_mapping.clone(),
             id_to_def: [
                 ("Foo".into(), DefinitionId(5)),
@@ -290,7 +286,7 @@ impl TestEnvironment {
             .cloned()
             .collect(),
             class_names,
-        }) as Box<dyn SymbolResolver + Send + Sync>));
+        }) as Box<dyn SymbolResolver + Send + Sync>);
 
         TestEnvironment {
             unifier,
diff --git a/nac3standalone/src/basic_symbol_resolver.rs b/nac3standalone/src/basic_symbol_resolver.rs
index b74c27f..8b0a16d 100644
--- a/nac3standalone/src/basic_symbol_resolver.rs
+++ b/nac3standalone/src/basic_symbol_resolver.rs
@@ -32,8 +32,4 @@ impl SymbolResolver for Resolver {
     fn get_identifier_def(&self, id: &str) -> Option<DefinitionId> {
         self.id_to_def.get(id).cloned()
     }
-
-    fn add_id_def(&mut self, _: String, _: DefinitionId) {
-        unimplemented!();
-    }
 }
diff --git a/nac3standalone/src/main.rs b/nac3standalone/src/main.rs
index 682ca30..06ee2a2 100644
--- a/nac3standalone/src/main.rs
+++ b/nac3standalone/src/main.rs
@@ -164,11 +164,11 @@ fn main() {
         .collect();
     id_to_type.insert("output".into(), output_fun);
 
-    let resolver = Arc::new(Mutex::new(Box::new(basic_symbol_resolver::Resolver {
+    let resolver = Arc::new(Box::new(basic_symbol_resolver::Resolver {
         class_names: Default::default(),
         id_to_type,
         id_to_def,
-    }) as Box<dyn SymbolResolver + Send + Sync>));
+    }) as Box<dyn SymbolResolver + Send + Sync>);
 
     for (_, (id, ast, signature)) in functions.into_iter() {
         if let TopLevelDef::Function {
@@ -253,7 +253,7 @@ fn main() {
 
     let instance = {
         let defs = top_level.definitions.read();
-        let mut instance = defs[resolver.lock().get_identifier_def("run").unwrap().0].write();
+        let mut instance = defs[resolver.get_identifier_def("run").unwrap().0].write();
         if let TopLevelDef::Function {
             instance_to_stmt,
             instance_to_symbol,