From f5a588defc0ad22ce2f0d3b32ef8f0e22e43e672 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 24 Dec 2019 21:46:29 +0000 Subject: Ensure inferred type is always in normal form --- dhall/src/semantics/core/value.rs | 3 +++ dhall/src/semantics/phase/mod.rs | 11 ++++++++++- dhall/src/semantics/phase/typecheck.rs | 5 ++++- dhall/src/tests.rs | 7 ++----- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/dhall/src/semantics/core/value.rs b/dhall/src/semantics/core/value.rs index ca7c4bc..6fa00ac 100644 --- a/dhall/src/semantics/core/value.rs +++ b/dhall/src/semantics/core/value.rs @@ -200,6 +200,9 @@ impl Value { WHNF | NF => {} } } + pub(crate) fn normalize_nf(&self) { + self.as_internal_mut().normalize_nf(); + } pub(crate) fn app(&self, v: Value) -> Value { let body_t = match &*self.get_type_not_sort().as_whnf() { diff --git a/dhall/src/semantics/phase/mod.rs b/dhall/src/semantics/phase/mod.rs index b22120d..5332eb3 100644 --- a/dhall/src/semantics/phase/mod.rs +++ b/dhall/src/semantics/phase/mod.rs @@ -63,6 +63,11 @@ impl Parsed { pub fn encode(&self) -> Result, EncodeError> { binary::encode(&self.0) } + + /// Converts a value back to the corresponding AST expression. + pub fn to_expr(&self) -> ParsedExpr { + self.0.clone() + } } impl Resolved { @@ -73,6 +78,10 @@ impl Resolved { Ok(typecheck::typecheck_with(self.0, ty.normalize_to_expr())? .into_typed()) } + /// Converts a value back to the corresponding AST expression. + pub fn to_expr(&self) -> ResolvedExpr { + self.0.clone() + } } impl Typed { @@ -96,7 +105,7 @@ impl Typed { } /// Converts a value back to the corresponding AST expression. - pub(crate) fn to_expr(&self) -> NormalizedExpr { + pub fn to_expr(&self) -> ResolvedExpr { self.0.to_expr(ToExprOptions { alpha: false, normalize: false, diff --git a/dhall/src/semantics/phase/typecheck.rs b/dhall/src/semantics/phase/typecheck.rs index e9836e8..3960146 100644 --- a/dhall/src/semantics/phase/typecheck.rs +++ b/dhall/src/semantics/phase/typecheck.rs @@ -315,6 +315,7 @@ fn type_with( Ok(match e.as_ref() { Lam(var, annot, body) => { let annot = type_with(ctx, annot.clone())?; + annot.normalize_nf(); let ctx2 = ctx.insert_type(var, annot.clone()); let body = type_with(&ctx2, body.clone())?; let body_type = body.get_type()?; @@ -401,7 +402,9 @@ fn type_last_layer( return mkerr(TypeMismatch(f.clone(), tx.clone(), a.clone())); } - RetTypeOnly(tb.subst_shift(&x.into(), a)) + let ret = tb.subst_shift(&x.into(), a); + ret.normalize_nf(); + RetTypeOnly(ret) } Annot(x, t) => { if &x.get_type()? != t { diff --git a/dhall/src/tests.rs b/dhall/src/tests.rs index 7a3a540..0163c4d 100644 --- a/dhall/src/tests.rs +++ b/dhall/src/tests.rs @@ -160,11 +160,8 @@ pub fn run_test(test: Test<'_>) -> Result<()> { TypeInferenceSuccess(expr_file_path, expected_file_path) => { let expr = parse_file_str(&expr_file_path)?.resolve()?.typecheck()?; - let ty = expr.get_type()?.normalize_to_expr(); - let expected = parse_file_str(&expected_file_path)? - .resolve()? - .typecheck()? - .normalize_to_expr(); + let ty = expr.get_type()?.to_expr(); + let expected = parse_file_str(&expected_file_path)?.to_expr(); assert_eq_display!(ty, expected); } TypeInferenceFailure(file_path) => { -- cgit v1.2.3