-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove unnecessary Clone
requirement
#136
Comments
I believe these are separate issues. We're not deriving Backing up a second, this crate works by emitting macros, which themselves contain inline assembly. That ASM does very little other than store the macro arguments, or a pointer to them, in a few registers. This is pretty great, but that's a lot of casting and pointer shenanigans that is about as unsafe as it gets in Rust. To ensure that the macros are called with valid arguments, we create a small closure that returns the probe macro arguments. The emitted macros in turn attempt to use those arguments in a function with the same types as the probe arguments -- a call site that will fail at compile time, regardless of whether it's ever issued at runtime. This may all be quite abstract, so here's an example. Below is a small snippet of the fn main() {
{
let __usdt_private_args_lambda = || (0, "something");
#[allow(unused_imports)]
#[allow(non_snake_case)]
fn __usdt_private_doesit_work_type_check(
_: impl ::std::borrow::Borrow<u8>,
_: impl AsRef<str>,
) {
}
let _ = || {
let args = __usdt_private_args_lambda.clone()();
__usdt_private_doesit_work_type_check(args.0, args.1);
};
// Remainder omitted So first, we see the closure Why are we doing this? First, we wanted type checking of some kind. Second, we require that the arguments be passed to the macros themselves as a closure. The reason for that is to emphasize the conditional nature of the probes -- they only fire when they're enabled, and so whatever code is used to generate the arguments will only run when they're enabled. So we needed a way to take a lambda and verify that its returned values are the right type, without ever evaluating it. And this approach is where we landed. Looking at this for the first time in several years, it does seem plausible that we could relax the bound. We unpack the arguments inside the probe macro in order to pass them in registers. One could do the same type-checked-but-never-called trick at the call site. It's not obvious to me if that would work, though one could try. That would be here, in the if is_enabled != 0 {
let args = __usdt_private_args_lambda();
let arg_0 = (*<_ as ::std::borrow::Borrow<u8>>::borrow(&args.0) as i64);
let arg_1 = [(args.1.as_ref() as &str).as_bytes(), &[0_u8]].concat();
// Could insert type check call here possibly.
// The typecheck function would need to take refs to the args, or we need Clone anyway. In any case, it's never really been an issue that the types must implement |
Hey, thanks for the thorough response! This is very interesting stuff. It does seem to me like the forced-typechecking implementation could relax the So thanks for the time! If I have any further questions I'll happily reach out 😄 |
- Rework construction of the internal type-checking function to remove the clone requirement. Construct and call the type-check-function right at the site we already expand the probe argument closure, rather than outside. This means we don't need to expand things twice, and don't need to clone the closure, and so don't need the argument types to be cloneable either. - Fixup tests for new method, add some comments. - Update trybuild tests - Closes #136
- Rework construction of the internal type-checking function to remove the clone requirement. Construct and call the type-check-function right at the site we already expand the probe argument closure, rather than outside. This means we don't need to expand things twice, and don't need to clone the closure, and so don't need the argument types to be cloneable either. - Fixup tests for new method, add some comments. - Update trybuild tests - Closes #136
- Rework construction of the internal type-checking function to remove the clone requirement. Construct and call the type-check-function right at the site we already expand the probe argument closure, rather than outside. This means we don't need to expand things twice, and don't need to clone the closure, and so don't need the argument types to be cloneable either. - Fixup tests for new method, add some comments. - Update trybuild tests - Closes #136
- Rework construction of the internal type-checking function to remove the clone requirement. Construct and call the type-check-function right at the site we already expand the probe argument closure, rather than outside. This means we don't need to expand things twice, and don't need to clone the closure, and so don't need the argument types to be cloneable either. - Fixup tests for new method, add some comments. - Update trybuild tests - Closes #136
- Rework construction of the internal type-checking function to remove the clone requirement. Construct and call the type-check-function right at the site we already expand the probe argument closure, rather than outside. This means we don't need to expand things twice, and don't need to clone the closure, and so don't need the argument types to be cloneable either. - Fixup tests for new method, add some comments. - Update trybuild tests - Closes #136
- Rework construction of the internal type-checking function to remove the clone requirement. Construct and call the type-check-function right at the site we already expand the probe argument closure, rather than outside. This means we don't need to expand things twice, and don't need to clone the closure, and so don't need the argument types to be cloneable either. - Fixup tests for new method, add some comments. - Update trybuild tests - Closes #136
- Rework construction of the internal type-checking function to remove the clone requirement. Construct and call the type-check-function right at the site we already expand the probe argument closure, rather than outside. This means we don't need to expand things twice, and don't need to clone the closure, and so don't need the argument types to be cloneable either. - Fixup tests for new method, add some comments. - Update trybuild tests - Closes #136
- Rework construction of the internal type-checking function to remove the clone requirement. Construct and call the type-check-function right at the site we already expand the probe argument closure, rather than outside. This means we don't need to expand things twice, and don't need to clone the closure, and so don't need the argument types to be cloneable either. - Fixup tests for new method, add some comments. - Update trybuild tests - Closes #136
- Rework construction of the internal type-checking function to remove the clone requirement. Construct and call the type-check-function right at the site we already expand the probe argument closure, rather than outside. This means we don't need to expand things twice, and don't need to clone the closure, and so don't need the argument types to be cloneable either. - Fixup tests for new method, add some comments. - Update trybuild tests - Closes #136
The docs mention a
Clone
requirement on arbitrary serializable types you'd like to include in a probe, and specifically mentions that the data involved is never actually cloned.I wonder if the issue is similar to the one the
sqlx
project had for theirPoolOptions
type (see: launchbadge/sqlx#2553), where aClone
derive on a type which involvesT
in a generic manner results in an excessiveClone
requirement on it even though the data is never actually cloned. In this case, the solution was to manually implementClone
on the containing type, as shown in the linked pull request.It's possible this isn't the cause (I haven't yet dug into the code to see), but reading the docs triggered my feeling that it might be a similar issue. I'm happy to tinker (with some guidance on the right place to look) to see if I can remove the
Clone
requirement!The text was updated successfully, but these errors were encountered: