diff --git a/src/bit_encoding/decode.rs b/src/bit_encoding/decode.rs
index d396a3dc..df98fb2d 100644
--- a/src/bit_encoding/decode.rs
+++ b/src/bit_encoding/decode.rs
@@ -133,7 +133,7 @@ enum DecodeNode<J: Jet> {
     Word(Word),
 }
 
-impl<'d, J: Jet> DagLike for (usize, &'d [DecodeNode<J>]) {
+impl<J: Jet> DagLike for (usize, &'_ [DecodeNode<J>]) {
     type Node = DecodeNode<J>;
 
     fn data(&self) -> &DecodeNode<J> {
diff --git a/src/bit_encoding/encode.rs b/src/bit_encoding/encode.rs
index 8ccf35db..e0df43f8 100644
--- a/src/bit_encoding/encode.rs
+++ b/src/bit_encoding/encode.rs
@@ -35,7 +35,7 @@ impl<'n, N: node::Marker> Disconnectable<EncodeNode<'n, N>> for EncodeNode<'n, N
     }
 }
 
-impl<'n, N: node::Marker> DagLike for EncodeNode<'n, N> {
+impl<N: node::Marker> DagLike for EncodeNode<'_, N> {
     type Node = Self;
     fn data(&self) -> &Self {
         self
@@ -125,7 +125,7 @@ impl<N: node::Marker> Default for EncodeSharing<N> {
     }
 }
 
-impl<'n, N: node::Marker> SharingTracker<EncodeNode<'n, N>> for EncodeSharing<N> {
+impl<N: node::Marker> SharingTracker<EncodeNode<'_, N>> for EncodeSharing<N> {
     fn record(&mut self, d: &EncodeNode<N>, index: usize) -> Option<usize> {
         let id = match d {
             EncodeNode::Node(n) => EncodeId::Node(n.sharing_id()?),
diff --git a/src/bit_machine/mod.rs b/src/bit_machine/mod.rs
index 2fbb52aa..de61bcf6 100644
--- a/src/bit_machine/mod.rs
+++ b/src/bit_machine/mod.rs
@@ -221,7 +221,7 @@ impl BitMachine {
         }
 
         // Not used, but useful for debugging, so keep it around
-        impl<'a, J: Jet> fmt::Debug for CallStack<'a, J> {
+        impl<J: Jet> fmt::Debug for CallStack<'_, J> {
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 match self {
                     CallStack::Goto(ins) => write!(f, "goto {}", ins.inner()),
diff --git a/src/dag.rs b/src/dag.rs
index 9f87af40..fe710bfa 100644
--- a/src/dag.rs
+++ b/src/dag.rs
@@ -369,7 +369,7 @@ impl<D: DagLike> DagLike for SwapChildren<D> {
     }
 }
 
-impl<'a, N: node::Marker> DagLike for &'a Node<N> {
+impl<N: node::Marker> DagLike for &'_ Node<N> {
     type Node = Node<N>;
 
     fn data(&self) -> &Node<N> {
diff --git a/src/human_encoding/mod.rs b/src/human_encoding/mod.rs
index fb8915b8..4c508d8c 100644
--- a/src/human_encoding/mod.rs
+++ b/src/human_encoding/mod.rs
@@ -75,7 +75,7 @@ impl WitnessOrHole {
     }
 }
 
-impl<'a> From<&'a NoWitness> for WitnessOrHole {
+impl From<&'_ NoWitness> for WitnessOrHole {
     fn from(_: &NoWitness) -> Self {
         WitnessOrHole::Witness
     }
diff --git a/src/human_encoding/named_node.rs b/src/human_encoding/named_node.rs
index ccb6ac2d..e1bb9e7e 100644
--- a/src/human_encoding/named_node.rs
+++ b/src/human_encoding/named_node.rs
@@ -120,7 +120,7 @@ impl<J: Jet> NamedCommitNode<J> {
             phantom: PhantomData<J>,
         }
 
-        impl<'a, J: Jet> Converter<Named<Commit<J>>, Witness<J>> for Populator<'a, J> {
+        impl<J: Jet> Converter<Named<Commit<J>>, Witness<J>> for Populator<'_, J> {
             type Error = ();
 
             fn convert_witness(
diff --git a/src/human_encoding/parse/mod.rs b/src/human_encoding/parse/mod.rs
index cf227eac..92b043d5 100644
--- a/src/human_encoding/parse/mod.rs
+++ b/src/human_encoding/parse/mod.rs
@@ -136,7 +136,7 @@ struct ResolvedExpression<J: Jet> {
     in_degree: AtomicUsize,
 }
 
-impl<'a, J: Jet> DagLike for &'a ResolvedExpression<J> {
+impl<J: Jet> DagLike for &'_ ResolvedExpression<J> {
     type Node = ResolvedExpression<J>;
     fn data(&self) -> &ResolvedExpression<J> {
         self
diff --git a/src/node/redeem.rs b/src/node/redeem.rs
index 96a4a9d5..e91fa410 100644
--- a/src/node/redeem.rs
+++ b/src/node/redeem.rs
@@ -288,8 +288,8 @@ impl<J: Jet> RedeemNode<J> {
             phantom: PhantomData<J>,
         }
 
-        impl<'bits, J: Jet, I: Iterator<Item = u8>> Converter<Construct<J>, Redeem<J>>
-            for DecodeFinalizer<'bits, J, I>
+        impl<J: Jet, I: Iterator<Item = u8>> Converter<Construct<J>, Redeem<J>>
+            for DecodeFinalizer<'_, J, I>
         {
             type Error = Error;
             fn convert_witness(
diff --git a/src/policy/satisfy.rs b/src/policy/satisfy.rs
index 54cdcc64..7af203cb 100644
--- a/src/policy/satisfy.rs
+++ b/src/policy/satisfy.rs
@@ -250,7 +250,7 @@ mod tests {
         pub index: usize,
     }
 
-    impl<'a, Pk: ToXOnlyPubkey> Satisfier<Pk> for PolicySatisfier<'a, Pk> {
+    impl<Pk: ToXOnlyPubkey> Satisfier<Pk> for PolicySatisfier<'_, Pk> {
         fn lookup_tap_leaf_script_sig(
             &self,
             pk: &Pk,
diff --git a/src/types/context.rs b/src/types/context.rs
index 5185ba12..3cf9b364 100644
--- a/src/types/context.rs
+++ b/src/types/context.rs
@@ -245,6 +245,19 @@ pub struct BoundRef {
     index: usize,
 }
 
+// SAFETY: The pointer inside `BoundRef` is always (eventually) constructed from Arc::as_ptr
+// from the slab of a type-inference context.
+//
+// Arc will prevent the pointer from ever changing, except to be deallocated when the last
+// Arc goes away. But this occurs only when the context itself goes away, which in turn
+// happens only when every type bound referring to the context goes away.
+//
+// If this were untrue, our use of `BoundRef` would lead to dereferences of a dangling
+// pointer, and `Send`/`Sync` would be the least of our concerns!
+unsafe impl Send for BoundRef {}
+// SAFETY: see comment on `Send`
+unsafe impl Sync for BoundRef {}
+
 impl BoundRef {
     pub fn assert_matches_context(&self, ctx: &Context) {
         assert_eq!(
@@ -282,7 +295,7 @@ impl super::PointerLike for BoundRef {
     }
 }
 
-impl<'ctx> DagLike for (&'ctx Context, BoundRef) {
+impl DagLike for (&'_ Context, BoundRef) {
     type Node = BoundRef;
     fn data(&self) -> &BoundRef {
         &self.1
@@ -318,7 +331,7 @@ struct LockedContext<'ctx> {
     slab: MutexGuard<'ctx, Vec<Bound>>,
 }
 
-impl<'ctx> LockedContext<'ctx> {
+impl LockedContext<'_> {
     fn alloc_bound(&mut self, bound: Bound) -> BoundRef {
         self.slab.push(bound);
         let index = self.slab.len() - 1;
diff --git a/src/types/final_data.rs b/src/types/final_data.rs
index e50808ee..4786cf8a 100644
--- a/src/types/final_data.rs
+++ b/src/types/final_data.rs
@@ -134,7 +134,7 @@ impl fmt::Display for Final {
     }
 }
 
-impl<'a> DagLike for &'a Final {
+impl DagLike for &'_ Final {
     type Node = Final;
     fn data(&self) -> &Final {
         self
diff --git a/src/value.rs b/src/value.rs
index fff336f9..9b3f4a8f 100644
--- a/src/value.rs
+++ b/src/value.rs
@@ -47,7 +47,7 @@ enum ValueInner {
     Product(Arc<Value>, Arc<Value>),
 }
 
-impl<'a> DagLike for &'a Value {
+impl DagLike for &'_ Value {
     type Node = Value;
 
     fn data(&self) -> &Value {
@@ -361,7 +361,7 @@ impl<'a> PaddedBitsIter<'a> {
     }
 }
 
-impl<'a> Iterator for PaddedBitsIter<'a> {
+impl Iterator for PaddedBitsIter<'_> {
     type Item = bool;
 
     fn next(&mut self) -> Option<Self::Item> {