diff options
Diffstat (limited to '')
-rw-r--r-- | dhall/src/phase/binary.rs | 45 | ||||
-rw-r--r-- | dhall/src/phase/mod.rs | 10 | ||||
-rw-r--r-- | dhall/src/phase/parse.rs | 4 | ||||
-rw-r--r-- | dhall/src/phase/typecheck.rs | 16 | ||||
-rw-r--r-- | dhall_syntax/src/core/expr.rs | 131 | ||||
-rw-r--r-- | dhall_syntax/src/core/visitor.rs | 40 | ||||
-rw-r--r-- | dhall_syntax/src/parser.rs | 39 | ||||
-rw-r--r-- | dhall_syntax/src/printer.rs | 12 | ||||
-rw-r--r-- | serde_dhall/src/serde.rs | 9 |
9 files changed, 126 insertions, 180 deletions
diff --git a/dhall/src/phase/binary.rs b/dhall/src/phase/binary.rs index f4a9cc1..3292617 100644 --- a/dhall/src/phase/binary.rs +++ b/dhall/src/phase/binary.rs @@ -631,14 +631,12 @@ where ImportLocation::Remote(url) => { match &url.headers { None => ser_seq.serialize_element(&Null)?, - Some(location_hashed) => { - ser_seq.serialize_element(&self::Serialize::Expr( - &SubExpr::from_expr_no_note(ExprF::Embed(Import { - mode: ImportMode::Code, - location_hashed: location_hashed.as_ref().clone(), - })), - ))? - } + Some(location_hashed) => ser_seq.serialize_element( + &self::Serialize::Expr(&rc(ExprF::Embed(Import { + mode: ImportMode::Code, + location_hashed: location_hashed.as_ref().clone(), + }))), + )?, }; ser_seq.serialize_element(&url.authority)?; for p in &url.path { @@ -689,13 +687,13 @@ impl<'a> serde::ser::Serialize for Serialize<'a> { } } -fn collect_nested_applications<'a, N, E>( - e: &'a SubExpr<N, E>, -) -> (&'a SubExpr<N, E>, Vec<&'a SubExpr<N, E>>) { - fn go<'a, N, E>( - e: &'a SubExpr<N, E>, - vec: &mut Vec<&'a SubExpr<N, E>>, - ) -> &'a SubExpr<N, E> { +fn collect_nested_applications<'a, E>( + e: &'a SubExpr<E>, +) -> (&'a SubExpr<E>, Vec<&'a SubExpr<E>>) { + fn go<'a, E>( + e: &'a SubExpr<E>, + vec: &mut Vec<&'a SubExpr<E>>, + ) -> &'a SubExpr<E> { match e.as_ref() { ExprF::App(f, a) => { vec.push(a); @@ -709,16 +707,15 @@ fn collect_nested_applications<'a, N, E>( (e, vec) } -type LetBinding<'a, N, E> = - (&'a Label, &'a Option<SubExpr<N, E>>, &'a SubExpr<N, E>); +type LetBinding<'a, E> = (&'a Label, &'a Option<SubExpr<E>>, &'a SubExpr<E>); -fn collect_nested_lets<'a, N, E>( - e: &'a SubExpr<N, E>, -) -> (&'a SubExpr<N, E>, Vec<LetBinding<'a, N, E>>) { - fn go<'a, N, E>( - e: &'a SubExpr<N, E>, - vec: &mut Vec<LetBinding<'a, N, E>>, - ) -> &'a SubExpr<N, E> { +fn collect_nested_lets<'a, E>( + e: &'a SubExpr<E>, +) -> (&'a SubExpr<E>, Vec<LetBinding<'a, E>>) { + fn go<'a, E>( + e: &'a SubExpr<E>, + vec: &mut Vec<LetBinding<'a, E>>, + ) -> &'a SubExpr<E> { match e.as_ref() { ExprF::Let(l, t, v, e) => { vec.push((l, t, v)); diff --git a/dhall/src/phase/mod.rs b/dhall/src/phase/mod.rs index 27a6901..8c93889 100644 --- a/dhall/src/phase/mod.rs +++ b/dhall/src/phase/mod.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::fmt::Display; use std::path::Path; -use dhall_syntax::{Const, Import, Span, SubExpr, X}; +use dhall_syntax::{Const, Import, SubExpr, X}; use crate::core::thunk::{Thunk, TypedThunk}; use crate::core::value::Value; @@ -17,10 +17,10 @@ pub(crate) mod parse; pub(crate) mod resolve; pub(crate) mod typecheck; -pub type ParsedSubExpr = SubExpr<Span, Import>; -pub type DecodedSubExpr = SubExpr<X, Import>; -pub type ResolvedSubExpr = SubExpr<Span, Normalized>; -pub type NormalizedSubExpr = SubExpr<X, X>; +pub type ParsedSubExpr = SubExpr<Import>; +pub type DecodedSubExpr = SubExpr<Import>; +pub type ResolvedSubExpr = SubExpr<Normalized>; +pub type NormalizedSubExpr = SubExpr<X>; #[derive(Debug, Clone)] pub struct Parsed(ParsedSubExpr, ImportRoot); diff --git a/dhall/src/phase/parse.rs b/dhall/src/phase/parse.rs index 734f6e1..9f3f2f4 100644 --- a/dhall/src/phase/parse.rs +++ b/dhall/src/phase/parse.rs @@ -25,7 +25,7 @@ pub fn parse_str(s: &str) -> Result<Parsed, Error> { pub fn parse_binary(data: &[u8]) -> Result<Parsed, Error> { let expr = crate::phase::binary::decode(data)?; let root = ImportRoot::LocalDir(std::env::current_dir()?); - Ok(Parsed(expr.note_absurd(), root)) + Ok(Parsed(expr, root)) } pub fn parse_binary_file(f: &Path) -> Result<Parsed, Error> { @@ -33,5 +33,5 @@ pub fn parse_binary_file(f: &Path) -> Result<Parsed, Error> { File::open(f)?.read_to_end(&mut buffer)?; let expr = crate::phase::binary::decode(&buffer)?; let root = ImportRoot::LocalDir(f.parent().unwrap().to_owned()); - Ok(Parsed(expr.note_absurd(), root)) + Ok(Parsed(expr, root)) } diff --git a/dhall/src/phase/typecheck.rs b/dhall/src/phase/typecheck.rs index a19e1ca..ecf9793 100644 --- a/dhall/src/phase/typecheck.rs +++ b/dhall/src/phase/typecheck.rs @@ -1,8 +1,8 @@ use std::collections::HashMap; use dhall_syntax::{ - rc, Builtin, Const, Expr, ExprF, InterpolatedTextContents, Label, Span, - SubExpr, X, + rc, Builtin, Const, Expr, ExprF, InterpolatedTextContents, Label, SubExpr, + X, }; use crate::core::context::{NormalizationContext, TypecheckContext}; @@ -214,7 +214,7 @@ macro_rules! make_type { }; } -fn type_of_builtin(b: Builtin) -> Expr<X, X> { +fn type_of_builtin(b: Builtin) -> Expr<X> { use dhall_syntax::Builtin::*; match b { Bool | Natural | Integer | Double | Text => make_type!(Type), @@ -303,7 +303,7 @@ fn type_of_builtin(b: Builtin) -> Expr<X, X> { /// and turn it into a type, typechecking it along the way. pub fn mktype( ctx: &TypecheckContext, - e: SubExpr<Span, Normalized>, + e: SubExpr<Normalized>, ) -> Result<Type, TypeError> { Ok(type_with(ctx, e)?.to_type()) } @@ -326,7 +326,7 @@ enum Ret { /// normalized as well. fn type_with( ctx: &TypecheckContext, - e: SubExpr<Span, Normalized>, + e: SubExpr<Normalized>, ) -> Result<Typed, TypeError> { use dhall_syntax::ExprF::{Annot, Embed, Lam, Let, Pi, Var}; @@ -1002,7 +1002,7 @@ fn type_last_layer( /// `typeOf` is the same as `type_with` with an empty context, meaning that the /// expression must be closed (i.e. no free variables), otherwise type-checking /// will fail. -fn type_of(e: SubExpr<Span, Normalized>) -> Result<Typed, TypeError> { +fn type_of(e: SubExpr<Normalized>) -> Result<Typed, TypeError> { let ctx = TypecheckContext::new(); let e = type_with(&ctx, e)?; // Ensure `e` has a type (i.e. `e` is not `Sort`) @@ -1015,8 +1015,8 @@ pub fn typecheck(e: Resolved) -> Result<Typed, TypeError> { } pub fn typecheck_with(e: Resolved, ty: &Type) -> Result<Typed, TypeError> { - let expr: SubExpr<_, _> = e.0; - let ty: SubExpr<_, _> = ty.to_expr().absurd(); + let expr: SubExpr<_> = e.0; + let ty: SubExpr<_> = ty.to_expr().absurd(); type_of(expr.rewrap(ExprF::Annot(expr.clone(), ty))) } pub fn skip_typecheck(e: Resolved) -> Typed { diff --git a/dhall_syntax/src/core/expr.rs b/dhall_syntax/src/core/expr.rs index 6522cb1..0cbece3 100644 --- a/dhall_syntax/src/core/expr.rs +++ b/dhall_syntax/src/core/expr.rs @@ -19,6 +19,30 @@ pub fn trivial_result<T>(x: Result<T, X>) -> T { } } +/// A location in the source text +#[derive(Debug, Clone)] +pub struct Span { + input: Rc<str>, + /// # Safety + /// + /// Must be a valid character boundary index into `input`. + start: usize, + /// # Safety + /// + /// Must be a valid character boundary index into `input`. + end: usize, +} + +impl Span { + pub(crate) fn make(input: Rc<str>, sp: pest::Span) -> Self { + Span { + input, + start: sp.start(), + end: sp.end(), + } + } +} + /// Double with bitwise equality #[derive(Debug, Copy, Clone)] pub struct NaiveDouble(f64); @@ -137,23 +161,19 @@ pub enum Builtin { TextShow, } -pub type ParsedExpr = SubExpr<X, Import>; -pub type ResolvedExpr = SubExpr<X, X>; -pub type DhallExpr = ResolvedExpr; - // Each node carries an annotation. In practice it's either X (no annotation) or a Span. #[derive(Debug)] -pub struct SubExpr<Note, Embed>(Rc<(Expr<Note, Embed>, Option<Note>)>); +pub struct SubExpr<Embed>(Rc<(Expr<Embed>, Option<Span>)>); -impl<Note, Embed: PartialEq> std::cmp::PartialEq for SubExpr<Note, Embed> { +impl<Embed: PartialEq> std::cmp::PartialEq for SubExpr<Embed> { fn eq(&self, other: &Self) -> bool { self.0.as_ref().0 == other.0.as_ref().0 } } -impl<Note, Embed: Eq> std::cmp::Eq for SubExpr<Note, Embed> {} +impl<Embed: Eq> std::cmp::Eq for SubExpr<Embed> {} -pub type Expr<Note, Embed> = ExprF<SubExpr<Note, Embed>, Embed>; +pub type Expr<Embed> = ExprF<SubExpr<Embed>, Embed>; /// Syntax tree for expressions // Having the recursion out of the enum definition enables writing @@ -293,31 +313,22 @@ impl<SE, E> ExprF<SE, E> { } } -impl<N, E> Expr<N, E> { +impl<E> Expr<E> { fn traverse_embed<E2, Err>( &self, visit_embed: impl FnMut(&E) -> Result<E2, Err>, - ) -> Result<Expr<N, E2>, Err> - where - N: Clone, - { + ) -> Result<Expr<E2>, Err> { self.visit(&mut visitor::TraverseEmbedVisitor(visit_embed)) } - fn map_embed<E2>(&self, mut map_embed: impl FnMut(&E) -> E2) -> Expr<N, E2> - where - N: Clone, - { + fn map_embed<E2>(&self, mut map_embed: impl FnMut(&E) -> E2) -> Expr<E2> { trivial_result(self.traverse_embed(|x| Ok(map_embed(x)))) } pub fn traverse_resolve<E2, Err>( &self, visit_embed: impl FnMut(&E) -> Result<E2, Err>, - ) -> Result<Expr<N, E2>, Err> - where - N: Clone, - { + ) -> Result<Expr<E2>, Err> { self.traverse_resolve_with_visitor(&mut visitor::ResolveVisitor( visit_embed, )) @@ -326,9 +337,8 @@ impl<N, E> Expr<N, E> { pub(crate) fn traverse_resolve_with_visitor<E2, Err, F1>( &self, visitor: &mut visitor::ResolveVisitor<F1>, - ) -> Result<Expr<N, E2>, Err> + ) -> Result<Expr<E2>, Err> where - N: Clone, F1: FnMut(&E) -> Result<E2, Err>, { match self { @@ -341,59 +351,44 @@ impl<N, E> Expr<N, E> { } } -impl Expr<X, X> { - pub fn absurd<N, E>(&self) -> Expr<N, E> { +impl Expr<X> { + pub fn absurd<E>(&self) -> Expr<E> { self.visit(&mut visitor::AbsurdVisitor) } } -impl<E: Clone> Expr<X, E> { - pub fn note_absurd<N>(&self) -> Expr<N, E> { - self.visit(&mut visitor::NoteAbsurdVisitor) - } -} - -impl<N, E> SubExpr<N, E> { - pub fn as_ref(&self) -> &Expr<N, E> { +impl<E> SubExpr<E> { + pub fn as_ref(&self) -> &Expr<E> { &self.0.as_ref().0 } - pub fn new(x: Expr<N, E>, n: N) -> Self { + pub fn new(x: Expr<E>, n: Span) -> Self { SubExpr(Rc::new((x, Some(n)))) } - pub fn from_expr_no_note(x: Expr<N, E>) -> Self { + pub fn from_expr_no_span(x: Expr<E>) -> Self { SubExpr(Rc::new((x, None))) } pub fn from_builtin(b: Builtin) -> Self { - SubExpr::from_expr_no_note(ExprF::Builtin(b)) + SubExpr::from_expr_no_span(ExprF::Builtin(b)) } - pub fn rewrap<E2>(&self, x: Expr<N, E2>) -> SubExpr<N, E2> - where - N: Clone, - { + pub fn rewrap<E2>(&self, x: Expr<E2>) -> SubExpr<E2> { SubExpr(Rc::new((x, (self.0).1.clone()))) } pub fn traverse_embed<E2, Err>( &self, visit_embed: impl FnMut(&E) -> Result<E2, Err>, - ) -> Result<SubExpr<N, E2>, Err> - where - N: Clone, - { + ) -> Result<SubExpr<E2>, Err> { Ok(self.rewrap(self.as_ref().traverse_embed(visit_embed)?)) } pub fn map_embed<E2>( &self, map_embed: impl FnMut(&E) -> E2, - ) -> SubExpr<N, E2> - where - N: Clone, - { + ) -> SubExpr<E2> { self.rewrap(self.as_ref().map_embed(map_embed)) } @@ -401,10 +396,7 @@ impl<N, E> SubExpr<N, E> { &'a self, map_expr: impl FnMut(&'a Self) -> Self, map_under_binder: impl FnMut(&'a Label, &'a Self) -> Self, - ) -> Self - where - N: Clone, - { + ) -> Self { match self.as_ref() { ExprF::Embed(_) => SubExpr::clone(self), // This calls ExprF::map_ref @@ -419,35 +411,38 @@ impl<N, E> SubExpr<N, E> { pub fn traverse_resolve<E2, Err>( &self, visit_embed: impl FnMut(&E) -> Result<E2, Err>, - ) -> Result<SubExpr<N, E2>, Err> - where - N: Clone, - { + ) -> Result<SubExpr<E2>, Err> { Ok(self.rewrap(self.as_ref().traverse_resolve(visit_embed)?)) } } -impl SubExpr<X, X> { - pub fn absurd<N: Clone, T>(&self) -> SubExpr<N, T> { - SubExpr::from_expr_no_note(self.as_ref().absurd()) - } -} - -impl<E: Clone> SubExpr<X, E> { - pub fn note_absurd<N>(&self) -> SubExpr<N, E> { - SubExpr::from_expr_no_note(self.as_ref().note_absurd()) +impl SubExpr<X> { + pub fn absurd<T>(&self) -> SubExpr<T> { + SubExpr::from_expr_no_span(self.as_ref().absurd()) } } -impl<N, E> Clone for SubExpr<N, E> { +impl<E> Clone for SubExpr<E> { fn clone(&self) -> Self { SubExpr(Rc::clone(&self.0)) } } // Should probably rename this -pub fn rc<E>(x: Expr<X, E>) -> SubExpr<X, E> { - SubExpr::from_expr_no_note(x) +pub fn rc<E>(x: Expr<E>) -> SubExpr<E> { + SubExpr::from_expr_no_span(x) +} + +pub(crate) fn spanned( + span: Span, + x: crate::parser::ParsedExpr, +) -> crate::parser::ParsedSubExpr { + SubExpr::new(x, span) +} +pub(crate) fn unspanned( + x: crate::parser::ParsedExpr, +) -> crate::parser::ParsedSubExpr { + SubExpr::from_expr_no_span(x) } /// Add an isize to an usize diff --git a/dhall_syntax/src/core/visitor.rs b/dhall_syntax/src/core/visitor.rs index 18f76d9..50ec68a 100644 --- a/dhall_syntax/src/core/visitor.rs +++ b/dhall_syntax/src/core/visitor.rs @@ -336,19 +336,18 @@ where pub struct TraverseEmbedVisitor<F1>(pub F1); -impl<'a, 'b, N, E, E2, Err, F1> - ExprFFallibleVisitor<'a, SubExpr<N, E>, SubExpr<N, E2>, E, E2> +impl<'a, 'b, E, E2, Err, F1> + ExprFFallibleVisitor<'a, SubExpr<E>, SubExpr<E2>, E, E2> for &'b mut TraverseEmbedVisitor<F1> where - N: Clone + 'a, F1: FnMut(&E) -> Result<E2, Err>, { type Error = Err; fn visit_subexpr( &mut self, - subexpr: &'a SubExpr<N, E>, - ) -> Result<SubExpr<N, E2>, Self::Error> { + subexpr: &'a SubExpr<E>, + ) -> Result<SubExpr<E2>, Self::Error> { Ok(subexpr.rewrap(subexpr.as_ref().visit(&mut **self)?)) } fn visit_embed(self, embed: &'a E) -> Result<E2, Self::Error> { @@ -358,19 +357,18 @@ where pub struct ResolveVisitor<F1>(pub F1); -impl<'a, 'b, N, E, E2, Err, F1> - ExprFFallibleVisitor<'a, SubExpr<N, E>, SubExpr<N, E2>, E, E2> +impl<'a, 'b, E, E2, Err, F1> + ExprFFallibleVisitor<'a, SubExpr<E>, SubExpr<E2>, E, E2> for &'b mut ResolveVisitor<F1> where - N: Clone + 'a, F1: FnMut(&E) -> Result<E2, Err>, { type Error = Err; fn visit_subexpr( &mut self, - subexpr: &'a SubExpr<N, E>, - ) -> Result<SubExpr<N, E2>, Self::Error> { + subexpr: &'a SubExpr<E>, + ) -> Result<SubExpr<E2>, Self::Error> { Ok(subexpr.rewrap( subexpr .as_ref() @@ -381,30 +379,14 @@ where (self.0)(embed) } } -pub struct NoteAbsurdVisitor; - -impl<'a, 'b, N, E> - ExprFInFallibleVisitor<'a, SubExpr<X, E>, SubExpr<N, E>, E, E> - for &'b mut NoteAbsurdVisitor -where - E: Clone + 'a, -{ - fn visit_subexpr(&mut self, subexpr: &'a SubExpr<X, E>) -> SubExpr<N, E> { - SubExpr::from_expr_no_note(subexpr.as_ref().visit(&mut **self)) - } - fn visit_embed(self, embed: &'a E) -> E { - E::clone(embed) - } -} pub struct AbsurdVisitor; -impl<'a, 'b, N, E> - ExprFInFallibleVisitor<'a, SubExpr<X, X>, SubExpr<N, E>, X, E> +impl<'a, 'b, E> ExprFInFallibleVisitor<'a, SubExpr<X>, SubExpr<E>, X, E> for &'b mut AbsurdVisitor { - fn visit_subexpr(&mut self, subexpr: &'a SubExpr<X, X>) -> SubExpr<N, E> { - SubExpr::from_expr_no_note(subexpr.as_ref().visit(&mut **self)) + fn visit_subexpr(&mut self, subexpr: &'a SubExpr<X>) -> SubExpr<E> { + SubExpr::from_expr_no_span(subexpr.as_ref().visit(&mut **self)) } fn visit_embed(self, embed: &'a X) -> E { match *embed {} diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs index 9ae6dc8..1ab6e6d 100644 --- a/dhall_syntax/src/parser.rs +++ b/dhall_syntax/src/parser.rs @@ -15,46 +15,15 @@ use crate::*; // their own crate because they are quite general and useful. For now they // are here and hopefully you can figure out how they work. -type ParsedExpr = Expr<Span, Import>; -type ParsedSubExpr = SubExpr<Span, Import>; -type ParsedText = InterpolatedText<SubExpr<Span, Import>>; -type ParsedTextContents = InterpolatedTextContents<SubExpr<Span, Import>>; +pub(crate) type ParsedExpr = Expr<Import>; +pub(crate) type ParsedSubExpr = SubExpr<Import>; +type ParsedText = InterpolatedText<SubExpr<Import>>; +type ParsedTextContents = InterpolatedTextContents<SubExpr<Import>>; pub type ParseError = pest::error::Error<Rule>; pub type ParseResult<T> = Result<T, ParseError>; -fn unspanned(x: ParsedExpr) -> ParsedSubExpr { - SubExpr::from_expr_no_note(x) -} - -#[derive(Debug, Clone)] -pub struct Span { - input: Rc<str>, - /// # Safety - /// - /// Must be a valid character boundary index into `input`. - start: usize, - /// # Safety - /// - /// Must be a valid character boundary index into `input`. - end: usize, -} - -impl Span { - fn make(input: Rc<str>, sp: pest::Span) -> Self { - Span { - input, - start: sp.start(), - end: sp.end(), - } - } -} - -fn spanned(span: Span, x: ParsedExpr) -> ParsedSubExpr { - SubExpr::new(x, span) -} - #[derive(Debug)] enum Either<A, B> { Left(A), diff --git a/dhall_syntax/src/printer.rs b/dhall_syntax/src/printer.rs index 70b224e..95eafe5 100644 --- a/dhall_syntax/src/printer.rs +++ b/dhall_syntax/src/printer.rs @@ -111,21 +111,21 @@ enum PrintPhase { // Wraps an Expr with a phase, so that phase selsction can be done // separate from the actual printing #[derive(Clone)] -struct PhasedExpr<'a, S, A>(&'a SubExpr<S, A>, PrintPhase); +struct PhasedExpr<'a, A>(&'a SubExpr<A>, PrintPhase); -impl<'a, S: Clone, A: Display + Clone> Display for PhasedExpr<'a, S, A> { +impl<'a, A: Display + Clone> Display for PhasedExpr<'a, A> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { self.0.as_ref().fmt_phase(f, self.1) } } -impl<'a, S: Clone, A: Display + Clone> PhasedExpr<'a, S, A> { - fn phase(self, phase: PrintPhase) -> PhasedExpr<'a, S, A> { +impl<'a, A: Display + Clone> PhasedExpr<'a, A> { + fn phase(self, phase: PrintPhase) -> PhasedExpr<'a, A> { PhasedExpr(self.0, phase) } } -impl<S: Clone, A: Display + Clone> Expr<S, A> { +impl<A: Display + Clone> Expr<A> { fn fmt_phase( &self, f: &mut fmt::Formatter, @@ -196,7 +196,7 @@ impl<S: Clone, A: Display + Clone> Expr<S, A> { } } -impl<S: Clone, A: Display + Clone> Display for SubExpr<S, A> { +impl<A: Display + Clone> Display for SubExpr<A> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { self.as_ref().fmt_phase(f, PrintPhase::Base) } diff --git a/serde_dhall/src/serde.rs b/serde_dhall/src/serde.rs index 10d5a17..d891127 100644 --- a/serde_dhall/src/serde.rs +++ b/serde_dhall/src/serde.rs @@ -1,7 +1,10 @@ +use std::borrow::Cow; + +use dhall::phase::NormalizedSubExpr; +use dhall_syntax::ExprF; + use crate::de::{Deserialize, Error, Result}; use crate::Value; -use dhall_syntax::{ExprF, SubExpr, X}; -use std::borrow::Cow; impl<'a, T> Deserialize for T where @@ -12,7 +15,7 @@ where } } -struct Deserializer<'a>(Cow<'a, SubExpr<X, X>>); +struct Deserializer<'a>(Cow<'a, NormalizedSubExpr>); impl<'de: 'a, 'a> serde::de::IntoDeserializer<'de, Error> for Deserializer<'a> { type Deserializer = Deserializer<'a>; |