From 0fb7c510b5f28a3b85a82a9436ba57e3cc7a8c4c Mon Sep 17 00:00:00 2001 From: ivanlele Date: Tue, 28 Apr 2026 12:33:47 +0300 Subject: [PATCH] Migrate execution to dynamic dispatch --- fuzz/fuzz_lib/program.rs | 6 +- fuzz/fuzz_targets/c_rust_merkle.rs | 2 +- fuzz/fuzz_targets/decode_program.rs | 2 +- fuzz/fuzz_targets/parse_human.rs | 4 +- fuzz/fuzz_targets/regression_286.rs | 2 +- simpcli/src/main.rs | 12 +- src/analysis.rs | 2 +- src/bit_encoding/bitwriter.rs | 3 +- src/bit_encoding/decode.rs | 64 +++---- src/bit_encoding/encode.rs | 1 - src/bit_machine/limits.rs | 4 +- src/bit_machine/mod.rs | 47 +++-- src/bit_machine/tracker.rs | 30 ++- src/human_encoding/mod.rs | 20 +- src/human_encoding/named_node.rs | 141 +++++++------- src/human_encoding/parse/ast.rs | 72 ++++---- src/human_encoding/parse/mod.rs | 79 ++++---- src/jet/elements/tests.rs | 2 +- src/jet/mod.rs | 91 ++++++++- src/lib.rs | 4 +- src/merkle/amr.rs | 4 +- src/merkle/cmr.rs | 24 +-- src/merkle/ihr.rs | 2 +- src/node/commit.rs | 96 +++++----- src/node/construct.rs | 275 ++++++++++++---------------- src/node/convert.rs | 19 +- src/node/display.rs | 4 +- src/node/hiding.rs | 7 +- src/node/inner.rs | 83 ++++++--- src/node/mod.rs | 55 +++--- src/node/redeem.rs | 212 ++++++++++----------- src/policy/ast.rs | 7 +- src/policy/satisfy.rs | 37 ++-- src/policy/serialize.rs | 64 +++---- src/types/arrow.rs | 4 +- src/types/incomplete.rs | 1 - src/types/mod.rs | 17 +- 37 files changed, 750 insertions(+), 749 deletions(-) diff --git a/fuzz/fuzz_lib/program.rs b/fuzz/fuzz_lib/program.rs index 63bd833d..ae39baf9 100644 --- a/fuzz/fuzz_lib/program.rs +++ b/fuzz/fuzz_lib/program.rs @@ -49,8 +49,8 @@ impl Extractor<'_> { &mut self, ctx: &types::Context<'brand>, force_control: Option, - ) -> Option>> { - type ArcNode<'brand> = Arc>; + ) -> Option>> { + type ArcNode<'brand> = Arc>; let mut stack: Vec = vec![]; @@ -165,7 +165,7 @@ impl Extractor<'_> { _ => { let extra_bits = usize::from(control >> 6); let idx = (extra_bits << 8) + usize::from(self.extract_u8()?); - stack.push(ArcNode::jet(ctx, Core::ALL[idx % Core::ALL.len()])); + stack.push(ArcNode::jet(ctx, &Core::ALL[idx % Core::ALL.len()])); } } } diff --git a/fuzz/fuzz_targets/c_rust_merkle.rs b/fuzz/fuzz_targets/c_rust_merkle.rs index 0871d429..1df41db2 100644 --- a/fuzz/fuzz_targets/c_rust_merkle.rs +++ b/fuzz/fuzz_targets/c_rust_merkle.rs @@ -36,7 +36,7 @@ fn do_test(data: &[u8]) { let prog_iter = BitIter::from(program); let wit_iter = BitIter::from(witness); - let rust_result = RedeemNode::::decode(prog_iter, wit_iter); + let rust_result = RedeemNode::decode::<_, _, Elements>(prog_iter, wit_iter); match (c_result, rust_result) { (Ok(_), Err(e)) => panic!("C accepted code that Rust rejected: {}", e), diff --git a/fuzz/fuzz_targets/decode_program.rs b/fuzz/fuzz_targets/decode_program.rs index 2ff860a1..6624c803 100644 --- a/fuzz/fuzz_targets/decode_program.rs +++ b/fuzz/fuzz_targets/decode_program.rs @@ -9,7 +9,7 @@ fn do_test(data: &[u8]) { let prog_iter = BitIter::new(data.iter().cloned()); let wit_iter = BitIter::new(core::iter::repeat(0)); - if let Ok(program) = RedeemNode::::decode(prog_iter, wit_iter) { + if let Ok(program) = RedeemNode::decode::<_, _, Core>(prog_iter, wit_iter) { let mut prog_reser = Vec::::new(); let mut wit_reser = Vec::::new(); diff --git a/fuzz/fuzz_targets/parse_human.rs b/fuzz/fuzz_targets/parse_human.rs index 877e5a8b..39b8af1a 100644 --- a/fuzz/fuzz_targets/parse_human.rs +++ b/fuzz/fuzz_targets/parse_human.rs @@ -12,9 +12,9 @@ fn do_test(data: &[u8]) { Err(_) => return, }; - if let Ok(program) = Forest::::parse(s) { + if let Ok(program) = Forest::parse::(s) { let reserialize = program.string_serialize(); - let round_trip = Forest::::parse(&reserialize).unwrap(); + let round_trip = Forest::parse::(&reserialize).unwrap(); assert_eq!(program, round_trip); } } diff --git a/fuzz/fuzz_targets/regression_286.rs b/fuzz/fuzz_targets/regression_286.rs index 2dbef6ed..be9aa9c5 100644 --- a/fuzz/fuzz_targets/regression_286.rs +++ b/fuzz/fuzz_targets/regression_286.rs @@ -32,7 +32,7 @@ fn do_test(data: &[u8]) { let prog = finalized.encode_to_vec(); //println!("{}", simplicity::bitcoin::hex::DisplayHex::as_hex(&prog)); let prog = BitIter::from(prog); - let decode = CommitNode::::decode(prog).unwrap(); + let decode = CommitNode::decode::<_, Core>(prog).unwrap(); assert_eq!( finalized, decode, "Constructed committed LHS; encoded and decoded to get RHS", diff --git a/simpcli/src/main.rs b/simpcli/src/main.rs index cb7660a7..4e063217 100644 --- a/simpcli/src/main.rs +++ b/simpcli/src/main.rs @@ -75,9 +75,9 @@ impl Command { } } -fn parse_file(name: &str) -> Result, String> { +fn parse_file(name: &str) -> Result { let s = fs::read_to_string(name).map_err(|e| format!("failed to read file {}: {}", name, e))?; - match Forest::parse(&s) { + match Forest::parse::(&s) { Ok(prog) => Ok(prog), Err(mut errs) => { errs.add_context(std::sync::Arc::from(s)); @@ -154,16 +154,16 @@ fn main() -> Result<(), String> { let v = simplicity::base64::Engine::decode(&STANDARD, first_arg.as_bytes()) .map_err(|e| format!("failed to parse base64: {}", e))?; let iter = BitIter::from(v.into_iter()); - let commit = - CommitNode::decode(iter).map_err(|e| format!("failed to decode program: {}", e))?; - let prog = Forest::::from_program(commit); + let commit = CommitNode::decode::<_, DefaultJet>(iter) + .map_err(|e| format!("failed to decode program: {}", e))?; + let prog = Forest::from_program(commit); println!("{}", prog.string_serialize()); } Command::Graph => { let v = simplicity::base64::Engine::decode(&STANDARD, first_arg.as_bytes()) .map_err(|e| format!("failed to parse base64: {}", e))?; let iter = BitIter::from(v.into_iter()); - let commit = CommitNode::::decode(iter) + let commit = CommitNode::decode::<_, DefaultJet>(iter) .map_err(|e| format!("failed to decode program: {}", e))?; println!("{}", commit.display_as_dot()); } diff --git a/src/analysis.rs b/src/analysis.rs index 581f4070..1585e2d9 100644 --- a/src/analysis.rs +++ b/src/analysis.rs @@ -370,7 +370,7 @@ impl NodeBounds { } /// Node bounds for an arbitrary jet node - pub fn jet(jet: J) -> NodeBounds { + pub fn jet(jet: &dyn Jet) -> NodeBounds { NodeBounds { extra_cells: 0, extra_frames: 0, diff --git a/src/bit_encoding/bitwriter.rs b/src/bit_encoding/bitwriter.rs index 7964e1e3..97d3226d 100644 --- a/src/bit_encoding/bitwriter.rs +++ b/src/bit_encoding/bitwriter.rs @@ -115,7 +115,6 @@ where #[cfg(test)] mod tests { use super::*; - use crate::jet::Core; use crate::node::CoreConstructible; use crate::types; use crate::ConstructNode; @@ -124,7 +123,7 @@ mod tests { #[test] fn vec() { types::Context::with_context(|ctx| { - let program = Arc::>::unit(&ctx); + let program = Arc::::unit(&ctx); let _ = write_to_vec(|w| program.encode_without_witness(w)); }) } diff --git a/src/bit_encoding/decode.rs b/src/bit_encoding/decode.rs index fc89e9a4..92f63afe 100644 --- a/src/bit_encoding/decode.rs +++ b/src/bit_encoding/decode.rs @@ -21,7 +21,7 @@ use std::{cmp, error, fmt}; use super::bititer::{u2, DecodeNaturalError}; -type ArcNode<'brand, J> = Arc>; +type ArcNode<'brand> = Arc>; /// Decoding error #[non_exhaustive] @@ -104,7 +104,7 @@ impl error::Error for Error { } #[derive(Debug)] -enum DecodeNode { +enum DecodeNode { Iden, Unit, InjL(usize), @@ -119,14 +119,14 @@ enum DecodeNode { Witness, Fail(FailEntropy), Hidden(Cmr), - Jet(J), + Jet(Box), Word(Word), } -impl DagLike for (usize, &'_ [DecodeNode]) { - type Node = DecodeNode; +impl DagLike for (usize, &'_ [DecodeNode]) { + type Node = DecodeNode; - fn data(&self) -> &DecodeNode { + fn data(&self) -> &DecodeNode { &self.1[self.0] } @@ -156,14 +156,14 @@ impl DagLike for (usize, &'_ [DecodeNode]) { pub fn decode_expression<'brand, I: Iterator, J: Jet>( ctx: &types::Context<'brand>, bits: &mut BitIter, -) -> Result, Error> { - enum Converted<'brand, J: Jet> { - Node(ArcNode<'brand, J>), +) -> Result, Error> { + enum Converted<'brand> { + Node(ArcNode<'brand>), Hidden(Cmr), } use Converted::{Hidden, Node}; - impl<'brand, J: Jet> Converted<'brand, J> { - fn get(&self) -> Result<&ArcNode<'brand, J>, Error> { + impl<'brand> Converted<'brand> { + fn get(&self) -> Result<&ArcNode<'brand>, Error> { match self { Node(arc) => Ok(arc), Hidden(_) => Err(Error::HiddenNode), @@ -176,34 +176,34 @@ pub fn decode_expression<'brand, I: Iterator, J: Jet>( let mut nodes = Vec::with_capacity(cmp::min(len, 10_000)); for _ in 0..len { - let new_node = decode_node(bits, nodes.len())?; + let new_node = decode_node::(bits, nodes.len())?; nodes.push(new_node); } // It is a sharing violation for any hidden node to be repeated. Track them in this set. let mut hidden_set = HashSet::::new(); // Convert the DecodeNode structure into a CommitNode structure - let mut converted = Vec::>::with_capacity(len); + let mut converted = Vec::::with_capacity(len); for data in (nodes.len() - 1, &nodes[..]).post_order_iter::() { // Check canonical order as we go if data.index != data.node.0 { return Err(Error::NotInCanonicalOrder); } - let new = match nodes[data.node.0] { + let new = match &nodes[data.node.0] { DecodeNode::Unit => Node(ArcNode::unit(ctx)), DecodeNode::Iden => Node(ArcNode::iden(ctx)), - DecodeNode::InjL(i) => Node(ArcNode::injl(converted[i].get()?)), - DecodeNode::InjR(i) => Node(ArcNode::injr(converted[i].get()?)), - DecodeNode::Take(i) => Node(ArcNode::take(converted[i].get()?)), - DecodeNode::Drop(i) => Node(ArcNode::drop_(converted[i].get()?)), + DecodeNode::InjL(i) => Node(ArcNode::injl(converted[*i].get()?)), + DecodeNode::InjR(i) => Node(ArcNode::injr(converted[*i].get()?)), + DecodeNode::Take(i) => Node(ArcNode::take(converted[*i].get()?)), + DecodeNode::Drop(i) => Node(ArcNode::drop_(converted[*i].get()?)), DecodeNode::Comp(i, j) => { - Node(ArcNode::comp(converted[i].get()?, converted[j].get()?)?) + Node(ArcNode::comp(converted[*i].get()?, converted[*j].get()?)?) } DecodeNode::Case(i, j) => { // Case is a special case, since it uniquely is allowed to have hidden // children (but only one!) in which case it becomes an assertion. - match (&converted[i], &converted[j]) { + match (&converted[*i], &converted[*j]) { (Node(left), Node(right)) => Node(ArcNode::case(left, right)?), (Node(left), Hidden(cmr)) => Node(ArcNode::assertl(left, *cmr)?), (Hidden(cmr), Node(right)) => Node(ArcNode::assertr(*cmr, right)?), @@ -211,22 +211,22 @@ pub fn decode_expression<'brand, I: Iterator, J: Jet>( } } DecodeNode::Pair(i, j) => { - Node(ArcNode::pair(converted[i].get()?, converted[j].get()?)?) + Node(ArcNode::pair(converted[*i].get()?, converted[*j].get()?)?) } - DecodeNode::Disconnect1(i) => Node(ArcNode::disconnect(converted[i].get()?, &None)?), + DecodeNode::Disconnect1(i) => Node(ArcNode::disconnect(converted[*i].get()?, &None)?), DecodeNode::Disconnect(i, j) => Node(ArcNode::disconnect( - converted[i].get()?, - &Some(Arc::clone(converted[j].get()?)), + converted[*i].get()?, + &Some(Arc::clone(converted[*j].get()?)), )?), DecodeNode::Witness => Node(ArcNode::witness(ctx, None)), - DecodeNode::Fail(entropy) => Node(ArcNode::fail(ctx, entropy)), + DecodeNode::Fail(entropy) => Node(ArcNode::fail(ctx, *entropy)), DecodeNode::Hidden(cmr) => { - if !hidden_set.insert(cmr) { + if !hidden_set.insert(*cmr) { return Err(Error::SharingNotMaximal); } - Hidden(cmr) + Hidden(*cmr) } - DecodeNode::Jet(j) => Node(ArcNode::jet(ctx, j)), + DecodeNode::Jet(j) => Node(ArcNode::jet(ctx, j.as_ref())), DecodeNode::Word(ref w) => Node(ArcNode::const_word(ctx, w.shallow_clone())), }; converted.push(new); @@ -240,12 +240,12 @@ pub fn decode_expression<'brand, I: Iterator, J: Jet>( fn decode_node, J: Jet>( bits: &mut BitIter, index: usize, -) -> Result, Error> { +) -> Result { // First bit: 1 for jets/words, 0 for normal combinators if bits.read_bit()? { // Second bit: 1 for jets, 0 for words if bits.read_bit()? { - J::decode(bits).map(|jet| DecodeNode::Jet(jet)) + J::decode(bits).map(|jet| DecodeNode::Jet(Box::new(jet))) } else { let n = bits.read_natural(Some(32))?; let word = Word::from_bits(bits, n - 1)?; @@ -321,10 +321,10 @@ mod tests { }); // ...but NOT as a CommitNode let iter = BitIter::from(&justjet[..]); - CommitNode::::decode(iter).unwrap_err(); + CommitNode::decode::<_, Core>(iter).unwrap_err(); // ...or as a RedeemNode let iter = BitIter::from(&justjet[..]); - RedeemNode::::decode(iter, BitIter::from(&[][..])).unwrap_err(); + RedeemNode::decode::<_, _, Core>(iter, BitIter::from(&[][..])).unwrap_err(); } #[test] diff --git a/src/bit_encoding/encode.rs b/src/bit_encoding/encode.rs index 546b0ba5..6667abbe 100644 --- a/src/bit_encoding/encode.rs +++ b/src/bit_encoding/encode.rs @@ -8,7 +8,6 @@ //! to read it visually the way you can with Bitcoin Script. use crate::dag::{Dag, DagLike, PostOrderIterItem, SharingTracker}; -use crate::jet::Jet; use crate::node::{self, Disconnectable}; use crate::{BitWriter, Cmr, Value}; diff --git a/src/bit_machine/limits.rs b/src/bit_machine/limits.rs index 70d01d37..ed23324d 100644 --- a/src/bit_machine/limits.rs +++ b/src/bit_machine/limits.rs @@ -93,9 +93,7 @@ impl LimitError { } /// Helper function to check every value and sum for being within bounds. - pub(super) fn check_program( - program: &crate::RedeemNode, - ) -> Result<(), Self> { + pub(super) fn check_program(program: &crate::RedeemNode) -> Result<(), Self> { let source_ty_width = program.arrow().source.bit_width(); let target_ty_width = program.arrow().target.bit_width(); let bounds = program.bounds(); diff --git a/src/bit_machine/mod.rs b/src/bit_machine/mod.rs index e5c466de..c2d70739 100644 --- a/src/bit_machine/mod.rs +++ b/src/bit_machine/mod.rs @@ -47,7 +47,7 @@ pub struct BitMachine { impl BitMachine { /// Construct a Bit Machine with enough space to execute the given program. - pub fn for_program(program: &RedeemNode) -> Result { + pub fn for_program(program: &RedeemNode) -> Result { LimitError::check_program(program)?; let io_width = program.arrow().source.bit_width() + program.arrow().target.bit_width(); @@ -62,7 +62,7 @@ impl BitMachine { #[cfg(test)] pub fn test_exec( - program: Arc>, + program: Arc, env: &JE, ) -> Result { use crate::node::SimpleFinalizer; @@ -223,7 +223,7 @@ impl BitMachine { /// The Bit Machine is constructed via [`Self::for_program()`] to ensure enough space. pub fn exec( &mut self, - program: &RedeemNode, + program: &RedeemNode, env: &JE, ) -> Result { self.exec_with_tracker(program, env, &mut NoTracker) @@ -237,14 +237,14 @@ impl BitMachine { /// ## Precondition /// /// The Bit Machine is constructed via [`Self::for_program()`] to ensure enough space. - pub fn exec_with_tracker>( + pub fn exec_with_tracker( &mut self, - program: &RedeemNode, + program: &RedeemNode, env: &JE, tracker: &mut T, ) -> Result { - enum CallStack<'a, JE: JetEnvironment> { - Goto(&'a RedeemNode), + enum CallStack<'a> { + Goto(&'a RedeemNode), MoveWriteFrameToRead, DropReadFrame, CopyFwd(usize), @@ -252,7 +252,7 @@ impl BitMachine { } // Not used, but useful for debugging, so keep it around - impl fmt::Debug for CallStack<'_, JE> { + impl fmt::Debug for CallStack<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { CallStack::Goto(ins) => write!(f, "goto {}", ins.inner()), @@ -269,7 +269,7 @@ impl BitMachine { } let mut ip = program; - let mut call_stack: Vec> = vec![]; + let mut call_stack: Vec> = vec![]; let output_width = ip.arrow().target.bit_width(); if output_width > 0 { @@ -370,7 +370,12 @@ impl BitMachine { } node::Inner::Witness(value) => self.write_value(value), node::Inner::Jet(jet) => { - jet_result = self.exec_jet(*jet, env); + let typed_jet = jet + .as_ref() + .as_any() + .downcast_ref::() + .ok_or(ExecutionError::JetTypeMismatch)?; + jet_result = self.exec_jet(typed_jet, env); } node::Inner::Word(value) => self.write_value(value.as_value()), node::Inner::Fail(entropy) => { @@ -436,7 +441,7 @@ impl BitMachine { } } - fn exec_jet(&mut self, jet: JE::Jet, env: &JE) -> Result<(), JetFailed> { + fn exec_jet(&mut self, jet: &JE::Jet, env: &JE) -> Result<(), JetFailed> { use crate::ffi::c_jets::frame_ffi::{c_readBit, c_writeBit, CFrameItem}; use crate::ffi::c_jets::uword_width; use crate::ffi::ffi::UWORD; @@ -525,7 +530,7 @@ impl BitMachine { let (input_read_frame, _input_buffer) = unsafe { get_input_frame(self, input_width) }; let (mut output_write_frame, output_buffer) = unsafe { get_output_frame(output_width) }; - let jet_fn = JE::c_jet_ptr(&jet); + let jet_fn = JE::c_jet_ptr(jet); let c_env = env.c_jet_env(); let success = jet_fn(&mut output_write_frame, input_read_frame, c_env); @@ -551,6 +556,8 @@ pub enum ExecutionError { LimitExceeded(LimitError), /// Jet failed during execution JetFailed(JetFailed), + /// Jet type mismatch between program and execution environment + JetTypeMismatch, } impl fmt::Display for ExecutionError { @@ -567,6 +574,9 @@ impl fmt::Display for ExecutionError { } ExecutionError::LimitExceeded(e) => e.fmt(f), ExecutionError::JetFailed(jet_failed) => jet_failed.fmt(f), + ExecutionError::JetTypeMismatch => { + f.write_str("Jet type mismatch between program and execution environment") + } } } } @@ -576,7 +586,8 @@ impl error::Error for ExecutionError { match self { Self::InputWrongType(..) | Self::ReachedFailNode(..) - | Self::ReachedPrunedBranch(..) => None, + | Self::ReachedPrunedBranch(..) + | Self::JetTypeMismatch => None, Self::LimitExceeded(ref e) => Some(e), Self::JetFailed(ref e) => Some(e), } @@ -599,9 +610,9 @@ impl From for ExecutionError { mod tests { use super::*; - use crate::jet::CoreEnv; #[cfg(feature = "elements")] - use crate::jet::{elements::ElementsEnv, Elements}; + use crate::jet::elements::ElementsEnv; + use crate::jet::CoreEnv; #[cfg(feature = "elements")] use crate::{node::RedeemNode, BitIter}; #[cfg(feature = "elements")] @@ -619,7 +630,7 @@ mod tests { let prog = BitIter::from(prog_bytes); let witness = BitIter::from(witness_bytes); - let prog = match RedeemNode::::decode(prog, witness) { + let prog = match RedeemNode::decode::<_, _, crate::jet::Elements>(prog, witness) { Ok(prog) => prog, Err(e) => panic!("program {} failed: {}", prog_hex, e), }; @@ -689,12 +700,12 @@ mod tests { fn crash_regression2() { use crate::node::{CoreConstructible as _, JetConstructible as _}; - type Node<'brand> = Arc>; + type Node<'brand> = Arc>; crate::types::Context::with_context(|ctx| { let mut bomb = Node::jet( &ctx, - crate::jet::Core::Ch8, // arbitrary jet with nonzero output size + &crate::jet::Core::Ch8, // arbitrary jet with nonzero output size ); for _ in 0..100 { bomb = Node::pair(&bomb, &bomb).unwrap(); diff --git a/src/bit_machine/tracker.rs b/src/bit_machine/tracker.rs index 8cecd337..124fb0ad 100644 --- a/src/bit_machine/tracker.rs +++ b/src/bit_machine/tracker.rs @@ -10,7 +10,6 @@ use std::collections::HashSet; -use crate::jet::Jet; use crate::node::Inner; use crate::{Ihr, RedeemNode, Value}; @@ -42,7 +41,7 @@ pub enum NodeOutput<'m> { /// [`RedeemNode::prune_with_tracker`] to prune the program. The most straightforward /// way to do this is to embed a [`SetTracker`] in your tracker and forward all the trait /// methods to that. -pub trait ExecTracker { +pub trait ExecTracker { /// Called immediately after a specific node of the program is executed, but before /// its children are executed. /// @@ -60,11 +59,10 @@ pub trait ExecTracker { /// * `input` is an iterator over the read frame when the node's execution began /// * for terminal nodes (`witness`, `unit`, `iden` and jets), `output` is an iterator /// the write frame after the node has executed. See [`NodeOutput`] for more information. - fn visit_node(&mut self, _node: &RedeemNode, _input: super::FrameIter, _output: NodeOutput) { - } + fn visit_node(&mut self, _node: &RedeemNode, _input: super::FrameIter, _output: NodeOutput) {} } -pub trait PruneTracker: ExecTracker { +pub trait PruneTracker: ExecTracker { /// Returns true if the left branch of the of the `Case` node with the IHR `ihr` was taken. fn contains_left(&self, ihr: Ihr) -> bool; @@ -79,10 +77,10 @@ pub struct SetTracker { right: HashSet, } -impl ExecTracker for SetTracker { +impl ExecTracker for SetTracker { fn visit_node<'d>( &mut self, - node: &RedeemNode, + node: &RedeemNode, mut input: super::FrameIter, _output: NodeOutput, ) { @@ -98,7 +96,7 @@ impl ExecTracker for SetTracker { } } -impl PruneTracker for SetTracker { +impl PruneTracker for SetTracker { fn contains_left(&self, ihr: Ihr) -> bool { self.left.contains(&ihr) } @@ -112,10 +110,10 @@ impl PruneTracker for SetTracker { #[derive(Copy, Clone, Debug)] pub struct NoTracker; -impl ExecTracker for NoTracker { +impl ExecTracker for NoTracker { fn visit_node<'d>( &mut self, - node: &RedeemNode, + node: &RedeemNode, mut input: super::FrameIter, output: NodeOutput, ) { @@ -146,8 +144,8 @@ impl StderrTracker { } } -impl ExecTracker for StderrTracker { - fn visit_node(&mut self, node: &RedeemNode, input: super::FrameIter, output: NodeOutput) { +impl ExecTracker for StderrTracker { + fn visit_node(&mut self, node: &RedeemNode, input: super::FrameIter, output: NodeOutput) { let input_val = Value::from_padded_bits(&mut input.clone(), &node.arrow().source) .expect("input from bit machine will always be well-formed"); eprintln!( @@ -176,15 +174,15 @@ impl ExecTracker for StderrTracker { eprintln!(" [debug] assertL CMR {cmr}"); } - ExecTracker::::visit_node(&mut self.inner, node, input, output); + ExecTracker::visit_node(&mut self.inner, node, input, output); self.exec_count += 1; eprintln!(); } } -impl PruneTracker for StderrTracker { +impl PruneTracker for StderrTracker { fn contains_left(&self, ihr: Ihr) -> bool { - if PruneTracker::::contains_left(&self.inner, ihr) { + if PruneTracker::contains_left(&self.inner, ihr) { true } else { eprintln!("Pruning unexecuted left child of IHR {ihr}"); @@ -193,7 +191,7 @@ impl PruneTracker for StderrTracker { } fn contains_right(&self, ihr: Ihr) -> bool { - if PruneTracker::::contains_right(&self.inner, ihr) { + if PruneTracker::contains_right(&self.inner, ihr) { true } else { eprintln!("Pruning unexecuted right child of IHR {ihr}"); diff --git a/src/human_encoding/mod.rs b/src/human_encoding/mod.rs index f8c0fed8..7bbba011 100644 --- a/src/human_encoding/mod.rs +++ b/src/human_encoding/mod.rs @@ -68,18 +68,18 @@ impl From<&'_ NoWitness> for WitnessOrHole { } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct Forest { - roots: HashMap, Arc>>, +pub struct Forest { + roots: HashMap, Arc>, } -impl Forest { +impl Forest { /// Parses a forest from a string - pub fn parse(s: &str) -> Result { - parse::parse(s).map(|roots| Forest { roots }) + pub fn parse(s: &str) -> Result { + parse::parse::(s).map(|roots| Forest { roots }) } /// Parses a program from a bytestring - pub fn from_program(root: Arc>) -> Self { + pub fn from_program(root: Arc) -> Self { let root = NamedCommitNode::from_node(&root); let mut roots = HashMap::new(); roots.insert("main".into(), root); @@ -87,7 +87,7 @@ impl Forest { } /// Accessor for the map of roots of this forest - pub fn roots(&self) -> &HashMap, Arc>> { + pub fn roots(&self) -> &HashMap, Arc> { &self.roots } @@ -200,7 +200,7 @@ impl Forest { &self, inference_context: &types::Context<'brand>, witness: &HashMap, Value>, - ) -> Option>> { + ) -> Option>> { let main = self.roots.get("main")?; Some(main.to_construct_node(inference_context, witness, self.roots())) } @@ -221,7 +221,7 @@ mod tests { env: &JE, ) { types::Context::with_context(|ctx| { - let program = Forest::::parse(s) + let program = Forest::parse::(s) .expect("Failed to parse human encoding") .to_witness_node(&ctx, witness) .expect("Forest is missing expected root") @@ -239,7 +239,7 @@ mod tests { err_msg: &'static str, ) { types::Context::with_context(|ctx| { - let program = match Forest::::parse(s) + let program = match Forest::parse::(s) .expect("Failed to parse human encoding") .to_witness_node(&ctx, witness) .expect("Forest is missing expected root") diff --git a/src/human_encoding/named_node.rs b/src/human_encoding/named_node.rs index e53122a6..9548abd1 100644 --- a/src/human_encoding/named_node.rs +++ b/src/human_encoding/named_node.rs @@ -4,7 +4,6 @@ use crate::dag::{InternalSharing, MaxSharing, PostOrderIterItem}; use crate::human_encoding::{Error, ErrorSet, Position, WitnessOrHole}; -use crate::jet::Jet; use crate::node::{ self, Commit, CommitData, CommitNode, Construct, ConstructData, Constructible as _, Converter, CoreConstructible as _, Inner, NoDisconnect, NoWitness, Node, @@ -19,7 +18,7 @@ use std::io; use std::marker::PhantomData; use std::sync::Arc; -pub type NamedCommitNode = Node>>; +pub type NamedCommitNode = Node>; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Named { @@ -29,30 +28,29 @@ pub struct Named { phantom: std::marker::PhantomData, } -impl node::Marker for Named> { - type CachedData = NamedCommitData; - type Witness = as node::Marker>::Witness; +impl node::Marker for Named { + type CachedData = NamedCommitData; + type Witness = ::Witness; type Disconnect = Arc; - type SharingId = as node::Marker>::SharingId; - type Jet = J; + type SharingId = ::SharingId; fn compute_sharing_id(cmr: Cmr, cached_data: &Self::CachedData) -> Option { - Commit::::compute_sharing_id(cmr, &cached_data.internal) + Commit::compute_sharing_id(cmr, &cached_data.internal) } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct NamedCommitData { +pub struct NamedCommitData { /// Data related to the node itself - internal: Arc>, + internal: Arc, /// Name assigned to the node. name: Arc, } -impl NamedCommitNode { - pub fn from_node(root: &CommitNode) -> Arc { +impl NamedCommitNode { + pub fn from_node(root: &CommitNode) -> Arc { let mut namer = Namer::new_rooted(root.cmr()); - root.convert::>, _, _>(&mut namer) + root.convert::, _, _>(&mut namer) .unwrap() } @@ -72,14 +70,14 @@ impl NamedCommitNode { } /// Forget the names, yielding an ordinary [`CommitNode`]. - pub fn to_commit_node(&self) -> Arc> { - struct Forgetter(PhantomData); + pub fn to_commit_node(&self) -> Arc { + struct Forgetter(PhantomData<()>); - impl Converter>, Commit> for Forgetter { + impl Converter, Commit> for Forgetter { type Error = (); fn convert_witness( &mut self, - _: &PostOrderIterItem<&NamedCommitNode>, + _: &PostOrderIterItem<&NamedCommitNode>, _: &NoWitness, ) -> Result { Ok(NoWitness) @@ -87,8 +85,8 @@ impl NamedCommitNode { fn convert_disconnect( &mut self, - _: &PostOrderIterItem<&NamedCommitNode>, - _: Option<&Arc>>, + _: &PostOrderIterItem<&NamedCommitNode>, + _: Option<&Arc>, _: &Arc, ) -> Result { Ok(NoDisconnect) @@ -96,9 +94,9 @@ impl NamedCommitNode { fn convert_data( &mut self, - data: &PostOrderIterItem<&NamedCommitNode>, - _: node::Inner<&Arc>, J, &NoDisconnect, &NoWitness>, - ) -> Result>, Self::Error> { + data: &PostOrderIterItem<&NamedCommitNode>, + _: node::Inner<&Arc, &NoDisconnect, &NoWitness>, + ) -> Result, Self::Error> { Ok(Arc::clone(&data.node.cached_data().internal)) } } @@ -111,23 +109,20 @@ impl NamedCommitNode { &self, inference_context: &types::Context<'brand>, witness: &HashMap, Value>, - disconnect: &HashMap, Arc>>, - ) -> Arc> { - struct Populator<'a, 'brand, J: Jet> { + disconnect: &HashMap, Arc>, + ) -> Arc> { + struct Populator<'a, 'brand> { witness_map: &'a HashMap, Value>, - disconnect_map: &'a HashMap, Arc>>, + disconnect_map: &'a HashMap, Arc>, inference_context: &'a types::Context<'brand>, - phantom: PhantomData, } - impl<'brand, J: Jet> Converter>, Construct<'brand, J>> - for Populator<'_, 'brand, J> - { + impl<'brand> Converter, Construct<'brand>> for Populator<'_, 'brand> { type Error = (); fn convert_witness( &mut self, - data: &PostOrderIterItem<&Node>>>, + data: &PostOrderIterItem<&Node>>, _: &NoWitness, ) -> Result, Self::Error> { let name = &data.node.cached_data().name; @@ -141,10 +136,10 @@ impl NamedCommitNode { fn convert_disconnect( &mut self, - data: &PostOrderIterItem<&Node>>>, - maybe_converted: Option<&Arc>>>, + data: &PostOrderIterItem<&Node>>, + maybe_converted: Option<&Arc>>>, _: &Arc, - ) -> Result>>>, Self::Error> { + ) -> Result>>>, Self::Error> { if let Some(converted) = maybe_converted { Ok(Some(converted.clone())) } else { @@ -172,14 +167,13 @@ impl NamedCommitNode { fn convert_data( &mut self, - _: &PostOrderIterItem<&Node>>>, + _: &PostOrderIterItem<&Node>>, inner: Inner< - &Arc>>, - J, - &Option>>, + &Arc>>, + &Option>>, &Option, >, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { let inner = inner .map(|node| node.cached_data()) .map_witness(|maybe_value| maybe_value.clone()); @@ -192,7 +186,6 @@ impl NamedCommitNode { witness_map: witness, disconnect_map: disconnect, inference_context, - phantom: PhantomData, }) .unwrap() } @@ -217,24 +210,23 @@ impl NamedCommitNode { } } -pub type NamedConstructNode<'brand, J> = Node>>; +pub type NamedConstructNode<'brand> = Node>>; -impl<'brand, J: Jet> node::Marker for Named> { - type CachedData = NamedConstructData<'brand, J>; +impl<'brand> node::Marker for Named> { + type CachedData = NamedConstructData<'brand>; type Witness = WitnessOrHole; - type Disconnect = Arc>; - type SharingId = as node::Marker>::SharingId; - type Jet = J; + type Disconnect = Arc>; + type SharingId = as node::Marker>::SharingId; fn compute_sharing_id(cmr: Cmr, cached_data: &Self::CachedData) -> Option { - Construct::::compute_sharing_id(cmr, &cached_data.internal) + Construct::compute_sharing_id(cmr, &cached_data.internal) } } #[derive(Clone, Debug)] -pub struct NamedConstructData<'brand, J> { +pub struct NamedConstructData<'brand> { /// Data related to the node itself - internal: ConstructData<'brand, J>, + internal: ConstructData<'brand>, /// Name assigned to the node name: Arc, /// Position of the node, if it comes from source code. @@ -247,7 +239,7 @@ pub struct NamedConstructData<'brand, J> { user_target_types: Arc<[types::Type<'brand>]>, } -impl<'brand, J: Jet> NamedConstructNode<'brand, J> { +impl<'brand> NamedConstructNode<'brand> { /// Construct a named construct node from parts. pub fn new( inference_context: &types::Context<'brand>, @@ -255,7 +247,7 @@ impl<'brand, J: Jet> NamedConstructNode<'brand, J> { position: Position, user_source_types: Arc<[types::Type<'brand>]>, user_target_types: Arc<[types::Type<'brand>]>, - inner: node::Inner, J, Arc, WitnessOrHole>, + inner: node::Inner, Arc, WitnessOrHole>, ) -> Result { let construct_data = ConstructData::from_inner( inference_context, @@ -308,31 +300,27 @@ impl<'brand, J: Jet> NamedConstructNode<'brand, J> { } /// Finalizes the types of the underlying [`crate::ConstructNode`]. - pub fn finalize_types_main(&self) -> Result>, ErrorSet> { + pub fn finalize_types_main(&self) -> Result, ErrorSet> { self.finalize_types_inner(true) } /// Finalizes the types of the underlying [`crate::ConstructNode`], without setting /// the root node's arrow to 1->1. - pub fn finalize_types_non_main(&self) -> Result>, ErrorSet> { + pub fn finalize_types_non_main(&self) -> Result, ErrorSet> { self.finalize_types_inner(false) } - pub fn finalize_types_inner( - &self, - for_main: bool, - ) -> Result>, ErrorSet> { - struct FinalizeTypes { + pub fn finalize_types_inner(&self, for_main: bool) -> Result, ErrorSet> { + struct FinalizeTypes { for_main: bool, errors: ErrorSet, pending_hole_error: Option<(Position, Error)>, - phantom: PhantomData, } - impl<'brand, J: Jet> Converter>, Named>> for FinalizeTypes { + impl<'brand> Converter>, Named> for FinalizeTypes { type Error = ErrorSet; - fn visit_node(&mut self, data: &PostOrderIterItem<&NamedConstructNode>) { + fn visit_node(&mut self, data: &PostOrderIterItem<&NamedConstructNode>) { // If we encounter a typed hole, this is an error *except* when the typed // hole is the right child of a disconnect combinator. Conveniently, this // case is very easy to detect: it will always appear as a hole immediately @@ -367,7 +355,7 @@ impl<'brand, J: Jet> NamedConstructNode<'brand, J> { fn convert_witness( &mut self, - _: &PostOrderIterItem<&NamedConstructNode>, + _: &PostOrderIterItem<&NamedConstructNode>, _: &WitnessOrHole, ) -> Result { Ok(NoWitness) @@ -375,9 +363,9 @@ impl<'brand, J: Jet> NamedConstructNode<'brand, J> { fn convert_disconnect( &mut self, - data: &PostOrderIterItem<&NamedConstructNode>, - _: Option<&Arc>>, - disc: &Arc>, + data: &PostOrderIterItem<&NamedConstructNode>, + _: Option<&Arc>, + disc: &Arc, ) -> Result, Self::Error> { match disc.inner() { node::Inner::Witness(WitnessOrHole::TypedHole(hole_name)) => { @@ -393,9 +381,9 @@ impl<'brand, J: Jet> NamedConstructNode<'brand, J> { fn convert_data( &mut self, - data: &PostOrderIterItem<&NamedConstructNode>, - inner: node::Inner<&Arc>, J, &Arc, &NoWitness>, - ) -> Result, Self::Error> { + data: &PostOrderIterItem<&NamedConstructNode>, + inner: node::Inner<&Arc, &Arc, &NoWitness>, + ) -> Result { let converted_data = inner .as_ref() .map(|node| &node.cached_data().internal) @@ -464,7 +452,6 @@ impl<'brand, J: Jet> NamedConstructNode<'brand, J> { for_main, errors: ErrorSet::default(), pending_hole_error: None, - phantom: PhantomData, }; if for_main { @@ -526,7 +513,7 @@ impl Namer { } /// Generate a fresh name for the given node. - pub fn assign_name(&mut self, inner: node::Inner) -> String { + pub fn assign_name(&mut self, inner: node::Inner) -> String { let prefix = match inner { node::Inner::Iden => "id", node::Inner::Unit => "ut", @@ -558,11 +545,11 @@ impl Namer { } } -impl Converter, Named>> for Namer { +impl Converter> for Namer { type Error = (); fn convert_witness( &mut self, - _: &PostOrderIterItem<&CommitNode>, + _: &PostOrderIterItem<&CommitNode>, _: &NoWitness, ) -> Result { Ok(NoWitness) @@ -570,8 +557,8 @@ impl Converter, Named>> for Namer { fn convert_disconnect( &mut self, - _: &PostOrderIterItem<&CommitNode>, - _: Option<&Arc>>, + _: &PostOrderIterItem<&CommitNode>, + _: Option<&Arc>, _: &NoDisconnect, ) -> Result, Self::Error> { let hole_idx = self.other_idx; @@ -581,9 +568,9 @@ impl Converter, Named>> for Namer { fn convert_data( &mut self, - data: &PostOrderIterItem<&CommitNode>, - inner: node::Inner<&Arc>, J, &Arc, &NoWitness>, - ) -> Result, Self::Error> { + data: &PostOrderIterItem<&CommitNode>, + inner: node::Inner<&Arc, &Arc, &NoWitness>, + ) -> Result { // Special-case the root node, which is always called main. // The CMR of the root node, conveniently, is guaranteed to be // unique, so we can key on the CMR to figure out which node to do. diff --git a/src/human_encoding/parse/ast.rs b/src/human_encoding/parse/ast.rs index dd2d7e02..cfad2fe0 100644 --- a/src/human_encoding/parse/ast.rs +++ b/src/human_encoding/parse/ast.rs @@ -17,25 +17,25 @@ use crate::{BitIter, FailEntropy}; /// /// A program is simply a list of such lines #[derive(Debug, PartialEq, Eq, Clone, Hash)] -pub struct Line { +pub struct Line { /// Position of the first character of the line. pub position: Position, /// The name of the expression being named on the line. pub name: Arc, /// The actual expression, if present (missing for type declarations). - pub expression: Option>, + pub expression: Option, /// The type of the expression, if given (inferred if missing). pub arrow: (Option, Option), } /// An expression, as represented in the AST #[derive(Debug, PartialEq, Eq, Clone, Hash)] -pub struct Expression { - pub inner: ExprInner, +pub struct Expression { + pub inner: ExprInner, pub position: Position, } -impl Expression { +impl Expression { fn reference(name: Arc, position: Position) -> Self { Expression { inner: ExprInner::Reference(name), @@ -46,21 +46,21 @@ impl Expression { /// An expression, as represented in the AST #[derive(Debug, PartialEq, Eq, Clone, Hash)] -pub enum ExprInner { +pub enum ExprInner { /// A reference to another expression Reference(Arc), /// A left assertion (referring to the CMR of an expression on the right) - AssertL(Arc>, AstCmr), + AssertL(Arc, AstCmr), /// A right assertion (referring to the CMR of an expression on the left) - AssertR(AstCmr, Arc>), + AssertR(AstCmr, Arc), /// An inline expression - Inline(node::Inner>, J, Arc>, WitnessOrHole>), + Inline(node::Inner, Arc, WitnessOrHole>), } /// A CMR, as represented in the AST #[derive(Debug, PartialEq, Eq, Clone, Hash)] -pub enum AstCmr { - Expr(Arc>), +pub enum AstCmr { + Expr(Arc), Literal, } @@ -339,23 +339,23 @@ impl Parser { } /// Takes a program as a string and parses it into an AST -pub fn parse_line_vector(input: &str) -> Result>, ErrorSet> { +pub fn parse_line_vector(input: &str) -> Result, ErrorSet> { let tokens = lex_all(input)?; let mut parser = Parser::new(tokens); let mut lines = Vec::new(); while !parser.at_end() { - lines.push(parse_line(&mut parser)?); + lines.push(parse_line::(&mut parser)?); } Ok(lines) } /// Parse a line -fn parse_line(p: &mut Parser) -> Result, ErrorSet> { +fn parse_line(p: &mut Parser) -> Result { let (name, position) = parse_symbol_value(p)?; if p.eat(&Token::Assign) { // symbol ":=" expr (optionally followed by ":" arrow) - let expr = parse_expr(p)?; + let expr = parse_expr::(p)?; let arrow = if p.eat(&Token::Colon) { parse_arrow(p)? } else { @@ -395,13 +395,13 @@ fn parse_arrow(p: &mut Parser) -> Result<(Option, Option), ErrorSet> } /// Parse an expression -fn parse_expr(p: &mut Parser) -> Result, ErrorSet> { +fn parse_expr(p: &mut Parser) -> Result { let position = p.current_position(); match p.peek().cloned() { Some(Token::LParen) => { p.advance(); - let inner = parse_expr(p)?; + let inner = parse_expr::(p)?; p.expect(&Token::RParen)?; Ok(inner) } @@ -431,8 +431,8 @@ fn parse_expr(p: &mut Parser) -> Result, ErrorSe } Some(Token::AssertL) => { p.advance(); - let left = parse_expr(p)?; - let cmr = parse_cmr(p)?; + let left = parse_expr::(p)?; + let cmr = parse_cmr::(p)?; Ok(Expression { inner: ExprInner::AssertL(Arc::new(left), cmr), position, @@ -440,8 +440,8 @@ fn parse_expr(p: &mut Parser) -> Result, ErrorSe } Some(Token::AssertR) => { p.advance(); - let cmr = parse_cmr(p)?; - let right = parse_expr(p)?; + let cmr = parse_cmr::(p)?; + let right = parse_expr::(p)?; Ok(Expression { inner: ExprInner::AssertR(cmr, Arc::new(right)), position, @@ -499,14 +499,14 @@ fn parse_expr(p: &mut Parser) -> Result, ErrorSe return Err(ErrorSet::single(position, Error::UnknownJet(jet_name))); }; Ok(Expression { - inner: ExprInner::Inline(node::Inner::Jet(jet)), + inner: ExprInner::Inline(node::Inner::Jet(Box::new(jet))), position, }) } // Unary Some(Token::InjL) => { p.advance(); - let child = Arc::new(parse_expr(p)?); + let child = Arc::new(parse_expr::(p)?); Ok(Expression { inner: ExprInner::Inline(node::Inner::InjL(child)), position, @@ -514,7 +514,7 @@ fn parse_expr(p: &mut Parser) -> Result, ErrorSe } Some(Token::InjR) => { p.advance(); - let child = Arc::new(parse_expr(p)?); + let child = Arc::new(parse_expr::(p)?); Ok(Expression { inner: ExprInner::Inline(node::Inner::InjR(child)), position, @@ -522,7 +522,7 @@ fn parse_expr(p: &mut Parser) -> Result, ErrorSe } Some(Token::Take) => { p.advance(); - let child = Arc::new(parse_expr(p)?); + let child = Arc::new(parse_expr::(p)?); Ok(Expression { inner: ExprInner::Inline(node::Inner::Take(child)), position, @@ -530,7 +530,7 @@ fn parse_expr(p: &mut Parser) -> Result, ErrorSe } Some(Token::Drop) => { p.advance(); - let child = Arc::new(parse_expr(p)?); + let child = Arc::new(parse_expr::(p)?); Ok(Expression { inner: ExprInner::Inline(node::Inner::Drop(child)), position, @@ -539,8 +539,8 @@ fn parse_expr(p: &mut Parser) -> Result, ErrorSe // Binary Some(Token::Case) => { p.advance(); - let left = Arc::new(parse_expr(p)?); - let right = Arc::new(parse_expr(p)?); + let left = Arc::new(parse_expr::(p)?); + let right = Arc::new(parse_expr::(p)?); Ok(Expression { inner: ExprInner::Inline(node::Inner::Case(left, right)), position, @@ -548,8 +548,8 @@ fn parse_expr(p: &mut Parser) -> Result, ErrorSe } Some(Token::Comp) => { p.advance(); - let left = Arc::new(parse_expr(p)?); - let right = Arc::new(parse_expr(p)?); + let left = Arc::new(parse_expr::(p)?); + let right = Arc::new(parse_expr::(p)?); Ok(Expression { inner: ExprInner::Inline(node::Inner::Comp(left, right)), position, @@ -557,8 +557,8 @@ fn parse_expr(p: &mut Parser) -> Result, ErrorSe } Some(Token::Pair) => { p.advance(); - let left = Arc::new(parse_expr(p)?); - let right = Arc::new(parse_expr(p)?); + let left = Arc::new(parse_expr::(p)?); + let right = Arc::new(parse_expr::(p)?); Ok(Expression { inner: ExprInner::Inline(node::Inner::Pair(left, right)), position, @@ -566,8 +566,8 @@ fn parse_expr(p: &mut Parser) -> Result, ErrorSe } Some(Token::Disconnect) => { p.advance(); - let left = Arc::new(parse_expr(p)?); - let right = Arc::new(parse_expr(p)?); + let left = Arc::new(parse_expr::(p)?); + let right = Arc::new(parse_expr::(p)?); Ok(Expression { inner: ExprInner::Inline(node::Inner::Disconnect(left, right)), position, @@ -586,9 +586,9 @@ fn parse_expr(p: &mut Parser) -> Result, ErrorSe } /// Parse a CMR (either an expression in #{} or a literal) -fn parse_cmr(p: &mut Parser) -> Result, ErrorSet> { +fn parse_cmr(p: &mut Parser) -> Result { if p.eat(&Token::HashBrace) { - let expr = parse_expr(p)?; + let expr = parse_expr::(p)?; p.expect(&Token::RBrace)?; return Ok(AstCmr::Expr(Arc::new(expr))); } diff --git a/src/human_encoding/parse/mod.rs b/src/human_encoding/parse/mod.rs index e57e3518..64045a77 100644 --- a/src/human_encoding/parse/mod.rs +++ b/src/human_encoding/parse/mod.rs @@ -19,12 +19,12 @@ use super::{Position, WitnessOrHole}; use super::{Error, ErrorSet}; #[derive(Clone)] -struct UnresolvedExpression<'brand, J: Jet> { - inner: UnresolvedInner<'brand, J>, +struct UnresolvedExpression<'brand> { + inner: UnresolvedInner<'brand>, position: Position, } -impl<'brand, J: Jet> UnresolvedExpression<'brand, J> { +impl<'brand> UnresolvedExpression<'brand> { fn from_name(name: Arc, position: Position) -> Self { UnresolvedExpression { inner: UnresolvedInner::NoExpr { @@ -36,7 +36,7 @@ impl<'brand, J: Jet> UnresolvedExpression<'brand, J> { } } - fn from_inline_expression(expr_inner: ast::ExprInner, position: Position) -> Self { + fn from_inline_expression(expr_inner: ast::ExprInner, position: Position) -> Self { UnresolvedExpression { inner: UnresolvedInner::Inline { expr_inner }, position, @@ -45,7 +45,7 @@ impl<'brand, J: Jet> UnresolvedExpression<'brand, J> { fn add_expression( &mut self, - expr_inner: ast::ExprInner, + expr_inner: ast::ExprInner, position: Position, ) -> Result<(), ErrorSet> { match self.inner { @@ -108,25 +108,25 @@ impl<'brand, J: Jet> UnresolvedExpression<'brand, J> { } #[derive(Clone)] -enum UnresolvedInner<'brand, J: Jet> { +enum UnresolvedInner<'brand> { NoExpr { name: Arc, user_source_types: Vec>, user_target_types: Vec>, }, Inline { - expr_inner: ast::ExprInner, + expr_inner: ast::ExprInner, }, Named { name: Arc, user_source_types: Vec>, user_target_types: Vec>, - expr_inner: ast::ExprInner, + expr_inner: ast::ExprInner, }, } -struct ResolvedExpression<'brand, J: Jet> { - inner: ResolvedInner<'brand, J>, +struct ResolvedExpression<'brand> { + inner: ResolvedInner<'brand>, position: Position, name: Option>, @@ -136,9 +136,9 @@ struct ResolvedExpression<'brand, J: Jet> { in_degree: AtomicUsize, } -impl<'brand, J: Jet> DagLike for &'_ ResolvedExpression<'brand, J> { - type Node = ResolvedExpression<'brand, J>; - fn data(&self) -> &ResolvedExpression<'brand, J> { +impl<'brand> DagLike for &'_ ResolvedExpression<'brand> { + type Node = ResolvedExpression<'brand>; + fn data(&self) -> &ResolvedExpression<'brand> { self } @@ -157,49 +157,46 @@ impl<'brand, J: Jet> DagLike for &'_ ResolvedExpression<'brand, J> { } } -enum ResolvedCmr<'brand, J: Jet> { - Expr(Arc>), +enum ResolvedCmr<'brand> { + Expr(Arc>), Literal, } -enum ResolvedInner<'brand, J: Jet> { +enum ResolvedInner<'brand> { /// A reference to a missing expression Missing { name: Arc }, /// A reference to a name with no associated expression NoExpr { name: Arc }, /// A reference to another expression - Reference(Arc>), + Reference(Arc>), /// A left assertion (referring to the CMR of an expression on the right) - AssertL(Arc>, ResolvedCmr<'brand, J>), + AssertL(Arc>, ResolvedCmr<'brand>), /// A right assertion (referring to the CMR of an expression on the left) - AssertR(ResolvedCmr<'brand, J>, Arc>), + AssertR(ResolvedCmr<'brand>, Arc>), /// An inline expression Inline( node::Inner< - Arc>, - J, - Arc>, + Arc>, + Arc>, WitnessOrHole, >, ), } -pub fn parse( - program: &str, -) -> Result, Arc>>, ErrorSet> { - types::Context::with_context(|ctx| parse_inner(ctx, program)) +pub fn parse(program: &str) -> Result, Arc>, ErrorSet> { + types::Context::with_context(|ctx| parse_inner::(ctx, program)) } -fn parse_inner( +fn parse_inner( inference_context: types::Context<'_>, program: &str, -) -> Result, Arc>>, ErrorSet> { +) -> Result, Arc>, ErrorSet> { let mut errors = ErrorSet::new(); // ** // Step 1: Read expressions into HashMap, checking for dupes and illegal names. // ** - let mut unresolved_map = HashMap::, UnresolvedExpression>::new(); - for line in ast::parse_line_vector(program)? { + let mut unresolved_map = HashMap::, UnresolvedExpression>::new(); + for line in ast::parse_line_vector::(program)? { if line.name.as_ref() == "_" || line.name.starts_with("prim") { errors.add(line.position, Error::NameIllegal(Arc::clone(&line.name))); continue; @@ -232,15 +229,15 @@ fn parse_inner( // we may have multiple disconnected components. // ** let mut resolved_map = - HashMap::, Arc>>::with_capacity(unresolved_map.len()); + HashMap::, Arc>::with_capacity(unresolved_map.len()); while let Some(name) = unresolved_map.keys().next() { let name = Arc::clone(name); let expr = unresolved_map.remove(&name).unwrap(); #[derive(Clone)] - struct StackItem<'brand, J: Jet> { - expr: UnresolvedExpression<'brand, J>, + struct StackItem<'brand> { + expr: UnresolvedExpression<'brand>, name: Option>, done_children: bool, } @@ -263,7 +260,7 @@ fn parse_inner( // On the other hand, inline expressions do not have names or any other identifying // characteristics except the order in which they appear. So for these we need to // use the `inline_stack` to keep track of which ones we've already resolved.. - let mut inline_stack: Vec>> = vec![]; + let mut inline_stack: Vec> = vec![]; stack.push(StackItem { expr, name: Some(Arc::clone(&name)), @@ -276,7 +273,7 @@ fn parse_inner( stack_item.done_children = true; stack.push(stack_item.clone()); - let push_ast_expr = |stack: &mut Vec<_>, expr: &ast::Expression<_>| { + let push_ast_expr = |stack: &mut Vec<_>, expr: &ast::Expression| { stack.push(StackItem { expr: UnresolvedExpression::from_inline_expression( expr.inner.clone(), @@ -325,7 +322,7 @@ fn parse_inner( continue; } - let mut convert_expr_inner = |expr_inner: &ast::ExprInner| match expr_inner { + let mut convert_expr_inner = |expr_inner: &ast::ExprInner| match expr_inner { ast::ExprInner::Reference(ref ref_name) => { if let Some(referent) = resolved_map.get(ref_name) { referent.in_degree.fetch_add(1, Ordering::SeqCst); @@ -384,7 +381,7 @@ fn parse_inner( // Then, convert the node. At this point if we are missing any children // it is because there was a resolution error, i.e. the expression // references a child that doesn't exist. - let resolved: ResolvedExpression = match stack_item.expr.inner { + let resolved: ResolvedExpression = match stack_item.expr.inner { UnresolvedInner::NoExpr { ref name, ref user_source_types, @@ -433,14 +430,14 @@ fn parse_inner( drop(unresolved_map); // ** Step 3: convert each DAG of names/expressions into a DAG of NamedNodes. - let mut roots = HashMap::, Arc>>::new(); + let mut roots = HashMap::, Arc>::new(); for (name, expr) in &resolved_map { if expr.in_degree.load(Ordering::SeqCst) > 0 { continue; } let mut namer = Namer::new(); - let mut converted: Vec>>> = vec![]; + let mut converted: Vec>> = vec![]; for data in expr.as_ref().post_order_iter::() { let left = data .left_index @@ -586,7 +583,7 @@ mod tests { use crate::dag::MaxSharing; use crate::human_encoding::Forest; - use crate::jet::{Core, CoreEnv, Jet, JetEnvironment}; + use crate::jet::{Core, CoreEnv, JetEnvironment}; use crate::node::Inner; use crate::value::Word; use crate::{BitMachine, Value}; @@ -708,7 +705,7 @@ mod tests { #[test] fn preserve_name() { - let program = &Forest::::parse("main := x x := unit").unwrap(); + let program = &Forest::parse::("main := x x := unit").unwrap(); assert!(program.string_serialize().contains("main := unit")); } diff --git a/src/jet/elements/tests.rs b/src/jet/elements/tests.rs index 45baa95b..42d72fcd 100644 --- a/src/jet/elements/tests.rs +++ b/src/jet/elements/tests.rs @@ -101,7 +101,7 @@ fn test_ffi_env() { ); types::Context::with_context(|ctx| { - let prog = Arc::>::jet(&ctx, Elements::LockTime); + let prog = Arc::::jet(&ctx, &Elements::LockTime); assert_eq!( BitMachine::test_exec(prog, &env).expect("executing"), Value::u32(100), diff --git a/src/jet/mod.rs b/src/jet/mod.rs index b6cc0059..a412aaf8 100644 --- a/src/jet/mod.rs +++ b/src/jet/mod.rs @@ -38,7 +38,9 @@ use crate::decode; use crate::jet::type_name::TypeName; use crate::merkle::cmr::Cmr; use crate::{BitIter, BitWriter}; -use std::hash::Hash; +use std::any::{Any, TypeId}; +use std::cmp::Ordering; +use std::hash::{Hash, Hasher}; use std::io::Write; /// Generic error that a jet failed during its execution. @@ -80,7 +82,7 @@ pub trait JetEnvironment { /// Jets may read values from their _environment_. /// /// Jets are **always** leaves in a Simplicity DAG. -pub trait Jet: Copy + Eq + Ord + Hash + std::fmt::Debug + std::fmt::Display + 'static { +pub trait Jet: DynJet + std::fmt::Debug + std::fmt::Display + Send + Sync + 'static { /// Return the CMR of the jet. fn cmr(&self) -> Cmr; @@ -107,6 +109,75 @@ pub trait Jet: Copy + Eq + Ord + Hash + std::fmt::Debug + std::fmt::Display + 's Self: Sized; } +/// Lets `Box` work with `Clone`, `Eq`, `Ord`, and `Hash`. +pub trait DynJet { + fn as_any(&self) -> &dyn Any; + fn dyn_clone(&self) -> Box; + fn dyn_eq(&self, other: &dyn Jet) -> bool; + fn dyn_cmp(&self, other: &dyn Jet) -> Ordering; + fn dyn_hash(&self, state: &mut dyn Hasher); +} + +impl DynJet for T { + fn as_any(&self) -> &dyn Any { + self + } + + fn dyn_clone(&self) -> Box { + Box::new(self.clone()) + } + + fn dyn_eq(&self, other: &dyn Jet) -> bool { + other + .as_any() + .downcast_ref::() + .is_some_and(|other| self == other) + } + + fn dyn_cmp(&self, other: &dyn Jet) -> Ordering { + match other.as_any().downcast_ref::() { + Some(other) => self.cmp(other), + None => TypeId::of::().cmp(&other.as_any().type_id()), + } + } + + fn dyn_hash(&self, mut state: &mut dyn Hasher) { + self.hash(&mut state) + } +} + +impl Clone for Box { + fn clone(&self) -> Self { + (**self).dyn_clone() + } +} + +impl PartialEq for Box { + fn eq(&self, other: &Self) -> bool { + (**self).dyn_eq(&**other) + } +} + +impl Eq for Box {} + +impl PartialOrd for Box { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Box { + fn cmp(&self, other: &Self) -> Ordering { + (**self).dyn_cmp(&**other) + } +} + +impl Hash for Box { + fn hash(&self, state: &mut H) { + (**self).dyn_hash(state) + } +} + #[cfg(test)] mod tests { use crate::jet::{Core, CoreEnv}; @@ -119,13 +190,13 @@ mod tests { #[test] fn test_ffi_jet() { types::Context::with_context(|ctx| { - let two_words = Arc::>::comp( - &Arc::>::pair( - &Arc::>::const_word(&ctx, Word::u32(2)), - &Arc::>::const_word(&ctx, Word::u32(16)), + let two_words = Arc::::comp( + &Arc::::pair( + &Arc::::const_word(&ctx, Word::u32(2)), + &Arc::::const_word(&ctx, Word::u32(16)), ) .unwrap(), - &Arc::>::jet(&ctx, Core::Add32), + &Arc::::jet(&ctx, &Core::Add32), ) .unwrap(); assert_eq!( @@ -141,9 +212,9 @@ mod tests { #[test] fn test_simple() { types::Context::with_context(|ctx| { - let two_words = Arc::>::pair( - &Arc::>::const_word(&ctx, Word::u32(2)), - &Arc::>::const_word(&ctx, Word::u16(16)), + let two_words = Arc::::pair( + &Arc::::const_word(&ctx, Word::u32(2)), + &Arc::::const_word(&ctx, Word::u16(16)), ) .unwrap(); assert_eq!( diff --git a/src/lib.rs b/src/lib.rs index 9db51a0c..e2830f69 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,12 +36,12 @@ //! ```rust //! use simplicity::node::CoreConstructible; //! use simplicity::types::Context; -//! use simplicity::{ConstructNode, jet::Core}; +//! use simplicity::ConstructNode; //! use std::sync::Arc; //! //! // Create a trivial Simplicity program //! let program = Context::with_context(|ctx| { -//! let construct = Arc::>::unit(&ctx); +//! let construct = Arc::::unit(&ctx); //! construct.finalize_types().unwrap() //! }); //! diff --git a/src/merkle/amr.rs b/src/merkle/amr.rs index 523b9dd5..32b04caa 100644 --- a/src/merkle/amr.rs +++ b/src/merkle/amr.rs @@ -160,7 +160,7 @@ impl Amr { } /// Produce a CMR for a jet - pub fn jet(jet: J) -> Self { + pub fn jet(jet: &dyn Jet) -> Self { Cmr::jet(jet).into() } @@ -298,7 +298,7 @@ mod tests { #[test] fn fixed_amr() { types::Context::with_context(|ctx| { - let node = Arc::>::jet(&ctx, Core::Verify) + let node = Arc::::jet(&ctx, &Core::Verify) .finalize_types_non_program() .unwrap(); // Checked against C implementation diff --git a/src/merkle/cmr.rs b/src/merkle/cmr.rs index 4f0abe00..d1f8684e 100644 --- a/src/merkle/cmr.rs +++ b/src/merkle/cmr.rs @@ -93,7 +93,7 @@ impl Cmr { } /// Produce a CMR for a jet - pub fn jet(jet: J) -> Self { + pub fn jet(jet: &dyn Jet) -> Self { jet.cmr() } @@ -378,8 +378,8 @@ impl<'brand, W> WitnessConstructible<'brand, W> for ConstructibleCmr<'brand> { } } -impl<'brand, J: Jet> JetConstructible<'brand, J> for ConstructibleCmr<'brand> { - fn jet(inference_context: &types::Context<'brand>, jet: J) -> Self { +impl<'brand> JetConstructible<'brand> for ConstructibleCmr<'brand> { + fn jet(inference_context: &types::Context<'brand>, jet: &dyn Jet) -> Self { ConstructibleCmr { cmr: jet.cmr(), inference_context: inference_context.shallow_clone(), @@ -391,7 +391,6 @@ impl<'brand, J: Jet> JetConstructible<'brand, J> for ConstructibleCmr<'brand> { mod tests { use super::*; - use crate::jet::Core; use crate::node::{ConstructNode, CoreConstructible}; use std::str::FromStr; @@ -400,7 +399,7 @@ mod tests { #[test] fn cmr_display_unit() { types::Context::with_context(|ctx| { - let c = Arc::>::unit(&ctx); + let c = Arc::::unit(&ctx); assert_eq!( c.cmr().to_string(), @@ -429,11 +428,11 @@ mod tests { #[test] fn bit_cmr() { types::Context::with_context(|ctx| { - let unit = Arc::>::unit(&ctx); - let bit0 = Arc::>::injl(&unit); + let unit = Arc::::unit(&ctx); + let bit0 = Arc::::injl(&unit); assert_eq!(bit0.cmr(), Cmr::BITS[0]); - let bit1 = Arc::>::injr(&unit); + let bit1 = Arc::::injr(&unit); assert_eq!(bit1.cmr(), Cmr::BITS[1]); }); } @@ -483,13 +482,10 @@ mod tests { #[test] fn const_bits() { /// The scribe expression, as defined in the Simplicity tech report. - fn scribe<'brand>( - ctx: &types::Context<'brand>, - bit: u8, - ) -> Arc> { + fn scribe<'brand>(ctx: &types::Context<'brand>, bit: u8) -> Arc> { match bit { - 0 => Arc::>::injl(&Arc::>::unit(ctx)), - 1 => Arc::>::injr(&Arc::>::unit(ctx)), + 0 => Arc::::injl(&Arc::::unit(ctx)), + 1 => Arc::::injr(&Arc::::unit(ctx)), _ => panic!("Unexpected bit {bit}"), } } diff --git a/src/merkle/ihr.rs b/src/merkle/ihr.rs index 364aa6a6..e5eecbd6 100644 --- a/src/merkle/ihr.rs +++ b/src/merkle/ihr.rs @@ -118,7 +118,7 @@ impl Imr { } /// Produce a CMR for a jet - pub fn jet(jet: J) -> Self { + pub fn jet(jet: &dyn Jet) -> Self { Cmr::jet(jet).into() } diff --git a/src/node/commit.rs b/src/node/commit.rs index 935984c6..616a6001 100644 --- a/src/node/commit.rs +++ b/src/node/commit.rs @@ -12,31 +12,27 @@ use super::{ }; use std::io; -use std::marker::PhantomData; use std::sync::Arc; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] -pub struct Commit { +pub struct Commit { /// Makes the type non-constructible. never: std::convert::Infallible, - /// Required by Rust. - phantom: std::marker::PhantomData, } -impl Marker for Commit { - type CachedData = Arc>; +impl Marker for Commit { + type CachedData = Arc; type Witness = NoWitness; type Disconnect = NoDisconnect; type SharingId = Ihr; - type Jet = J; - fn compute_sharing_id(_: Cmr, cached_data: &Arc>) -> Option { + fn compute_sharing_id(_: Cmr, cached_data: &Arc) -> Option { cached_data.ihr } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct CommitData { +pub struct CommitData { /// The source and target types of the node arrow: FinalArrow, /// The IMR of the node if it exists. This is distinct from its IHR; it is @@ -48,13 +44,9 @@ pub struct CommitData { /// The IHR of the node if it exists, meaning, if it is not (an ancestor of) /// a witness or disconnect node. ihr: Option, - /// This isn't really necessary, but it helps type inference if every - /// struct has a \ parameter, since it forces the choice of jets to - /// be consistent without the user needing to specify it too many times. - phantom: PhantomData, } -impl CommitData { +impl CommitData { /// Accessor for the node's arrow pub fn arrow(&self) -> &FinalArrow { &self.arrow @@ -67,7 +59,7 @@ impl CommitData { /// Helper function to compute a cached AMR fn incomplete_amr( - inner: Inner<&Arc, J, &NoDisconnect, &NoWitness>, + inner: Inner<&Arc, &NoDisconnect, &NoWitness>, arrow: &FinalArrow, ) -> Option { match inner { @@ -97,13 +89,13 @@ impl CommitData { Inner::Disconnect(..) => None, Inner::Witness(..) => None, Inner::Fail(entropy) => Some(Amr::fail(entropy)), - Inner::Jet(jet) => Some(Amr::jet(jet)), + Inner::Jet(jet) => Some(Amr::jet(jet.as_ref())), Inner::Word(ref val) => Some(Amr::const_word(val)), } } /// Helper function to compute a cached first-pass IHR - fn imr(inner: Inner<&Arc, J, &NoDisconnect, &NoWitness>) -> Option { + fn imr(inner: Inner<&Arc, &NoDisconnect, &NoWitness>) -> Option { match inner { Inner::Iden => Some(Imr::iden()), Inner::Unit => Some(Imr::unit()), @@ -119,14 +111,14 @@ impl CommitData { Inner::Disconnect(..) => None, Inner::Witness(..) => None, Inner::Fail(entropy) => Some(Imr::fail(entropy)), - Inner::Jet(jet) => Some(Imr::jet(jet)), + Inner::Jet(jet) => Some(Imr::jet(jet.as_ref())), Inner::Word(ref val) => Some(Imr::const_word(val)), } } pub fn new( arrow: &Arrow, - inner: Inner<&Arc, J, &NoDisconnect, &NoWitness>, + inner: Inner<&Arc, &NoDisconnect, &NoWitness>, ) -> Result { let final_arrow = arrow.finalize()?; let imr = Self::imr(inner.clone()); @@ -136,13 +128,12 @@ impl CommitData { amr, ihr: imr.map(|ihr| Ihr::from_imr(ihr, &final_arrow)), arrow: final_arrow, - phantom: PhantomData, }) } pub fn from_final( arrow: FinalArrow, - inner: Inner<&Arc, J, &NoDisconnect, &NoWitness>, + inner: Inner<&Arc, &NoDisconnect, &NoWitness>, ) -> Self { let imr = Self::imr(inner.clone()); let amr = Self::incomplete_amr(inner, &arrow); @@ -151,14 +142,13 @@ impl CommitData { amr, ihr: imr.map(|ihr| Ihr::from_imr(ihr, &arrow)), arrow, - phantom: PhantomData, } } } -pub type CommitNode = Node>; +pub type CommitNode = Node; -impl CommitNode { +impl CommitNode { /// Accessor for the node's arrow pub fn arrow(&self) -> &FinalArrow { &self.data.arrow @@ -179,28 +169,27 @@ impl CommitNode { /// /// This is a thin wrapper around [`Node::convert`] which fixes a few types to make /// it easier to use. - pub fn finalize, Redeem>>( + pub fn finalize>( &self, converter: &mut C, - ) -> Result>, C::Error> { - self.convert::, _>(converter) + ) -> Result, C::Error> { + self.convert::(converter) } /// Convert a [`CommitNode`] back to a [`ConstructNode`] by redoing type inference pub fn unfinalize_types<'brand>( &self, inference_context: &types::Context<'brand>, - ) -> Result>, types::Error> { - struct UnfinalizeTypes<'a, 'brand, J: Jet> { + ) -> Result>, types::Error> { + struct UnfinalizeTypes<'a, 'brand> { inference_context: &'a types::Context<'brand>, - phantom: PhantomData, } - impl<'brand, J: Jet> Converter, Construct<'brand, J>> for UnfinalizeTypes<'_, 'brand, J> { + impl<'brand> Converter> for UnfinalizeTypes<'_, 'brand> { type Error = types::Error; fn convert_witness( &mut self, - _: &PostOrderIterItem<&CommitNode>, + _: &PostOrderIterItem<&CommitNode>, _: &NoWitness, ) -> Result, Self::Error> { Ok(None) @@ -208,23 +197,22 @@ impl CommitNode { fn convert_disconnect( &mut self, - _: &PostOrderIterItem<&CommitNode>, - _: Option<&Arc>>, + _: &PostOrderIterItem<&CommitNode>, + _: Option<&Arc>>, _: &NoDisconnect, - ) -> Result>>, Self::Error> { + ) -> Result>>, Self::Error> { Ok(None) } fn convert_data( &mut self, - _: &PostOrderIterItem<&CommitNode>, + _: &PostOrderIterItem<&CommitNode>, inner: Inner< - &Arc>, - J, - &Option>>, + &Arc>, + &Option>>, &Option, >, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { let inner = inner .map(|node| node.arrow()) .map_disconnect(|maybe_node| maybe_node.as_ref().map(|node| node.arrow())); @@ -236,10 +224,7 @@ impl CommitNode { } } - self.convert::>, _, _>(&mut UnfinalizeTypes { - inference_context, - phantom: PhantomData, - }) + self.convert::, _, _>(&mut UnfinalizeTypes { inference_context }) } /// Decode a Simplicity program from bits, without witness data. @@ -251,17 +236,19 @@ impl CommitNode { /// or the witness is provided by other means. /// /// If the serialization contains the witness data, then use [`RedeemNode::decode()`]. - pub fn decode>(bits: BitIter) -> Result, DecodeError> { + pub fn decode, J: Jet>( + bits: BitIter, + ) -> Result, DecodeError> { use crate::decode; // 1. Decode program with out witnesses. let program = types::Context::with_context(|ctx| { let construct = - crate::ConstructNode::decode(&ctx, bits).map_err(DecodeError::Decode)?; + crate::ConstructNode::decode::(&ctx, bits).map_err(DecodeError::Decode)?; construct.finalize_types().map_err(DecodeError::Type) })?; // 2. Do sharing check, using incomplete IHRs - if program.as_ref().is_shared_as::>>() { + if program.as_ref().is_shared_as::>() { Ok(program) } else { Err(DecodeError::Decode(decode::Error::SharingNotMaximal)) @@ -278,7 +265,7 @@ impl CommitNode { .decode(s) .map_err(crate::ParseError::Base64)?; let iter = crate::BitIter::new(v.into_iter()); - Self::decode(iter).map_err(crate::ParseError::Decode) + Self::decode::<_, crate::jet::Core>(iter).map_err(crate::ParseError::Decode) } /// Encode a Simplicity expression to bits without any witness data @@ -308,8 +295,7 @@ mod tests { use hex::DisplayHex; use std::fmt; - use crate::decode::Error; - use crate::jet::Core; + use crate::{decode::Error, jet::Core}; #[cfg(feature = "human_encoding")] use crate::{human_encoding::Forest, jet::CoreEnv, node::SimpleFinalizer, BitMachine, Value}; @@ -321,8 +307,8 @@ mod tests { prog_bytes: &[u8], cmr_str: &str, b64_str: &str, - ) -> Arc> { - let forest = match Forest::::parse(prog_str) { + ) -> Arc { + let forest = match Forest::parse::(prog_str) { Ok(forest) => forest, Err(e) => panic!("Failed to parse program `{}`: {}", prog_str, e), }; @@ -349,7 +335,7 @@ mod tests { ); let iter = BitIter::from(prog_bytes); - let prog = match CommitNode::::decode(iter) { + let prog = match CommitNode::decode::<_, J>(iter) { Ok(prog) => prog, Err(e) => panic!("program {} failed: {}", prog_hex, e), }; @@ -388,7 +374,7 @@ mod tests { let err_str = err.to_string(); let iter = BitIter::from(prog); - match CommitNode::::decode(iter) { + match CommitNode::decode::<_, J>(iter) { Ok(prog) => panic!( "Program {} succeded (expected error {}). Program parsed as:\n{:?}", prog_hex, err, prog @@ -591,7 +577,7 @@ mod tests { id := iden main := case (drop id) id "; - match Forest::::parse(bad_prog) { + match Forest::parse::(bad_prog) { Ok(_) => panic!("program should have failed"), Err(set) => { let mut errs_happened = (false, false); diff --git a/src/node/construct.rs b/src/node/construct.rs index 9abc228f..85fdcf83 100644 --- a/src/node/construct.rs +++ b/src/node/construct.rs @@ -23,28 +23,27 @@ use super::{CoreConstructible, DisconnectConstructible, JetConstructible, Witnes pub enum ConstructId {} #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] -pub struct Construct<'brand, J> { +pub struct Construct<'brand> { /// Makes the type non-constructible. never: std::convert::Infallible, /// Required by Rust. - phantom: std::marker::PhantomData<&'brand J>, + phantom: std::marker::PhantomData<&'brand ()>, } -impl<'brand, J: Jet> Marker for Construct<'brand, J> { - type CachedData = ConstructData<'brand, J>; +impl<'brand> Marker for Construct<'brand> { + type CachedData = ConstructData<'brand>; type Witness = Option; - type Disconnect = Option>>; + type Disconnect = Option>>; type SharingId = ConstructId; - type Jet = J; - fn compute_sharing_id(_: Cmr, _: &ConstructData) -> Option { + fn compute_sharing_id(_: Cmr, _: &ConstructData<'brand>) -> Option { None } } -pub type ConstructNode<'brand, J> = Node>; +pub type ConstructNode<'brand> = Node>; -impl<'brand, J: Jet> ConstructNode<'brand, J> { +impl<'brand> ConstructNode<'brand> { /// Accessor for the node's arrow pub fn arrow(&self) -> &Arrow<'brand> { self.data.arrow() @@ -73,7 +72,7 @@ impl<'brand, J: Jet> ConstructNode<'brand, J> { /// certainly what you want, since the resulting `CommitNode` cannot be further /// composed, and needs to be 1->1 to go on-chain. But if you don't, call /// [`Self::finalize_types_non_program`] instead. - pub fn finalize_types(&self) -> Result>, types::Error> { + pub fn finalize_types(&self) -> Result, types::Error> { self.set_arrow_to_program()?; self.finalize_types_non_program() } @@ -81,15 +80,15 @@ impl<'brand, J: Jet> ConstructNode<'brand, J> { /// Convert a [`ConstructNode`] to a [`CommitNode`] by finalizing all of the types. /// /// Does *not* sets the source and target type of this node to unit. - pub fn finalize_types_non_program(&self) -> Result>, types::Error> { - struct FinalizeTypes(PhantomData); + pub fn finalize_types_non_program(&self) -> Result, types::Error> { + struct FinalizeTypes; - impl<'brand, J: Jet> Converter, Commit> for FinalizeTypes { + impl<'brand> Converter, Commit> for FinalizeTypes { type Error = types::Error; fn convert_witness( &mut self, - _: &PostOrderIterItem<&ConstructNode>, + _: &PostOrderIterItem<&ConstructNode>, _: &Option, ) -> Result { Ok(NoWitness) @@ -97,24 +96,24 @@ impl<'brand, J: Jet> ConstructNode<'brand, J> { fn convert_disconnect( &mut self, - _: &PostOrderIterItem<&ConstructNode>, - _: Option<&Arc>>, - _: &Option>>, + _: &PostOrderIterItem<&ConstructNode>, + _: Option<&Arc>, + _: &Option>, ) -> Result { Ok(NoDisconnect) } fn convert_data( &mut self, - data: &PostOrderIterItem<&ConstructNode>, - inner: Inner<&Arc>, J, &NoDisconnect, &NoWitness>, - ) -> Result>, Self::Error> { + data: &PostOrderIterItem<&ConstructNode>, + inner: Inner<&Arc, &NoDisconnect, &NoWitness>, + ) -> Result, Self::Error> { let converted_data = inner.map(|node| node.cached_data()); CommitData::new(&data.node.data.arrow, converted_data).map(Arc::new) } } - self.convert::(&mut FinalizeTypes(PhantomData)) + self.convert::(&mut FinalizeTypes) } /// Finalize the witness program as an unpruned redeem program. @@ -129,15 +128,15 @@ impl<'brand, J: Jet> ConstructNode<'brand, J> { /// ## See /// /// [`RedeemNode::prune`] - pub fn finalize_unpruned(&self) -> Result>, FinalizeError> { - struct Finalizer(PhantomData); + pub fn finalize_unpruned(&self) -> Result, FinalizeError> { + struct Finalizer(PhantomData<()>); - impl<'brand, J: Jet> Converter, Redeem> for Finalizer { + impl<'brand> Converter, Redeem> for Finalizer { type Error = FinalizeError; fn convert_witness( &mut self, - data: &PostOrderIterItem<&ConstructNode>, + data: &PostOrderIterItem<&ConstructNode>, wit: &Option, ) -> Result { if let Some(ref wit) = wit { @@ -170,10 +169,10 @@ impl<'brand, J: Jet> ConstructNode<'brand, J> { fn convert_disconnect( &mut self, - _: &PostOrderIterItem<&ConstructNode>, - maybe_converted: Option<&Arc>>, - _: &Option>>, - ) -> Result>, Self::Error> { + _: &PostOrderIterItem<&ConstructNode>, + maybe_converted: Option<&Arc>, + _: &Option>, + ) -> Result, Self::Error> { if let Some(child) = maybe_converted { Ok(Arc::clone(child)) } else { @@ -183,9 +182,9 @@ impl<'brand, J: Jet> ConstructNode<'brand, J> { fn convert_data( &mut self, - data: &PostOrderIterItem<&ConstructNode>, - inner: Inner<&Arc>, J, &Arc>, &Value>, - ) -> Result>, Self::Error> { + data: &PostOrderIterItem<&ConstructNode>, + inner: Inner<&Arc, &Arc, &Value>, + ) -> Result, Self::Error> { let converted_data = inner .map(|node| node.cached_data()) .map_disconnect(|node| node.cached_data()) @@ -212,10 +211,10 @@ impl<'brand, J: Jet> ConstructNode<'brand, J> { /// ## See /// /// [`RedeemNode::prune`] - pub fn finalize_pruned>( + pub fn finalize_pruned( &self, env: &JE, - ) -> Result>, FinalizeError> { + ) -> Result, FinalizeError> { let unpruned = self.finalize_unpruned()?; unpruned.prune(env).map_err(FinalizeError::Execution) } @@ -229,18 +228,18 @@ impl<'brand, J: Jet> ConstructNode<'brand, J> { /// or the witness is provided by other means. /// /// If the serialization contains the witness data, then use [`crate::RedeemNode::decode()`]. - pub fn decode>( + pub fn decode, J: Jet>( context: &types::Context<'brand>, mut bits: BitIter, ) -> Result, crate::decode::Error> { - let res = crate::decode::decode_expression(context, &mut bits)?; + let res = crate::decode::decode_expression::(context, &mut bits)?; bits.close()?; Ok(res) } #[cfg(feature = "base64")] #[allow(clippy::should_implement_trait)] // returns Arc, needs tyctx - pub fn from_str( + pub fn from_str( context: &types::Context<'brand>, s: &str, ) -> Result, crate::ParseError> { @@ -251,7 +250,7 @@ impl<'brand, J: Jet> ConstructNode<'brand, J> { .decode(s) .map_err(crate::ParseError::Base64)?; let iter = crate::BitIter::new(v.into_iter()); - Self::decode(context, iter) + Self::decode::<_, J>(context, iter) .map_err(crate::DecodeError::Decode) .map_err(crate::ParseError::Decode) } @@ -266,21 +265,14 @@ impl<'brand, J: Jet> ConstructNode<'brand, J> { } #[derive(Clone, Debug)] -pub struct ConstructData<'brand, J> { +pub struct ConstructData<'brand> { arrow: Arrow<'brand>, - /// This isn't really necessary, but it helps type inference if every - /// struct has a \ parameter, since it forces the choice of jets to - /// be consistent without the user needing to specify it too many times. - phantom: PhantomData, } -impl<'brand, J: Jet> ConstructData<'brand, J> { +impl<'brand> ConstructData<'brand> { /// Constructs a new [`ConstructData`] from an (unfinalized) type arrow pub fn new(arrow: Arrow<'brand>) -> Self { - ConstructData { - arrow, - phantom: PhantomData, - } + ConstructData { arrow } } /// Accessor for the node's arrow @@ -289,95 +281,82 @@ impl<'brand, J: Jet> ConstructData<'brand, J> { } } -impl<'brand, J> CoreConstructible<'brand> for ConstructData<'brand, J> { +impl<'brand> CoreConstructible<'brand> for ConstructData<'brand> { fn iden(inference_context: &types::Context<'brand>) -> Self { ConstructData { arrow: Arrow::iden(inference_context), - phantom: PhantomData, } } fn unit(inference_context: &types::Context<'brand>) -> Self { ConstructData { arrow: Arrow::unit(inference_context), - phantom: PhantomData, } } fn injl(child: &Self) -> Self { ConstructData { arrow: Arrow::injl(&child.arrow), - phantom: PhantomData, } } fn injr(child: &Self) -> Self { ConstructData { arrow: Arrow::injr(&child.arrow), - phantom: PhantomData, } } fn take(child: &Self) -> Self { ConstructData { arrow: Arrow::take(&child.arrow), - phantom: PhantomData, } } fn drop_(child: &Self) -> Self { ConstructData { arrow: Arrow::drop_(&child.arrow), - phantom: PhantomData, } } fn comp(left: &Self, right: &Self) -> Result { Ok(ConstructData { arrow: Arrow::comp(&left.arrow, &right.arrow)?, - phantom: PhantomData, }) } fn case(left: &Self, right: &Self) -> Result { Ok(ConstructData { arrow: Arrow::case(&left.arrow, &right.arrow)?, - phantom: PhantomData, }) } fn assertl(left: &Self, right: Cmr) -> Result { Ok(ConstructData { arrow: Arrow::assertl(&left.arrow, right)?, - phantom: PhantomData, }) } fn assertr(left: Cmr, right: &Self) -> Result { Ok(ConstructData { arrow: Arrow::assertr(left, &right.arrow)?, - phantom: PhantomData, }) } fn pair(left: &Self, right: &Self) -> Result { Ok(ConstructData { arrow: Arrow::pair(&left.arrow, &right.arrow)?, - phantom: PhantomData, }) } fn fail(inference_context: &types::Context<'brand>, entropy: FailEntropy) -> Self { ConstructData { arrow: Arrow::fail(inference_context, entropy), - phantom: PhantomData, } } fn const_word(inference_context: &types::Context<'brand>, word: Word) -> Self { ConstructData { arrow: Arrow::const_word(inference_context, word), - phantom: PhantomData, } } @@ -386,35 +365,32 @@ impl<'brand, J> CoreConstructible<'brand> for ConstructData<'brand, J> { } } -impl<'brand, J: Jet> DisconnectConstructible<'brand, Option>>> - for ConstructData<'brand, J> +impl<'brand> DisconnectConstructible<'brand, Option>>> + for ConstructData<'brand> { fn disconnect( left: &Self, - right: &Option>>, + right: &Option>>, ) -> Result { let right = right.as_ref(); Ok(ConstructData { arrow: Arrow::disconnect(&left.arrow, &right.map(|n| n.arrow()))?, - phantom: PhantomData, }) } } -impl<'brand, J> WitnessConstructible<'brand, Option> for ConstructData<'brand, J> { +impl<'brand> WitnessConstructible<'brand, Option> for ConstructData<'brand> { fn witness(inference_context: &types::Context<'brand>, _witness: Option) -> Self { ConstructData { arrow: Arrow::witness(inference_context, NoWitness), - phantom: PhantomData, } } } -impl<'brand, J: Jet> JetConstructible<'brand, J> for ConstructData<'brand, J> { - fn jet(inference_context: &types::Context<'brand>, jet: J) -> Self { +impl<'brand> JetConstructible<'brand> for ConstructData<'brand> { + fn jet(inference_context: &types::Context<'brand>, jet: &dyn Jet) -> Self { ConstructData { arrow: Arrow::jet(inference_context, jet), - phantom: PhantomData, } } } @@ -422,16 +398,14 @@ impl<'brand, J: Jet> JetConstructible<'brand, J> for ConstructData<'brand, J> { #[cfg(test)] mod tests { use super::*; - use crate::jet::Core; use crate::types::Final; use crate::Value; #[test] fn occurs_check_error() { types::Context::with_context(|ctx| { - let iden = Arc::>::iden(&ctx); - let node = - Arc::>::disconnect(&iden, &Some(Arc::clone(&iden))).unwrap(); + let iden = Arc::::iden(&ctx); + let node = Arc::::disconnect(&iden, &Some(Arc::clone(&iden))).unwrap(); assert!(matches!( node.finalize_types_non_program(), @@ -444,16 +418,16 @@ mod tests { fn occurs_check_2() { types::Context::with_context(|ctx| { // A more complicated occurs-check test that caused a deadlock in the past. - let iden = Arc::>::iden(&ctx); - let injr = Arc::>::injr(&iden); - let pair = Arc::>::pair(&injr, &iden).unwrap(); - let drop = Arc::>::drop_(&pair); + let iden = Arc::::iden(&ctx); + let injr = Arc::::injr(&iden); + let pair = Arc::::pair(&injr, &iden).unwrap(); + let drop = Arc::::drop_(&pair); - let case1 = Arc::>::case(&drop, &drop).unwrap(); - let case2 = Arc::>::case(&case1, &case1).unwrap(); + let case1 = Arc::::case(&drop, &drop).unwrap(); + let case2 = Arc::::case(&case1, &case1).unwrap(); - let comp1 = Arc::>::comp(&case2, &case2).unwrap(); - let comp2 = Arc::>::comp(&comp1, &case1).unwrap(); + let comp1 = Arc::::comp(&case2, &case2).unwrap(); + let comp2 = Arc::::comp(&comp1, &case1).unwrap(); assert!(matches!( comp2.finalize_types_non_program(), @@ -466,23 +440,23 @@ mod tests { fn occurs_check_3() { types::Context::with_context(|ctx| { // A similar example that caused a slightly different deadlock in the past. - let wit = Arc::>::witness(&ctx, None); - let drop = Arc::>::drop_(&wit); + let wit = Arc::::witness(&ctx, None); + let drop = Arc::::drop_(&wit); - let comp1 = Arc::>::comp(&drop, &drop).unwrap(); - let comp2 = Arc::>::comp(&comp1, &comp1).unwrap(); - let comp3 = Arc::>::comp(&comp2, &comp2).unwrap(); - let comp4 = Arc::>::comp(&comp3, &comp3).unwrap(); - let comp5 = Arc::>::comp(&comp4, &comp4).unwrap(); + let comp1 = Arc::::comp(&drop, &drop).unwrap(); + let comp2 = Arc::::comp(&comp1, &comp1).unwrap(); + let comp3 = Arc::::comp(&comp2, &comp2).unwrap(); + let comp4 = Arc::::comp(&comp3, &comp3).unwrap(); + let comp5 = Arc::::comp(&comp4, &comp4).unwrap(); - let case = Arc::>::case(&comp5, &comp4).unwrap(); - let drop2 = Arc::>::drop_(&case); - let case2 = Arc::>::case(&drop2, &case).unwrap(); - let comp6 = Arc::>::comp(&case2, &case2).unwrap(); - let case3 = Arc::>::case(&comp6, &comp6).unwrap(); + let case = Arc::::case(&comp5, &comp4).unwrap(); + let drop2 = Arc::::drop_(&case); + let case2 = Arc::::case(&drop2, &case).unwrap(); + let comp6 = Arc::::comp(&case2, &case2).unwrap(); + let case3 = Arc::::case(&comp6, &comp6).unwrap(); - let comp7 = Arc::>::comp(&case3, &case3).unwrap(); - let comp8 = Arc::>::comp(&comp7, &comp7).unwrap(); + let comp7 = Arc::::comp(&case3, &case3).unwrap(); + let comp8 = Arc::::comp(&comp7, &comp7).unwrap(); assert!(matches!( comp8.finalize_types_non_program(), @@ -494,11 +468,11 @@ mod tests { #[test] fn type_check_error() { types::Context::with_context(|ctx| { - let unit = Arc::>::unit(&ctx); - let case = Arc::>::case(&unit, &unit).unwrap(); + let unit = Arc::::unit(&ctx); + let case = Arc::::case(&unit, &unit).unwrap(); assert!(matches!( - Arc::>::disconnect(&case, &Some(unit)), + Arc::::disconnect(&case, &Some(unit)), Err(types::Error::Bind { .. }), )); }); @@ -510,48 +484,39 @@ mod tests { // since everything has concrete types and anyway we only care // about CMRs, for which type inference is irrelevant. types::Context::with_context(|ctx| { - let unit = Arc::>::unit(&ctx); - let bit0 = Arc::>::const_word(&ctx, Word::u1(0)); - let bit1 = Arc::>::const_word(&ctx, Word::u1(1)); + let unit = Arc::::unit(&ctx); + let bit0 = Arc::::const_word(&ctx, Word::u1(0)); + let bit1 = Arc::::const_word(&ctx, Word::u1(1)); assert_eq!( unit.cmr(), - Arc::>::scribe(&ctx, &Value::unit()).cmr() + Arc::::scribe(&ctx, &Value::unit()).cmr() ); assert_eq!( bit0.cmr(), - Arc::>::scribe(&ctx, &Value::u1(0)).cmr() + Arc::::scribe(&ctx, &Value::u1(0)).cmr() ); assert_eq!( bit1.cmr(), - Arc::>::scribe(&ctx, &Value::u1(1)).cmr() + Arc::::scribe(&ctx, &Value::u1(1)).cmr() ); assert_eq!( - Arc::>::const_word(&ctx, Word::u2(1)).cmr(), - Arc::>::scribe(&ctx, &Value::u2(1)).cmr() + Arc::::const_word(&ctx, Word::u2(1)).cmr(), + Arc::::scribe(&ctx, &Value::u2(1)).cmr() ); assert_eq!( - Arc::>::injl(&bit0).cmr(), - Arc::>::scribe(&ctx, &Value::left(Value::u1(0), Final::unit())) - .cmr() + Arc::::injl(&bit0).cmr(), + Arc::::scribe(&ctx, &Value::left(Value::u1(0), Final::unit())).cmr() ); assert_eq!( - Arc::>::injr(&bit1).cmr(), - Arc::>::scribe( - &ctx, - &Value::right(Final::unit(), Value::u1(1)) - ) - .cmr() + Arc::::injr(&bit1).cmr(), + Arc::::scribe(&ctx, &Value::right(Final::unit(), Value::u1(1))) + .cmr() ); assert_eq!( - Arc::>::pair(&unit, &unit) - .unwrap() - .cmr(), - Arc::>::scribe( - &ctx, - &Value::product(Value::unit(), Value::unit()) - ) - .cmr() + Arc::::pair(&unit, &unit).unwrap().cmr(), + Arc::::scribe(&ctx, &Value::product(Value::unit(), Value::unit())) + .cmr() ); }); } @@ -563,24 +528,24 @@ mod tests { types::Context::with_context(|ctx| { let cmr = Cmr::from_byte_array([0xde; 32]); - let u0 = Arc::>::unit(&ctx); - let i1 = Arc::>::injl(&u0); - let i2 = Arc::>::injr(&i1); - let i3 = Arc::>::injr(&i2); - let i4 = Arc::>::injl(&i3); - let u5 = Arc::>::unit(&ctx); - let i6 = Arc::>::injl(&u5); - let i7 = Arc::>::injr(&i6); - let p8 = Arc::>::pair(&i4, &i7).unwrap(); - let u9 = Arc::>::unit(&ctx); - let a10 = Arc::>::assertr(cmr, &u9).unwrap(); - let u11 = Arc::>::unit(&ctx); - let a12 = Arc::>::assertr(cmr, &u11).unwrap(); - let a13 = Arc::>::assertl(&a12, cmr).unwrap(); - let c14 = Arc::>::case(&a10, &a13).unwrap(); - let c15 = Arc::>::comp(&p8, &c14).unwrap(); - - let finalized: Arc> = c15.finalize_types().unwrap(); + let u0 = Arc::::unit(&ctx); + let i1 = Arc::::injl(&u0); + let i2 = Arc::::injr(&i1); + let i3 = Arc::::injr(&i2); + let i4 = Arc::::injl(&i3); + let u5 = Arc::::unit(&ctx); + let i6 = Arc::::injl(&u5); + let i7 = Arc::::injr(&i6); + let p8 = Arc::::pair(&i4, &i7).unwrap(); + let u9 = Arc::::unit(&ctx); + let a10 = Arc::::assertr(cmr, &u9).unwrap(); + let u11 = Arc::::unit(&ctx); + let a12 = Arc::::assertr(cmr, &u11).unwrap(); + let a13 = Arc::::assertl(&a12, cmr).unwrap(); + let c14 = Arc::::case(&a10, &a13).unwrap(); + let c15 = Arc::::comp(&p8, &c14).unwrap(); + + let finalized: Arc = c15.finalize_types().unwrap(); let prog = finalized.to_vec_without_witness(); // In #286 we are encoding correctly... assert_eq!( @@ -589,7 +554,7 @@ mod tests { ); let prog = BitIter::from(prog); - let decode = CommitNode::::decode(prog).unwrap(); + let decode = CommitNode::decode::<_, crate::jet::Core>(prog).unwrap(); // ...but then during decoding we read the program incorrectly and this assertion fails. assert_eq!(finalized, decode); @@ -606,17 +571,17 @@ mod tests { // It also exhibits the bug earlier than the other one -- it *should* just fail to // typecheck and not be constructible. So we can't get an encoding of it. types::Context::with_context(|ctx| { - let w0 = Arc::>::witness(&ctx, None); - let i1 = Arc::>::iden(&ctx); - let d2 = Arc::>::drop_(&i1); - let i3 = Arc::>::iden(&ctx); - let i4 = Arc::>::iden(&ctx); - let t5 = Arc::>::take(&i4); - let ca6 = Arc::>::case(&i3, &t5).unwrap(); - let ca7 = Arc::>::case(&d2, &ca6).unwrap(); - let c8 = Arc::>::comp(&w0, &ca7).unwrap(); - let u9 = Arc::>::unit(&ctx); - let c10 = Arc::>::comp(&c8, &u9).unwrap(); + let w0 = Arc::::witness(&ctx, None); + let i1 = Arc::::iden(&ctx); + let d2 = Arc::::drop_(&i1); + let i3 = Arc::::iden(&ctx); + let i4 = Arc::::iden(&ctx); + let t5 = Arc::::take(&i4); + let ca6 = Arc::::case(&i3, &t5).unwrap(); + let ca7 = Arc::::case(&d2, &ca6).unwrap(); + let c8 = Arc::::comp(&w0, &ca7).unwrap(); + let u9 = Arc::::unit(&ctx); + let c10 = Arc::::comp(&c8, &u9).unwrap(); // In #286 we incorrectly succeed finalizing the types, and then encode a bad program. let err = c10.finalize_types().unwrap_err(); diff --git a/src/node/convert.rs b/src/node/convert.rs index 69976eee..05652d94 100644 --- a/src/node/convert.rs +++ b/src/node/convert.rs @@ -16,7 +16,6 @@ //! use crate::dag::PostOrderIterItem; -use crate::jet::Jet; use crate::Value; use super::{ @@ -142,7 +141,7 @@ pub trait Converter { fn convert_data( &mut self, data: &PostOrderIterItem<&Node>, - inner: Inner<&Arc>, M::Jet, &M::Disconnect, &M::Witness>, + inner: Inner<&Arc>, &M::Disconnect, &M::Witness>, ) -> Result; } @@ -168,12 +167,12 @@ impl> SimpleFinalizer { } } -impl, J: Jet> Converter, Redeem> for SimpleFinalizer { +impl> Converter for SimpleFinalizer { type Error = crate::FinalizeError; fn convert_witness( &mut self, - data: &PostOrderIterItem<&CommitNode>, + data: &PostOrderIterItem<&CommitNode>, _: &NoWitness, ) -> Result { Ok(self @@ -184,18 +183,18 @@ impl, J: Jet> Converter, Redeem> for Simp fn convert_disconnect( &mut self, - _: &PostOrderIterItem<&CommitNode>, - _: Option<&Arc>>, + _: &PostOrderIterItem<&CommitNode>, + _: Option<&Arc>, _: &NoDisconnect, - ) -> Result>, Self::Error> { + ) -> Result, Self::Error> { Err(crate::FinalizeError::DisconnectRedeemTime) } fn convert_data( &mut self, - data: &PostOrderIterItem<&CommitNode>, - inner: Inner<&Arc>, J, &Arc>, &Value>, - ) -> Result>, Self::Error> { + data: &PostOrderIterItem<&CommitNode>, + inner: Inner<&Arc, &Arc, &Value>, + ) -> Result, Self::Error> { let converted_data = inner .map(|node| node.cached_data()) .map_disconnect(|node| node.cached_data()) diff --git a/src/node/display.rs b/src/node/display.rs index 92c1b1c6..ec0a9665 100644 --- a/src/node/display.rs +++ b/src/node/display.rs @@ -368,10 +368,10 @@ mod tests { use std::collections::HashMap; use std::sync::Arc; - fn parse_program(s: &str) -> Arc> { + fn parse_program(s: &str) -> Arc { types::Context::with_context(|ctx| { let empty_witness = HashMap::new(); - Forest::::parse(s) + Forest::parse::(s) .unwrap() .to_witness_node(&ctx, &empty_witness) .unwrap() diff --git a/src/node/hiding.rs b/src/node/hiding.rs index 3ba97b5c..a891824e 100644 --- a/src/node/hiding.rs +++ b/src/node/hiding.rs @@ -1,3 +1,4 @@ +use crate::jet::Jet; use crate::node::{ CoreConstructible, DisconnectConstructible, JetConstructible, WitnessConstructible, }; @@ -216,11 +217,11 @@ impl<'brand, N: CoreConstructible<'brand> + HasCmr> CoreConstructible<'brand> } } -impl<'brand, J, N> JetConstructible<'brand, J> for Hiding<'brand, N> +impl<'brand, N> JetConstructible<'brand> for Hiding<'brand, N> where - N: JetConstructible<'brand, J> + CoreConstructible<'brand>, + N: JetConstructible<'brand> + CoreConstructible<'brand>, { - fn jet(inference_context: &Context<'brand>, jet: J) -> Self { + fn jet(inference_context: &Context<'brand>, jet: &dyn Jet) -> Self { N::jet(inference_context, jet).into() } } diff --git a/src/node/inner.rs b/src/node/inner.rs index 06bbd5d1..d897c6fc 100644 --- a/src/node/inner.rs +++ b/src/node/inner.rs @@ -4,6 +4,7 @@ use super::{Disconnectable, FailEntropy}; use crate::dag::Dag; use crate::Cmr; +use crate::jet::Jet; use crate::value::Word; use std::fmt; use std::sync::Arc; @@ -12,8 +13,9 @@ use std::sync::Arc; /// /// This structure is used to indicate the type of a node and provide /// pointers or references to its children, if any. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] -pub enum Inner { +#[derive(Clone, Eq, PartialOrd, Ord, Debug, Hash)] +#[allow(clippy::derived_hash_with_manual_eq)] // see comment on manual `PartialEq` impl below +pub enum Inner { /// Identity Iden, /// Unit constant @@ -43,14 +45,40 @@ pub enum Inner { /// Universal fail Fail(FailEntropy), /// Application jet - Jet(J), + Jet(Box), /// Constant word Word(Word), } -impl Inner { +// Manually implemented because the 1.74 (MSRV) derive expands to a body that +// moves out of the non-Copy `Box` field, later rustc versions are +// fine. +impl PartialEq for Inner { + fn eq(&self, other: &Self) -> bool { + use Inner::*; + match (self, other) { + (Iden, Iden) | (Unit, Unit) => true, + (InjL(a), InjL(b)) | (InjR(a), InjR(b)) | (Take(a), Take(b)) | (Drop(a), Drop(b)) => { + a == b + } + (Comp(a, b), Comp(c, d)) | (Case(a, b), Case(c, d)) | (Pair(a, b), Pair(c, d)) => { + a == c && b == d + } + (AssertL(a, b), AssertL(c, d)) => a == c && b == d, + (AssertR(a, b), AssertR(c, d)) => a == c && b == d, + (Disconnect(a, b), Disconnect(c, d)) => a == c && b == d, + (Witness(a), Witness(b)) => a == b, + (Fail(a), Fail(b)) => a == b, + (Jet(a), Jet(b)) => a == b, + (Word(a), Word(b)) => a == b, + _ => false, + } + } +} + +impl Inner { /// Convert a node's combinator data to a different type. - pub fn map D>(self, mut f: F) -> Inner { + pub fn map D>(self, mut f: F) -> Inner { match self { Inner::Iden => Inner::Iden, Inner::Unit => Inner::Unit, @@ -75,7 +103,7 @@ impl Inner { pub fn map_result Result>( self, mut f: F, - ) -> Result, E> { + ) -> Result, E> { Ok(match self { Inner::Iden => Inner::Iden, Inner::Unit => Inner::Unit, @@ -102,7 +130,7 @@ impl Inner { /// Importantly, the child of an `AssertR` node is considered the left /// child, because as a DAG node, this is the sole (left) child, even /// though as a combinator, it is a right child. - pub fn map_left_right(self, fl: FL, fr: FR) -> Inner + pub fn map_left_right(self, fl: FL, fr: FR) -> Inner where FL: FnOnce(C) -> D, FR: FnOnce(C) -> D, @@ -128,7 +156,7 @@ impl Inner { } /// Take references to all contained data. - pub fn as_ref(&self) -> Inner<&C, J, &X, &W> { + pub fn as_ref(&self) -> Inner<&C, &X, &W> { match self { Inner::Iden => Inner::Iden, Inner::Unit => Inner::Unit, @@ -150,9 +178,8 @@ impl Inner { } /// Take references to only the disconnect node. - pub fn disconnect_as_ref(&self) -> Inner + pub fn disconnect_as_ref(&self) -> Inner where - J: Copy, C: Copy, W: Copy, { @@ -171,12 +198,12 @@ impl Inner { Inner::Disconnect(cl, ref cr) => Inner::Disconnect(cl, cr), Inner::Witness(w) => Inner::Witness(w), Inner::Fail(entropy) => Inner::Fail(entropy), - Inner::Jet(j) => Inner::Jet(j), + Inner::Jet(ref j) => Inner::Jet(j.dyn_clone()), Inner::Word(ref w) => Inner::Word(w.shallow_clone()), } } - pub fn map_disconnect Y>(self, f: F) -> Inner { + pub fn map_disconnect Y>(self, f: F) -> Inner { match self { Inner::Iden => Inner::Iden, Inner::Unit => Inner::Unit, @@ -201,7 +228,7 @@ impl Inner { pub fn map_disconnect_result Result>( self, f: F, - ) -> Result, E> { + ) -> Result, E> { Ok(match self { Inner::Iden => Inner::Iden, Inner::Unit => Inner::Unit, @@ -223,7 +250,7 @@ impl Inner { } /// Convert a node's witness data to a different type. - pub fn map_witness V>(self, f: F) -> Inner { + pub fn map_witness V>(self, f: F) -> Inner { match self { Inner::Iden => Inner::Iden, Inner::Unit => Inner::Unit, @@ -248,7 +275,7 @@ impl Inner { pub fn map_witness_result Result>( self, f: F, - ) -> Result, E> { + ) -> Result, E> { Ok(match self { Inner::Iden => Inner::Iden, Inner::Unit => Inner::Unit, @@ -270,7 +297,7 @@ impl Inner { } } -impl, W> Inner, J, X, W> { +impl, W> Inner, X, W> { /// Collapse the node information to a `Dag` pub fn as_dag(&self) -> Dag<&C> { match self { @@ -292,9 +319,9 @@ impl, W> Inner, J, X, W> { } } -impl Inner, J, X, W> { +impl Inner, X, W> { /// Convert an `Inner, J, W>` to an `Option>`. - pub fn transpose(self) -> Option> { + pub fn transpose(self) -> Option> { Some(match self { Inner::Iden => Inner::Iden, Inner::Unit => Inner::Unit, @@ -316,9 +343,9 @@ impl Inner, J, X, W> { } } -impl Inner, W> { +impl Inner, W> { /// Convert an `Inner, J, W>` to an `Option>`. - pub fn transpose_disconnect(self) -> Option> { + pub fn transpose_disconnect(self) -> Option> { Some(match self { Inner::Iden => Inner::Iden, Inner::Unit => Inner::Unit, @@ -340,9 +367,9 @@ impl Inner, W> { } } -impl Inner> { - /// Convert an `Inner>` to an `Option>`. - pub fn transpose_witness(self) -> Option> { +impl Inner> { + /// Convert an `Inner>` to an `Option>`. + pub fn transpose_witness(self) -> Option> { Some(match self { Inner::Iden => Inner::Iden, Inner::Unit => Inner::Unit, @@ -364,27 +391,27 @@ impl Inner> { } } -impl Inner { +impl Inner { /// Copies witness data. /// /// Useful in conjunction with [`Inner::as_ref`] when you don't want to /// take a reference to witness data. - pub fn copy_witness(self) -> Inner { + pub fn copy_witness(self) -> Inner { self.map_witness(W::clone) } } -impl Inner { +impl Inner { /// Copies disconnect data. /// /// Useful in conjunction with [`Inner::as_ref`] when you don't want to /// take a reference to disconnect data. - pub fn copy_disconnect(self) -> Inner { + pub fn copy_disconnect(self) -> Inner { self.map_disconnect(X::clone) } } -impl fmt::Display for Inner { +impl fmt::Display for Inner { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Inner::Iden => f.write_str("iden"), diff --git a/src/node/mod.rs b/src/node/mod.rs index e860523f..f0da02f8 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -110,9 +110,6 @@ pub trait Marker: /// during iteration over the DAG. type SharingId: hash::Hash + Clone + Eq; - /// The jet catalogue used with this node type. - type Jet: Jet; - /// Yields the sharing ID for a given type, starting from its CMR and its cached data. /// /// If the type cannot be uniquely identified (e.g. because it is missing data), then @@ -131,8 +128,8 @@ impl From for Option { } } -pub trait Constructible<'brand, J, X, W>: - JetConstructible<'brand, J> +pub trait Constructible<'brand, X, W>: + JetConstructible<'brand> + DisconnectConstructible<'brand, X> + WitnessConstructible<'brand, W> + CoreConstructible<'brand> @@ -140,7 +137,7 @@ pub trait Constructible<'brand, J, X, W>: { fn from_inner( inference_context: &types::Context<'brand>, - inner: Inner<&Self, J, &X, W>, + inner: Inner<&Self, &X, W>, ) -> Result { match inner { Inner::Iden => Ok(Self::iden(inference_context)), @@ -157,15 +154,15 @@ pub trait Constructible<'brand, J, X, W>: Inner::Disconnect(left, right) => Self::disconnect(left, right), Inner::Fail(entropy) => Ok(Self::fail(inference_context, entropy)), Inner::Word(ref w) => Ok(Self::const_word(inference_context, w.shallow_clone())), - Inner::Jet(j) => Ok(Self::jet(inference_context, j)), + Inner::Jet(j) => Ok(Self::jet(inference_context, j.as_ref())), Inner::Witness(w) => Ok(Self::witness(inference_context, w)), } } } -impl<'brand, J, X, W, T> Constructible<'brand, J, X, W> for T where +impl<'brand, X, W, T> Constructible<'brand, X, W> for T where T: DisconnectConstructible<'brand, X> - + JetConstructible<'brand, J> + + JetConstructible<'brand> + WitnessConstructible<'brand, W> + CoreConstructible<'brand> + Sized @@ -347,8 +344,8 @@ pub trait DisconnectConstructible<'brand, X>: Sized { fn disconnect(left: &Self, right: &X) -> Result; } -pub trait JetConstructible<'brand, J>: Sized { - fn jet(inference_context: &types::Context<'brand>, jet: J) -> Self; +pub trait JetConstructible<'brand>: Sized { + fn jet(inference_context: &types::Context<'brand>, jet: &dyn Jet) -> Self; } pub trait WitnessConstructible<'brand, W>: Sized { @@ -369,7 +366,7 @@ pub trait WitnessConstructible<'brand, W>: Sized { /// for [`Marker::CachedData`] and think carefully about whether and how to /// implement the [`std::hash::Hash`] or equality traits. pub struct Node { - inner: Inner>, N::Jet, N::Disconnect, N::Witness>, + inner: Inner>, N::Disconnect, N::Witness>, cmr: Cmr, data: N::CachedData, } @@ -575,23 +572,23 @@ where } } -impl<'brand, N> JetConstructible<'brand, N::Jet> for Arc> +impl<'brand, N> JetConstructible<'brand> for Arc> where N: Marker, - N::CachedData: JetConstructible<'brand, N::Jet>, + N::CachedData: JetConstructible<'brand>, { - fn jet(inference_context: &types::Context<'brand>, jet: N::Jet) -> Self { + fn jet(inference_context: &types::Context<'brand>, jet: &dyn Jet) -> Self { Arc::new(Node { cmr: Cmr::jet(jet), data: N::CachedData::jet(inference_context, jet), - inner: Inner::Jet(jet), + inner: Inner::Jet(jet.dyn_clone()), }) } } impl Node { /// Accessor for the node's "inner value", i.e. its combinator - pub fn inner(&self) -> &Inner>, N::Jet, N::Disconnect, N::Witness> { + pub fn inner(&self) -> &Inner>, N::Disconnect, N::Witness> { &self.inner } @@ -619,10 +616,10 @@ impl Node { /// If available, [`Constructible`] and its dependent traits will be easier to /// use. pub fn from_parts( - inner: Inner, N::Jet, N::Disconnect, N::Witness>, + inner: Inner, N::Disconnect, N::Witness>, data: N::CachedData, ) -> Self { - let cmr = match inner { + let cmr = match &inner { Inner::Unit => Cmr::unit(), Inner::Iden => Cmr::iden(), Inner::InjL(ref c) => Cmr::injl(c.cmr()), @@ -631,13 +628,13 @@ impl Node { Inner::Drop(ref c) => Cmr::drop(c.cmr()), Inner::Comp(ref cl, ref cr) => Cmr::comp(cl.cmr(), cr.cmr()), Inner::Case(ref cl, ref cr) => Cmr::case(cl.cmr(), cr.cmr()), - Inner::AssertL(ref c, cmr) => Cmr::case(c.cmr(), cmr), - Inner::AssertR(cmr, ref c) => Cmr::case(cmr, c.cmr()), + Inner::AssertL(ref c, cmr) => Cmr::case(c.cmr(), *cmr), + Inner::AssertR(cmr, ref c) => Cmr::case(*cmr, c.cmr()), Inner::Pair(ref cl, ref cr) => Cmr::pair(cl.cmr(), cr.cmr()), Inner::Disconnect(ref cl, _) => Cmr::disconnect(cl.cmr()), Inner::Witness(_) => Cmr::witness(), - Inner::Fail(entropy) => Cmr::fail(entropy), - Inner::Jet(j) => Cmr::jet(j), + Inner::Fail(entropy) => Cmr::fail(*entropy), + Inner::Jet(j) => Cmr::jet(j.as_ref()), Inner::Word(ref w) => Cmr::const_word(w), }; @@ -654,7 +651,7 @@ impl Node { pub fn convert(&self, converter: &mut C) -> Result>, C::Error> where S: for<'a> SharingTracker<&'a Self> + Default, - M: Marker::Jet>, + M: Marker, C: Converter, { let mut converted: Vec>> = vec![]; @@ -665,27 +662,27 @@ impl Node { // Construct an Inner where pointers are replaced by indices. // Note that `map_left_right`'s internal logic will ensure that these // `unwrap`s are only called when they will succeed. - let indexed_inner: Inner = data + let indexed_inner: Inner = data .node .inner .as_ref() .map_left_right(|_| data.left_index.unwrap(), |_| data.right_index.unwrap()); // Then, convert witness data, if this is a witness node. - let witness_inner: Inner<&usize, M::Jet, &&N::Disconnect, M::Witness> = indexed_inner + let witness_inner: Inner<&usize, &&N::Disconnect, M::Witness> = indexed_inner .as_ref() .map_witness_result(|wit| converter.convert_witness(&data, wit))?; // Then convert disconnect nodes data. let maybe_converted = data.right_index.map(|idx| &converted[idx]); - let witness_inner: Inner<&usize, N::Jet, M::Disconnect, M::Witness> = witness_inner + let witness_inner: Inner<&usize, M::Disconnect, M::Witness> = witness_inner .map_disconnect_result(|disc| { converter.convert_disconnect(&data, maybe_converted, disc) })?; // Then put the converted nodes in place (it's easier to do this in this // order because of the way the reference types work out). - let converted_inner: Inner>, M::Jet, M::Disconnect, M::Witness> = + let converted_inner: Inner>, M::Disconnect, M::Witness> = witness_inner.map(|idx| Arc::clone(&converted[*idx])); // Next, prune case nodes into asserts, if applicable @@ -827,7 +824,7 @@ mod tests { None, ) .unwrap(); - let prog = RedeemNode::::decode(prog, witness).unwrap(); + let prog = RedeemNode::decode::<_, _, Elements>(prog, witness).unwrap(); assert_eq!(prog.cmr().to_byte_array(), test.cmr); assert_eq!(prog.amr().to_byte_array(), test.amr); assert_eq!(prog.ihr().to_byte_array(), test.ihr); diff --git a/src/node/redeem.rs b/src/node/redeem.rs index f9a5b932..4ce41dd2 100644 --- a/src/node/redeem.rs +++ b/src/node/redeem.rs @@ -19,55 +19,48 @@ use std::marker::PhantomData; use std::sync::Arc; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] -pub struct Redeem { +pub struct Redeem { /// Makes the type non-constructible. never: std::convert::Infallible, - /// Required by Rust. - phantom: std::marker::PhantomData, } -impl Marker for Redeem { - type CachedData = Arc>; +impl Marker for Redeem { + type CachedData = Arc; type Witness = Value; - type Disconnect = Arc>; + type Disconnect = Arc; type SharingId = Ihr; - type Jet = J; - fn compute_sharing_id(_: Cmr, cached_data: &Arc>) -> Option { + fn compute_sharing_id(_: Cmr, cached_data: &Arc) -> Option { Some(cached_data.ihr) } } -pub type RedeemNode = Node>; +pub type RedeemNode = Node; #[derive(Clone, Debug)] -pub struct RedeemData { +pub struct RedeemData { amr: Amr, imr: Imr, ihr: Ihr, arrow: FinalArrow, bounds: NodeBounds, - /// This isn't really necessary, but it helps type inference if every - /// struct has a \ parameter, since it forces the choice of jets to - /// be consistent without the user needing to specify it too many times. - phantom: PhantomData, } -impl PartialEq for RedeemData { +impl PartialEq for RedeemData { fn eq(&self, other: &Self) -> bool { self.ihr == other.ihr } } -impl Eq for RedeemData {} +impl Eq for RedeemData {} -impl std::hash::Hash for RedeemData { +impl std::hash::Hash for RedeemData { fn hash(&self, hasher: &mut H) { self.ihr.hash(hasher) } } -impl RedeemData { - pub fn new(arrow: FinalArrow, inner: Inner<&Arc, J, &Arc, Value>) -> Self { +impl RedeemData { + pub fn new(arrow: FinalArrow, inner: Inner<&Arc, &Arc, Value>) -> Self { let (amr, imr, bounds) = match inner { Inner::Iden => ( Amr::iden(&arrow), @@ -137,7 +130,11 @@ impl RedeemData { NodeBounds::witness(arrow.target.bit_width()), ), Inner::Fail(entropy) => (Amr::fail(entropy), Imr::fail(entropy), NodeBounds::fail()), - Inner::Jet(jet) => (Amr::jet(jet), Imr::jet(jet), NodeBounds::jet(jet)), + Inner::Jet(jet) => ( + Amr::jet(jet.as_ref()), + Imr::jet(jet.as_ref()), + NodeBounds::jet(jet.as_ref()), + ), Inner::Word(ref val) => ( Amr::const_word(val), Imr::const_word(val), @@ -151,12 +148,11 @@ impl RedeemData { ihr: Ihr::from_imr(imr, &arrow), arrow, bounds, - phantom: PhantomData, } } } -impl RedeemNode { +impl RedeemNode { /// Accessor for the node's AMR pub fn amr(&self) -> Amr { self.data.amr @@ -179,14 +175,14 @@ impl RedeemNode { /// Convert a [`RedeemNode`] back to a [`CommitNode`] by forgetting witnesses /// and cached data. - pub fn unfinalize(&self) -> Result>, types::Error> { - struct Unfinalizer(PhantomData); + pub fn unfinalize(&self) -> Result, types::Error> { + struct Unfinalizer(PhantomData<()>); - impl Converter, Commit> for Unfinalizer { + impl Converter for Unfinalizer { type Error = types::Error; fn convert_witness( &mut self, - _: &PostOrderIterItem<&RedeemNode>, + _: &PostOrderIterItem<&RedeemNode>, _: &Value, ) -> Result { Ok(NoWitness) @@ -194,18 +190,18 @@ impl RedeemNode { fn convert_disconnect( &mut self, - _: &PostOrderIterItem<&RedeemNode>, - _: Option<&Arc>>, - _: &Arc>, + _: &PostOrderIterItem<&RedeemNode>, + _: Option<&Arc>, + _: &Arc, ) -> Result { Ok(NoDisconnect) } fn convert_data( &mut self, - data: &PostOrderIterItem<&RedeemNode>, - inner: Inner<&Arc>, J, &NoDisconnect, &NoWitness>, - ) -> Result>, Self::Error> { + data: &PostOrderIterItem<&RedeemNode>, + inner: Inner<&Arc, &NoDisconnect, &NoWitness>, + ) -> Result, Self::Error> { let converted_data = inner.map(|node| node.cached_data()); Ok(Arc::new(CommitData::from_final( data.node.data.arrow.shallow_clone(), @@ -214,7 +210,7 @@ impl RedeemNode { } } - self.convert::>, _, _>(&mut Unfinalizer(PhantomData)) + self.convert::, _, _>(&mut Unfinalizer(PhantomData)) } /// Convert a [`RedeemNode`] back into a [`ConstructNode`] @@ -222,18 +218,17 @@ impl RedeemNode { pub fn to_construct_node<'brand>( &self, inference_context: &types::Context<'brand>, - ) -> Arc> { - struct ToConstruct<'a, 'brand, J> { + ) -> Arc> { + struct ToConstruct<'a, 'brand> { inference_context: &'a types::Context<'brand>, - phantom: PhantomData, } - impl<'brand, J: Jet> Converter, Construct<'brand, J>> for ToConstruct<'_, 'brand, J> { + impl<'brand> Converter> for ToConstruct<'_, 'brand> { type Error = (); fn convert_witness( &mut self, - _: &PostOrderIterItem<&Node>>, + _: &PostOrderIterItem<&Node>, witness: &Value, ) -> Result, Self::Error> { Ok(Some(witness.clone())) @@ -241,23 +236,22 @@ impl RedeemNode { fn convert_disconnect( &mut self, - _: &PostOrderIterItem<&Node>>, - right: Option<&Arc>>>, - _: &Arc>, - ) -> Result>>>, Self::Error> { + _: &PostOrderIterItem<&Node>, + right: Option<&Arc>>>, + _: &Arc, + ) -> Result>>>, Self::Error> { Ok(right.cloned()) } fn convert_data( &mut self, - _: &PostOrderIterItem<&Node>>, + _: &PostOrderIterItem<&Node>, inner: Inner< - &Arc>>, - J, - &Option>>, + &Arc>>, + &Option>>, &Option, >, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { let inner = inner .map(|node| node.cached_data()) .map_witness(|maybe_value| maybe_value.clone()); @@ -266,11 +260,8 @@ impl RedeemNode { } } - self.convert::(&mut ToConstruct { - inference_context, - phantom: PhantomData, - }) - .unwrap() + self.convert::(&mut ToConstruct { inference_context }) + .unwrap() } /// Prune the redeem program for the given transaction environment. @@ -289,10 +280,7 @@ impl RedeemNode { /// Pruning fails if the original, unpruned program fails to run on the Bit Machine (step 1). /// In this case, the witness data needs to be revised. /// The other pruning steps (2 & 3) never fail. - pub fn prune>( - &self, - env: &JE, - ) -> Result>, ExecutionError> { + pub fn prune(&self, env: &JE) -> Result, ExecutionError> { self.prune_with_tracker(env, &mut SetTracker::default()) } @@ -301,27 +289,25 @@ impl RedeemNode { /// /// See [`crate::bit_machine::StderrTracker`] as an example which outputs the IHR of /// each case combinator that we prune a child of. - pub fn prune_with_tracker, T: PruneTracker>( + pub fn prune_with_tracker( &self, env: &JE, tracker: &mut T, - ) -> Result>, ExecutionError> { - struct Pruner<'brand, 't, J, T> { + ) -> Result, ExecutionError> { + struct Pruner<'brand, 't, T> { inference_context: types::Context<'brand>, tracker: &'t mut T, - phantom: PhantomData, } - impl<'brand, 't, J, T> Converter, Construct<'brand, J>> for Pruner<'brand, 't, J, T> + impl<'brand, 't, T> Converter> for Pruner<'brand, 't, T> where - J: Jet, - T: PruneTracker, + T: PruneTracker, { type Error = std::convert::Infallible; fn convert_witness( &mut self, - _: &PostOrderIterItem<&RedeemNode>, + _: &PostOrderIterItem<&RedeemNode>, witness: &Value, ) -> Result, Self::Error> { // The pruned type is not finalized at this point, @@ -331,10 +317,10 @@ impl RedeemNode { fn convert_disconnect( &mut self, - _: &PostOrderIterItem<&RedeemNode>, - right: Option<&Arc>>, - _: &Arc>, - ) -> Result>>, Self::Error> { + _: &PostOrderIterItem<&RedeemNode>, + right: Option<&Arc>>, + _: &Arc, + ) -> Result>>, Self::Error> { debug_assert!( right.is_some(), "disconnected branch should exist in unpruned redeem program" @@ -344,9 +330,9 @@ impl RedeemNode { fn prune_case( &mut self, - data: &PostOrderIterItem<&RedeemNode>, - _left: &Arc>, - _right: &Arc>, + data: &PostOrderIterItem<&RedeemNode>, + _left: &Arc, + _right: &Arc, ) -> Result { // The IHR of the pruned program may change, // but the Converter trait gives us access to the unpruned node (`data`). @@ -364,14 +350,13 @@ impl RedeemNode { fn convert_data( &mut self, - _: &PostOrderIterItem<&RedeemNode>, + _: &PostOrderIterItem<&RedeemNode>, inner: Inner< - &Arc>, - J, - &Option>>, + &Arc>, + &Option>>, &Option, >, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { let converted_inner = inner .map(|node| node.cached_data()) .map_witness(Option::::clone); @@ -381,14 +366,14 @@ impl RedeemNode { } } - struct Finalizer(PhantomData); + struct Finalizer; - impl<'brand, J: Jet> Converter, Redeem> for Finalizer { + impl<'brand> Converter, Redeem> for Finalizer { type Error = std::convert::Infallible; fn convert_witness( &mut self, - data: &PostOrderIterItem<&ConstructNode>, + data: &PostOrderIterItem<&ConstructNode>, witness: &Option, ) -> Result { let pruned_target_ty = data @@ -407,10 +392,10 @@ impl RedeemNode { fn convert_disconnect( &mut self, - _: &PostOrderIterItem<&ConstructNode>, - right: Option<&Arc>>, - _: &Option>>, - ) -> Result>, Self::Error> { + _: &PostOrderIterItem<&ConstructNode>, + right: Option<&Arc>, + _: &Option>, + ) -> Result, Self::Error> { Ok(right .map(Arc::clone) .expect("disconnect node that originally stems from redeem program should have all branches")) @@ -418,9 +403,9 @@ impl RedeemNode { fn convert_data( &mut self, - data: &PostOrderIterItem<&ConstructNode>, - inner: Inner<&Arc>, J, &Arc>, &Value>, - ) -> Result>, Self::Error> { + data: &PostOrderIterItem<&ConstructNode>, + inner: Inner<&Arc, &Arc, &Value>, + ) -> Result, Self::Error> { // Finalize target types of witness nodes in advance so we can prune their values. let final_arrow = data .node @@ -448,7 +433,6 @@ impl RedeemNode { .convert::(&mut Pruner { inference_context, tracker, - phantom: PhantomData, }) .expect("pruning unused branches is infallible"); @@ -456,13 +440,13 @@ impl RedeemNode { // We obtain the pruned redeem program. // Once the pruned type is finalized, we can proceed to prune witness values. Ok(pruned_witness_program - .convert::(&mut Finalizer(PhantomData)) + .convert::(&mut Finalizer) .expect("finalization is infallible")) }) } /// Decode a Simplicity program from bits, including the witness data. - pub fn decode( + pub fn decode( program: BitIter, mut witness: BitIter, ) -> Result, DecodeError> @@ -471,18 +455,17 @@ impl RedeemNode { I2: Iterator, { // 0. Set up a type to help with the call to `convert` below - struct DecodeFinalizer<'bits, J: Jet, I: Iterator> { + struct DecodeFinalizer<'bits, I: Iterator> { bits: &'bits mut BitIter, - phantom: PhantomData, } - impl<'brand, J: Jet, I: Iterator> Converter, Redeem> - for DecodeFinalizer<'_, J, I> + impl<'brand, I: Iterator> Converter, Redeem> + for DecodeFinalizer<'_, I> { type Error = DecodeError; fn convert_witness( &mut self, - data: &PostOrderIterItem<&ConstructNode>, + data: &PostOrderIterItem<&ConstructNode>, _: &Option, ) -> Result { let arrow = data.node.data.arrow(); @@ -494,10 +477,10 @@ impl RedeemNode { fn convert_disconnect( &mut self, - _: &PostOrderIterItem<&ConstructNode>, - right: Option<&Arc>>, - _: &Option>>, - ) -> Result>, Self::Error> { + _: &PostOrderIterItem<&ConstructNode>, + right: Option<&Arc>, + _: &Option>, + ) -> Result, Self::Error> { if let Some(child) = right { Ok(Arc::clone(child)) } else { @@ -507,9 +490,9 @@ impl RedeemNode { fn convert_data( &mut self, - data: &PostOrderIterItem<&ConstructNode>, - inner: Inner<&Arc>, J, &Arc>, &Value>, - ) -> Result>, Self::Error> { + data: &PostOrderIterItem<&ConstructNode>, + inner: Inner<&Arc, &Arc, &Value>, + ) -> Result, Self::Error> { let arrow = data .node .data @@ -527,17 +510,14 @@ impl RedeemNode { // 1. Decode program without witnesses as ConstructNode let program: Arc = types::Context::with_context(|ctx| { let construct = - crate::ConstructNode::decode(&ctx, program).map_err(DecodeError::Decode)?; + crate::ConstructNode::decode::<_, J>(&ctx, program).map_err(DecodeError::Decode)?; construct .set_arrow_to_program() .map_err(DecodeError::Type)?; // Importantly, we use `InternalSharing` here to make sure that we respect // the sharing choices that were actually encoded in the bitstream. - construct.convert::(&mut DecodeFinalizer { - bits: &mut witness, - phantom: PhantomData, - }) + construct.convert::(&mut DecodeFinalizer { bits: &mut witness }) })?; // 3. Check that we read exactly as much witness data as we expected @@ -561,7 +541,7 @@ impl RedeemNode { #[cfg(feature = "base64")] #[allow(clippy::should_implement_trait)] // returns Arc - pub fn from_str(prog: &str, wit: &str) -> Result, crate::ParseError> { + pub fn from_str(prog: &str, wit: &str) -> Result, crate::ParseError> { use crate::base64::engine::general_purpose; use crate::base64::Engine as _; use crate::hex::FromHex as _; @@ -573,7 +553,7 @@ impl RedeemNode { let v = Vec::from_hex(wit).map_err(crate::ParseError::Hex)?; let wit_iter = crate::BitIter::new(v.into_iter()); - Self::decode(prog_iter, wit_iter).map_err(crate::ParseError::Decode) + Self::decode::<_, _, J>(prog_iter, wit_iter).map_err(crate::ParseError::Decode) } /// Encode the program to bits. @@ -585,7 +565,7 @@ impl RedeemNode { prog: &mut BitWriter<&mut dyn io::Write>, witness: &mut BitWriter<&mut dyn io::Write>, ) -> io::Result { - let sharing_iter = self.post_order_iter::>>(); + let sharing_iter = self.post_order_iter::>(); let program_bits = encode::encode_program(self, prog)?; prog.flush_all()?; let witness_bits = encode::encode_witness(sharing_iter.into_witnesses(), witness)?; @@ -624,13 +604,13 @@ mod tests { amr_str: &str, ihr_str: &str, b64_str: &str, - ) -> Arc> { + ) -> Arc { let prog_hex = prog_bytes.as_hex(); let witness_hex = witness_bytes.as_hex(); let prog = BitIter::from(prog_bytes); let witness = BitIter::from(witness_bytes); - let prog = match RedeemNode::::decode(prog, witness) { + let prog = match RedeemNode::decode::<_, _, J>(prog, witness) { Ok(prog) => prog, Err(e) => panic!("program {} failed: {}", prog_hex, e), }; @@ -703,7 +683,7 @@ mod tests { let prog = BitIter::from(prog_bytes); let witness = BitIter::from(witness_bytes); - match RedeemNode::::decode(prog, witness) { + match RedeemNode::decode::<_, _, J>(prog, witness) { Ok(prog) => panic!( "Program {} wit {} succeded (expected error {}). Program parsed as:\n{:?}", prog_hex, witness_hex, err, prog @@ -726,7 +706,7 @@ mod tests { // main = comp wits_are_equal jet_verify :: 1 -> 1 let eqwits = [0xcd, 0xdc, 0x51, 0xb6, 0xe2, 0x08, 0xc0, 0x40]; let iter = BitIter::from(&eqwits[..]); - let eqwits_prog = CommitNode::::decode(iter).unwrap(); + let eqwits_prog = CommitNode::decode::<_, Core>(iter).unwrap(); let eqwits_final = eqwits_prog .finalize(&mut SimpleFinalizer::new(std::iter::repeat(Value::u32( @@ -781,7 +761,7 @@ mod tests { // "main = unit", but with a witness attached. Found by fuzzer. let prog = BitIter::from(&[0x24][..]); let wit = BitIter::from(&[0x00][..]); - match RedeemNode::::decode(prog, wit) { + match RedeemNode::decode::<_, _, Core>(prog, wit) { Err(DecodeError::Decode(crate::decode::Error::BitIter( crate::BitIterCloseError::TrailingBytes { first_byte: 0 }, ))) => {} // ok, @@ -971,7 +951,7 @@ mod tests { env: &JE, ) { let unpruned_program = types::Context::with_context(|ctx| { - Forest::::parse(unpruned_prog) + Forest::parse::(unpruned_prog) .expect("unpruned program should parse") .to_witness_node(&ctx, unpruned_wit) .expect("unpruned program should have main") @@ -979,7 +959,7 @@ mod tests { .expect("unpruned program should finalize") }); let expected_unpruned_program = types::Context::with_context(|ctx| { - Forest::::parse(expected_pruned_prog) + Forest::parse::(expected_pruned_prog) .expect("expected pruned program should parse") .to_witness_node(&ctx, expected_pruned_wit) .expect("expected pruned program should have main") diff --git a/src/policy/ast.rs b/src/policy/ast.rs index 1f89f2e8..846ebc92 100644 --- a/src/policy/ast.rs +++ b/src/policy/ast.rs @@ -12,7 +12,6 @@ use std::convert::TryFrom; use std::sync::Arc; use std::{fmt, iter, mem}; -use crate::jet::Elements; use crate::node::{ConstructNode, CoreConstructible, JetConstructible, WitnessConstructible}; use crate::policy::serialize::{self, AssemblyConstructible}; use crate::{types, Value}; @@ -63,7 +62,7 @@ impl Policy { ) -> Option where N: CoreConstructible<'brand> - + JetConstructible<'brand, Elements> + + JetConstructible<'brand> + WitnessConstructible<'brand, Option> + AssemblyConstructible<'brand>, { @@ -108,9 +107,9 @@ impl Policy { } /// Return the program commitment of the policy. - pub fn commit(&self) -> Option>> { + pub fn commit(&self) -> Option> { types::Context::with_context(|ctx| { - let construct: Arc> = self.serialize_no_witness(&ctx)?; + let construct: Arc = self.serialize_no_witness(&ctx)?; let commit = construct.finalize_types().expect("policy has sound types"); Some(commit) }) diff --git a/src/policy/satisfy.rs b/src/policy/satisfy.rs index 7b323961..952ef9fc 100644 --- a/src/policy/satisfy.rs +++ b/src/policy/satisfy.rs @@ -1,7 +1,6 @@ // SPDX-License-Identifier: CC0-1.0 use crate::analysis::Cost; -use crate::jet::Elements; use crate::node::{ConstructNode, Hiding, RedeemNode}; use crate::policy::ToXOnlyPubkey; use crate::types; @@ -73,7 +72,7 @@ pub trait Satisfier<'brand, Pk: ToXOnlyPubkey> { /// /// If the assembly program fails to run for the current transaction environment, /// then implementations should return `None`. - fn lookup_asm_program(&self, _: Cmr) -> Option>> { + fn lookup_asm_program(&self, _: Cmr) -> Option>> { None } } @@ -133,7 +132,7 @@ pub enum SatisfierError { AssemblyFailed(crate::bit_machine::ExecutionError), } -type SatResult<'brand> = Hiding<'brand, Arc>>; +type SatResult<'brand> = Hiding<'brand, Arc>>; fn ok_if(condition: bool, expr: SatResult) -> SatResult { match condition { @@ -275,7 +274,7 @@ impl Policy { &self, satisfier: &S, env: &ElementsEnv>, - ) -> Result>, SatisfierError> { + ) -> Result, SatisfierError> { let result = self.satisfy_internal(satisfier)?; match result.get_node() { Some(program) => program @@ -294,6 +293,7 @@ mod tests { use crate::bit_encoding::BitCollector; use crate::dag::{DagLike, NoSharing}; use crate::jet::elements::ElementsEnv; + use crate::jet::Elements; use crate::node::{CoreConstructible, JetConstructible, SimpleFinalizer, WitnessConstructible}; use crate::policy::serialize; use crate::{BitMachine, FailEntropy, SimplicityKey}; @@ -307,7 +307,7 @@ mod tests { pub context: types::Context<'brand>, pub preimages: HashMap, pub signatures: HashMap, - pub assembly: HashMap>>, + pub assembly: HashMap>>, pub tx: &'a elements::Transaction, pub index: usize, } @@ -338,7 +338,7 @@ mod tests { Satisfier::::check_after(&(&self.context, self.tx.lock_time), locktime) } - fn lookup_asm_program(&self, cmr: Cmr) -> Option>> { + fn lookup_asm_program(&self, cmr: Cmr) -> Option>> { self.assembly.get(&cmr).cloned() } } @@ -383,23 +383,20 @@ mod tests { } } - fn execute_successful( - program: Arc>, - env: &ElementsEnv>, - ) { + fn execute_successful(program: Arc, env: &ElementsEnv>) { let mut mac = BitMachine::for_program(&program).unwrap(); assert!(mac.exec(&program, env).is_ok()); } fn execute_unsuccessful( - program: Arc>, + program: Arc, env: &ElementsEnv>, ) { let mut mac = BitMachine::for_program(&program).unwrap(); assert!(mac.exec(&program, env).is_err()); } - fn to_witness(program: &RedeemNode) -> Vec<&Value> { + fn to_witness(program: &RedeemNode) -> Vec<&Value> { program .post_order_iter::() .into_witnesses() @@ -739,12 +736,12 @@ mod tests { let mut assert_branch = |witness0: Value, witness1: Value| { let ctx = &satisfier.context; let asm_program = serialize::verify_bexp( - &Arc::>::pair( - &Arc::>::witness(ctx, Some(witness0.clone())), - &Arc::>::witness(ctx, Some(witness1.clone())), + &Arc::::pair( + &Arc::::witness(ctx, Some(witness0.clone())), + &Arc::::witness(ctx, Some(witness1.clone())), ) .expect("sound types"), - &Arc::>::jet(ctx, Elements::Eq8), + &Arc::::jet(ctx, &Elements::Eq8), ); let cmr = asm_program.cmr(); satisfier.assembly.insert(cmr, asm_program); @@ -787,12 +784,12 @@ mod tests { let mut assert_branch = |witness0: Value, witness1: Value| { let ctx = &satisfier.context; let asm_program = serialize::verify_bexp( - &Arc::>::pair( - &Arc::>::witness(ctx, Some(witness0.clone())), - &Arc::>::witness(ctx, Some(witness1.clone())), + &Arc::::pair( + &Arc::::witness(ctx, Some(witness0.clone())), + &Arc::::witness(ctx, Some(witness1.clone())), ) .expect("sound types"), - &Arc::>::jet(ctx, Elements::Eq8), + &Arc::::jet(ctx, &Elements::Eq8), ); let cmr = asm_program.cmr(); satisfier.assembly.insert(cmr, asm_program); diff --git a/src/policy/serialize.rs b/src/policy/serialize.rs index be855152..5e85a5eb 100644 --- a/src/policy/serialize.rs +++ b/src/policy/serialize.rs @@ -2,7 +2,7 @@ //! Serialization of Policy as Simplicity -use crate::jet::{Elements, Jet}; +use crate::jet::Elements; use crate::merkle::cmr::ConstructibleCmr; use crate::node::{CoreConstructible, JetConstructible, WitnessConstructible}; use crate::types; @@ -32,7 +32,7 @@ impl<'brand> AssemblyConstructible<'brand> for ConstructibleCmr<'brand> { } } -impl<'brand, J: Jet> AssemblyConstructible<'brand> for Arc> { +impl<'brand> AssemblyConstructible<'brand> for Arc> { fn assembly(_: &types::Context, _cmr: Cmr) -> Option { None } @@ -58,58 +58,62 @@ where pub fn key<'brand, Pk, N, W>(inference_context: &types::Context<'brand>, key: &Pk, witness: W) -> N where Pk: ToXOnlyPubkey, - N: CoreConstructible<'brand> - + JetConstructible<'brand, Elements> - + WitnessConstructible<'brand, W>, + N: CoreConstructible<'brand> + JetConstructible<'brand> + WitnessConstructible<'brand, W>, { let key_value = Word::u256(key.to_x_only_pubkey().serialize()); let const_key = N::const_word(inference_context, key_value); - let sighash_all = N::jet(inference_context, Elements::SigAllHash); + let sighash_all = N::jet(inference_context, &Elements::SigAllHash); let pair_key_msg = N::pair(&const_key, &sighash_all).expect("consistent types"); let witness = N::witness(inference_context, witness); let pair_key_msg_sig = N::pair(&pair_key_msg, &witness).expect("consistent types"); - let bip_0340_verify = N::jet(inference_context, Elements::Bip0340Verify); + let bip_0340_verify = N::jet(inference_context, &Elements::Bip0340Verify); N::comp(&pair_key_msg_sig, &bip_0340_verify).expect("consistent types") } pub fn after<'brand, N>(inference_context: &types::Context<'brand>, n: u32) -> N where - N: CoreConstructible<'brand> + JetConstructible<'brand, Elements>, + N: CoreConstructible<'brand> + JetConstructible<'brand>, { let n_value = Word::u32(n); let const_n = N::const_word(inference_context, n_value); - let check_lock_height = N::jet(inference_context, Elements::CheckLockHeight); + let check_lock_height = N::jet(inference_context, &Elements::CheckLockHeight); N::comp(&const_n, &check_lock_height).expect("consistent types") } pub fn older<'brand, N>(inference_context: &types::Context<'brand>, n: u16) -> N where - N: CoreConstructible<'brand> + JetConstructible<'brand, Elements>, + N: CoreConstructible<'brand> + JetConstructible<'brand>, { let n_value = Word::u16(n); let const_n = N::const_word(inference_context, n_value); - let check_lock_distance = N::jet(inference_context, Elements::BrokenDoNotUseCheckLockDistance); + let check_lock_distance = N::jet( + inference_context, + &Elements::BrokenDoNotUseCheckLockDistance, + ); N::comp(&const_n, &check_lock_distance).expect("consistent types") } pub fn compute_sha256<'brand, N>(witness256: &N) -> N where - N: CoreConstructible<'brand> + JetConstructible<'brand, Elements>, + N: CoreConstructible<'brand> + JetConstructible<'brand>, { - let ctx = N::jet(witness256.inference_context(), Elements::Sha256Ctx8Init); + let ctx = N::jet(witness256.inference_context(), &Elements::Sha256Ctx8Init); let pair_ctx_witness = N::pair(&ctx, witness256).expect("consistent types"); - let add256 = N::jet(witness256.inference_context(), Elements::Sha256Ctx8Add32); + let add256 = N::jet(witness256.inference_context(), &Elements::Sha256Ctx8Add32); let digest_ctx = N::comp(&pair_ctx_witness, &add256).expect("consistent types"); - let finalize = N::jet(witness256.inference_context(), Elements::Sha256Ctx8Finalize); + let finalize = N::jet( + witness256.inference_context(), + &Elements::Sha256Ctx8Finalize, + ); N::comp(&digest_ctx, &finalize).expect("consistent types") } pub fn verify_bexp<'brand, N>(input: &N, bexp: &N) -> N where - N: CoreConstructible<'brand> + JetConstructible<'brand, Elements>, + N: CoreConstructible<'brand> + JetConstructible<'brand>, { assert_eq!( input.inference_context(), @@ -117,7 +121,7 @@ where "cannot compose policy fragments with different type inference contexts", ); let computed_bexp = N::comp(input, bexp).expect("consistent types"); - let verify = N::jet(input.inference_context(), Elements::Verify); + let verify = N::jet(input.inference_context(), &Elements::Verify); N::comp(&computed_bexp, &verify).expect("consistent types") } @@ -128,16 +132,14 @@ pub fn sha256<'brand, Pk, N, W>( ) -> N where Pk: ToXOnlyPubkey, - N: CoreConstructible<'brand> - + JetConstructible<'brand, Elements> - + WitnessConstructible<'brand, W>, + N: CoreConstructible<'brand> + JetConstructible<'brand> + WitnessConstructible<'brand, W>, { let hash_value = Word::u256(Pk::to_sha256(hash).to_byte_array()); let const_hash = N::const_word(inference_context, hash_value); let witness256 = N::witness(inference_context, witness); let computed_hash = compute_sha256(&witness256); let pair_hash_computed_hash = N::pair(&const_hash, &computed_hash).expect("consistent types"); - let eq256 = N::jet(inference_context, Elements::Eq256); + let eq256 = N::jet(inference_context, &Elements::Eq256); verify_bexp(&pair_hash_computed_hash, &eq256) } @@ -208,7 +210,7 @@ where /// add(sum, summand): 1 → 2^32 pub fn thresh_add<'brand, N>(sum: &N, summand: &N) -> N where - N: CoreConstructible<'brand> + JetConstructible<'brand, Elements>, + N: CoreConstructible<'brand> + JetConstructible<'brand>, { assert_eq!( sum.inference_context(), @@ -218,7 +220,7 @@ where // 1 → 2^32 × 2^32 let pair_sum_summand = N::pair(sum, summand).expect("consistent types"); // 2^32 × 2^32 → 2 × 2^32 - let add32 = N::jet(sum.inference_context(), Elements::Add32); + let add32 = N::jet(sum.inference_context(), &Elements::Add32); // 1 → 2 x 2^32 let full_sum = N::comp(&pair_sum_summand, &add32).expect("consistent types"); // 2^32 → 2^32 @@ -235,14 +237,14 @@ where /// verify(sum): 1 → 1 pub fn thresh_verify<'brand, N>(sum: &N, k: u32) -> N where - N: CoreConstructible<'brand> + JetConstructible<'brand, Elements>, + N: CoreConstructible<'brand> + JetConstructible<'brand>, { // 1 → 2^32 let const_k = N::const_word(sum.inference_context(), Word::u32(k)); // 1 → 2^32 × 2^32 let pair_k_sum = N::pair(&const_k, sum).expect("consistent types"); // 2^32 × 2^32 → 2 - let eq32 = N::jet(sum.inference_context(), Elements::Eq32); + let eq32 = N::jet(sum.inference_context(), &Elements::Eq32); // 1 → 1 verify_bexp(&pair_k_sum, &eq32) @@ -250,9 +252,7 @@ where pub fn threshold<'brand, N, W>(k: u32, subs: &[N], witness_bits: &[W]) -> N where - N: CoreConstructible<'brand> - + JetConstructible<'brand, Elements> - + WitnessConstructible<'brand, W>, + N: CoreConstructible<'brand> + JetConstructible<'brand> + WitnessConstructible<'brand, W>, W: Clone, { let n = u32::try_from(subs.len()).expect("can have at most 2^32 children in a threshold"); @@ -270,7 +270,6 @@ where #[cfg(test)] mod tests { - use super::*; use crate::jet::elements::ElementsEnv; use crate::node::SimpleFinalizer; use crate::policy::Policy; @@ -283,10 +282,7 @@ mod tests { fn compile( policy: Policy, - ) -> ( - Arc>, - ElementsEnv>, - ) { + ) -> (Arc, ElementsEnv>) { let commit = policy.commit().expect("no asm"); let env = ElementsEnv::dummy(); @@ -294,7 +290,7 @@ mod tests { } fn execute_successful( - commit: &CommitNode, + commit: &CommitNode, witness: Vec, env: &ElementsEnv>, ) -> bool { diff --git a/src/types/arrow.rs b/src/types/arrow.rs index 338ca6df..f0a74949 100644 --- a/src/types/arrow.rs +++ b/src/types/arrow.rs @@ -354,8 +354,8 @@ impl<'brand> DisconnectConstructible<'brand, Option<&Arrow<'brand>>> for Arrow<' } } -impl<'brand, J: Jet> JetConstructible<'brand, J> for Arrow<'brand> { - fn jet(inference_context: &Context<'brand>, jet: J) -> Self { +impl<'brand> JetConstructible<'brand> for Arrow<'brand> { + fn jet(inference_context: &Context<'brand>, jet: &dyn Jet) -> Self { Arrow { source: jet.source_ty().to_type(inference_context), target: jet.target_ty().to_type(inference_context), diff --git a/src/types/incomplete.rs b/src/types/incomplete.rs index 4f7531af..d66473b4 100644 --- a/src/types/incomplete.rs +++ b/src/types/incomplete.rs @@ -113,7 +113,6 @@ impl Incomplete { use std::collections::HashSet; use super::context::OccursCheckId; - use super::BoundRef; /// Helper type for the occurs-check. enum OccursCheckStack<'brand> { diff --git a/src/types/mod.rs b/src/types/mod.rs index c7336975..39e4d4cd 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -415,34 +415,33 @@ impl fmt::Display for Type<'_> { mod tests { use super::*; - use crate::jet::Core; use crate::node::{ConstructNode, CoreConstructible}; #[test] fn inference_failure() { Context::with_context(|ctx| { // unit: A -> 1 - let unit = Arc::>::unit(&ctx); // 1 -> 1 + let unit = Arc::::unit(&ctx); // 1 -> 1 // Force unit to be 1->1 - Arc::>::comp(&unit, &unit).unwrap(); + Arc::::comp(&unit, &unit).unwrap(); // take unit: 1 * B -> 1 - let take_unit = Arc::>::take(&unit); // 1*1 -> 1 + let take_unit = Arc::::take(&unit); // 1*1 -> 1 // Pair will try to unify 1 and 1*B - Arc::>::pair(&unit, &take_unit).unwrap_err(); + Arc::::pair(&unit, &take_unit).unwrap_err(); // Trying to do it again should not work. - Arc::>::pair(&unit, &take_unit).unwrap_err(); + Arc::::pair(&unit, &take_unit).unwrap_err(); }); } #[test] fn memory_leak() { Context::with_context(|ctx| { - let iden = Arc::>::iden(&ctx); - let drop = Arc::>::drop_(&iden); - let case = Arc::>::case(&iden, &drop).unwrap(); + let iden = Arc::::iden(&ctx); + let drop = Arc::::drop_(&iden); + let case = Arc::::case(&iden, &drop).unwrap(); let _ = format!("{:?}", case.arrow().source); });