Skip to content

Commit fe1f888

Browse files
committed
Merge BlockstreamResearch#361: Runtime jet type check
24ce63a add the Context jet type check (ivanlele) Pull request description: This PR introduces a runtime jet type check in the Context to prevent unintended behavior. ACKs for top commit: apoelstra: ACK 24ce63a; successfully ran local tests Tree-SHA512: d162294d9acbda40c8f28f9da5ff3f0841ecaaa48acd9104a4b9d920df79bc0ed577ea0f472084f278ad5b10de06ea481c44b50bc384e1027cfaf2b6a442a508
2 parents a5f4c0b + 24ce63a commit fe1f888

3 files changed

Lines changed: 49 additions & 1 deletion

File tree

src/types/arrow.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,8 @@ impl<'brand> DisconnectConstructible<'brand, Option<&Arrow<'brand>>> for Arrow<'
356356

357357
impl<'brand> JetConstructible<'brand> for Arrow<'brand> {
358358
fn jet(inference_context: &Context<'brand>, jet: &dyn Jet) -> Self {
359+
inference_context.check_jet(jet);
360+
359361
Arrow {
360362
source: jet.source_ty().to_type(inference_context),
361363
target: jet.target_ty().to_type(inference_context),

src/types/context.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
//! the other.
1515
//!
1616
17+
use std::any::TypeId;
1718
use std::fmt;
1819
use std::marker::PhantomData;
1920
use std::sync::{Arc, Mutex, MutexGuard};
2021

2122
use ghost_cell::GhostToken;
2223

2324
use crate::dag::{Dag, DagLike};
25+
use crate::jet::Jet;
2426

2527
use super::{
2628
Bound, CompleteBound, Error, Final, Incomplete, Type, TypeInner, UbElement, WithGhostToken,
@@ -48,6 +50,8 @@ pub struct Context<'brand> {
4850

4951
struct ContextInner<'brand> {
5052
slab: Vec<Bound<'brand>>,
53+
/// Concrete jet type registered in this context, if any.
54+
jet_type: Option<TypeId>,
5155
}
5256

5357
impl fmt::Debug for Context<'_> {
@@ -81,7 +85,10 @@ impl<'brand> Context<'brand> {
8185
Context {
8286
inner: Arc::new(Mutex::new(WithGhostToken {
8387
token,
84-
inner: ContextInner { slab: vec![] },
88+
inner: ContextInner {
89+
slab: vec![],
90+
jet_type: None,
91+
},
8592
})),
8693
}
8794
}
@@ -147,6 +154,23 @@ impl<'brand> Context<'brand> {
147154
}
148155
}
149156

157+
/// Asserts that all jets in this context have the same concrete type.
158+
///
159+
/// Records the jet's type on first call, panics on subsequent calls with
160+
/// a different concrete type.
161+
pub fn check_jet(&self, jet: &dyn Jet) {
162+
let new_id = jet.as_any().type_id();
163+
let mut lock = self.lock();
164+
165+
if let Some(existing_id) = lock.inner.jet_type {
166+
assert!(existing_id == new_id, "mixed jet types in context");
167+
168+
return;
169+
}
170+
171+
lock.inner.jet_type = Some(new_id);
172+
}
173+
150174
/// Accesses a bound.
151175
pub(super) fn get(&self, bound: &BoundRef<'brand>) -> Bound<'brand> {
152176
let lock = self.lock();

src/types/mod.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,8 @@ impl fmt::Display for Type<'_> {
415415
mod tests {
416416
use super::*;
417417

418+
use crate::jet::Core;
419+
use crate::node::JetConstructible;
418420
use crate::node::{ConstructNode, CoreConstructible};
419421

420422
#[test]
@@ -446,4 +448,24 @@ mod tests {
446448
let _ = format!("{:?}", case.arrow().source);
447449
});
448450
}
451+
452+
#[test]
453+
fn check_jet_same_type_ok() {
454+
Context::with_context(|ctx| {
455+
let _ = Arc::<ConstructNode>::jet(&ctx, &Core::Add32);
456+
let _ = Arc::<ConstructNode>::jet(&ctx, &Core::Subtract32);
457+
});
458+
}
459+
460+
#[cfg(feature = "elements")]
461+
#[test]
462+
#[should_panic(expected = "mixed jet types in context")]
463+
fn check_jet_different_types_panics() {
464+
use crate::jet::Elements;
465+
466+
Context::with_context(|ctx| {
467+
let _ = Arc::<ConstructNode>::jet(&ctx, &Core::Add32);
468+
let _ = Arc::<ConstructNode>::jet(&ctx, &Elements::Add32);
469+
});
470+
}
449471
}

0 commit comments

Comments
 (0)