Skip to content

Commit 500b4a5

Browse files
committed
Remove type_check from Property trait
The blanket implementation of `type_check` is only used on `CompilerExtData` while `ExtData` and `Type` override the impl and don't need the `child` parameter. Moreover, the fn isn't called as Property generic. So the blanket implementation of `type_check` is moved as a impl in `CompilerExtData` and the overrides in `ExtData` and `Type` are moved as simple impl on the type, making it possible to remove the unused `child` parameter.
1 parent b485f43 commit 500b4a5

File tree

6 files changed

+193
-196
lines changed

6 files changed

+193
-196
lines changed

src/miniscript/astelem.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use elements::{opcodes, script, Sequence};
1818
use super::limits::{MAX_SCRIPT_ELEMENT_SIZE, MAX_STANDARD_P2WSH_STACK_ITEM_SIZE};
1919
use crate::extensions::ParseableExt;
2020
use crate::miniscript::context::SigType;
21-
use crate::miniscript::types::{self, Property};
21+
use crate::miniscript::types;
2222
use crate::miniscript::ScriptContext;
2323
use crate::util::MsKeyBuilder;
2424
use crate::{
@@ -303,7 +303,7 @@ where
303303
{
304304
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
305305
f.write_str("[")?;
306-
if let Ok(type_map) = types::Type::type_check(self, |_| None) {
306+
if let Ok(type_map) = types::Type::type_check(self) {
307307
f.write_str(match type_map.corr.base {
308308
types::Base::B => "B",
309309
types::Base::K => "K",

src/miniscript/decode.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,14 @@ use crate::extensions::ParseableExt;
1717
use crate::miniscript::lex::{Token as Tk, TokenIter};
1818
use crate::miniscript::limits::{MAX_BLOCK_WEIGHT, MAX_PUBKEYS_PER_MULTISIG};
1919
use crate::miniscript::types::extra_props::ExtData;
20-
use crate::miniscript::types::{Property, Type};
20+
use crate::miniscript::types::Type;
2121
use crate::miniscript::ScriptContext;
2222
#[cfg(doc)]
2323
use crate::Descriptor;
2424
use crate::{
2525
bitcoin, hash256, AbsLockTime, Error, Extension, Miniscript, MiniscriptKey, NoExt, ToPublicKey,
2626
};
2727

28-
fn return_none<T>(_: usize) -> Option<T> {
29-
None
30-
}
31-
3228
/// Trait for parsing keys from byte slices
3329
pub trait ParseableKey: Sized + ToPublicKey + private::Sealed {
3430
/// Parse a key from slice
@@ -211,8 +207,8 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext, Ext: Extension> TerminalStack<Pk, Ct
211207

212208
///reduce, type check and push a 0-arg node
213209
fn reduce0(&mut self, ms: Terminal<Pk, Ctx, Ext>) -> Result<(), Error> {
214-
let ty = Type::type_check(&ms, return_none)?;
215-
let ext = ExtData::type_check(&ms, return_none)?;
210+
let ty = Type::type_check(&ms)?;
211+
let ext = ExtData::type_check(&ms)?;
216212
let ms = Miniscript {
217213
node: ms,
218214
ty,
@@ -232,8 +228,8 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext, Ext: Extension> TerminalStack<Pk, Ct
232228
let top = self.pop().unwrap();
233229
let wrapped_ms = wrap(Arc::new(top));
234230

235-
let ty = Type::type_check(&wrapped_ms, return_none)?;
236-
let ext = ExtData::type_check(&wrapped_ms, return_none)?;
231+
let ty = Type::type_check(&wrapped_ms)?;
232+
let ext = ExtData::type_check(&wrapped_ms)?;
237233
let ms = Miniscript {
238234
node: wrapped_ms,
239235
ty,
@@ -258,8 +254,8 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext, Ext: Extension> TerminalStack<Pk, Ct
258254

259255
let wrapped_ms = wrap(Arc::new(left), Arc::new(right));
260256

261-
let ty = Type::type_check(&wrapped_ms, return_none)?;
262-
let ext = ExtData::type_check(&wrapped_ms, return_none)?;
257+
let ty = Type::type_check(&wrapped_ms)?;
258+
let ext = ExtData::type_check(&wrapped_ms)?;
263259
let ms = Miniscript {
264260
node: wrapped_ms,
265261
ty,
@@ -562,8 +558,8 @@ pub fn parse<Ctx: ScriptContext, Ext: ParseableExt>(
562558
let c = term.pop().unwrap();
563559
let wrapped_ms = Terminal::AndOr(Arc::new(a), Arc::new(c), Arc::new(b));
564560

565-
let ty = Type::type_check(&wrapped_ms, return_none)?;
566-
let ext = ExtData::type_check(&wrapped_ms, return_none)?;
561+
let ty = Type::type_check(&wrapped_ms)?;
562+
let ext = ExtData::type_check(&wrapped_ms)?;
567563

568564
term.0.push(Miniscript {
569565
node: wrapped_ms,

src/miniscript/mod.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ use std::cmp;
3636
use std::sync::Arc;
3737

3838
use self::lex::{lex, TokenIter};
39-
use self::types::Property;
4039
use crate::extensions::ParseableExt;
4140
pub use crate::miniscript::context::ScriptContext;
4241
use crate::miniscript::decode::Terminal;
@@ -117,8 +116,8 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext, Ext: Extension> Miniscript<Pk, Ctx,
117116
/// Display code of type_check.
118117
pub fn from_ast(t: Terminal<Pk, Ctx, Ext>) -> Result<Miniscript<Pk, Ctx, Ext>, Error> {
119118
Ok(Miniscript {
120-
ty: Type::type_check(&t, |_| None)?,
121-
ext: ExtData::type_check(&t, |_| None)?,
119+
ty: Type::type_check(&t)?,
120+
ext: ExtData::type_check(&t)?,
122121
node: t,
123122
phantom: PhantomData,
124123
})
@@ -177,7 +176,7 @@ where
177176

178177
let top = decode::parse(&mut iter)?;
179178
Ctx::check_global_validity(&top)?;
180-
let type_check = types::Type::type_check(&top.node, |_| None)?;
179+
let type_check = types::Type::type_check(&top.node)?;
181180
if type_check.corr.base != types::Base::B {
182181
return Err(Error::NonTopLevel(format!("{:?}", top)));
183182
};
@@ -491,8 +490,8 @@ impl_from_tree!(
491490
fn from_tree(top: &expression::Tree<'_>) -> Result<Miniscript<Pk, Ctx, Ext>, Error> {
492491
let inner: Terminal<Pk, Ctx, Ext> = expression::FromTree::from_tree(top)?;
493492
Ok(Miniscript {
494-
ty: Type::type_check(&inner, |_| None)?,
495-
ext: ExtData::type_check(&inner, |_| None)?,
493+
ty: Type::type_check(&inner)?,
494+
ext: ExtData::type_check(&inner)?,
496495
node: inner,
497496
phantom: PhantomData,
498497
})

src/miniscript/types/extra_props.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -890,15 +890,14 @@ impl Property for ExtData {
890890
fn from_ext<E: Extension>(e: &E) -> Self {
891891
e.extra_prop()
892892
}
893-
893+
}
894+
impl ExtData {
894895
/// Compute the type of a fragment assuming all the children of
895896
/// Miniscript have been computed already.
896-
fn type_check<Pk, Ctx, C, Ext>(
897+
pub fn type_check<Pk, Ctx, Ext>(
897898
fragment: &Terminal<Pk, Ctx, Ext>,
898-
_child: C,
899899
) -> Result<Self, Error<Pk, Ctx, Ext>>
900900
where
901-
C: FnMut(usize) -> Option<Self>,
902901
Ctx: ScriptContext,
903902
Pk: MiniscriptKey,
904903
Ext: Extension,

src/miniscript/types/mod.rs

Lines changed: 3 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,6 @@ pub use self::malleability::{Dissat, Malleability};
1919
use super::ScriptContext;
2020
use crate::{Extension, MiniscriptKey, NoExt, Terminal};
2121

22-
/// None-returning function to help type inference when we need a
23-
/// closure that simply returns `None`
24-
fn return_none<T>(_: usize) -> Option<T> {
25-
None
26-
}
27-
2822
/// Detailed type of a typechecker error
2923
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
3024
pub enum ErrorKind {
@@ -378,161 +372,6 @@ pub trait Property: Sized {
378372
/// Extensions are always leaf, they should have a fixed type property and hence
379373
/// should not fail
380374
fn from_ext<E: Extension>(e: &E) -> Self;
381-
382-
/// Compute the type of a fragment, given a function to look up
383-
/// the types of its children, if available and relevant for the
384-
/// given fragment
385-
fn type_check<Pk, Ctx, C, Ext>(
386-
fragment: &Terminal<Pk, Ctx, Ext>,
387-
mut child: C,
388-
) -> Result<Self, Error<Pk, Ctx, Ext>>
389-
where
390-
C: FnMut(usize) -> Option<Self>,
391-
Pk: MiniscriptKey,
392-
Ctx: ScriptContext,
393-
Ext: Extension,
394-
{
395-
let mut get_child = |sub, n| {
396-
child(n)
397-
.map(Ok)
398-
.unwrap_or_else(|| Self::type_check(sub, return_none))
399-
};
400-
let wrap_err = |result: Result<Self, ErrorKind>| {
401-
result.map_err(|kind| Error {
402-
fragment: fragment.clone(),
403-
error: kind,
404-
})
405-
};
406-
407-
let ret = match *fragment {
408-
Terminal::True => Ok(Self::from_true()),
409-
Terminal::False => Ok(Self::from_false()),
410-
Terminal::PkK(..) => Ok(Self::from_pk_k::<Ctx>()),
411-
Terminal::PkH(..) | Terminal::RawPkH(..) => Ok(Self::from_pk_h::<Ctx>()),
412-
Terminal::Multi(k, ref pks) | Terminal::MultiA(k, ref pks) => {
413-
if k == 0 {
414-
return Err(Error {
415-
fragment: fragment.clone(),
416-
error: ErrorKind::ZeroThreshold,
417-
});
418-
}
419-
if k > pks.len() {
420-
return Err(Error {
421-
fragment: fragment.clone(),
422-
error: ErrorKind::OverThreshold(k, pks.len()),
423-
});
424-
}
425-
match *fragment {
426-
Terminal::Multi(..) => Ok(Self::from_multi(k, pks.len())),
427-
Terminal::MultiA(..) => Ok(Self::from_multi_a(k, pks.len())),
428-
_ => unreachable!(),
429-
}
430-
}
431-
Terminal::After(t) => {
432-
// Note that for CLTV this is a limitation not of Bitcoin but Miniscript. The
433-
// number on the stack would be a 5 bytes signed integer but Miniscript's B type
434-
// only consumes 4 bytes from the stack.
435-
if t == LockTime::ZERO.into() {
436-
return Err(Error {
437-
fragment: fragment.clone(),
438-
error: ErrorKind::InvalidTime,
439-
});
440-
}
441-
Ok(Self::from_after(t.into()))
442-
}
443-
Terminal::Older(t) => {
444-
if t == Sequence::ZERO || !t.is_relative_lock_time() {
445-
return Err(Error {
446-
fragment: fragment.clone(),
447-
error: ErrorKind::InvalidTime,
448-
});
449-
}
450-
Ok(Self::from_older(t))
451-
}
452-
Terminal::Sha256(..) => Ok(Self::from_sha256()),
453-
Terminal::Hash256(..) => Ok(Self::from_hash256()),
454-
Terminal::Ripemd160(..) => Ok(Self::from_ripemd160()),
455-
Terminal::Hash160(..) => Ok(Self::from_hash160()),
456-
Terminal::Alt(ref sub) => wrap_err(Self::cast_alt(get_child(&sub.node, 0)?)),
457-
Terminal::Swap(ref sub) => wrap_err(Self::cast_swap(get_child(&sub.node, 0)?)),
458-
Terminal::Check(ref sub) => wrap_err(Self::cast_check(get_child(&sub.node, 0)?)),
459-
Terminal::DupIf(ref sub) => wrap_err(Self::cast_dupif(get_child(&sub.node, 0)?)),
460-
Terminal::Verify(ref sub) => wrap_err(Self::cast_verify(get_child(&sub.node, 0)?)),
461-
Terminal::NonZero(ref sub) => wrap_err(Self::cast_nonzero(get_child(&sub.node, 0)?)),
462-
Terminal::ZeroNotEqual(ref sub) => {
463-
wrap_err(Self::cast_zeronotequal(get_child(&sub.node, 0)?))
464-
}
465-
Terminal::AndB(ref l, ref r) => {
466-
let ltype = get_child(&l.node, 0)?;
467-
let rtype = get_child(&r.node, 1)?;
468-
wrap_err(Self::and_b(ltype, rtype))
469-
}
470-
Terminal::AndV(ref l, ref r) => {
471-
let ltype = get_child(&l.node, 0)?;
472-
let rtype = get_child(&r.node, 1)?;
473-
wrap_err(Self::and_v(ltype, rtype))
474-
}
475-
Terminal::OrB(ref l, ref r) => {
476-
let ltype = get_child(&l.node, 0)?;
477-
let rtype = get_child(&r.node, 1)?;
478-
wrap_err(Self::or_b(ltype, rtype))
479-
}
480-
Terminal::OrD(ref l, ref r) => {
481-
let ltype = get_child(&l.node, 0)?;
482-
let rtype = get_child(&r.node, 1)?;
483-
wrap_err(Self::or_d(ltype, rtype))
484-
}
485-
Terminal::OrC(ref l, ref r) => {
486-
let ltype = get_child(&l.node, 0)?;
487-
let rtype = get_child(&r.node, 1)?;
488-
wrap_err(Self::or_c(ltype, rtype))
489-
}
490-
Terminal::OrI(ref l, ref r) => {
491-
let ltype = get_child(&l.node, 0)?;
492-
let rtype = get_child(&r.node, 1)?;
493-
wrap_err(Self::or_i(ltype, rtype))
494-
}
495-
Terminal::AndOr(ref a, ref b, ref c) => {
496-
let atype = get_child(&a.node, 0)?;
497-
let btype = get_child(&b.node, 1)?;
498-
let ctype = get_child(&c.node, 2)?;
499-
wrap_err(Self::and_or(atype, btype, ctype))
500-
}
501-
Terminal::Thresh(k, ref subs) => {
502-
if k == 0 {
503-
return Err(Error {
504-
fragment: fragment.clone(),
505-
error: ErrorKind::ZeroThreshold,
506-
});
507-
}
508-
if k > subs.len() {
509-
return Err(Error {
510-
fragment: fragment.clone(),
511-
error: ErrorKind::OverThreshold(k, subs.len()),
512-
});
513-
}
514-
515-
let mut last_err_frag = None;
516-
let res = Self::threshold(k, subs.len(), |n| match get_child(&subs[n].node, n) {
517-
Ok(x) => Ok(x),
518-
Err(e) => {
519-
last_err_frag = Some(e.fragment);
520-
Err(e.error)
521-
}
522-
});
523-
524-
res.map_err(|kind| Error {
525-
fragment: last_err_frag.unwrap_or_else(|| fragment.clone()),
526-
error: kind,
527-
})
528-
}
529-
Terminal::Ext(ref ext) => Ok(Self::from_ext(ext)),
530-
};
531-
if let Ok(ref ret) = ret {
532-
ret.sanity_checks()
533-
}
534-
ret
535-
}
536375
}
537376

538377
impl Property for Type {
@@ -783,15 +622,14 @@ impl Property for Type {
783622
mall: Property::from_ext(e),
784623
}
785624
}
786-
625+
}
626+
impl Type {
787627
/// Compute the type of a fragment assuming all the children of
788628
/// Miniscript have been computed already.
789-
fn type_check<Pk, Ctx, C, Ext>(
629+
pub fn type_check<Pk, Ctx, Ext>(
790630
fragment: &Terminal<Pk, Ctx, Ext>,
791-
_child: C,
792631
) -> Result<Self, Error<Pk, Ctx, Ext>>
793632
where
794-
C: FnMut(usize) -> Option<Self>,
795633
Pk: MiniscriptKey,
796634
Ctx: ScriptContext,
797635
Ext: Extension,

0 commit comments

Comments
 (0)