diff --git a/case_studies/tests/src/structs.rs b/case_studies/tests/src/structs.rs
index 181449786bba1d642b6df9484cf7d452aec50153..179fc3d078206725b0abe0fd96fc345c576577f9 100644
--- a/case_studies/tests/src/structs.rs
+++ b/case_studies/tests/src/structs.rs
@@ -56,3 +56,23 @@ impl EvenInt {
         self.add();
     }
 }
+
+
+
+pub struct Foo {}
+
+impl Foo {
+    #[rr::params("x", "γ")]
+    #[rr::args("(#x, γ)")]
+    #[rr::returns("()")]
+    pub fn a(&mut self) {
+        assert!(true);
+    }
+
+    #[rr::params("x", "γ")]
+    #[rr::args("(#x, γ)")]
+    #[rr::returns("()")]
+    pub fn b(&mut self) {
+        assert!(true);
+    }
+}
diff --git a/rr_frontend/translation/src/lib.rs b/rr_frontend/translation/src/lib.rs
index b3a42dad9eedee3601b8a3a4ae4eb48069f8021f..5cf086378e6f6919f09cf5e93f6a2dc7ac6a7538 100644
--- a/rr_frontend/translation/src/lib.rs
+++ b/rr_frontend/translation/src/lib.rs
@@ -629,17 +629,17 @@ fn translate_functions<'rcx, 'tcx>(vcx: &mut VerificationCtxt<'tcx, 'rcx>) {
             // Only generate a spec
             match translator.and_then(|t| t.generate_spec()) {
                 Ok(spec) => {
-                    info!("Successfully generated spec for {}", fname);
+                    println!("Successfully generated spec for {}", fname);
                     vcx.procedure_registry.provide_specced_function(&f.to_def_id(), spec);
                 },
                 Err(function_body::TranslationError::FatalError(err)) => {
-                    error!("Encountered fatal cross-function error in translation: {:?}", err);
-                    error!("Aborting...");
+                    println!("Encountered fatal cross-function error in translation: {:?}", err);
+                    println!("Aborting...");
                     return;
                 },
                 Err(err) => {
-                    warn!("Encountered error: {:?}", err);
-                    warn!("Skipping function {}", fname);
+                    println!("Encountered error: {:?}", err);
+                    println!("Skipping function {}", fname);
                     if !rrconfig::skip_unsupported_features() {
                         exit_with_error(&format!("Encountered error when translating function {}, stopping...", fname));
                     }
@@ -650,17 +650,17 @@ fn translate_functions<'rcx, 'tcx>(vcx: &mut VerificationCtxt<'tcx, 'rcx>) {
             // Fully translate the function
             match translator.and_then(|t| t.translate()) {
                 Ok(fun) => {
-                    info!("Successfully translated {}", fname);
+                    println!("Successfully translated {}", fname);
                     vcx.procedure_registry.provide_translated_function(&f.to_def_id(), fun);
                 },
                 Err(function_body::TranslationError::FatalError(err)) => {
-                    error!("Encountered fatal cross-function error in translation: {:?}", err);
-                    error!("Aborting...");
+                    println!("Encountered fatal cross-function error in translation: {:?}", err);
+                    println!("Aborting...");
                     return;
                 },
                 Err(err) => {
-                    warn!("Encountered error: {:?}", err);
-                    warn!("Skipping function {}", fname);
+                    println!("Encountered error: {:?}", err);
+                    println!("Skipping function {}", fname);
                     if !rrconfig::skip_unsupported_features() {
                         exit_with_error(&format!("Encountered error when translating function {}, stopping...", fname));
                     }
diff --git a/rr_frontend/translation/src/type_translator.rs b/rr_frontend/translation/src/type_translator.rs
index ecb9961ee83b1bcb4648aa223f299fef03b20437..0b98511a1fd6e84357b3e6d9c80853b5de66a602 100644
--- a/rr_frontend/translation/src/type_translator.rs
+++ b/rr_frontend/translation/src/type_translator.rs
@@ -393,19 +393,23 @@ impl <'def, 'tcx : 'def> TypeTranslator<'def, 'tcx> {
         let mut generic_syntys = Vec::new();
 
         for arg in args.into_iter() {
-            let arg_ty = arg.expect_ty();
-            let mut translated_ty;
-            if let Some(ref mut adt_deps) = adt_deps {
-                translated_ty = self.translate_type_with_deps(&arg_ty, Some(&mut *adt_deps))?;
+            if let Some(arg_ty) = arg.as_type() {
+                let mut translated_ty;
+                if let Some(ref mut adt_deps) = adt_deps {
+                    translated_ty = self.translate_type_with_deps(&arg_ty, Some(&mut *adt_deps))?;
+                }
+                else {
+                    translated_ty = self.translate_type_with_deps(&arg_ty, None)?;
+                }
+                // we need to substitute in the variables according to the function scope
+                translated_ty.subst(generic_env.as_slice());
+                //translated_ty.subst
+                generic_syntys.push(translated_ty.get_syn_type());
+                params.push(translated_ty);
             }
             else {
-                translated_ty = self.translate_type_with_deps(&arg_ty, None)?;
+                return Err(TranslationError::UnsupportedFeature{ description: "structs with lifetime parameters are not supported".to_string()})
             }
-            // we need to substitute in the variables according to the function scope
-            translated_ty.subst(generic_env.as_slice());
-            //translated_ty.subst
-            generic_syntys.push(translated_ty.get_syn_type());
-            params.push(translated_ty);
         }
 
         let struct_use = radium::AbstractStructUse::new(struct_ref, params, radium::TypeIsRaw::No);
@@ -580,27 +584,35 @@ impl <'def, 'tcx : 'def> TypeTranslator<'def, 'tcx> {
         let struct_name = strip_coq_ident(&ty.ident(tcx).to_string());
         self.variant_registry.borrow_mut().insert(ty.def_id, (struct_name.clone(), &*struct_def_init, ty, false));
 
-        let struct_name = strip_coq_ident(&ty.ident(tcx).to_string());
-        let (variant_def, invariant_def) = self.make_adt_variant(&struct_name, ty, adt, &ty_param_defs, &st_params, Some(&mut adt_deps))?;
-
-        let mut struct_def = radium::AbstractStruct::new(variant_def, ty_param_defs, st_params);
-        if let Some(invariant_def) = invariant_def {
-            struct_def.add_invariant(invariant_def);
-        }
+        let translate_adt = || {
+            let struct_name = strip_coq_ident(&ty.ident(tcx).to_string());
+            let (variant_def, invariant_def) = self.make_adt_variant(&struct_name, ty, adt, &ty_param_defs, &st_params, Some(&mut adt_deps))?;
 
-        // TODO for generating the semtype definition, we will also need to track dependencies
-        // between structs so that we know when we need recursive types etc.
+            let mut struct_def = radium::AbstractStruct::new(variant_def, ty_param_defs, st_params);
+            if let Some(invariant_def) = invariant_def {
+                struct_def.add_invariant(invariant_def);
+            }
+            Ok(struct_def)
+        };
 
-        // finalize the definition
-        {
-            let mut struct_def_ref = struct_def_init.borrow_mut();
-            *struct_def_ref = Some(struct_def);
+        match translate_adt() {
+            Ok(struct_def) => {
+                // finalize the definition
+                // TODO for generating the semtype definition, we will also need to track dependencies
+                // between structs so that we know when we need recursive types etc.
+                let mut struct_def_ref = struct_def_init.borrow_mut();
+                *struct_def_ref = Some(struct_def);
 
-            let mut deps_ref = self.adt_deps.borrow_mut();
-            deps_ref.insert(adt.did(), adt_deps);
+                let mut deps_ref = self.adt_deps.borrow_mut();
+                deps_ref.insert(adt.did(), adt_deps);
+                Ok(())
+            }
+            Err(err) => {
+                // remove the partial definition
+                self.variant_registry.borrow_mut().remove(&ty.def_id);
+                Err(err)
+            }
         }
-
-        Ok(())
     }
 
     /// Make an ADT variant.
@@ -881,7 +893,6 @@ impl <'def, 'tcx : 'def> TypeTranslator<'def, 'tcx> {
 
         // TODO: currently a hack, I don't know how to query the name properly
         let enum_name = strip_coq_ident(format!("{:?}", def).as_str());
-        self.enum_registry.borrow_mut().insert(def.did(), (enum_name.clone(), &*enum_def_init, def));
 
         // first thing: figure out the generics we are using here.
         // we need to search all of the variant types for that.
@@ -906,131 +917,142 @@ impl <'def, 'tcx : 'def> TypeTranslator<'def, 'tcx> {
 
         info!("enum using generics: {:?}", used_generics);
 
-        // now build masks describing which generics each of the variants uses
-        // and register the variants
-        let mut variant_masks: HashMap<DefId, Vec<bool>> = HashMap::new();
-        let mut variant_attrs = Vec::new();
-        for v in def.variants().iter() {
-            let mut folder = TyVarFolder::new(self.env.tcx());
-            for f in v.fields.iter() {
-                let f_ty = self.env.tcx().type_of(f.did).instantiate_identity();
-                f_ty.fold_with(&mut folder);
-            }
-            let variant_generics: HashSet<ty::ParamTy> = folder.get_result();
-
-            let mut mask = Vec::new();
-            let mut these_param_defs = Vec::new();
-            let mut these_st_params = Vec::new();
-            for ((param, param_defs), st_param) in used_generics.iter().zip(ty_param_defs.iter()).zip(st_params.iter()) {
-                if variant_generics.contains(param) {
-                    mask.push(true);
-                    these_param_defs.push(param_defs.clone());
-                    these_st_params.push(st_param.clone());
+        // insert partial definition for recursive occurrences
+        self.enum_registry.borrow_mut().insert(def.did(), (enum_name.clone(), &*enum_def_init, def));
+
+        let translate_variants = || {
+            // now build masks describing which generics each of the variants uses
+            // and register the variants
+            let mut variant_masks: HashMap<DefId, Vec<bool>> = HashMap::new();
+            let mut variant_attrs = Vec::new();
+            for v in def.variants().iter() {
+                let mut folder = TyVarFolder::new(self.env.tcx());
+                for f in v.fields.iter() {
+                    let f_ty = self.env.tcx().type_of(f.did).instantiate_identity();
+                    f_ty.fold_with(&mut folder);
                 }
-                else {
-                    mask.push(false);
+                let variant_generics: HashSet<ty::ParamTy> = folder.get_result();
+
+                let mut mask = Vec::new();
+                let mut these_param_defs = Vec::new();
+                let mut these_st_params = Vec::new();
+                for ((param, param_defs), st_param) in used_generics.iter().zip(ty_param_defs.iter()).zip(st_params.iter()) {
+                    if variant_generics.contains(param) {
+                        mask.push(true);
+                        these_param_defs.push(param_defs.clone());
+                        these_st_params.push(st_param.clone());
+                    }
+                    else {
+                        mask.push(false);
+                    }
                 }
-            }
-            variant_masks.insert(v.def_id, mask);
+                variant_masks.insert(v.def_id, mask);
 
-            // now generate the variant
-            let struct_def_init = self.struct_arena.alloc(RefCell::new(None));
+                // now generate the variant
+                let struct_def_init = self.struct_arena.alloc(RefCell::new(None));
 
-            let struct_name = strip_coq_ident(format!("{}_{}", enum_name, v.ident(tcx)).as_str());
-            self.variant_registry.borrow_mut().insert(v.def_id, (struct_name.clone(), &*struct_def_init, v, true));
+                let struct_name = strip_coq_ident(format!("{}_{}", enum_name, v.ident(tcx)).as_str());
+                self.variant_registry.borrow_mut().insert(v.def_id, (struct_name.clone(), &*struct_def_init, v, true));
 
-            // IMPORTANT: use the full enum's ty_param_defs to account for indexing
-            let (variant_def, invariant_def) = self.make_adt_variant(struct_name.as_str(), v, def, &ty_param_defs, &st_params, Some(&mut adt_deps))?;
+                // IMPORTANT: use the full enum's ty_param_defs to account for indexing
+                let (variant_def, invariant_def) = self.make_adt_variant(struct_name.as_str(), v, def, &ty_param_defs, &st_params, Some(&mut adt_deps))?;
 
-            // IMPORTANT: use the subset of actually used params for the definition
-            let mut struct_def = radium::AbstractStruct::new(variant_def, these_param_defs, these_st_params);
-            if let Some(invariant_def) = invariant_def {
-                struct_def.add_invariant(invariant_def);
-            }
+                // IMPORTANT: use the subset of actually used params for the definition
+                let mut struct_def = radium::AbstractStruct::new(variant_def, these_param_defs, these_st_params);
+                if let Some(invariant_def) = invariant_def {
+                    struct_def.add_invariant(invariant_def);
+                }
 
-            // also remember the attributes for additional processing
-            let outer_attrs = self.env.get_attributes(v.def_id);
-            let outer_attrs = crate::utils::filter_tool_attrs(outer_attrs);
-            variant_attrs.push(outer_attrs);
+                // also remember the attributes for additional processing
+                let outer_attrs = self.env.get_attributes(v.def_id);
+                let outer_attrs = crate::utils::filter_tool_attrs(outer_attrs);
+                variant_attrs.push(outer_attrs);
 
-            // finalize the definition
-            {
-                let mut struct_def_ref = struct_def_init.borrow_mut();
-                *struct_def_ref = Some(struct_def);
+                // finalize the definition
+                {
+                    let mut struct_def_ref = struct_def_init.borrow_mut();
+                    *struct_def_ref = Some(struct_def);
+                }
             }
-        }
 
-        // get the type of the discriminant
-        let it = def.repr().discr_type();
-        let translated_it = self.translate_integer_type(it)?;
+            // get the type of the discriminant
+            let it = def.repr().discr_type();
+            let translated_it = self.translate_integer_type(it)?;
 
-        // build the discriminant map
-        let discrs = self.build_discriminant_map(def)?;
+            // build the discriminant map
+            let discrs = self.build_discriminant_map(def)?;
 
-        // get representation options
-        let repr = def.repr();
-        let mut repr_opt = radium::EnumRepr::ReprRust;
-        if repr.c() {
-            repr_opt = radium::EnumRepr::ReprC;
-        }
-        else if repr.simd() {
-            return Err(TranslationError::UnsupportedFeature { description: "The SIMD flag is currently unsupported".to_string() })
-        }
-        else if repr.packed() {
-            return Err(TranslationError::UnsupportedFeature { description: "The repr(packed) flag is currently unsupported".to_string() })
-        }
-        else if repr.linear() {
-            return Err(TranslationError::UnsupportedFeature { description: "The linear flag is currently unsupported".to_string() })
-        }
-        else if repr.transparent() {
-            repr_opt = radium::EnumRepr::ReprTransparent;
-        }
+            // get representation options
+            let repr = def.repr();
+            let mut repr_opt = radium::EnumRepr::ReprRust;
+            if repr.c() {
+                repr_opt = radium::EnumRepr::ReprC;
+            }
+            else if repr.simd() {
+                return Err(TranslationError::UnsupportedFeature { description: "The SIMD flag is currently unsupported".to_string() })
+            }
+            else if repr.packed() {
+                return Err(TranslationError::UnsupportedFeature { description: "The repr(packed) flag is currently unsupported".to_string() })
+            }
+            else if repr.linear() {
+                return Err(TranslationError::UnsupportedFeature { description: "The linear flag is currently unsupported".to_string() })
+            }
+            else if repr.transparent() {
+                repr_opt = radium::EnumRepr::ReprTransparent;
+            }
 
-        // parse annotations for enum type
-        let enum_spec;
-        let mut inductive_decl = None;
-        let builtin_spec = self.get_builtin_enum_spec(def.did())?;
-        if let Some(spec) = builtin_spec {
-            enum_spec = spec;
-        }
-        else if self.env.has_tool_attribute(def.did(), "refined_by") {
-            let attributes = self.env.get_attributes(def.did());
-            let attributes = crate::utils::filter_tool_attrs(attributes);
+            // parse annotations for enum type
+            let enum_spec;
+            let mut inductive_decl = None;
+            let builtin_spec = self.get_builtin_enum_spec(def.did())?;
+            if let Some(spec) = builtin_spec {
+                enum_spec = spec;
+            }
+            else if self.env.has_tool_attribute(def.did(), "refined_by") {
+                let attributes = self.env.get_attributes(def.did());
+                let attributes = crate::utils::filter_tool_attrs(attributes);
 
-            // TODO: change once we handle lft parameters properly
-            let lft_params: Vec<(Option<String>, radium::Lft)> = Vec::new();
+                // TODO: change once we handle lft parameters properly
+                let lft_params: Vec<(Option<String>, radium::Lft)> = Vec::new();
 
-            let mut parser = VerboseEnumSpecParser::new();
-            enum_spec = parser.parse_enum_spec("", &attributes, &variant_attrs, &ty_param_defs, &lft_params)
-                .map_err(|err| TranslationError::FatalError(err))?;
-        }
-        else {
-            // generate a specification
-            let decl;
-            (decl, enum_spec) = self.generate_enum_spec(def, &enum_name);
-            inductive_decl = Some(decl);
-        }
+                let mut parser = VerboseEnumSpecParser::new();
+                enum_spec = parser.parse_enum_spec("", &attributes, &variant_attrs, &ty_param_defs, &lft_params)
+                    .map_err(|err| TranslationError::FatalError(err))?;
+            }
+            else {
+                // generate a specification
+                let decl;
+                (decl, enum_spec) = self.generate_enum_spec(def, &enum_name);
+                inductive_decl = Some(decl);
+            }
 
-        let mut enum_builder = radium::EnumBuilder::new(enum_name, ty_param_defs, st_params, translated_it, repr_opt);
-        // now build the enum itself
-        for v in def.variants().iter() {
-            let variant_ref = self.lookup_adt_variant(v.def_id)?;
-            let variant_name = strip_coq_ident(&v.ident(tcx).to_string());
-            let discriminant = discrs.get(&variant_name).unwrap();
-            enum_builder.add_variant(&variant_name, variant_ref, variant_masks.remove(&v.def_id).unwrap(), *discriminant);
-        }
+            let mut enum_builder = radium::EnumBuilder::new(enum_name, ty_param_defs, st_params, translated_it, repr_opt);
+            // now build the enum itself
+            for v in def.variants().iter() {
+                let variant_ref = self.lookup_adt_variant(v.def_id)?;
+                let variant_name = strip_coq_ident(&v.ident(tcx).to_string());
+                let discriminant = discrs.get(&variant_name).unwrap();
+                enum_builder.add_variant(&variant_name, variant_ref, variant_masks.remove(&v.def_id).unwrap(), *discriminant);
+            }
+            Ok(enum_builder.finish(inductive_decl, enum_spec))
+        };
 
-        let enum_def = enum_builder.finish(inductive_decl, enum_spec);
-        // finalize the definition
-        {
-            let mut enum_def_ref = enum_def_init.borrow_mut();
-            *enum_def_ref = Some(enum_def);
+        match translate_variants() {
+            Ok(enum_def) => {
+                // finalize the definition
+                let mut enum_def_ref = enum_def_init.borrow_mut();
+                *enum_def_ref = Some(enum_def);
 
-            let mut deps_ref = self.adt_deps.borrow_mut();
-            deps_ref.insert(def.did(), adt_deps);
+                let mut deps_ref = self.adt_deps.borrow_mut();
+                deps_ref.insert(def.did(), adt_deps);
+                Ok(())
+            },
+            Err(err) => {
+                // deregister the ADT again
+                self.enum_registry.borrow_mut().remove(&def.did());
+                Err(err)
+            },
         }
-
-        Ok(())
     }
 
     /// Translate type.