Store independent rust name and c++ name for extern functions

This commit is contained in:
David Tolnay 2020-09-08 14:05:53 -07:00
parent f3a9afae50
commit a4641c738a
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
8 changed files with 43 additions and 30 deletions

View File

@ -370,7 +370,7 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
for method in methods {
write!(out, " ");
let sig = &method.sig;
let local_name = method.ident.to_string();
let local_name = method.ident.cxx.to_string();
write_rust_function_shim_decl(out, &local_name, sig, false);
writeln!(out, ";");
}
@ -517,8 +517,8 @@ fn write_cxx_function_shim(
write!(out, " ");
write_return_type(out, &efn.ret);
match &efn.receiver {
None => write!(out, "(*{}$)(", efn.ident),
Some(receiver) => write!(out, "({}::*{}$)(", receiver.ty, efn.ident),
None => write!(out, "(*{}$)(", efn.ident.rust),
Some(receiver) => write!(out, "({}::*{}$)(", receiver.ty, efn.ident.rust),
}
for (i, arg) in efn.args.iter().enumerate() {
if i > 0 {
@ -534,8 +534,8 @@ fn write_cxx_function_shim(
}
write!(out, " = ");
match &efn.receiver {
None => write!(out, "{}", efn.ident),
Some(receiver) => write!(out, "&{}::{}", receiver.ty, efn.ident),
None => write!(out, "{}", efn.ident.cxx),
Some(receiver) => write!(out, "&{}::{}", receiver.ty, efn.ident.cxx),
}
writeln!(out, ";");
write!(out, " ");
@ -562,8 +562,8 @@ fn write_cxx_function_shim(
_ => {}
}
match &efn.receiver {
None => write!(out, "{}$(", efn.ident),
Some(_) => write!(out, "(self.*{}$)(", efn.ident),
None => write!(out, "{}$(", efn.ident.rust),
Some(_) => write!(out, "(self.*{}$)(", efn.ident.rust),
}
for (i, arg) in efn.args.iter().enumerate() {
if i > 0 {
@ -697,8 +697,8 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
writeln!(out, "//{}", line);
}
let local_name = match &efn.sig.receiver {
None => efn.ident.to_string(),
Some(receiver) => format!("{}::{}", receiver.ty, efn.ident),
None => efn.ident.cxx.to_string(),
Some(receiver) => format!("{}::{}", receiver.ty, efn.ident.cxx),
};
let invoke = mangle::extern_fn(&out.namespace, efn);
let indirect_call = false;

View File

@ -206,7 +206,6 @@ fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
}
fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
let ident = &efn.ident;
let receiver = efn.receiver.iter().map(|receiver| {
let receiver_type = receiver.ty();
quote!(_: #receiver_type)
@ -238,7 +237,7 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
outparam = Some(quote!(__return: *mut #ret));
}
let link_name = mangle::extern_fn(namespace, efn);
let local_name = format_ident!("__{}", ident);
let local_name = format_ident!("__{}", efn.ident.rust);
quote! {
#[link_name = #link_name]
fn #local_name(#(#all_args,)* #outparam) #ret;
@ -246,7 +245,6 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
}
fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
let ident = &efn.ident;
let doc = &efn.doc;
let decl = expand_cxx_function_decl(namespace, efn, types);
let receiver = efn.receiver.iter().map(|receiver| {
@ -329,7 +327,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
}
})
.collect::<TokenStream>();
let local_name = format_ident!("__{}", ident);
let local_name = format_ident!("__{}", efn.ident.rust);
let call = if indirect_return {
let ret = expand_extern_type(efn.ret.as_ref().unwrap());
setup.extend(quote! {
@ -426,6 +424,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
if unsafety.is_none() {
dispatch = quote!(unsafe { #dispatch });
}
let ident = &efn.ident.rust;
let function_shim = quote! {
#doc
pub #unsafety fn #ident(#(#all_args,)*) #ret {
@ -455,7 +454,7 @@ fn expand_function_pointer_trampoline(
let c_trampoline = mangle::c_trampoline(namespace, efn, var);
let r_trampoline = mangle::r_trampoline(namespace, efn, var);
let local_name = parse_quote!(__);
let catch_unwind_label = format!("::{}::{}", efn.ident, var);
let catch_unwind_label = format!("::{}::{}", efn.ident.rust, var);
let shim = expand_rust_function_shim_impl(
sig,
types,
@ -510,11 +509,10 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
}
fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
let ident = &efn.ident;
let link_name = mangle::extern_fn(namespace, efn);
let local_name = format_ident!("__{}", ident);
let catch_unwind_label = format!("::{}", ident);
let invoke = Some(ident);
let local_name = format_ident!("__{}", efn.ident.rust);
let catch_unwind_label = format!("::{}", efn.ident.rust);
let invoke = Some(&efn.ident.rust);
expand_rust_function_shim_impl(
efn,
types,

View File

@ -214,8 +214,8 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
if let Some(reason) = cx.types.required_trivial.get(&ety.ident) {
let what = match reason {
TrivialReason::StructField(strct) => format!("a field of `{}`", strct.ident),
TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident),
TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.ident),
TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident.rust),
TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.ident.rust),
};
let msg = format!(
"needs a cxx::ExternType impl in order to be used as {}",

View File

@ -37,7 +37,7 @@ pub(crate) fn check_all(cx: &mut Check, namespace: &Namespace, apis: &[Api]) {
check(cx, &ety.ident);
}
Api::CxxFunction(efn) | Api::RustFunction(efn) => {
check(cx, &efn.ident);
check(cx, &efn.ident.rust);
for arg in &efn.args {
check(cx, &arg.ident);
}

View File

@ -13,8 +13,8 @@ macro_rules! join {
pub fn extern_fn(namespace: &Namespace, efn: &ExternFn) -> Symbol {
match &efn.receiver {
Some(receiver) => join!(namespace, CXXBRIDGE, receiver.ty, efn.ident),
None => join!(namespace, CXXBRIDGE, efn.ident),
Some(receiver) => join!(namespace, CXXBRIDGE, receiver.ty, efn.ident.rust),
None => join!(namespace, CXXBRIDGE, efn.ident.rust),
}
}

View File

@ -71,10 +71,15 @@ pub struct Enum {
pub repr: Atom,
}
pub struct Pair {
pub cxx: Ident,
pub rust: Ident,
}
pub struct ExternFn {
pub lang: Lang,
pub doc: Doc,
pub ident: Ident,
pub ident: Pair,
pub sig: Signature,
pub semi_token: Token![;],
}

View File

@ -3,7 +3,7 @@ use crate::syntax::file::{Item, ItemForeignMod};
use crate::syntax::report::Errors;
use crate::syntax::Atom::*;
use crate::syntax::{
attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Lang, Pair, Receiver, Ref, Signature,
Slice, Struct, Ty1, Type, TypeAlias, Var, Variant,
};
use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
@ -370,7 +370,10 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
Ok(api_function(ExternFn {
lang,
doc,
ident,
ident: Pair {
cxx: ident.clone(),
rust: ident,
},
sig: Signature {
unsafety,
fn_token,

View File

@ -51,7 +51,8 @@ impl<'a> Types<'a> {
}
let mut type_names = UnorderedSet::new();
let mut function_names = UnorderedSet::new();
let mut cxx_function_names = UnorderedSet::new();
let mut rust_function_names = UnorderedSet::new();
for api in apis {
// The same identifier is permitted to be declared as both a shared
// enum and extern C++ type, or shared struct and extern C++ type.
@ -116,9 +117,15 @@ impl<'a> Types<'a> {
rust.insert(ident);
}
Api::CxxFunction(efn) | Api::RustFunction(efn) => {
let ident = &efn.ident;
if !function_names.insert((&efn.receiver, ident)) {
duplicate_name(cx, efn, ident);
let cxx_fn = (&efn.receiver, &efn.ident.cxx);
let rust_fn = (&efn.receiver, &efn.ident.rust);
let cxx_duplicate = !cxx_function_names.insert(cxx_fn);
if !rust_function_names.insert(rust_fn) {
duplicate_name(cx, efn, &efn.ident.rust);
} else if cxx_duplicate {
// Insert into cxx_function_names either way, but hide
// error if we're already erroring on the rust name.
duplicate_name(cx, efn, &efn.ident.cxx);
}
for arg in &efn.args {
visit(&mut all, &arg.ty);