dtolnay / linkme

Safe cross-platform linker shenanigans
Apache License 2.0
628 stars 42 forks source link

Recognize distributed_slice on functions as a special case #24

Closed dtolnay closed 4 years ago

dtolnay commented 4 years ago

Building registries of function pointers is probably the most common use case for distributed_slice.

The benchmark harness use case in the readme is one example, or the following registry of error type conversions for crates to register semantically meaningful conversions into Python errors for their custom error types.

use cpython::{exc, PyErr, Python};
use distributed_slice::distributed_slice;
use std::io;

#[distributed_slice]
pub static INTO_PYERR: [fn(&anyhow::Error, py: Python<'_>) -> Option<PyErr>] = [..];

#[distributed_slice(INTO_PYERR)]
static IO_INTO_PYERR: fn(&anyhow::Error, py: Python<'_>) -> Option<PyErr> = io_into_pyerr;

fn io_into_pyerr(err: &anyhow::Error, py: Python<'_>) -> Option<PyErr> {
    let err = err.downcast_ref::<io::Error>()?;
    Some(PyErr::new::<exc::IOError, _>(
        py,
        (e.raw_os_error(), e.to_string()),
    ))
}

It would be great to handle function pointers as a special case in our attribute macro to allow this more concise invocation:

#[distributed_slice(INTO_PYERR)]
fn io_into_pyerr(err: &anyhow::Error, py: Python<'_>) -> Option<PyErr> {
    ...
}

which would expand to the pair of IO_INTO_PYERR static + io_into_pyerr function as above.