Skip to content
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

Undeclared lifetime when function pointer argument contains lifetime from extern signature #739

Closed
dtolnay opened this issue Mar 17, 2021 · 1 comment · Fixed by #828
Closed
Labels

Comments

@dtolnay
Copy link
Owner

dtolnay commented Mar 17, 2021

Repro:

// src/main.rs

#[cxx::bridge]
mod ffi {
    unsafe extern "C++" {
        include!("example/include/header.h");

        fn call_back<'a>(i: &'a i32, f: fn(&'a i32));
    }
}

fn main() {
    let i = 0i32;
    ffi::call_back(&i, |_| {});
}
// include/header.h

#pragma once
#include "rust/cxx.h"

inline void call_back(const int32_t &i, rust::Fn<void(const int32_t &)> f) {
  f(i);
}
error[E0261]: use of undeclared lifetime name `'a`
 --> src/main.rs:6:45
  |
1 | #[cxx::bridge]
  |               - lifetime `'a` is missing in item created through this procedural macro
...
6 |         fn call_back<'a>(i: &'a i32, f: fn(&'a i32));
  |                                             ^^ undeclared lifetime
  |
  = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
  = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
help: consider making the type lifetime-generic with a new `'a` lifetime
  |
6 |         fn call_back<'a>(i: &'a i32, f: for<'a> fn(&'a i32));
  |                                         ^^^^^^^
@dtolnay dtolnay added the bug label Mar 17, 2021
@dtolnay
Copy link
Owner Author

dtolnay commented Mar 17, 2021

The code being generated looks like:

pub fn call_back<'a>(i: &'a i32, f: fn(arg0: &'a i32)) {
    extern "C" {
        #[link_name = "cxxbridge1$call_back"]
        fn __call_back<'a>(i: &'a i32, f: ::cxx::private::FatFunction);
    }
    let f = ::cxx::private::FatFunction {
        trampoline: {
            extern "C" {
                #[link_name = "cxxbridge1$call_back$f$0"]
                fn trampoline();
            }
            #[doc(hidden)]
            #[export_name = "cxxbridge1$call_back$f$1"]
            unsafe extern "C" fn __(arg0: &'a i32, __extern: *const ()) {
                let __fn = "example::ffi::call_back::f";
                ::cxx::private::catch_unwind(__fn, move || {
                    ::std::mem::transmute::<*const (), fn(arg0: &'a i32)>(__extern)(arg0)
                })
            }
            trampoline as usize as *const ()
        },
        ptr: f as usize as *const (),
    };
    unsafe { __call_back(i, f) }
}

where the bug is that 'a is undeclared on the line starting with unsafe extern "C" fn.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant