diff options
author | Nadrieril | 2020-12-07 13:47:21 +0000 |
---|---|---|
committer | Nadrieril | 2020-12-07 19:34:39 +0000 |
commit | 3c522217b7445c6df9e170d830f485086ad7e062 (patch) | |
tree | 2b32d2c9106e6f0f6ad5edc7b3144f33b5991d8c | |
parent | c785b7c0c6cd8b3b1cc15eb79caf982a757020ba (diff) |
Tag cx ids with the cx lifetime
To make sure we don't let ids escape and we don't mix scopes.
-rw-r--r-- | dhall/src/ctxt.rs | 42 | ||||
-rw-r--r-- | dhall/src/semantics/resolve/env.rs | 6 | ||||
-rw-r--r-- | dhall/src/semantics/resolve/resolve.rs | 2 |
3 files changed, 31 insertions, 19 deletions
diff --git a/dhall/src/ctxt.rs b/dhall/src/ctxt.rs index a171ebe..8bdf99d 100644 --- a/dhall/src/ctxt.rs +++ b/dhall/src/ctxt.rs @@ -1,14 +1,16 @@ use elsa::vec::FrozenVec; use once_cell::sync::OnceCell; +use std::marker::PhantomData; +use std::ops::{Deref, Index}; use crate::semantics::{Import, ImportLocation}; use crate::syntax::Span; use crate::Typed; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct ImportId(usize); +pub struct ImportId<'cx>(usize, PhantomData<&'cx ()>); #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct ImportResultId(usize); +pub struct ImportResultId<'cx>(usize, PhantomData<&'cx ()>); /// What's stored for each `ImportId`. Allows getting and setting a result for this import. pub struct StoredImport<'cx> { @@ -16,7 +18,7 @@ pub struct StoredImport<'cx> { pub base_location: ImportLocation, pub import: Import, pub span: Span, - result: OnceCell<ImportResultId>, + result: OnceCell<ImportResultId<'cx>>, } /// Implementation detail. Made public for the `Index` instances. @@ -45,7 +47,7 @@ impl<'cx> Ctxt<'cx> { base_location: ImportLocation, import: Import, span: Span, - ) -> ImportId { + ) -> ImportId<'cx> { let stored = StoredImport { cx: self, base_location, @@ -55,24 +57,24 @@ impl<'cx> Ctxt<'cx> { }; let id = self.0.imports.len(); self.0.imports.push(Box::new(stored)); - ImportId(id) + ImportId(id, PhantomData) } /// Store the result of fetching an import. - pub fn push_import_result(self, res: Typed<'cx>) -> ImportResultId { + pub fn push_import_result(self, res: Typed<'cx>) -> ImportResultId<'cx> { let id = self.0.import_results.len(); self.0.import_results.push(Box::new(res)); - ImportResultId(id) + ImportResultId(id, PhantomData) } } impl<'cx> StoredImport<'cx> { /// Get the id of the result of fetching this import. Returns `None` if the result has not yet /// been fetched. - pub fn get_resultid(&self) -> Option<ImportResultId> { + pub fn get_resultid(&self) -> Option<ImportResultId<'cx>> { self.result.get().copied() } /// Store the result of fetching this import. - pub fn set_resultid(&self, res: ImportResultId) { + pub fn set_resultid(&self, res: ImportResultId<'cx>) { let _ = self.result.set(res); } /// Get the result of fetching this import. Returns `None` if the result has not yet been @@ -82,32 +84,42 @@ impl<'cx> StoredImport<'cx> { Some(&self.cx[res]) } /// Store the result of fetching this import. - pub fn set_result(&self, res: Typed<'cx>) -> ImportResultId { + pub fn set_result(&self, res: Typed<'cx>) -> ImportResultId<'cx> { let res = self.cx.push_import_result(res); self.set_resultid(res); res } } -impl<'cx> std::ops::Deref for Ctxt<'cx> { +impl<'cx> Deref for Ctxt<'cx> { type Target = &'cx CtxtS<'cx>; fn deref(&self) -> &&'cx CtxtS<'cx> { &self.0 } } -impl<'cx> std::ops::Index<ImportId> for CtxtS<'cx> { +impl<'cx> Index<ImportId<'cx>> for CtxtS<'cx> { type Output = StoredImport<'cx>; - fn index(&self, id: ImportId) -> &StoredImport<'cx> { + fn index(&self, id: ImportId<'cx>) -> &StoredImport<'cx> { &self.imports[id.0] } } -impl<'cx> std::ops::Index<ImportResultId> for CtxtS<'cx> { +impl<'cx> Index<ImportResultId<'cx>> for CtxtS<'cx> { type Output = Typed<'cx>; - fn index(&self, id: ImportResultId) -> &Typed<'cx> { + fn index(&self, id: ImportResultId<'cx>) -> &Typed<'cx> { &self.import_results[id.0] } } +impl<'a, 'cx, T> Index<&'a T> for CtxtS<'cx> +where + Self: Index<T>, + T: Copy, +{ + type Output = <Self as Index<T>>::Output; + fn index(&self, id: &'a T) -> &Self::Output { + &self[*id] + } +} /// Empty impl, because `FrozenVec` does not implement `Debug` and I can't be bothered to do it /// myself. diff --git a/dhall/src/semantics/resolve/env.rs b/dhall/src/semantics/resolve/env.rs index 2b998f8..ba6205f 100644 --- a/dhall/src/semantics/resolve/env.rs +++ b/dhall/src/semantics/resolve/env.rs @@ -17,7 +17,7 @@ pub type CyclesStack = Vec<ImportLocation>; pub struct ImportEnv<'cx> { cx: Ctxt<'cx>, disk_cache: Option<Cache>, // `None` if it failed to initialize - mem_cache: HashMap<ImportLocation, ImportResultId>, + mem_cache: HashMap<ImportLocation, ImportResultId<'cx>>, stack: CyclesStack, } @@ -82,7 +82,7 @@ impl<'cx> ImportEnv<'cx> { pub fn get_from_mem_cache( &self, location: &ImportLocation, - ) -> Option<ImportResultId> { + ) -> Option<ImportResultId<'cx>> { Some(*self.mem_cache.get(location)?) } @@ -98,7 +98,7 @@ impl<'cx> ImportEnv<'cx> { pub fn write_to_mem_cache( &mut self, location: ImportLocation, - result: ImportResultId, + result: ImportResultId<'cx>, ) { self.mem_cache.insert(location, result); } diff --git a/dhall/src/semantics/resolve/resolve.rs b/dhall/src/semantics/resolve/resolve.rs index 488c516..9021155 100644 --- a/dhall/src/semantics/resolve/resolve.rs +++ b/dhall/src/semantics/resolve/resolve.rs @@ -398,7 +398,7 @@ fn traverse_resolve_expr<'cx>( /// Fetch the import and store the result in the global context. fn fetch_import<'cx>( env: &mut ImportEnv<'cx>, - import_id: ImportId, + import_id: ImportId<'cx>, ) -> Result<(), Error> { let cx = env.cx(); let import = &cx[import_id].import; |