Allow lifetime in extern fn signature
diff --git a/syntax/check.rs b/syntax/check.rs
index 7e368f4..9aaf738 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -147,10 +147,6 @@
}
fn check_type_ref(cx: &mut Check, ty: &Ref) {
- if ty.lifetime.is_some() {
- cx.error(ty, "references with explicit lifetimes are not supported");
- }
-
if ty.mutability.is_some() && !ty.pinned {
if let Some(requires_pin) = match &ty.inner {
Type::Ident(ident) if ident.rust == CxxString || is_opaque_cxx(cx, &ident.rust) => {
@@ -249,6 +245,25 @@
}
fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
+ match efn.lang {
+ Lang::Cxx => {
+ if !efn.generics.params.is_empty() && !efn.trusted {
+ let ref span = span_for_generics_error(efn);
+ cx.error(span, "extern C++ function with lifetimes must be declared in `unsafe extern \"C++\"` block");
+ }
+ }
+ Lang::Rust => {
+ if !efn.generics.params.is_empty() && efn.unsafety.is_none() {
+ let ref span = span_for_generics_error(efn);
+ let message = format!(
+ "must be `unsafe fn {}` in order to expose explicit lifetimes to C++",
+ efn.name.rust,
+ );
+ cx.error(span, message);
+ }
+ }
+ }
+
if let Some(receiver) = &efn.receiver {
let ref span = span_for_receiver_error(receiver);
@@ -281,10 +296,6 @@
),
);
}
-
- if receiver.lifetime.is_some() {
- cx.error(span, "references with explicit lifetimes are not supported");
- }
}
for arg in &efn.args {
@@ -436,6 +447,13 @@
}
}
+fn span_for_generics_error(efn: &ExternFn) -> TokenStream {
+ let unsafety = efn.unsafety;
+ let fn_token = efn.fn_token;
+ let generics = &efn.generics;
+ quote!(#unsafety #fn_token #generics)
+}
+
fn describe(cx: &mut Check, ty: &Type) -> String {
match ty {
Type::Ident(ident) => {