Repository: PistonDevelopers/glfw-rs (language: rust)

Issue:
Fix compiler error about callback lifetime
This fixes a compiler error I got after upgrading to the latest Rust version. The commit message contains details about the error.

Please review this extra-carefully. I think I understand what I did there, but I'm not 100% sure :)
I'm especially not sure, if this is the cleanest way to do this.

Anyway, I've tested the examples, and they all still work, as far as I can tell.



Discussion / hints:
We need to eventually use channels for these, but this looks ok to me.

I've pushed the changes you requested.

Awesome! One other thing - could you squash the first three commits into one?

r? @cmr

Your wish is my command :)

Oops, I squashed all of them when you were only asking for the first three. Is this ok or should I try to  fix it?

Never mind. The squashed commits were still around and I redid the squashing.

I don't think this is correct. Using `&'static Cb` means that the callback will never be able to safely keep state. Instead, it should be using `~Cb:'static`. The `'static` bound here means that this trait object can only be created from a type that implements `Cb` but also contains no references that don't have the `'static` lifetime (essentially, it is "deeply owned", in that it has no restrictions on any lifetimes it needs to fulfill).

I tried to change the type according to your suggestion, but it's not the quick fix I hoped it would be:

```
src/lib/callbacks.rs:38:64: 38:74 error: kind bounds can only be used on trait types
src/lib/callbacks.rs:38 pub fn set_error_callback<Cb: ErrorCallback + Send>(callback: ~Cb:'static, f: |ffi::GLFWerrorfun| ) {
                                                                                       ^~~~~~~~~~
error: aborting due to previous error
make: *** [lib] Error 101
```

I don't know how to fix this right now. We've reached depths of Rust's type system that I'm not familiar with :)

I don't have any time left right now. Unless someone else picks this up in the meantime, I'll look into it by Monday.


Fix patch:
diff --git a/src/lib/callbacks.rs b/src/lib/callbacks.rs
index 3623f6ec..453c6453 100644
--- a/src/lib/callbacks.rs
+++ b/src/lib/callbacks.rs
@@ -24,33 +24,33 @@ use super::*;
 
 // Global callbacks
 
-static error_callback_tls_key: local_data::Key<~ErrorCallback> = &local_data::Key;
-static monitor_callback_tls_key: local_data::Key<~MonitorCallback> = &local_data::Key;
+local_data_key!(ERROR_CALLBACK: ~ErrorCallback:'static)
+local_data_key!(MONITOR_CALLBACK: ~MonitorCallback:'static)
 
 pub extern "C" fn error_callback(error: c_int, description: *c_char) {
-    local_data::get(error_callback_tls_key, (|data| {
+    local_data::get(ERROR_CALLBACK, (|data| {
         data.as_ref().map(|&ref cb| {
             unsafe { cb.call(cast::transmute(error), str::raw::from_c_str(description)) }
         });
     }));
 }
 
-pub fn set_error_callback<Cb: ErrorCallback + Send>(callback: ~Cb, f: |ffi::GLFWerrorfun| ) {
-    local_data::set(error_callback_tls_key, callback as ~ErrorCallback);
+pub fn set_error_callback(callback: ~ErrorCallback:'static, f: |ffi::GLFWerrorfun| ) {
+    local_data::set(ERROR_CALLBACK, callback);
     f(error_callback);
 }
 
 
 pub extern "C" fn monitor_callback(monitor: *ffi::GLFWmonitor, event: c_int) {
-    local_data::get(monitor_callback_tls_key, (|data| {
+    local_data::get(MONITOR_CALLBACK, (|data| {
         data.as_ref().map(|&ref cb| {
             unsafe { cb.call(&Monitor { ptr: monitor }, cast::transmute(event)) }
         });
     }));
 }
 
-pub fn set_monitor_callback<Cb: MonitorCallback + Send>(callback: ~Cb, f: |ffi::GLFWmonitorfun| ) {
-    local_data::set(monitor_callback_tls_key, callback as ~MonitorCallback);
+pub fn set_monitor_callback(callback: ~MonitorCallback:'static, f: |ffi::GLFWmonitorfun| ) {
+    local_data::set(MONITOR_CALLBACK, callback);
     f(monitor_callback);
 }
 
diff --git a/src/lib/lib.rs b/src/lib/lib.rs
index e5420c6c..69d6a85b 100644
--- a/src/lib/lib.rs
+++ b/src/lib/lib.rs
@@ -320,7 +320,7 @@ pub fn get_version_string() -> ~str {
 pub trait ErrorCallback { fn call(&self, error: Error, description: ~str); }
 
 /// Wrapper for `glfwSetErrorCallback`.
-pub fn set_error_callback<Cb: ErrorCallback + Send>(callback: ~Cb) {
+pub fn set_error_callback(callback: ~ErrorCallback:'static) {
     callbacks::set_error_callback(callback, (|ext_cb| {
         unsafe { ffi::glfwSetErrorCallback(Some(ext_cb)); }
     }));
@@ -389,7 +389,7 @@ impl Monitor {
     }
 
     /// Wrapper for `glfwSetMonitorCallback`.
-    pub fn set_callback<Cb: MonitorCallback + Send>(callback: ~Cb) {
+    pub fn set_callback(callback: ~MonitorCallback:'static) {
         callbacks::set_monitor_callback(callback, (|ext_cb| {
             unsafe { ffi::glfwSetMonitorCallback(Some(ext_cb)); }
         }));


Test patch: