diff --git a/elfo-core/src/envelope.rs b/elfo-core/src/envelope.rs index d8f4a1d8..fb8202c6 100644 --- a/elfo-core/src/envelope.rs +++ b/elfo-core/src/envelope.rs @@ -31,7 +31,7 @@ assert_eq_size!(Envelope, usize); // TODO: the current size (on x86-64) is 64 bytes, but it can be reduced. // And... it should be reduced once `TraceId` is extended to 16 bytes. pub(crate) struct EnvelopeHeader { - /// See [`mailbox.rs`] for more details. + /// See `mailbox.rs` for more details. pub(crate) link: mailbox::Link, created_time: Instant, // Now used also as a sent time. trace_id: TraceId, @@ -237,7 +237,7 @@ impl Envelope { let message_offset = self.header().message_offset; // SAFETY: `message_offset` refers to the same allocation object. - let ptr = unsafe { self.0.as_ptr().cast::().add(message_offset as usize) }; + let ptr = unsafe { self.0.as_ptr().byte_add(message_offset as usize) }; // SAFETY: `envelope_repr_layout()` guarantees that `ptr` is valid. unsafe { NonNull::new_unchecked(ptr.cast()) } @@ -271,7 +271,10 @@ impl Envelope { // SAFETY: `self` is properly initialized. let header = unsafe { self.0.as_mut() }; - if let MessageKind::RequestAny(token) | MessageKind::RequestAll(token) = &mut header.kind { + let fake_kind = MessageKind::Regular { sender: Addr::NULL }; + let kind = mem::replace(&mut header.kind, fake_kind); + + if let MessageKind::RequestAny(token) | MessageKind::RequestAll(token) = kind { // FIXME: probably invalid for ALL requests, need to decrement remainder. // REVIEW: DO NOT forget check & fix it before merging. token.forget(); diff --git a/elfo-core/src/exec.rs b/elfo-core/src/exec.rs index a0290f8b..5f59fbef 100644 --- a/elfo-core/src/exec.rs +++ b/elfo-core/src/exec.rs @@ -40,7 +40,7 @@ impl ExecResult for () { impl ExecResult for never::Never { #[allow(private_interfaces)] fn unify(self) -> Result<(), BoxedError> { - unreachable!() + self } } diff --git a/elfo-core/src/mailbox.rs b/elfo-core/src/mailbox.rs index c6cdf4c0..7aa056a9 100644 --- a/elfo-core/src/mailbox.rs +++ b/elfo-core/src/mailbox.rs @@ -136,7 +136,7 @@ impl Mailbox { pub(crate) async fn recv(&self) -> RecvResult { loop { // TODO: it should be possible to use `dequeue_unchecked()` here. - // Preliminarily, we should guarantee that `recv()` can be called only + // Preliminarily, we should guarantee that it can be called only // by one consumer. However, it's not enough to create a dedicated // `MailboxConsumer` because users can steal `Context` to another // task/thread and create a race with the `drop_all()` method. diff --git a/elfo-core/src/message.rs b/elfo-core/src/message.rs index aa23ed7a..16b39fa7 100644 --- a/elfo-core/src/message.rs +++ b/elfo-core/src/message.rs @@ -74,12 +74,6 @@ pub trait Message: Self::_type_id() == type_id } - // Called in `_read()` and `_write()` to avoid - // * [rust#47384](https://github.com/rust-lang/rust/issues/47384) - // * [rust#99721](https://github.com/rust-lang/rust/issues/99721) - #[doc(hidden)] - fn _touch(&self); - #[doc(hidden)] #[inline(always)] fn _into_any(self) -> AnyMessage { @@ -122,9 +116,7 @@ pub trait Message: #[inline(always)] unsafe fn _read(ptr: NonNull) -> Self { let data_ref = &ptr.cast::>().as_ref().data; - let data = ptr::read(data_ref); - data._touch(); - data + ptr::read(data_ref) } /// # Safety @@ -137,7 +129,6 @@ pub trait Message: #[doc(hidden)] #[inline(always)] unsafe fn _write(self, ptr: NonNull) { - self._touch(); let repr = MessageRepr::new(self); ptr::write(ptr.cast::>().as_ptr(), repr); } diff --git a/elfo-core/src/message/any.rs b/elfo-core/src/message/any.rs index 42eb95e9..9a8d6f80 100644 --- a/elfo-core/src/message/any.rs +++ b/elfo-core/src/message/any.rs @@ -229,9 +229,6 @@ impl Message for AnyMessage { true } - #[inline(always)] - fn _touch(&self) {} - #[inline(always)] fn _into_any(self) -> AnyMessage { self @@ -431,16 +428,14 @@ impl<'a> AnyMessageRef<'a> { pub fn downcast_ref(&self) -> Option<&'a M> { let ret = self.inner.downcast_ref(); - // SAFETY: we produce lifetime bound to the original one. - // Note: semantically it's shortening not extending. + // SAFETY: we produce lifetime bound to the original `AnyMessage` or `Envelope`. unsafe { mem::transmute::, Option<&'a M>>(ret) } } pub(crate) unsafe fn downcast_ref_unchecked(&self) -> &'a M { let ret = self.inner.downcast_ref_unchecked(); - // SAFETY: we produce lifetime bound to the original one. - // Note: semantically it's shortening not extending. + // SAFETY: we produce lifetime bound to the original `AnyMessage` or `Envelope`. unsafe { mem::transmute::<&M, &'a M>(ret) } } } diff --git a/elfo-core/src/message/repr.rs b/elfo-core/src/message/repr.rs index 4b066f76..138167ef 100644 --- a/elfo-core/src/message/repr.rs +++ b/elfo-core/src/message/repr.rs @@ -1,5 +1,7 @@ use std::{ - alloc, fmt, + alloc, + borrow::Borrow, + fmt, ptr::{self, NonNull}, }; @@ -69,8 +71,9 @@ impl PartialEq for MessageTypeId { #[repr(C)] // It's `pub` only because used in private methods of `AnyMessage`. // Actually, it's not reexported at all. +#[derive(Clone)] #[doc(hidden)] -pub struct MessageRepr { +pub struct MessageRepr { pub(crate) vtable: &'static MessageVTable, pub(crate) data: M, } @@ -88,18 +91,13 @@ impl MessageRepr { } } +// Actually, it's not reexported at all. +#[doc(hidden)] +pub struct Erased; + // Protection against footgun. assert_not_impl_any!(MessageRepr: Clone); -impl Clone for MessageRepr { - fn clone(&self) -> Self { - Self { - vtable: self.vtable, - data: self.data.clone(), - } - } -} - // === MessageVTable === /// Message Virtual Table. @@ -269,28 +267,27 @@ mod vtablefns { #[linkme::distributed_slice] pub static MESSAGE_VTABLES_LIST: [&'static MessageVTable] = [..]; -static MESSAGE_VTABLES_MAP: Lazy> = - Lazy::new(|| { - MESSAGE_VTABLES_LIST - .iter() - .map(|vtable| ((vtable.protocol, vtable.name), *vtable)) - .collect() - }); +#[derive(PartialEq, Eq, Hash)] +pub struct Signature([&'static str; 2]); // [protocol, name] + +impl<'a> Borrow<[&'a str; 2]> for Signature { + fn borrow(&self) -> &[&'a str; 2] { + &self.0 + } +} + +static MESSAGE_VTABLES_MAP: Lazy> = Lazy::new(|| { + MESSAGE_VTABLES_LIST + .iter() + .map(|vtable| (Signature([vtable.protocol, vtable.name]), *vtable)) + .collect() +}); impl MessageVTable { /// Finds a vtable by protocol and name. /// Used for deserialization of `AnyMessage` and in networking. pub(crate) fn lookup(protocol: &str, name: &str) -> Option<&'static Self> { - // Extend lifetimes to static in order to get `(&'static str, &'static str)`. - // SAFETY: this pair doesn't overlive the function. - let (protocol, name) = unsafe { - ( - std::mem::transmute::<&str, &'static str>(protocol), - std::mem::transmute::<&str, &'static str>(name), - ) - }; - - MESSAGE_VTABLES_MAP.get(&(protocol, name)).copied() + MESSAGE_VTABLES_MAP.get(&[protocol, name]).copied() } } diff --git a/elfo-core/src/request_table.rs b/elfo-core/src/request_table.rs index 57444980..afe7bad1 100644 --- a/elfo-core/src/request_table.rs +++ b/elfo-core/src/request_table.rs @@ -251,7 +251,7 @@ impl ResponseToken { #[doc(hidden)] #[inline] - pub fn forget(&mut self) { + pub fn forget(mut self) { self.data = None; } diff --git a/elfo-logger/src/line_transaction.rs b/elfo-logger/src/line_transaction.rs index a353020f..70c0fd2b 100644 --- a/elfo-logger/src/line_transaction.rs +++ b/elfo-logger/src/line_transaction.rs @@ -5,7 +5,7 @@ use super::line_buffer::LineBuffer; /// This is needed due to rust's closure lifetimes binding limitation. Consider, /// for example, the following implementation: /// ```no_compile -/// triat LineFactory<'a>: FnOnce(&'a LineBuffer) -> Self::Line { +/// trait LineFactory<'a>: FnOnce(&'a LineBuffer) -> Self::Line { /// type Line: Line + 'a; /// } /// ``` diff --git a/elfo-macros-impl/src/message.rs b/elfo-macros-impl/src/message.rs index c646cc15..2eab6a0c 100644 --- a/elfo-macros-impl/src/message.rs +++ b/elfo-macros-impl/src/message.rs @@ -215,9 +215,6 @@ pub fn message_impl( fn _vtable(&self) -> &'static #internal::MessageVTable { VTABLE } - - #[inline(never)] - fn _touch(&self) {} } #[#internal::linkme::distributed_slice(#internal::MESSAGE_VTABLES_LIST)] diff --git a/elfo-network/src/worker/mod.rs b/elfo-network/src/worker/mod.rs index 16bea898..f4722145 100644 --- a/elfo-network/src/worker/mod.rs +++ b/elfo-network/src/worker/mod.rs @@ -300,7 +300,7 @@ fn make_network_envelope( (sender, trace_id, payload, token) } // Response - (Ok(envelope), Some(mut token)) => { + (Ok(envelope), Some(token)) => { let sender = envelope.sender(); let trace_id = envelope.trace_id(); let (message, kind) = envelope.unpack::().expect("impossible"); @@ -323,7 +323,7 @@ fn make_network_envelope( (sender, trace_id, payload, None) } // Failed/Ignored Response - (Err(err), Some(mut token)) => { + (Err(err), Some(token)) => { let sender = Addr::NULL; let trace_id = token.trace_id();