-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Wrong Type for ROUTER.add_route callback? #23818
Description
Background
I'm messing around with a typed version of the ipc::router::add_route method.
Original:
pub fn add_route(&self, receiver: OpaqueIpcReceiver, callback: RouterHandler)
// where
pub type RouterHandler = Box<FnMut(OpaqueIpcMessage) + Send>;Mine:
pub fn add_route<T>(&self, receiver: IpcReceiver<T>,
mut callback: Box<FnMut(Result<T, ipc_channel::Error>) + Send>)So I call the OpaqueIpcMessage::to message on behalf of the user, and hide all the implementations details about Opaque*.
When using the typed API I found two places in Servo where I couldn't get it to type check.
Actual Problem
From the latest master unmodified code. I'm looking at the function add_cache_listener_for_element in servo/components/script/dom/htmlimageelement.rs
The relevant parts are:
fn add_cache_listener_for_element(
...
let (responder_sender, responder_receiver) = ipc::channel().unwrap();
...
ROUTER.add_route(responder_receiver.to_opaque(), Box::new(move |message| {
...
let image = message.to().unwrap();
...
element.process_image_response_for_environment_change(image, ...);
...
}));
image_cache.add_listener(id, ImageResponder::new(responder_sender, id));Notice type inference is happening at two relevant places here: The type of channel<T>() and the type of to<T>(). I explicitly add a turbofish to channel:
- let (responder_sender, responder_receiver) = ipc::channel().unwrap();
+ let (responder_sender, responder_receiver) = ipc::channel::<PendingImageResponse>().unwrap();I know this is the correct type from the call to ImageResponder::new(responder_sender, id)); at the bottom which takes the responder_sender: pub fn new(sender: IpcSender<PendingImageResponse>, ...) -> .... The compiler agrees with me, and type checks the program.
Now I try adding the type for the call to .to():
- let image = message.to().unwrap();
+ let image = message.to::<PendingImageResponse>().unwrap();The message comes from the IpcReceiver<T> turned OpaqueReceiver. Which we have established has type PendingImageResponse. However, the way it is being using in the callback:
element.process_image_response_for_environment_change(image, ...);The compiler infers:
--> components/script/dom/htmlimageelement.rs:1012:83
|
1012 | element.process_image_response_for_environment_change(image,
| ^^^^^ expected enum `net_traits::image_cache::ImageResponse`, found struct `net_traits::image_cache::PendingImageResponse`
|
= note: expected type `net_traits::image_cache::ImageResponse`
found type `net_traits::image_cache::PendingImageResponse`
This compiles fine without the added ::<PendingResponse> to to since the compiler infers the type should be ImageResponse. I believe this is wrong, and if this code were to be executed at runtime, the call to to().unwrap() would fail and panic?
Unless I'm missing some implicit conversion between ImageResponse and PendingImageResponse?