using rustc 1.10.0
, i'm trying write code passes around boxed closures--the eventual goal procedurally generate animation of fractals. right have function signatures this:
pub fn interpolate_rectilinear(width: u32, height: u32, mut min_x: f64, mut max_x: f64, mut min_y: f64, mut max_y: f64) -> box<fn(u32, u32) -> complex64 + send + sync + 'static> { ... } pub fn interpolate_stretch(width: u32, height: u32, mut min_x: f64, mut max_x: f64, mut min_y: f64, mut max_y: f64) -> box<fn(u32, u32) -> complex64 + send + sync + 'static> { ... } pub fn parallel_image<f>(width: u32, height: u32, function: &f, interpolate: &box<fn(u32, u32) -> complex64 + send + sync>, threshold: f64) -> imagebuffer<image::luma<u8>, vec<u8>> f: sync + fn(complex64) -> complex64 { ... } pub fn sequential_image<f>(width: u32, height: u32, function: &f, interpolate: &box<fn(u32, u32) -> complex64>, threshold: f64) -> imagebuffer<image::luma<u8>, vec<u8>> f: fn(complex64) -> complex64 { ... }
running code 1 image @ time in binary works without problems:
let interpolate = interpolate_rectilinear(width, height, -1.0, 1.0, -1.0, 1.0); let image = parallel_image(width * 2, height * 2, &default_julia, &interpolate, 2.0);
however, wanted ensure serial , parallel image-production both producing same results, wrote following test function:
#[test] fn test_serial_parallel_agree() { let (width, height) = (200, 200); let threshold = 2.0; let interpolate = interpolate_stretch(width, height, -1.0, 1.0, -1.0, 1.0); assert!(parallel_image(width, height, &default_julia, &interpolate, threshold) .pixels() .zip(sequential_image(width, height, &default_julia, &interpolate, threshold) .pixels()) .all(|(p, s)| p == s)); }
this refuses compile, , can't figure out. error gives follows:
> cargo test compiling julia-set v0.3.0 src/lib.rs:231:66: 231:78 error: mismatched types [e0308] src/lib.rs:231 .zip(sequential_image(width, height, &default_julia, &interpolate, threshold) ^~~~~~~~~~~~ src/lib.rs:229:9: 233:36 note: in expansion of assert! (defined in <std macros>) src/lib.rs:231:66: 231:78 help: run `rustc --explain e0308` see detailed explanation src/lib.rs:231:66: 231:78 note: expected type `&box<std::ops::fn(u32, u32) -> num::complex<f64> + 'static>` src/lib.rs:231:66: 231:78 note: found type `&box<std::ops::fn(u32, u32) -> num::complex<f64> + send + sync>` error: aborting due previous error build failed, waiting other jobs finish... error: not compile `julia-set`.
i don't know what's going on there. don't know why i'm required manually mark send
, sync
in boxed return types of interpolation functions, when compiler typically derives traits automatically. still, kept adding in markers compiler suggested until things worked.
the real problem that, while think have pretty guess why can't mark boxed closure 'static
, don't know what's requiring lifetime in case or how fix it.
i did guess possibly issue was trying reference closure 2 read-borrows @ once, (which should ok, desperate); @ rate, wrapping interpolate
in rc
gives exact same error, wasn't problem.
the problem here:
pub fn sequential_image<f>( ..., interpolate: &box<fn(u32, u32) -> complex64>, ...) -> ...
the interpolate
doesn't expect &box<fn(u32, u32) -> complex64 + send + sync>
, , rust pretty bad @ handling variance through of complexity.
one solution cast it's called:
sequential_image(width, height, &default_julia, &(interpolate box<fn(u32, u32) -> complex64>), threshold)
but requires value case of sequential_image
, pretty damn ugly.
a nicer way fix parameter of sequential_image
both more general , easier compiler reason about: basic pointers.
pub fn sequential_image<f>( ..., interpolate: &fn(u32, u32) -> complex64, ...) -> ...
now can call just
sequential_image(width, height, &default_julia, &*interpolate, threshold)
and compiler can of variance magic itself.
Comments
Post a Comment