summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNadrieril2020-12-07 13:47:21 +0000
committerNadrieril2020-12-07 19:34:39 +0000
commit3c522217b7445c6df9e170d830f485086ad7e062 (patch)
tree2b32d2c9106e6f0f6ad5edc7b3144f33b5991d8c
parentc785b7c0c6cd8b3b1cc15eb79caf982a757020ba (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.rs42
-rw-r--r--dhall/src/semantics/resolve/env.rs6
-rw-r--r--dhall/src/semantics/resolve/resolve.rs2
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;