From d17d553a39aa3bffdfc19b7fe4801b85d6bd80f7 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 11 Apr 2019 16:41:06 +0200 Subject: Add lifetime parameters to Parsed and Resolved Future-proofing --- dhall/src/expr.rs | 35 +++++++++++++++++++++++++++++++---- dhall/src/imports.rs | 27 ++++++++++++++------------- dhall/src/tests.rs | 3 ++- dhall/src/traits/deserialize.rs | 8 ++++---- dhall/src/typecheck.rs | 2 +- 5 files changed, 52 insertions(+), 23 deletions(-) diff --git a/dhall/src/expr.rs b/dhall/src/expr.rs index 1ce20e3..e3a2fe5 100644 --- a/dhall/src/expr.rs +++ b/dhall/src/expr.rs @@ -1,5 +1,6 @@ use crate::imports::ImportRoot; use dhall_core::*; +use std::marker::PhantomData; macro_rules! derive_other_traits { ($ty:ident) => { @@ -20,13 +21,39 @@ macro_rules! derive_other_traits { }; } +macro_rules! derive_other_traits_ { + ($ty:ident) => { + impl<'a> std::cmp::PartialEq for $ty<'a> { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } + } + + impl<'a> std::fmt::Display for $ty<'a> { + fn fmt( + &self, + f: &mut std::fmt::Formatter, + ) -> Result<(), std::fmt::Error> { + self.0.fmt(f) + } + } + }; +} + #[derive(Debug, Clone, Eq)] -pub struct Parsed(pub(crate) SubExpr, pub(crate) ImportRoot); -derive_other_traits!(Parsed); +pub struct Parsed<'a>( + pub(crate) SubExpr, + pub(crate) ImportRoot, + pub(crate) PhantomData<&'a ()>, +); +derive_other_traits_!(Parsed); #[derive(Debug, Clone, Eq)] -pub struct Resolved(pub(crate) SubExpr); -derive_other_traits!(Resolved); +pub struct Resolved<'a>( + pub(crate) SubExpr, + pub(crate) PhantomData<&'a ()>, +); +derive_other_traits_!(Resolved); #[derive(Debug, Clone, Eq)] pub struct Typed(pub(crate) SubExpr, pub(crate) Option); diff --git a/dhall/src/imports.rs b/dhall/src/imports.rs index b5546b2..6b6e2e7 100644 --- a/dhall/src/imports.rs +++ b/dhall/src/imports.rs @@ -3,6 +3,7 @@ use crate::expr::*; use dhall_core::*; use std::fs::File; use std::io::Read; +use std::marker::PhantomData; use std::path::Path; use std::path::PathBuf; @@ -48,10 +49,10 @@ fn load_import(f: &Path) -> Result { Ok(Parsed::parse_file(f)?.resolve()?.typecheck()?.normalize()) } -fn resolve_expr( - Parsed(expr, root): Parsed, +fn resolve_expr<'a>( + Parsed(expr, root, marker): Parsed<'a>, allow_imports: bool, -) -> Result { +) -> Result, ImportError> { let resolve = |import: &Import| -> Result { if allow_imports { let expr = resolve_import(import, &root)?; @@ -61,36 +62,36 @@ fn resolve_expr( } }; let expr = expr.as_ref().traverse_embed(&resolve)?; - Ok(Resolved(rc(expr))) + Ok(Resolved(rc(expr), marker)) } -impl Parsed { - pub fn parse_file(f: &Path) -> Result { +impl<'a> Parsed<'a> { + pub fn parse_file(f: &Path) -> Result, Error> { let mut buffer = String::new(); File::open(f)?.read_to_string(&mut buffer)?; let expr = parse_expr(&*buffer)?; let root = ImportRoot::LocalDir(f.parent().unwrap().to_owned()); - Ok(Parsed(expr, root)) + Ok(Parsed(expr, root, PhantomData)) } - pub fn parse_str(s: &str) -> Result { + pub fn parse_str(s: &'a str) -> Result, Error> { let expr = parse_expr(s)?; let root = ImportRoot::LocalDir(std::env::current_dir()?); - Ok(Parsed(expr, root)) + Ok(Parsed(expr, root, PhantomData)) } - pub fn parse_binary_file(f: &Path) -> Result { + pub fn parse_binary_file(f: &Path) -> Result, Error> { let mut buffer = Vec::new(); File::open(f)?.read_to_end(&mut buffer)?; let expr = crate::binary::decode(&buffer)?; let root = ImportRoot::LocalDir(f.parent().unwrap().to_owned()); - Ok(Parsed(expr, root)) + Ok(Parsed(expr, root, PhantomData)) } - pub fn resolve(self) -> Result { + pub fn resolve(self) -> Result, ImportError> { crate::imports::resolve_expr(self, true) } - pub fn skip_resolve(self) -> Result { + pub fn skip_resolve(self) -> Result, ImportError> { crate::imports::resolve_expr(self, false) } } diff --git a/dhall/src/tests.rs b/dhall/src/tests.rs index 798f3e9..14c2a5f 100644 --- a/dhall/src/tests.rs +++ b/dhall/src/tests.rs @@ -99,7 +99,8 @@ pub fn run_test( assert_eq_pretty!(expr, expected); // Round-trip pretty-printer - let expr: Parsed = crate::from_str(&expr.to_string(), None)?; + let expr_string = expr.to_string(); + let expr: Parsed = crate::from_str(&expr_string, None)?; assert_eq!(expr, expected); return Ok(()); diff --git a/dhall/src/traits/deserialize.rs b/dhall/src/traits/deserialize.rs index 1fbdfe1..3e8cc5e 100644 --- a/dhall/src/traits/deserialize.rs +++ b/dhall/src/traits/deserialize.rs @@ -5,18 +5,18 @@ pub trait Deserialize<'a>: Sized { fn from_str(s: &'a str, ty: Option<&Type>) -> Result; } -impl<'a> Deserialize<'a> for Parsed { +impl<'de: 'a, 'a> Deserialize<'de> for Parsed<'a> { /// Simply parses the provided string. Ignores the /// provided type. - fn from_str(s: &'a str, _: Option<&Type>) -> Result { + fn from_str(s: &'de str, _: Option<&Type>) -> Result { Ok(Parsed::parse_str(s)?) } } -impl<'a> Deserialize<'a> for Resolved { +impl<'de: 'a, 'a> Deserialize<'de> for Resolved<'a> { /// Parses and resolves the provided string. Ignores the /// provided type. - fn from_str(s: &'a str, ty: Option<&Type>) -> Result { + fn from_str(s: &'de str, ty: Option<&Type>) -> Result { Ok(Parsed::from_str(s, ty)?.resolve()?) } } diff --git a/dhall/src/typecheck.rs b/dhall/src/typecheck.rs index 4881972..41c1b69 100644 --- a/dhall/src/typecheck.rs +++ b/dhall/src/typecheck.rs @@ -11,7 +11,7 @@ use dhall_generator as dhall; use self::TypeMessage::*; -impl Resolved { +impl<'a> Resolved<'a> { pub fn typecheck(self) -> Result { type_of(self.0.clone()) } -- cgit v1.2.3 From d9a2a77a19e56edd8eb96eba002e39bc7be3bde3 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 11 Apr 2019 20:45:43 +0200 Subject: Thread lifetimes through other newtypes Closes #55 --- dhall/src/expr.rs | 80 +++++++++++------------ dhall/src/imports.rs | 21 +++--- dhall/src/normalize.rs | 20 +++--- dhall/src/traits/deserialize.rs | 12 ++-- dhall/src/traits/dynamic_type.rs | 16 ++--- dhall/src/traits/static_type.rs | 45 ++++++------- dhall/src/typecheck.rs | 135 ++++++++++++++++++++++----------------- dhall/tests/traits.rs | 2 +- dhall_generator/src/derive.rs | 3 +- 9 files changed, 177 insertions(+), 157 deletions(-) diff --git a/dhall/src/expr.rs b/dhall/src/expr.rs index e3a2fe5..3987896 100644 --- a/dhall/src/expr.rs +++ b/dhall/src/expr.rs @@ -3,25 +3,6 @@ use dhall_core::*; use std::marker::PhantomData; macro_rules! derive_other_traits { - ($ty:ident) => { - impl std::cmp::PartialEq for $ty { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } - } - - impl std::fmt::Display for $ty { - fn fmt( - &self, - f: &mut std::fmt::Formatter, - ) -> Result<(), std::fmt::Error> { - self.0.fmt(f) - } - } - }; -} - -macro_rules! derive_other_traits_ { ($ty:ident) => { impl<'a> std::cmp::PartialEq for $ty<'a> { fn eq(&self, other: &Self) -> bool { @@ -46,85 +27,96 @@ pub struct Parsed<'a>( pub(crate) ImportRoot, pub(crate) PhantomData<&'a ()>, ); -derive_other_traits_!(Parsed); +derive_other_traits!(Parsed); #[derive(Debug, Clone, Eq)] pub struct Resolved<'a>( - pub(crate) SubExpr, + pub(crate) SubExpr>, pub(crate) PhantomData<&'a ()>, ); -derive_other_traits_!(Resolved); +derive_other_traits!(Resolved); #[derive(Debug, Clone, Eq)] -pub struct Typed(pub(crate) SubExpr, pub(crate) Option); +pub struct Typed<'a>( + pub(crate) SubExpr>, + pub(crate) Option>, + pub(crate) PhantomData<&'a ()>, +); derive_other_traits!(Typed); #[derive(Debug, Clone, Eq)] -pub struct Normalized(pub(crate) SubExpr, pub(crate) Option); +pub struct Normalized<'a>( + pub(crate) SubExpr, + pub(crate) Option>, + pub(crate) PhantomData<&'a ()>, +); derive_other_traits!(Normalized); /// An expression of type `Type` (like `Bool` or `Natural -> Text`, but not `Type`) #[derive(Debug, Clone, Eq)] -pub struct SimpleType(pub(crate) SubExpr); +pub struct SimpleType<'a>( + pub(crate) SubExpr, + pub(crate) PhantomData<&'a ()>, +); derive_other_traits!(SimpleType); #[derive(Debug, Clone, PartialEq, Eq)] -pub struct Type(pub(crate) TypeInternal); +pub struct Type<'a>(pub(crate) TypeInternal<'a>); #[derive(Debug, Clone, PartialEq, Eq)] -pub(crate) enum TypeInternal { - Expr(Box), +pub(crate) enum TypeInternal<'a> { + Expr(Box>), // The type of `Sort` SuperType, } // Exposed for the macros #[doc(hidden)] -impl From for SubExpr { - fn from(x: SimpleType) -> SubExpr { +impl<'a> From> for SubExpr { + fn from(x: SimpleType<'a>) -> SubExpr { x.0 } } // Exposed for the macros #[doc(hidden)] -impl From> for SimpleType { - fn from(x: SubExpr) -> SimpleType { - SimpleType(x) +impl<'a> From> for SimpleType<'a> { + fn from(x: SubExpr) -> SimpleType<'a> { + SimpleType(x, PhantomData) } } // Exposed for the macros #[doc(hidden)] -impl From for Typed { - fn from(x: Normalized) -> Typed { - Typed(x.0.absurd(), x.1) +impl<'a> From> for Typed<'a> { + fn from(x: Normalized<'a>) -> Typed<'a> { + Typed(x.0.absurd(), x.1, x.2) } } -impl Typed { - pub(crate) fn as_expr(&self) -> &SubExpr { +impl<'a> Typed<'a> { + pub(crate) fn as_expr(&self) -> &SubExpr> { &self.0 } - pub(crate) fn into_expr(self) -> SubExpr { + pub(crate) fn into_expr(self) -> SubExpr> { self.0 } } -impl Normalized { +impl<'a> Normalized<'a> { pub(crate) fn as_expr(&self) -> &SubExpr { &self.0 } pub(crate) fn into_expr(self) -> SubExpr { self.0.absurd() } - pub(crate) fn into_type(self) -> Type { + pub(crate) fn into_type(self) -> Type<'a> { crate::expr::Type(TypeInternal::Expr(Box::new(self))) } } -impl SimpleType { - pub(crate) fn into_type(self) -> Type { - Normalized(self.0, Some(Type::const_type())).into_type() +impl<'a> SimpleType<'a> { + pub(crate) fn into_type(self) -> Type<'a> { + Normalized(self.0, Some(Type::const_type()), PhantomData).into_type() } } diff --git a/dhall/src/imports.rs b/dhall/src/imports.rs index 6b6e2e7..cc9654a 100644 --- a/dhall/src/imports.rs +++ b/dhall/src/imports.rs @@ -22,7 +22,7 @@ pub enum ImportRoot { fn resolve_import( import: &Import, root: &ImportRoot, -) -> Result { +) -> Result, ImportError> { use self::ImportRoot::*; use dhall_core::FilePrefix::*; use dhall_core::ImportLocation::*; @@ -45,7 +45,7 @@ fn resolve_import( } } -fn load_import(f: &Path) -> Result { +fn load_import(f: &Path) -> Result, Error> { Ok(Parsed::parse_file(f)?.resolve()?.typecheck()?.normalize()) } @@ -53,14 +53,15 @@ fn resolve_expr<'a>( Parsed(expr, root, marker): Parsed<'a>, allow_imports: bool, ) -> Result, ImportError> { - let resolve = |import: &Import| -> Result { - if allow_imports { - let expr = resolve_import(import, &root)?; - Ok(expr) - } else { - Err(ImportError::UnexpectedImport(import.clone())) - } - }; + let resolve = + |import: &Import| -> Result, ImportError> { + if allow_imports { + let expr = resolve_import(import, &root)?; + Ok(expr) + } else { + Err(ImportError::UnexpectedImport(import.clone())) + } + }; let expr = expr.as_ref().traverse_embed(&resolve)?; Ok(Resolved(rc(expr), marker)) } diff --git a/dhall/src/normalize.rs b/dhall/src/normalize.rs index 1adc0f8..d6c3805 100644 --- a/dhall/src/normalize.rs +++ b/dhall/src/normalize.rs @@ -4,13 +4,17 @@ use dhall_core::*; use dhall_generator::dhall_expr; use std::fmt; -impl Typed { - pub fn normalize(self) -> Normalized { - Normalized(normalize(self.0), self.1) +impl<'a> Typed<'a> { + pub fn normalize(self) -> Normalized<'a> { + Normalized(normalize(self.0), self.1, self.2) } /// Pretends this expression is normalized. Use with care. - pub fn skip_normalize(self) -> Normalized { - Normalized(self.0.unroll().squash_embed(&|e| e.0.clone()), self.1) + pub fn skip_normalize(self) -> Normalized<'a> { + Normalized( + self.0.unroll().squash_embed(&|e| e.0.clone()), + self.1, + self.2, + ) } } @@ -221,11 +225,11 @@ enum WhatNext<'a, S, A> { DoneAsIs, } -fn normalize_ref(expr: &Expr) -> Expr { +fn normalize_ref(expr: &Expr>) -> Expr { use dhall_core::BinOp::*; use dhall_core::ExprF::*; // Recursively normalize all subexpressions - let expr: ExprF, Label, X, Normalized> = + let expr: ExprF, Label, X, Normalized<'static>> = expr.map_ref_simple(|e| normalize_ref(e.as_ref())); use WhatNext::*; @@ -327,7 +331,7 @@ fn normalize_ref(expr: &Expr) -> Expr { /// However, `normalize` will not fail if the expression is ill-typed and will /// leave ill-typed sub-expressions unevaluated. /// -fn normalize(e: SubExpr) -> SubExpr { +fn normalize(e: SubExpr>) -> SubExpr { normalize_ref(e.as_ref()).roll() } diff --git a/dhall/src/traits/deserialize.rs b/dhall/src/traits/deserialize.rs index 3e8cc5e..f1be054 100644 --- a/dhall/src/traits/deserialize.rs +++ b/dhall/src/traits/deserialize.rs @@ -21,9 +21,9 @@ impl<'de: 'a, 'a> Deserialize<'de> for Resolved<'a> { } } -impl<'a> Deserialize<'a> for Typed { +impl<'de: 'a, 'a> Deserialize<'de> for Typed<'a> { /// Parses, resolves and typechecks the provided string. - fn from_str(s: &'a str, ty: Option<&Type>) -> Result { + fn from_str(s: &'de str, ty: Option<&Type>) -> Result { let resolved = Resolved::from_str(s, ty)?; match ty { None => Ok(resolved.typecheck()?), @@ -32,15 +32,15 @@ impl<'a> Deserialize<'a> for Typed { } } -impl<'a> Deserialize<'a> for Normalized { +impl<'de: 'a, 'a> Deserialize<'de> for Normalized<'a> { /// Parses, resolves, typechecks and normalizes the provided string. - fn from_str(s: &'a str, ty: Option<&Type>) -> Result { + fn from_str(s: &'de str, ty: Option<&Type>) -> Result { Ok(Typed::from_str(s, ty)?.normalize()) } } -impl<'a> Deserialize<'a> for Type { - fn from_str(s: &'a str, ty: Option<&Type>) -> Result { +impl<'de: 'a, 'a> Deserialize<'de> for Type<'a> { + fn from_str(s: &'de str, ty: Option<&Type>) -> Result { Ok(Normalized::from_str(s, ty)?.into_type()) } } diff --git a/dhall/src/traits/dynamic_type.rs b/dhall/src/traits/dynamic_type.rs index d03f8cd..28ed76d 100644 --- a/dhall/src/traits/dynamic_type.rs +++ b/dhall/src/traits/dynamic_type.rs @@ -6,17 +6,17 @@ use dhall_core::{Const, ExprF}; use std::borrow::Cow; pub trait DynamicType { - fn get_type<'a>(&'a self) -> Result, TypeError>; + fn get_type<'a>(&'a self) -> Result>, TypeError>; } impl DynamicType for T { - fn get_type<'a>(&'a self) -> Result, TypeError> { + fn get_type<'a>(&'a self) -> Result>, TypeError> { Ok(Cow::Owned(T::get_static_type())) } } -impl DynamicType for Type { - fn get_type(&self) -> Result, TypeError> { +impl<'a> DynamicType for Type<'a> { + fn get_type(&self) -> Result>, TypeError> { use TypeInternal::*; match &self.0 { Expr(e) => e.get_type(), @@ -29,8 +29,8 @@ impl DynamicType for Type { } } -impl DynamicType for Normalized { - fn get_type(&self) -> Result, TypeError> { +impl<'a> DynamicType for Normalized<'a> { + fn get_type(&self) -> Result>, TypeError> { match &self.1 { Some(t) => Ok(Cow::Borrowed(t)), None => Err(TypeError::new( @@ -42,8 +42,8 @@ impl DynamicType for Normalized { } } -impl DynamicType for Typed { - fn get_type(&self) -> Result, TypeError> { +impl<'a> DynamicType for Typed<'a> { + fn get_type(&self) -> Result>, TypeError> { match &self.1 { Some(t) => Ok(Cow::Borrowed(t)), None => Err(TypeError::new( diff --git a/dhall/src/traits/static_type.rs b/dhall/src/traits/static_type.rs index 6b0f5c5..35d91e1 100644 --- a/dhall/src/traits/static_type.rs +++ b/dhall/src/traits/static_type.rs @@ -3,7 +3,7 @@ use dhall_core::*; use dhall_generator::*; pub trait StaticType { - fn get_static_type() -> Type; + fn get_static_type() -> Type<'static>; } /// Trait for rust types that can be represented in dhall in @@ -12,79 +12,80 @@ pub trait StaticType { /// is `HashMap` because dhall cannot represent records with a /// variable number of fields. pub trait SimpleStaticType { - fn get_simple_static_type() -> SimpleType; + fn get_simple_static_type<'a>() -> SimpleType<'a>; } -fn mktype(x: SubExpr) -> SimpleType { - SimpleType(x) +fn mktype<'a>(x: SubExpr) -> SimpleType<'a> { + SimpleType(x, std::marker::PhantomData) } impl StaticType for T { - fn get_static_type() -> Type { + fn get_static_type() -> Type<'static> { crate::expr::Normalized( T::get_simple_static_type().into(), Some(Type::const_type()), + std::marker::PhantomData, ) .into_type() } } -impl StaticType for SimpleType { - fn get_static_type() -> Type { +impl<'a> StaticType for SimpleType<'a> { + fn get_static_type() -> Type<'static> { Type::const_type() } } impl SimpleStaticType for bool { - fn get_simple_static_type() -> SimpleType { + fn get_simple_static_type<'a>() -> SimpleType<'a> { mktype(dhall_expr!(Bool)) } } impl SimpleStaticType for Natural { - fn get_simple_static_type() -> SimpleType { + fn get_simple_static_type<'a>() -> SimpleType<'a> { mktype(dhall_expr!(Natural)) } } impl SimpleStaticType for u32 { - fn get_simple_static_type() -> SimpleType { + fn get_simple_static_type<'a>() -> SimpleType<'a> { mktype(dhall_expr!(Natural)) } } impl SimpleStaticType for u64 { - fn get_simple_static_type() -> SimpleType { + fn get_simple_static_type<'a>() -> SimpleType<'a> { mktype(dhall_expr!(Natural)) } } impl SimpleStaticType for Integer { - fn get_simple_static_type() -> SimpleType { + fn get_simple_static_type<'a>() -> SimpleType<'a> { mktype(dhall_expr!(Integer)) } } impl SimpleStaticType for i32 { - fn get_simple_static_type() -> SimpleType { + fn get_simple_static_type<'a>() -> SimpleType<'a> { mktype(dhall_expr!(Integer)) } } impl SimpleStaticType for i64 { - fn get_simple_static_type() -> SimpleType { + fn get_simple_static_type<'a>() -> SimpleType<'a> { mktype(dhall_expr!(Integer)) } } impl SimpleStaticType for String { - fn get_simple_static_type() -> SimpleType { + fn get_simple_static_type<'a>() -> SimpleType<'a> { mktype(dhall_expr!(Text)) } } impl SimpleStaticType for (A, B) { - fn get_simple_static_type() -> SimpleType { + fn get_simple_static_type<'a>() -> SimpleType<'a> { let ta: SubExpr<_, _> = A::get_simple_static_type().into(); let tb: SubExpr<_, _> = B::get_simple_static_type().into(); mktype(dhall_expr!({ _1: ta, _2: tb })) @@ -92,27 +93,27 @@ impl SimpleStaticType for (A, B) { } impl SimpleStaticType for Option { - fn get_simple_static_type() -> SimpleType { + fn get_simple_static_type<'a>() -> SimpleType<'a> { let t: SubExpr<_, _> = T::get_simple_static_type().into(); mktype(dhall_expr!(Optional t)) } } impl SimpleStaticType for Vec { - fn get_simple_static_type() -> SimpleType { + fn get_simple_static_type<'a>() -> SimpleType<'a> { let t: SubExpr<_, _> = T::get_simple_static_type().into(); mktype(dhall_expr!(List t)) } } -impl<'a, T: SimpleStaticType> SimpleStaticType for &'a T { - fn get_simple_static_type() -> SimpleType { +impl<'b, T: SimpleStaticType> SimpleStaticType for &'b T { + fn get_simple_static_type<'a>() -> SimpleType<'a> { T::get_simple_static_type() } } impl SimpleStaticType for std::marker::PhantomData { - fn get_simple_static_type() -> SimpleType { + fn get_simple_static_type<'a>() -> SimpleType<'a> { mktype(dhall_expr!({})) } } @@ -120,7 +121,7 @@ impl SimpleStaticType for std::marker::PhantomData { impl SimpleStaticType for std::result::Result { - fn get_simple_static_type() -> SimpleType { + fn get_simple_static_type<'a>() -> SimpleType<'a> { let tt: SubExpr<_, _> = T::get_simple_static_type().into(); let te: SubExpr<_, _> = E::get_simple_static_type().into(); mktype(dhall_expr!(< Ok: tt | Err: te>)) diff --git a/dhall/src/typecheck.rs b/dhall/src/typecheck.rs index 41c1b69..d98095c 100644 --- a/dhall/src/typecheck.rs +++ b/dhall/src/typecheck.rs @@ -1,6 +1,7 @@ #![allow(non_snake_case)] use std::borrow::Borrow; use std::fmt; +use std::marker::PhantomData; use crate::expr::*; use crate::traits::DynamicType; @@ -12,21 +13,24 @@ use dhall_generator as dhall; use self::TypeMessage::*; impl<'a> Resolved<'a> { - pub fn typecheck(self) -> Result { + pub fn typecheck(self) -> Result, TypeError> { type_of(self.0.clone()) } - pub fn typecheck_with(self, ty: &Type) -> Result { + pub fn typecheck_with( + self, + ty: &Type, + ) -> Result, TypeError> { let expr: SubExpr<_, _> = self.0.clone(); let ty: SubExpr<_, _> = ty.as_normalized()?.as_expr().absurd(); type_of(dhall::subexpr!(expr: ty)) } /// Pretends this expression has been typechecked. Use with care. - pub fn skip_typecheck(self) -> Typed { - Typed(self.0, None) + pub fn skip_typecheck(self) -> Typed<'a> { + Typed(self.0, None, self.1) } } -impl Typed { - fn get_type_move(self) -> Result { +impl<'a> Typed<'a> { + fn get_type_move(self) -> Result, TypeError> { self.1.ok_or(TypeError::new( &Context::new(), self.0, @@ -34,18 +38,18 @@ impl Typed { )) } } -impl Normalized { +impl<'a> Normalized<'a> { // Expose the outermost constructor fn unroll_ref(&self) -> &Expr { self.as_expr().as_ref() } fn shift(&self, delta: isize, var: &V