diff --git a/case_studies/tests/src/lib.rs b/case_studies/tests/src/lib.rs
index f055b343572197b56d92a6bd6b0f8f220c6ead6e..ba2ad52eea965a0d5b00b018d39f0ebb4dd4dde9 100644
--- a/case_studies/tests/src/lib.rs
+++ b/case_studies/tests/src/lib.rs
@@ -14,4 +14,4 @@ mod mixed;
 mod closures;
 mod references;
 //
-//mod option;
+mod option;
diff --git a/case_studies/tests/src/option.rs b/case_studies/tests/src/option.rs
index 4ffe5cea57dd8ef2e42f2f55de4a1dbf55104dae..86599f3433f725a17ec89939bcf5fcf1215e764f 100644
--- a/case_studies/tests/src/option.rs
+++ b/case_studies/tests/src/option.rs
@@ -1,9 +1,12 @@
+#![rr::include("option")]
 
 pub trait Bla {
     fn bla(&self);
 }
 
 impl<T> Bla for Option<T> {
+    #[rr::params("x")]
+    #[rr::args("#x")]
     #[rr::returns("()")]
     fn bla(&self) {
 
diff --git a/rr_frontend/radium/src/coq.rs b/rr_frontend/radium/src/coq.rs
index 61e533903008b6af9714a6e02b7c95ce722479d4..7167e079d3fdc021a01569968e5cb6a61eb2b110 100644
--- a/rr_frontend/radium/src/coq.rs
+++ b/rr_frontend/radium/src/coq.rs
@@ -399,9 +399,55 @@ impl Display for CoqDefBody {
     }
 }
 
+#[derive(Debug, Clone)]
+pub enum CoqAttribute {
+    Global,
+    Local,
+}
+impl Display for CoqAttribute {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Global => write!(f, "global"),
+            Self::Local => write!(f, "local"),
+        }
+    }
+}
+
+#[derive(Debug, Clone)]
+pub struct CoqAttributes {
+    attrs: Vec<CoqAttribute>,
+}
+impl CoqAttributes {
+    pub fn empty() -> Self {
+        Self { attrs: vec![] }
+    }
+
+    pub fn new(attrs: Vec<CoqAttribute>) -> Self {
+        Self { attrs }
+    }
+}
+impl Display for CoqAttributes {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        if !self.attrs.is_empty() {
+            write!(f, "#[ ")?;
+            let mut needs_sep = false;
+            for attr in self.attrs.iter() {
+                if needs_sep {
+                    write!(f, ", ")?;
+                }
+                needs_sep = true;
+                write!(f, "{}", attr)?;
+            }
+            write!(f, "]")?;
+        }
+        Ok(())
+    }
+}
+
 /// A Coq typeclass instance declaration
 #[derive(Debug, Clone)]
 pub struct CoqInstanceDecl {
+    pub attrs: CoqAttributes,
     pub name: Option<String>,
     pub params: CoqParamList,
     pub ty: CoqType,
@@ -411,8 +457,10 @@ pub struct CoqInstanceDecl {
 impl Display for CoqInstanceDecl {
     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
         match self.name {
-            Some(ref name) => write!(f, "Instance {} {} : {}{}", name, self.params, self.ty, self.body),
-            None => write!(f, "Instance {} : {}{}", self.params, self.ty, self.body),
+            Some(ref name) => {
+                write!(f, "{} Instance {} {} : {}{}", self.attrs, name, self.params, self.ty, self.body)
+            },
+            None => write!(f, "{} Instance {} : {}{}", self.attrs, self.params, self.ty, self.body),
         }
     }
 }
diff --git a/rr_frontend/radium/src/specs.rs b/rr_frontend/radium/src/specs.rs
index 337dce8a66d80afdca7203ff2b2dd2d7e7458f69..98c36c1bd539a608e60b78c0cc17cb0730085b7a 100644
--- a/rr_frontend/radium/src/specs.rs
+++ b/rr_frontend/radium/src/specs.rs
@@ -1348,7 +1348,7 @@ impl<'def> AbstractVariant<'def> {
         write!(out, "{}Definition {} : type ({}).\n", indent, self.plain_ty_name, self.rfn_type).unwrap();
         write!(
             out,
-            "{indent}Proof using {}. exact ({}). Defined.\n",
+            "{indent}Proof using {} Type*. exact ({}). Defined.\n",
             ty_params.iter().map(|x| x.type_term.clone()).collect::<Vec<_>>().join(" "),
             self.generate_coq_type_term(sls_app)
         )
@@ -1375,7 +1375,7 @@ impl<'def> AbstractVariant<'def> {
     /// Generate a Coq definition for the struct type alias.
     /// TODO: maybe we should also generate a separate alias def for the refinement type to make
     /// things more readable?
-    pub fn generate_coq_type_def(&self, ty_params: &[LiteralTyParam]) -> String {
+    pub fn generate_coq_type_def(&self, ty_params: &[LiteralTyParam], extra_context: &[CoqParam]) -> String {
         let mut out = String::with_capacity(200);
         let indent = "  ";
         // the write_str impl will always return Ok.
@@ -1399,6 +1399,17 @@ impl<'def> AbstractVariant<'def> {
         }
         out.push_str("\n");
 
+        // write coq parameters
+        write!(out, "{} (* Additional parameters *)\n", indent).unwrap();
+        if !extra_context.is_empty() {
+            write!(out, "{}Context", indent).unwrap();
+            for param in extra_context.iter() {
+                write!(out, " {}", param).unwrap();
+            }
+            write!(out, ".\n").unwrap();
+        }
+        write!(out, "\n").unwrap();
+
         write!(out, "{}", self.generate_coq_type_def_core(ty_params)).unwrap();
 
         write!(out, "End {}.\n", self.plain_ty_name).unwrap();
@@ -1490,10 +1501,10 @@ impl<'def> AbstractStruct<'def> {
     }
 
     /// Generate a Coq definition for the struct type alias.
-    /// TODO: maybe we should also generate a separate alias def for the refinement type to make
-    /// things more readable?
     pub fn generate_coq_type_def(&self) -> String {
-        self.variant_def.generate_coq_type_def(&self.ty_params)
+        let extra_context = if let Some(ref inv) = self.invariant { inv.coq_params.as_slice() } else { &[] };
+
+        self.variant_def.generate_coq_type_def(&self.ty_params, extra_context)
     }
 
     /// Generate an optional definition for the invariant of this type, if one has been specified.
@@ -2122,6 +2133,7 @@ impl<'def> AbstractEnum<'def> {
             assertions.push(CoqTopLevelAssertion::InductiveDecl(ind.clone()));
             // prove that it is inhabited
             let instance_decl = CoqInstanceDecl {
+                attrs: CoqAttributes::new(vec![CoqAttribute::Global]),
                 name: None,
                 params: CoqParamList::empty(),
                 ty: CoqType::Literal(format!("Inhabited {}", ind.name)),
diff --git a/rr_frontend/translation/src/lib.rs b/rr_frontend/translation/src/lib.rs
index 907e9e5818e0827b19a3cddfd7f3ac3695c805eb..3be96a75965e171ff5630544b4ea4ffa7a7c8814 100644
--- a/rr_frontend/translation/src/lib.rs
+++ b/rr_frontend/translation/src/lib.rs
@@ -107,6 +107,8 @@ pub struct VerificationCtxt<'tcx, 'rcx> {
     functions: &'rcx [LocalDefId],
     /// the second component determines whether to include it in the code file as well
     extra_imports: HashSet<(radium::CoqPath, bool)>,
+    /// extra Coq module dependencies
+    extra_dependencies: HashSet<String>,
     coq_path_prefix: String,
     dune_package: Option<String>,
     shim_registry: shim_registry::ShimRegistry<'rcx>,
@@ -260,11 +262,23 @@ impl<'tcx, 'rcx> VerificationCtxt<'tcx, 'rcx> {
             }
         }
 
+        let mut module_dependencies: Vec<_> =
+            self.extra_imports.iter().filter_map(|(x, _)| x.path.clone()).collect();
+        module_dependencies.extend(self.extra_dependencies.iter().cloned());
+
         info!("Generated module summary ADTs: {:?}", adt_shims);
         info!("Generated module summary functions: {:?}", function_shims);
 
         let interface_file = File::create(path).unwrap();
-        shim_registry::write_shims(interface_file, module_path, module, name, adt_shims, function_shims);
+        shim_registry::write_shims(
+            interface_file,
+            module_path,
+            module,
+            name,
+            &module_dependencies,
+            adt_shims,
+            function_shims,
+        );
     }
 
     /// Write specifications of a verification unit.
@@ -561,7 +575,8 @@ impl<'tcx, 'rcx> VerificationCtxt<'tcx, 'rcx> {
             fs::create_dir_all(base_dir_path.as_path()).unwrap();
         }
 
-        let coq_module_path = format!("{}.{}", self.coq_path_prefix, stem);
+        let toplevel_module_path = self.coq_path_prefix.to_string();
+        let coq_module_path = format!("{}.{}", toplevel_module_path, stem);
         let generated_module_path = format!("{}.generated", coq_module_path);
         let proof_module_path = format!("{}.proofs", coq_module_path);
 
@@ -623,8 +638,11 @@ impl<'tcx, 'rcx> VerificationCtxt<'tcx, 'rcx> {
 
         // write dune meta file
         let mut dune_file = io::BufWriter::new(fs::File::create(generated_dune_path.as_path()).unwrap());
-        let extra_theories: Vec<_> =
+        let mut extra_theories: HashSet<_> =
             self.extra_imports.iter().filter_map(|(path, _)| path.path.clone()).collect();
+        extra_theories.extend(self.extra_dependencies.iter().cloned());
+        let extra_theories: Vec<_> = extra_theories.into_iter().collect();
+
         let dune_package = if let Some(ref dune_package) = self.dune_package {
             format!("(package {dune_package})\n")
         } else {
@@ -752,6 +770,8 @@ fn register_shims<'rcx, 'tcx>(vcx: &mut VerificationCtxt<'tcx, 'rcx>) -> Result<
     // add the extra imports
     vcx.extra_imports
         .extend(vcx.shim_registry.get_extra_imports().iter().map(|x| (x.clone(), true)));
+    // add the extra dependencies
+    vcx.extra_dependencies.extend(vcx.shim_registry.get_extra_dependencies().iter().cloned());
 
     Ok(())
 }
@@ -762,19 +782,18 @@ fn get_most_restrictive_function_mode<'tcx, 'rcx>(
 ) -> function_body::ProcedureMode {
     let mut mode = function_body::ProcedureMode::Prove;
 
-    let attrs = vcx.env.get_attributes(did);
-    let v = crate::utils::filter_tool_attrs(attrs);
+    let attrs = get_attributes_of_function(&vcx.env, did);
 
     // check if this is a purely spec function; if so, skip.
-    if crate::utils::has_tool_attr(attrs, "shim") {
+    if crate::utils::has_tool_attr_filtered(attrs.as_slice(), "shim") {
         mode = function_body::ProcedureMode::Shim;
     }
 
-    if crate::utils::has_tool_attr(attrs, "trust_me") {
+    if crate::utils::has_tool_attr_filtered(attrs.as_slice(), "trust_me") {
         mode = function_body::ProcedureMode::TrustMe;
-    } else if crate::utils::has_tool_attr(attrs, "only_spec") {
+    } else if crate::utils::has_tool_attr_filtered(attrs.as_slice(), "only_spec") {
         mode = function_body::ProcedureMode::OnlySpec;
-    } else if crate::utils::has_tool_attr(attrs, "ignore") {
+    } else if crate::utils::has_tool_attr_filtered(attrs.as_slice(), "ignore") {
         info!("Function {:?} will be ignored", did);
         mode = function_body::ProcedureMode::Ignore;
     }
@@ -839,6 +858,18 @@ fn propagate_attr_from_impl(it: &rustc_ast::ast::AttrItem) -> bool {
     }
 }
 
+fn get_attributes_of_function<'a>(env: &'a Environment, did: DefId) -> Vec<&'a rustc_ast::ast::AttrItem> {
+    let attrs = env.get_attributes(did);
+    let mut filtered_attrs = crate::utils::filter_tool_attrs(attrs);
+    // also add selected attributes from the surrounding impl
+    if let Some(impl_did) = env.tcx().impl_of_method(did) {
+        let impl_attrs = env.get_attributes(impl_did);
+        let filtered_impl_attrs = crate::utils::filter_tool_attrs(impl_attrs);
+        filtered_attrs.extend(filtered_impl_attrs.into_iter().filter(|x| propagate_attr_from_impl(x)));
+    }
+    filtered_attrs
+}
+
 /// Translate functions of the crate, assuming they were previously registered.
 fn translate_functions<'rcx, 'tcx>(vcx: &mut VerificationCtxt<'tcx, 'rcx>) {
     for &f in vcx.functions {
@@ -846,14 +877,7 @@ fn translate_functions<'rcx, 'tcx>(vcx: &mut VerificationCtxt<'tcx, 'rcx>) {
         let fname = vcx.env.get_item_name(f.to_def_id());
         let meta = vcx.procedure_registry.lookup_function(&f.to_def_id()).unwrap();
 
-        let attrs = vcx.env.get_attributes(f.to_def_id());
-        let mut filtered_attrs = crate::utils::filter_tool_attrs(attrs);
-        // also add selected attributes from the surrounding impl
-        if let Some(impl_did) = vcx.env.tcx().impl_of_method(f.to_def_id()) {
-            let impl_attrs = vcx.env.get_attributes(impl_did);
-            let filtered_impl_attrs = crate::utils::filter_tool_attrs(impl_attrs);
-            filtered_attrs.extend(filtered_impl_attrs.into_iter().filter(|x| propagate_attr_from_impl(x)));
-        }
+        let filtered_attrs = get_attributes_of_function(&vcx.env, f.to_def_id());
 
         let mode = meta.get_mode();
         if mode.is_shim() {
@@ -1165,6 +1189,7 @@ where
         type_translator: &type_translator,
         procedure_registry,
         extra_imports: imports.into_iter().map(|x| (x, false)).collect(),
+        extra_dependencies: HashSet::new(),
         coq_path_prefix: path_prefix,
         shim_registry,
         dune_package: package,
diff --git a/rr_frontend/translation/src/shim_registry.rs b/rr_frontend/translation/src/shim_registry.rs
index d2b88b5ff6ad7cb1ecd6cdf51b9bea6f18cb75db..0f30153a3d9f933c368f9763e09578f840fc462a 100644
--- a/rr_frontend/translation/src/shim_registry.rs
+++ b/rr_frontend/translation/src/shim_registry.rs
@@ -109,6 +109,8 @@ pub struct ShimRegistry<'a> {
     adt_shims: Vec<AdtShim<'a>>,
     /// extra imports
     imports: Vec<radium::specs::CoqPath>,
+    /// extra module dependencies
+    depends: Vec<String>,
 }
 
 impl<'a> ShimRegistry<'a> {
@@ -139,6 +141,7 @@ impl<'a> ShimRegistry<'a> {
             function_shims: Vec::new(),
             adt_shims: Vec::new(),
             imports: Vec::new(),
+            depends: Vec::new(),
         }
     }
 
@@ -186,6 +189,19 @@ impl<'a> ShimRegistry<'a> {
                 };
                 self.imports.push(coq_path);
 
+                let depends = obj
+                    .get("module_dependencies")
+                    .ok_or(format!("Missing attribute \"module_dependencies\""))?;
+                let depends = depends
+                    .as_array()
+                    .ok_or(format!("Expected array for \"module_dependencies\" attribute"))?;
+                for el in depends.iter() {
+                    let module = el
+                        .as_str()
+                        .ok_or(format!("Expected string for element of \"module_dependencies\" array"))?;
+                    self.depends.push(module.to_string());
+                }
+
                 let arr = obj.get("items").ok_or(format!("Missing attribute \"items\""))?;
                 let arr = arr.as_array().ok_or(format!("Expected array for \"items\" attribute"))?;
                 v = arr.clone();
@@ -237,6 +253,10 @@ impl<'a> ShimRegistry<'a> {
     pub fn get_extra_imports(&self) -> &[radium::specs::CoqPath] {
         &self.imports
     }
+
+    pub fn get_extra_dependencies(&self) -> &[String] {
+        &self.depends
+    }
 }
 
 /// Write serialized representation of shims to a file.
@@ -245,6 +265,7 @@ pub fn write_shims<'a>(
     load_path: &str,
     load_module: &str,
     name: &str,
+    module_dependencies: &[String],
     adt_shims: Vec<AdtShim<'a>>,
     function_shims: Vec<FunctionShim<'a>>,
 ) {
@@ -268,6 +289,7 @@ pub fn write_shims<'a>(
         "refinedrust_path": load_path,
         "refinedrust_module": load_module,
         "refinedrust_name": name,
+        "module_dependencies": module_dependencies,
         "items": array_val
     });
 
diff --git a/rr_frontend/translation/src/spec_parsers/crate_attr_parser.rs b/rr_frontend/translation/src/spec_parsers/crate_attr_parser.rs
index fa30039346372140661a17775873301a0b1d6a1c..5c1c6c242e23eab1b3694c9865c27064063eb85a 100644
--- a/rr_frontend/translation/src/spec_parsers/crate_attr_parser.rs
+++ b/rr_frontend/translation/src/spec_parsers/crate_attr_parser.rs
@@ -23,6 +23,7 @@ pub struct CrateAttrs {
     pub prefix: Option<String>,
     pub includes: Vec<String>,
     pub package: Option<String>,
+    pub context_params: Vec<specs::CoqParam>,
 }
 
 pub struct VerboseCrateAttrParser {}
@@ -44,6 +45,7 @@ impl CrateAttrParser for VerboseCrateAttrParser {
         let mut includes: Vec<String> = Vec::new();
         let mut prefix: Option<String> = None;
         let mut package: Option<String> = None;
+        let mut context_params = Vec::new();
 
         for &it in attrs.iter() {
             let ref path_segs = it.path.segments;
@@ -74,6 +76,15 @@ impl CrateAttrParser for VerboseCrateAttrParser {
                         }
                         package = Some(path.value().to_string());
                     },
+                    "context" => {
+                        let param: parse_utils::RRGlobalCoqContextItem =
+                            buffer.parse(&meta).map_err(str_err)?;
+                        context_params.push(specs::CoqParam::new(
+                            specs::CoqName::Unnamed,
+                            specs::CoqType::Literal(param.item),
+                            true,
+                        ));
+                    },
                     _ => {
                         return Err(format!("unknown attribute for crate specification: {:?}", args));
                     },
@@ -85,6 +96,7 @@ impl CrateAttrParser for VerboseCrateAttrParser {
             prefix,
             includes,
             package,
+            context_params,
         })
     }
 }
diff --git a/rr_frontend/translation/src/spec_parsers/module_attr_parser.rs b/rr_frontend/translation/src/spec_parsers/module_attr_parser.rs
index b4ee618efe13a8b1a80e2b5e2be72bf906880841..b89f23fda8c3f7be9414475ebe2f1f79a178d695 100644
--- a/rr_frontend/translation/src/spec_parsers/module_attr_parser.rs
+++ b/rr_frontend/translation/src/spec_parsers/module_attr_parser.rs
@@ -26,6 +26,7 @@ pub trait ModuleAttrParser {
 pub struct ModuleAttrs {
     pub imports: Vec<specs::CoqPath>,
     pub includes: Vec<String>,
+    pub context_params: Vec<specs::CoqParam>,
 }
 
 pub struct VerboseModuleAttrParser {}
@@ -49,6 +50,7 @@ impl ModuleAttrParser for VerboseModuleAttrParser {
         let meta = ();
         let mut imports: Vec<specs::CoqPath> = Vec::new();
         let mut includes: Vec<String> = Vec::new();
+        let mut context_params = Vec::new();
 
         for &it in attrs.iter() {
             let ref path_segs = it.path.segments;
@@ -65,12 +67,25 @@ impl ModuleAttrParser for VerboseModuleAttrParser {
                         let name: parse::LitStr = buffer.parse(&meta).map_err(str_err)?;
                         includes.push(name.value());
                     },
+                    "context" => {
+                        let param: parse_utils::RRGlobalCoqContextItem =
+                            buffer.parse(&meta).map_err(str_err)?;
+                        context_params.push(specs::CoqParam::new(
+                            specs::CoqName::Unnamed,
+                            specs::CoqType::Literal(param.item),
+                            true,
+                        ));
+                    },
                     _ => {
                         return Err(format!("unknown attribute for module specification: {:?}", args));
                     },
                 }
             }
         }
-        Ok(ModuleAttrs { imports, includes })
+        Ok(ModuleAttrs {
+            imports,
+            includes,
+            context_params,
+        })
     }
 }
diff --git a/rr_frontend/translation/src/spec_parsers/parse_utils.rs b/rr_frontend/translation/src/spec_parsers/parse_utils.rs
index fc147eb371fe47d25ab3f8a14ab7e0d9bad6aed0..123c9c9899c597597af6c17a75575d5f15624d7b 100644
--- a/rr_frontend/translation/src/spec_parsers/parse_utils.rs
+++ b/rr_frontend/translation/src/spec_parsers/parse_utils.rs
@@ -231,6 +231,19 @@ impl<'a> parse::Parse<ParseMeta<'a>> for RRCoqContextItem {
     }
 }
 
+/// a variant of `RRCoqContextItem` for module/crate scope
+#[derive(Debug)]
+pub struct RRGlobalCoqContextItem {
+    pub item: String,
+}
+impl<U> parse::Parse<U> for RRGlobalCoqContextItem {
+    fn parse(input: parse::ParseStream, meta: &U) -> parse::ParseResult<Self> {
+        let item: parse::LitStr = input.parse(meta)?;
+
+        Ok(RRGlobalCoqContextItem { item: item.value() })
+    }
+}
+
 pub type ParseMeta<'a> = (&'a [specs::LiteralTyParam], &'a [(Option<String>, specs::Lft)]);
 
 /// Handle escape sequences in the given string.
diff --git a/rr_frontend/translation/src/utils.rs b/rr_frontend/translation/src/utils.rs
index 82abb1136fc35c71d07e0881787a77884180965f..59152de11578f810b3c2d07c0422b02423611732 100644
--- a/rr_frontend/translation/src/utils.rs
+++ b/rr_frontend/translation/src/utils.rs
@@ -345,6 +345,16 @@ pub fn has_tool_attr(attrs: &[ast::Attribute], name: &str) -> bool {
     })
 }
 
+/// Check if `<tool>::name` is among the filtered attributes.
+pub fn has_tool_attr_filtered(attrs: &[&ast::AttrItem], name: &str) -> bool {
+    attrs.iter().any(|item| {
+        let segments = &item.path.segments;
+        segments.len() == 2
+            && segments[0].ident.as_str() == config::spec_hotword().as_str()
+            && segments[1].ident.as_str() == name
+    })
+}
+
 /// Check if any attribute starting with `<tool>` is among the attributes.
 pub fn has_any_tool_attr(attrs: &[ast::Attribute]) -> bool {
     attrs.iter().any(|attr| match &attr.kind {