133d722a9Sopenharmony_ciuse crate::syntax::atom::Atom::{self, *}; 233d722a9Sopenharmony_ciuse crate::syntax::report::Errors; 333d722a9Sopenharmony_ciuse crate::syntax::visit::{self, Visit}; 433d722a9Sopenharmony_ciuse crate::syntax::{ 533d722a9Sopenharmony_ci error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Lifetimes, 633d722a9Sopenharmony_ci NamedType, Ptr, Receiver, Ref, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types, 733d722a9Sopenharmony_ci}; 833d722a9Sopenharmony_ciuse proc_macro2::{Delimiter, Group, Ident, TokenStream}; 933d722a9Sopenharmony_ciuse quote::{quote, ToTokens}; 1033d722a9Sopenharmony_ciuse std::fmt::Display; 1133d722a9Sopenharmony_ciuse syn::{GenericParam, Generics, Lifetime}; 1233d722a9Sopenharmony_ci 1333d722a9Sopenharmony_cipub(crate) struct Check<'a> { 1433d722a9Sopenharmony_ci apis: &'a [Api], 1533d722a9Sopenharmony_ci types: &'a Types<'a>, 1633d722a9Sopenharmony_ci errors: &'a mut Errors, 1733d722a9Sopenharmony_ci generator: Generator, 1833d722a9Sopenharmony_ci} 1933d722a9Sopenharmony_ci 2033d722a9Sopenharmony_cipub(crate) enum Generator { 2133d722a9Sopenharmony_ci // cxx-build crate, cxxbridge cli, cxx-gen. 2233d722a9Sopenharmony_ci #[allow(dead_code)] 2333d722a9Sopenharmony_ci Build, 2433d722a9Sopenharmony_ci // cxxbridge-macro. This is relevant in that the macro output is going to 2533d722a9Sopenharmony_ci // get fed straight to rustc, so for errors that rustc already contains 2633d722a9Sopenharmony_ci // logic to catch (probably with a better diagnostic than what the proc 2733d722a9Sopenharmony_ci // macro API is able to produce), we avoid duplicating them in our own 2833d722a9Sopenharmony_ci // diagnostics. 2933d722a9Sopenharmony_ci #[allow(dead_code)] 3033d722a9Sopenharmony_ci Macro, 3133d722a9Sopenharmony_ci} 3233d722a9Sopenharmony_ci 3333d722a9Sopenharmony_cipub(crate) fn typecheck(cx: &mut Errors, apis: &[Api], types: &Types, generator: Generator) { 3433d722a9Sopenharmony_ci do_typecheck(&mut Check { 3533d722a9Sopenharmony_ci apis, 3633d722a9Sopenharmony_ci types, 3733d722a9Sopenharmony_ci errors: cx, 3833d722a9Sopenharmony_ci generator, 3933d722a9Sopenharmony_ci }); 4033d722a9Sopenharmony_ci} 4133d722a9Sopenharmony_ci 4233d722a9Sopenharmony_cifn do_typecheck(cx: &mut Check) { 4333d722a9Sopenharmony_ci ident::check_all(cx, cx.apis); 4433d722a9Sopenharmony_ci 4533d722a9Sopenharmony_ci for ty in cx.types { 4633d722a9Sopenharmony_ci match ty { 4733d722a9Sopenharmony_ci Type::Ident(ident) => check_type_ident(cx, ident), 4833d722a9Sopenharmony_ci Type::RustBox(ptr) => check_type_box(cx, ptr), 4933d722a9Sopenharmony_ci Type::RustVec(ty) => check_type_rust_vec(cx, ty), 5033d722a9Sopenharmony_ci Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr), 5133d722a9Sopenharmony_ci Type::SharedPtr(ptr) => check_type_shared_ptr(cx, ptr), 5233d722a9Sopenharmony_ci Type::WeakPtr(ptr) => check_type_weak_ptr(cx, ptr), 5333d722a9Sopenharmony_ci Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr), 5433d722a9Sopenharmony_ci Type::Ref(ty) => check_type_ref(cx, ty), 5533d722a9Sopenharmony_ci Type::Ptr(ty) => check_type_ptr(cx, ty), 5633d722a9Sopenharmony_ci Type::Array(array) => check_type_array(cx, array), 5733d722a9Sopenharmony_ci Type::Fn(ty) => check_type_fn(cx, ty), 5833d722a9Sopenharmony_ci Type::SliceRef(ty) => check_type_slice_ref(cx, ty), 5933d722a9Sopenharmony_ci Type::Str(_) | Type::Void(_) => {} 6033d722a9Sopenharmony_ci } 6133d722a9Sopenharmony_ci } 6233d722a9Sopenharmony_ci 6333d722a9Sopenharmony_ci for api in cx.apis { 6433d722a9Sopenharmony_ci match api { 6533d722a9Sopenharmony_ci Api::Include(_) => {} 6633d722a9Sopenharmony_ci Api::Struct(strct) => check_api_struct(cx, strct), 6733d722a9Sopenharmony_ci Api::Enum(enm) => check_api_enum(cx, enm), 6833d722a9Sopenharmony_ci Api::CxxType(ety) | Api::RustType(ety) => check_api_type(cx, ety), 6933d722a9Sopenharmony_ci Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(cx, efn), 7033d722a9Sopenharmony_ci Api::TypeAlias(alias) => check_api_type_alias(cx, alias), 7133d722a9Sopenharmony_ci Api::Impl(imp) => check_api_impl(cx, imp), 7233d722a9Sopenharmony_ci } 7333d722a9Sopenharmony_ci } 7433d722a9Sopenharmony_ci} 7533d722a9Sopenharmony_ci 7633d722a9Sopenharmony_ciimpl Check<'_> { 7733d722a9Sopenharmony_ci pub(crate) fn error(&mut self, sp: impl ToTokens, msg: impl Display) { 7833d722a9Sopenharmony_ci self.errors.error(sp, msg); 7933d722a9Sopenharmony_ci } 8033d722a9Sopenharmony_ci} 8133d722a9Sopenharmony_ci 8233d722a9Sopenharmony_cifn check_type_ident(cx: &mut Check, name: &NamedType) { 8333d722a9Sopenharmony_ci let ident = &name.rust; 8433d722a9Sopenharmony_ci if Atom::from(ident).is_none() 8533d722a9Sopenharmony_ci && !cx.types.structs.contains_key(ident) 8633d722a9Sopenharmony_ci && !cx.types.enums.contains_key(ident) 8733d722a9Sopenharmony_ci && !cx.types.cxx.contains(ident) 8833d722a9Sopenharmony_ci && !cx.types.rust.contains(ident) 8933d722a9Sopenharmony_ci { 9033d722a9Sopenharmony_ci let msg = format!("unsupported type: {}", ident); 9133d722a9Sopenharmony_ci cx.error(ident, msg); 9233d722a9Sopenharmony_ci } 9333d722a9Sopenharmony_ci} 9433d722a9Sopenharmony_ci 9533d722a9Sopenharmony_cifn check_type_box(cx: &mut Check, ptr: &Ty1) { 9633d722a9Sopenharmony_ci if let Type::Ident(ident) = &ptr.inner { 9733d722a9Sopenharmony_ci if cx.types.cxx.contains(&ident.rust) 9833d722a9Sopenharmony_ci && !cx.types.aliases.contains_key(&ident.rust) 9933d722a9Sopenharmony_ci && !cx.types.structs.contains_key(&ident.rust) 10033d722a9Sopenharmony_ci && !cx.types.enums.contains_key(&ident.rust) 10133d722a9Sopenharmony_ci { 10233d722a9Sopenharmony_ci cx.error(ptr, error::BOX_CXX_TYPE.msg); 10333d722a9Sopenharmony_ci } 10433d722a9Sopenharmony_ci 10533d722a9Sopenharmony_ci if Atom::from(&ident.rust).is_none() { 10633d722a9Sopenharmony_ci return; 10733d722a9Sopenharmony_ci } 10833d722a9Sopenharmony_ci } 10933d722a9Sopenharmony_ci 11033d722a9Sopenharmony_ci cx.error(ptr, "unsupported target type of Box"); 11133d722a9Sopenharmony_ci} 11233d722a9Sopenharmony_ci 11333d722a9Sopenharmony_cifn check_type_rust_vec(cx: &mut Check, ty: &Ty1) { 11433d722a9Sopenharmony_ci match &ty.inner { 11533d722a9Sopenharmony_ci Type::Ident(ident) => { 11633d722a9Sopenharmony_ci if cx.types.cxx.contains(&ident.rust) 11733d722a9Sopenharmony_ci && !cx.types.aliases.contains_key(&ident.rust) 11833d722a9Sopenharmony_ci && !cx.types.structs.contains_key(&ident.rust) 11933d722a9Sopenharmony_ci && !cx.types.enums.contains_key(&ident.rust) 12033d722a9Sopenharmony_ci { 12133d722a9Sopenharmony_ci cx.error(ty, "Rust Vec containing C++ type is not supported yet"); 12233d722a9Sopenharmony_ci return; 12333d722a9Sopenharmony_ci } 12433d722a9Sopenharmony_ci 12533d722a9Sopenharmony_ci match Atom::from(&ident.rust) { 12633d722a9Sopenharmony_ci None | Some(Bool) | Some(Char) | Some(U8) | Some(U16) | Some(U32) | Some(U64) 12733d722a9Sopenharmony_ci | Some(Usize) | Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) 12833d722a9Sopenharmony_ci | Some(F32) | Some(F64) | Some(RustString) => return, 12933d722a9Sopenharmony_ci Some(CxxString) => {} 13033d722a9Sopenharmony_ci } 13133d722a9Sopenharmony_ci } 13233d722a9Sopenharmony_ci Type::Str(_) => return, 13333d722a9Sopenharmony_ci _ => {} 13433d722a9Sopenharmony_ci } 13533d722a9Sopenharmony_ci 13633d722a9Sopenharmony_ci cx.error(ty, "unsupported element type of Vec"); 13733d722a9Sopenharmony_ci} 13833d722a9Sopenharmony_ci 13933d722a9Sopenharmony_cifn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) { 14033d722a9Sopenharmony_ci if let Type::Ident(ident) = &ptr.inner { 14133d722a9Sopenharmony_ci if cx.types.rust.contains(&ident.rust) { 14233d722a9Sopenharmony_ci cx.error(ptr, "unique_ptr of a Rust type is not supported yet"); 14333d722a9Sopenharmony_ci return; 14433d722a9Sopenharmony_ci } 14533d722a9Sopenharmony_ci 14633d722a9Sopenharmony_ci match Atom::from(&ident.rust) { 14733d722a9Sopenharmony_ci None | Some(CxxString) => return, 14833d722a9Sopenharmony_ci _ => {} 14933d722a9Sopenharmony_ci } 15033d722a9Sopenharmony_ci } else if let Type::CxxVector(_) = &ptr.inner { 15133d722a9Sopenharmony_ci return; 15233d722a9Sopenharmony_ci } 15333d722a9Sopenharmony_ci 15433d722a9Sopenharmony_ci cx.error(ptr, "unsupported unique_ptr target type"); 15533d722a9Sopenharmony_ci} 15633d722a9Sopenharmony_ci 15733d722a9Sopenharmony_cifn check_type_shared_ptr(cx: &mut Check, ptr: &Ty1) { 15833d722a9Sopenharmony_ci if let Type::Ident(ident) = &ptr.inner { 15933d722a9Sopenharmony_ci if cx.types.rust.contains(&ident.rust) { 16033d722a9Sopenharmony_ci cx.error(ptr, "shared_ptr of a Rust type is not supported yet"); 16133d722a9Sopenharmony_ci return; 16233d722a9Sopenharmony_ci } 16333d722a9Sopenharmony_ci 16433d722a9Sopenharmony_ci match Atom::from(&ident.rust) { 16533d722a9Sopenharmony_ci None | Some(Bool) | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) 16633d722a9Sopenharmony_ci | Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) 16733d722a9Sopenharmony_ci | Some(F64) | Some(CxxString) => return, 16833d722a9Sopenharmony_ci Some(Char) | Some(RustString) => {} 16933d722a9Sopenharmony_ci } 17033d722a9Sopenharmony_ci } else if let Type::CxxVector(_) = &ptr.inner { 17133d722a9Sopenharmony_ci cx.error(ptr, "std::shared_ptr<std::vector> is not supported yet"); 17233d722a9Sopenharmony_ci return; 17333d722a9Sopenharmony_ci } 17433d722a9Sopenharmony_ci 17533d722a9Sopenharmony_ci cx.error(ptr, "unsupported shared_ptr target type"); 17633d722a9Sopenharmony_ci} 17733d722a9Sopenharmony_ci 17833d722a9Sopenharmony_cifn check_type_weak_ptr(cx: &mut Check, ptr: &Ty1) { 17933d722a9Sopenharmony_ci if let Type::Ident(ident) = &ptr.inner { 18033d722a9Sopenharmony_ci if cx.types.rust.contains(&ident.rust) { 18133d722a9Sopenharmony_ci cx.error(ptr, "weak_ptr of a Rust type is not supported yet"); 18233d722a9Sopenharmony_ci return; 18333d722a9Sopenharmony_ci } 18433d722a9Sopenharmony_ci 18533d722a9Sopenharmony_ci match Atom::from(&ident.rust) { 18633d722a9Sopenharmony_ci None | Some(Bool) | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) 18733d722a9Sopenharmony_ci | Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) 18833d722a9Sopenharmony_ci | Some(F64) | Some(CxxString) => return, 18933d722a9Sopenharmony_ci Some(Char) | Some(RustString) => {} 19033d722a9Sopenharmony_ci } 19133d722a9Sopenharmony_ci } else if let Type::CxxVector(_) = &ptr.inner { 19233d722a9Sopenharmony_ci cx.error(ptr, "std::weak_ptr<std::vector> is not supported yet"); 19333d722a9Sopenharmony_ci return; 19433d722a9Sopenharmony_ci } 19533d722a9Sopenharmony_ci 19633d722a9Sopenharmony_ci cx.error(ptr, "unsupported weak_ptr target type"); 19733d722a9Sopenharmony_ci} 19833d722a9Sopenharmony_ci 19933d722a9Sopenharmony_cifn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) { 20033d722a9Sopenharmony_ci if let Type::Ident(ident) = &ptr.inner { 20133d722a9Sopenharmony_ci if cx.types.rust.contains(&ident.rust) { 20233d722a9Sopenharmony_ci cx.error( 20333d722a9Sopenharmony_ci ptr, 20433d722a9Sopenharmony_ci "C++ vector containing a Rust type is not supported yet", 20533d722a9Sopenharmony_ci ); 20633d722a9Sopenharmony_ci return; 20733d722a9Sopenharmony_ci } 20833d722a9Sopenharmony_ci 20933d722a9Sopenharmony_ci match Atom::from(&ident.rust) { 21033d722a9Sopenharmony_ci None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8) 21133d722a9Sopenharmony_ci | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64) 21233d722a9Sopenharmony_ci | Some(CxxString) => return, 21333d722a9Sopenharmony_ci Some(Char) => { /* todo */ } 21433d722a9Sopenharmony_ci Some(Bool) | Some(RustString) => {} 21533d722a9Sopenharmony_ci } 21633d722a9Sopenharmony_ci } 21733d722a9Sopenharmony_ci 21833d722a9Sopenharmony_ci cx.error(ptr, "unsupported vector element type"); 21933d722a9Sopenharmony_ci} 22033d722a9Sopenharmony_ci 22133d722a9Sopenharmony_cifn check_type_ref(cx: &mut Check, ty: &Ref) { 22233d722a9Sopenharmony_ci if ty.mutable && !ty.pinned { 22333d722a9Sopenharmony_ci if let Some(requires_pin) = match &ty.inner { 22433d722a9Sopenharmony_ci Type::Ident(ident) if ident.rust == CxxString || is_opaque_cxx(cx, &ident.rust) => { 22533d722a9Sopenharmony_ci Some(ident.rust.to_string()) 22633d722a9Sopenharmony_ci } 22733d722a9Sopenharmony_ci Type::CxxVector(_) => Some("CxxVector<...>".to_owned()), 22833d722a9Sopenharmony_ci _ => None, 22933d722a9Sopenharmony_ci } { 23033d722a9Sopenharmony_ci cx.error( 23133d722a9Sopenharmony_ci ty, 23233d722a9Sopenharmony_ci format!( 23333d722a9Sopenharmony_ci "mutable reference to C++ type requires a pin -- use Pin<&mut {}>", 23433d722a9Sopenharmony_ci requires_pin, 23533d722a9Sopenharmony_ci ), 23633d722a9Sopenharmony_ci ); 23733d722a9Sopenharmony_ci } 23833d722a9Sopenharmony_ci } 23933d722a9Sopenharmony_ci 24033d722a9Sopenharmony_ci match ty.inner { 24133d722a9Sopenharmony_ci Type::Fn(_) | Type::Void(_) => {} 24233d722a9Sopenharmony_ci Type::Ref(_) => { 24333d722a9Sopenharmony_ci cx.error(ty, "C++ does not allow references to references"); 24433d722a9Sopenharmony_ci return; 24533d722a9Sopenharmony_ci } 24633d722a9Sopenharmony_ci _ => return, 24733d722a9Sopenharmony_ci } 24833d722a9Sopenharmony_ci 24933d722a9Sopenharmony_ci cx.error(ty, "unsupported reference type"); 25033d722a9Sopenharmony_ci} 25133d722a9Sopenharmony_ci 25233d722a9Sopenharmony_cifn check_type_ptr(cx: &mut Check, ty: &Ptr) { 25333d722a9Sopenharmony_ci match ty.inner { 25433d722a9Sopenharmony_ci Type::Fn(_) | Type::Void(_) => {} 25533d722a9Sopenharmony_ci Type::Ref(_) => { 25633d722a9Sopenharmony_ci cx.error(ty, "C++ does not allow pointer to reference as a type"); 25733d722a9Sopenharmony_ci return; 25833d722a9Sopenharmony_ci } 25933d722a9Sopenharmony_ci _ => return, 26033d722a9Sopenharmony_ci } 26133d722a9Sopenharmony_ci 26233d722a9Sopenharmony_ci cx.error(ty, "unsupported pointer type"); 26333d722a9Sopenharmony_ci} 26433d722a9Sopenharmony_ci 26533d722a9Sopenharmony_cifn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) { 26633d722a9Sopenharmony_ci let supported = !is_unsized(cx, &ty.inner) 26733d722a9Sopenharmony_ci || match &ty.inner { 26833d722a9Sopenharmony_ci Type::Ident(ident) => { 26933d722a9Sopenharmony_ci cx.types.rust.contains(&ident.rust) || cx.types.aliases.contains_key(&ident.rust) 27033d722a9Sopenharmony_ci } 27133d722a9Sopenharmony_ci _ => false, 27233d722a9Sopenharmony_ci }; 27333d722a9Sopenharmony_ci 27433d722a9Sopenharmony_ci if !supported { 27533d722a9Sopenharmony_ci let mutable = if ty.mutable { "mut " } else { "" }; 27633d722a9Sopenharmony_ci let mut msg = format!("unsupported &{}[T] element type", mutable); 27733d722a9Sopenharmony_ci if let Type::Ident(ident) = &ty.inner { 27833d722a9Sopenharmony_ci if is_opaque_cxx(cx, &ident.rust) { 27933d722a9Sopenharmony_ci msg += ": opaque C++ type is not supported yet"; 28033d722a9Sopenharmony_ci } 28133d722a9Sopenharmony_ci } 28233d722a9Sopenharmony_ci cx.error(ty, msg); 28333d722a9Sopenharmony_ci } 28433d722a9Sopenharmony_ci} 28533d722a9Sopenharmony_ci 28633d722a9Sopenharmony_cifn check_type_array(cx: &mut Check, ty: &Array) { 28733d722a9Sopenharmony_ci let supported = !is_unsized(cx, &ty.inner); 28833d722a9Sopenharmony_ci 28933d722a9Sopenharmony_ci if !supported { 29033d722a9Sopenharmony_ci cx.error(ty, "unsupported array element type"); 29133d722a9Sopenharmony_ci } 29233d722a9Sopenharmony_ci} 29333d722a9Sopenharmony_ci 29433d722a9Sopenharmony_cifn check_type_fn(cx: &mut Check, ty: &Signature) { 29533d722a9Sopenharmony_ci if ty.throws { 29633d722a9Sopenharmony_ci cx.error(ty, "function pointer returning Result is not supported yet"); 29733d722a9Sopenharmony_ci } 29833d722a9Sopenharmony_ci 29933d722a9Sopenharmony_ci for arg in &ty.args { 30033d722a9Sopenharmony_ci if let Type::Ptr(_) = arg.ty { 30133d722a9Sopenharmony_ci if ty.unsafety.is_none() { 30233d722a9Sopenharmony_ci cx.error( 30333d722a9Sopenharmony_ci arg, 30433d722a9Sopenharmony_ci "pointer argument requires that the function pointer be marked unsafe", 30533d722a9Sopenharmony_ci ); 30633d722a9Sopenharmony_ci } 30733d722a9Sopenharmony_ci } 30833d722a9Sopenharmony_ci } 30933d722a9Sopenharmony_ci} 31033d722a9Sopenharmony_ci 31133d722a9Sopenharmony_cifn check_api_struct(cx: &mut Check, strct: &Struct) { 31233d722a9Sopenharmony_ci let name = &strct.name; 31333d722a9Sopenharmony_ci check_reserved_name(cx, &name.rust); 31433d722a9Sopenharmony_ci check_lifetimes(cx, &strct.generics); 31533d722a9Sopenharmony_ci 31633d722a9Sopenharmony_ci if strct.fields.is_empty() { 31733d722a9Sopenharmony_ci let span = span_for_struct_error(strct); 31833d722a9Sopenharmony_ci cx.error(span, "structs without any fields are not supported"); 31933d722a9Sopenharmony_ci } 32033d722a9Sopenharmony_ci 32133d722a9Sopenharmony_ci if cx.types.cxx.contains(&name.rust) { 32233d722a9Sopenharmony_ci if let Some(ety) = cx.types.untrusted.get(&name.rust) { 32333d722a9Sopenharmony_ci let msg = "extern shared struct must be declared in an `unsafe extern` block"; 32433d722a9Sopenharmony_ci cx.error(ety, msg); 32533d722a9Sopenharmony_ci } 32633d722a9Sopenharmony_ci } 32733d722a9Sopenharmony_ci 32833d722a9Sopenharmony_ci for derive in &strct.derives { 32933d722a9Sopenharmony_ci if derive.what == Trait::ExternType { 33033d722a9Sopenharmony_ci let msg = format!("derive({}) on shared struct is not supported", derive); 33133d722a9Sopenharmony_ci cx.error(derive, msg); 33233d722a9Sopenharmony_ci } 33333d722a9Sopenharmony_ci } 33433d722a9Sopenharmony_ci 33533d722a9Sopenharmony_ci for field in &strct.fields { 33633d722a9Sopenharmony_ci if let Type::Fn(_) = field.ty { 33733d722a9Sopenharmony_ci cx.error( 33833d722a9Sopenharmony_ci field, 33933d722a9Sopenharmony_ci "function pointers in a struct field are not implemented yet", 34033d722a9Sopenharmony_ci ); 34133d722a9Sopenharmony_ci } else if is_unsized(cx, &field.ty) { 34233d722a9Sopenharmony_ci let desc = describe(cx, &field.ty); 34333d722a9Sopenharmony_ci let msg = format!("using {} by value is not supported", desc); 34433d722a9Sopenharmony_ci cx.error(field, msg); 34533d722a9Sopenharmony_ci } 34633d722a9Sopenharmony_ci } 34733d722a9Sopenharmony_ci} 34833d722a9Sopenharmony_ci 34933d722a9Sopenharmony_cifn check_api_enum(cx: &mut Check, enm: &Enum) { 35033d722a9Sopenharmony_ci check_reserved_name(cx, &enm.name.rust); 35133d722a9Sopenharmony_ci check_lifetimes(cx, &enm.generics); 35233d722a9Sopenharmony_ci 35333d722a9Sopenharmony_ci if enm.variants.is_empty() && !enm.explicit_repr && !enm.variants_from_header { 35433d722a9Sopenharmony_ci let span = span_for_enum_error(enm); 35533d722a9Sopenharmony_ci cx.error( 35633d722a9Sopenharmony_ci span, 35733d722a9Sopenharmony_ci "explicit #[repr(...)] is required for enum without any variants", 35833d722a9Sopenharmony_ci ); 35933d722a9Sopenharmony_ci } 36033d722a9Sopenharmony_ci 36133d722a9Sopenharmony_ci for derive in &enm.derives { 36233d722a9Sopenharmony_ci if derive.what == Trait::Default || derive.what == Trait::ExternType { 36333d722a9Sopenharmony_ci let msg = format!("derive({}) on shared enum is not supported", derive); 36433d722a9Sopenharmony_ci cx.error(derive, msg); 36533d722a9Sopenharmony_ci } 36633d722a9Sopenharmony_ci } 36733d722a9Sopenharmony_ci} 36833d722a9Sopenharmony_ci 36933d722a9Sopenharmony_cifn check_api_type(cx: &mut Check, ety: &ExternType) { 37033d722a9Sopenharmony_ci check_reserved_name(cx, &ety.name.rust); 37133d722a9Sopenharmony_ci check_lifetimes(cx, &ety.generics); 37233d722a9Sopenharmony_ci 37333d722a9Sopenharmony_ci for derive in &ety.derives { 37433d722a9Sopenharmony_ci if derive.what == Trait::ExternType && ety.lang == Lang::Rust { 37533d722a9Sopenharmony_ci continue; 37633d722a9Sopenharmony_ci } 37733d722a9Sopenharmony_ci let lang = match ety.lang { 37833d722a9Sopenharmony_ci Lang::Rust => "Rust", 37933d722a9Sopenharmony_ci Lang::Cxx => "C++", 38033d722a9Sopenharmony_ci }; 38133d722a9Sopenharmony_ci let msg = format!( 38233d722a9Sopenharmony_ci "derive({}) on opaque {} type is not supported yet", 38333d722a9Sopenharmony_ci derive, lang, 38433d722a9Sopenharmony_ci ); 38533d722a9Sopenharmony_ci cx.error(derive, msg); 38633d722a9Sopenharmony_ci } 38733d722a9Sopenharmony_ci 38833d722a9Sopenharmony_ci if !ety.bounds.is_empty() { 38933d722a9Sopenharmony_ci let bounds = &ety.bounds; 39033d722a9Sopenharmony_ci let span = quote!(#(#bounds)*); 39133d722a9Sopenharmony_ci cx.error(span, "extern type bounds are not implemented yet"); 39233d722a9Sopenharmony_ci } 39333d722a9Sopenharmony_ci 39433d722a9Sopenharmony_ci if let Some(reasons) = cx.types.required_trivial.get(&ety.name.rust) { 39533d722a9Sopenharmony_ci let msg = format!( 39633d722a9Sopenharmony_ci "needs a cxx::ExternType impl in order to be used as {}", 39733d722a9Sopenharmony_ci trivial::as_what(&ety.name, reasons), 39833d722a9Sopenharmony_ci ); 39933d722a9Sopenharmony_ci cx.error(ety, msg); 40033d722a9Sopenharmony_ci } 40133d722a9Sopenharmony_ci} 40233d722a9Sopenharmony_ci 40333d722a9Sopenharmony_cifn check_api_fn(cx: &mut Check, efn: &ExternFn) { 40433d722a9Sopenharmony_ci match efn.lang { 40533d722a9Sopenharmony_ci Lang::Cxx => { 40633d722a9Sopenharmony_ci if !efn.generics.params.is_empty() && !efn.trusted { 40733d722a9Sopenharmony_ci let ref span = span_for_generics_error(efn); 40833d722a9Sopenharmony_ci cx.error(span, "extern C++ function with lifetimes must be declared in `unsafe extern \"C++\"` block"); 40933d722a9Sopenharmony_ci } 41033d722a9Sopenharmony_ci } 41133d722a9Sopenharmony_ci Lang::Rust => { 41233d722a9Sopenharmony_ci if !efn.generics.params.is_empty() && efn.unsafety.is_none() { 41333d722a9Sopenharmony_ci let ref span = span_for_generics_error(efn); 41433d722a9Sopenharmony_ci let message = format!( 41533d722a9Sopenharmony_ci "must be `unsafe fn {}` in order to expose explicit lifetimes to C++", 41633d722a9Sopenharmony_ci efn.name.rust, 41733d722a9Sopenharmony_ci ); 41833d722a9Sopenharmony_ci cx.error(span, message); 41933d722a9Sopenharmony_ci } 42033d722a9Sopenharmony_ci } 42133d722a9Sopenharmony_ci } 42233d722a9Sopenharmony_ci 42333d722a9Sopenharmony_ci check_generics(cx, &efn.sig.generics); 42433d722a9Sopenharmony_ci 42533d722a9Sopenharmony_ci if let Some(receiver) = &efn.receiver { 42633d722a9Sopenharmony_ci let ref span = span_for_receiver_error(receiver); 42733d722a9Sopenharmony_ci 42833d722a9Sopenharmony_ci if receiver.ty.rust == "Self" { 42933d722a9Sopenharmony_ci let mutability = match receiver.mutable { 43033d722a9Sopenharmony_ci true => "mut ", 43133d722a9Sopenharmony_ci false => "", 43233d722a9Sopenharmony_ci }; 43333d722a9Sopenharmony_ci let msg = format!( 43433d722a9Sopenharmony_ci "unnamed receiver type is only allowed if the surrounding extern block contains exactly one extern type; use `self: &{mutability}TheType`", 43533d722a9Sopenharmony_ci mutability = mutability, 43633d722a9Sopenharmony_ci ); 43733d722a9Sopenharmony_ci cx.error(span, msg); 43833d722a9Sopenharmony_ci } else if cx.types.enums.contains_key(&receiver.ty.rust) { 43933d722a9Sopenharmony_ci cx.error( 44033d722a9Sopenharmony_ci span, 44133d722a9Sopenharmony_ci "unsupported receiver type; C++ does not allow member functions on enums", 44233d722a9Sopenharmony_ci ); 44333d722a9Sopenharmony_ci } else if !cx.types.structs.contains_key(&receiver.ty.rust) 44433d722a9Sopenharmony_ci && !cx.types.cxx.contains(&receiver.ty.rust) 44533d722a9Sopenharmony_ci && !cx.types.rust.contains(&receiver.ty.rust) 44633d722a9Sopenharmony_ci { 44733d722a9Sopenharmony_ci cx.error(span, "unrecognized receiver type"); 44833d722a9Sopenharmony_ci } else if receiver.mutable && !receiver.pinned && is_opaque_cxx(cx, &receiver.ty.rust) { 44933d722a9Sopenharmony_ci cx.error( 45033d722a9Sopenharmony_ci span, 45133d722a9Sopenharmony_ci format!( 45233d722a9Sopenharmony_ci "mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut {}>`", 45333d722a9Sopenharmony_ci receiver.ty.rust, 45433d722a9Sopenharmony_ci ), 45533d722a9Sopenharmony_ci ); 45633d722a9Sopenharmony_ci } 45733d722a9Sopenharmony_ci } 45833d722a9Sopenharmony_ci 45933d722a9Sopenharmony_ci for arg in &efn.args { 46033d722a9Sopenharmony_ci if let Type::Fn(_) = arg.ty { 46133d722a9Sopenharmony_ci if efn.lang == Lang::Rust { 46233d722a9Sopenharmony_ci cx.error( 46333d722a9Sopenharmony_ci arg, 46433d722a9Sopenharmony_ci "passing a function pointer from C++ to Rust is not implemented yet", 46533d722a9Sopenharmony_ci ); 46633d722a9Sopenharmony_ci } 46733d722a9Sopenharmony_ci } else if let Type::Ptr(_) = arg.ty { 46833d722a9Sopenharmony_ci if efn.sig.unsafety.is_none() { 46933d722a9Sopenharmony_ci cx.error( 47033d722a9Sopenharmony_ci arg, 47133d722a9Sopenharmony_ci "pointer argument requires that the function be marked unsafe", 47233d722a9Sopenharmony_ci ); 47333d722a9Sopenharmony_ci } 47433d722a9Sopenharmony_ci } else if is_unsized(cx, &arg.ty) { 47533d722a9Sopenharmony_ci let desc = describe(cx, &arg.ty); 47633d722a9Sopenharmony_ci let msg = format!("passing {} by value is not supported", desc); 47733d722a9Sopenharmony_ci cx.error(arg, msg); 47833d722a9Sopenharmony_ci } 47933d722a9Sopenharmony_ci } 48033d722a9Sopenharmony_ci 48133d722a9Sopenharmony_ci if let Some(ty) = &efn.ret { 48233d722a9Sopenharmony_ci if let Type::Fn(_) = ty { 48333d722a9Sopenharmony_ci cx.error(ty, "returning a function pointer is not implemented yet"); 48433d722a9Sopenharmony_ci } else if is_unsized(cx, ty) { 48533d722a9Sopenharmony_ci let desc = describe(cx, ty); 48633d722a9Sopenharmony_ci let msg = format!("returning {} by value is not supported", desc); 48733d722a9Sopenharmony_ci cx.error(ty, msg); 48833d722a9Sopenharmony_ci } 48933d722a9Sopenharmony_ci } 49033d722a9Sopenharmony_ci 49133d722a9Sopenharmony_ci if efn.lang == Lang::Cxx { 49233d722a9Sopenharmony_ci check_mut_return_restriction(cx, efn); 49333d722a9Sopenharmony_ci } 49433d722a9Sopenharmony_ci} 49533d722a9Sopenharmony_ci 49633d722a9Sopenharmony_cifn check_api_type_alias(cx: &mut Check, alias: &TypeAlias) { 49733d722a9Sopenharmony_ci check_lifetimes(cx, &alias.generics); 49833d722a9Sopenharmony_ci 49933d722a9Sopenharmony_ci for derive in &alias.derives { 50033d722a9Sopenharmony_ci let msg = format!("derive({}) on extern type alias is not supported", derive); 50133d722a9Sopenharmony_ci cx.error(derive, msg); 50233d722a9Sopenharmony_ci } 50333d722a9Sopenharmony_ci} 50433d722a9Sopenharmony_ci 50533d722a9Sopenharmony_cifn check_api_impl(cx: &mut Check, imp: &Impl) { 50633d722a9Sopenharmony_ci let ty = &imp.ty; 50733d722a9Sopenharmony_ci 50833d722a9Sopenharmony_ci check_lifetimes(cx, &imp.impl_generics); 50933d722a9Sopenharmony_ci 51033d722a9Sopenharmony_ci if let Some(negative) = imp.negative_token { 51133d722a9Sopenharmony_ci let span = quote!(#negative #ty); 51233d722a9Sopenharmony_ci cx.error(span, "negative impl is not supported yet"); 51333d722a9Sopenharmony_ci return; 51433d722a9Sopenharmony_ci } 51533d722a9Sopenharmony_ci 51633d722a9Sopenharmony_ci match ty { 51733d722a9Sopenharmony_ci Type::RustBox(ty) 51833d722a9Sopenharmony_ci | Type::RustVec(ty) 51933d722a9Sopenharmony_ci | Type::UniquePtr(ty) 52033d722a9Sopenharmony_ci | Type::SharedPtr(ty) 52133d722a9Sopenharmony_ci | Type::WeakPtr(ty) 52233d722a9Sopenharmony_ci | Type::CxxVector(ty) => { 52333d722a9Sopenharmony_ci if let Type::Ident(inner) = &ty.inner { 52433d722a9Sopenharmony_ci if Atom::from(&inner.rust).is_none() { 52533d722a9Sopenharmony_ci return; 52633d722a9Sopenharmony_ci } 52733d722a9Sopenharmony_ci } 52833d722a9Sopenharmony_ci } 52933d722a9Sopenharmony_ci _ => {} 53033d722a9Sopenharmony_ci } 53133d722a9Sopenharmony_ci 53233d722a9Sopenharmony_ci cx.error(imp, "unsupported Self type of explicit impl"); 53333d722a9Sopenharmony_ci} 53433d722a9Sopenharmony_ci 53533d722a9Sopenharmony_cifn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) { 53633d722a9Sopenharmony_ci if efn.sig.unsafety.is_some() { 53733d722a9Sopenharmony_ci // Unrestricted as long as the function is made unsafe-to-call. 53833d722a9Sopenharmony_ci return; 53933d722a9Sopenharmony_ci } 54033d722a9Sopenharmony_ci 54133d722a9Sopenharmony_ci match &efn.ret { 54233d722a9Sopenharmony_ci Some(Type::Ref(ty)) if ty.mutable => {} 54333d722a9Sopenharmony_ci Some(Type::SliceRef(slice)) if slice.mutable => {} 54433d722a9Sopenharmony_ci _ => return, 54533d722a9Sopenharmony_ci } 54633d722a9Sopenharmony_ci 54733d722a9Sopenharmony_ci if let Some(receiver) = &efn.receiver { 54833d722a9Sopenharmony_ci if receiver.mutable { 54933d722a9Sopenharmony_ci return; 55033d722a9Sopenharmony_ci } 55133d722a9Sopenharmony_ci let resolve = match cx.types.try_resolve(&receiver.ty) { 55233d722a9Sopenharmony_ci Some(resolve) => resolve, 55333d722a9Sopenharmony_ci None => return, 55433d722a9Sopenharmony_ci }; 55533d722a9Sopenharmony_ci if !resolve.generics.lifetimes.is_empty() { 55633d722a9Sopenharmony_ci return; 55733d722a9Sopenharmony_ci } 55833d722a9Sopenharmony_ci } 55933d722a9Sopenharmony_ci 56033d722a9Sopenharmony_ci struct FindLifetimeMut<'a> { 56133d722a9Sopenharmony_ci cx: &'a Check<'a>, 56233d722a9Sopenharmony_ci found: bool, 56333d722a9Sopenharmony_ci } 56433d722a9Sopenharmony_ci 56533d722a9Sopenharmony_ci impl<'t, 'a> Visit<'t> for FindLifetimeMut<'a> { 56633d722a9Sopenharmony_ci fn visit_type(&mut self, ty: &'t Type) { 56733d722a9Sopenharmony_ci self.found |= match ty { 56833d722a9Sopenharmony_ci Type::Ref(ty) => ty.mutable, 56933d722a9Sopenharmony_ci Type::SliceRef(slice) => slice.mutable, 57033d722a9Sopenharmony_ci Type::Ident(ident) if Atom::from(&ident.rust).is_none() => { 57133d722a9Sopenharmony_ci match self.cx.types.try_resolve(ident) { 57233d722a9Sopenharmony_ci Some(resolve) => !resolve.generics.lifetimes.is_empty(), 57333d722a9Sopenharmony_ci None => true, 57433d722a9Sopenharmony_ci } 57533d722a9Sopenharmony_ci } 57633d722a9Sopenharmony_ci _ => false, 57733d722a9Sopenharmony_ci }; 57833d722a9Sopenharmony_ci visit::visit_type(self, ty); 57933d722a9Sopenharmony_ci } 58033d722a9Sopenharmony_ci } 58133d722a9Sopenharmony_ci 58233d722a9Sopenharmony_ci let mut visitor = FindLifetimeMut { cx, found: false }; 58333d722a9Sopenharmony_ci 58433d722a9Sopenharmony_ci for arg in &efn.args { 58533d722a9Sopenharmony_ci visitor.visit_type(&arg.ty); 58633d722a9Sopenharmony_ci } 58733d722a9Sopenharmony_ci 58833d722a9Sopenharmony_ci if visitor.found { 58933d722a9Sopenharmony_ci return; 59033d722a9Sopenharmony_ci } 59133d722a9Sopenharmony_ci 59233d722a9Sopenharmony_ci cx.error( 59333d722a9Sopenharmony_ci efn, 59433d722a9Sopenharmony_ci "&mut return type is not allowed unless there is a &mut argument", 59533d722a9Sopenharmony_ci ); 59633d722a9Sopenharmony_ci} 59733d722a9Sopenharmony_ci 59833d722a9Sopenharmony_cifn check_reserved_name(cx: &mut Check, ident: &Ident) { 59933d722a9Sopenharmony_ci if ident == "Box" 60033d722a9Sopenharmony_ci || ident == "UniquePtr" 60133d722a9Sopenharmony_ci || ident == "SharedPtr" 60233d722a9Sopenharmony_ci || ident == "WeakPtr" 60333d722a9Sopenharmony_ci || ident == "Vec" 60433d722a9Sopenharmony_ci || ident == "CxxVector" 60533d722a9Sopenharmony_ci || ident == "str" 60633d722a9Sopenharmony_ci || Atom::from(ident).is_some() 60733d722a9Sopenharmony_ci { 60833d722a9Sopenharmony_ci cx.error(ident, "reserved name"); 60933d722a9Sopenharmony_ci } 61033d722a9Sopenharmony_ci} 61133d722a9Sopenharmony_ci 61233d722a9Sopenharmony_cifn check_reserved_lifetime(cx: &mut Check, lifetime: &Lifetime) { 61333d722a9Sopenharmony_ci if lifetime.ident == "static" { 61433d722a9Sopenharmony_ci match cx.generator { 61533d722a9Sopenharmony_ci Generator::Macro => { /* rustc already reports this */ } 61633d722a9Sopenharmony_ci Generator::Build => { 61733d722a9Sopenharmony_ci cx.error(lifetime, error::RESERVED_LIFETIME); 61833d722a9Sopenharmony_ci } 61933d722a9Sopenharmony_ci } 62033d722a9Sopenharmony_ci } 62133d722a9Sopenharmony_ci} 62233d722a9Sopenharmony_ci 62333d722a9Sopenharmony_cifn check_lifetimes(cx: &mut Check, generics: &Lifetimes) { 62433d722a9Sopenharmony_ci for lifetime in &generics.lifetimes { 62533d722a9Sopenharmony_ci check_reserved_lifetime(cx, lifetime); 62633d722a9Sopenharmony_ci } 62733d722a9Sopenharmony_ci} 62833d722a9Sopenharmony_ci 62933d722a9Sopenharmony_cifn check_generics(cx: &mut Check, generics: &Generics) { 63033d722a9Sopenharmony_ci for generic_param in &generics.params { 63133d722a9Sopenharmony_ci if let GenericParam::Lifetime(def) = generic_param { 63233d722a9Sopenharmony_ci check_reserved_lifetime(cx, &def.lifetime); 63333d722a9Sopenharmony_ci } 63433d722a9Sopenharmony_ci } 63533d722a9Sopenharmony_ci} 63633d722a9Sopenharmony_ci 63733d722a9Sopenharmony_cifn is_unsized(cx: &mut Check, ty: &Type) -> bool { 63833d722a9Sopenharmony_ci match ty { 63933d722a9Sopenharmony_ci Type::Ident(ident) => { 64033d722a9Sopenharmony_ci let ident = &ident.rust; 64133d722a9Sopenharmony_ci ident == CxxString || is_opaque_cxx(cx, ident) || cx.types.rust.contains(ident) 64233d722a9Sopenharmony_ci } 64333d722a9Sopenharmony_ci Type::Array(array) => is_unsized(cx, &array.inner), 64433d722a9Sopenharmony_ci Type::CxxVector(_) | Type::Fn(_) | Type::Void(_) => true, 64533d722a9Sopenharmony_ci Type::RustBox(_) 64633d722a9Sopenharmony_ci | Type::RustVec(_) 64733d722a9Sopenharmony_ci | Type::UniquePtr(_) 64833d722a9Sopenharmony_ci | Type::SharedPtr(_) 64933d722a9Sopenharmony_ci | Type::WeakPtr(_) 65033d722a9Sopenharmony_ci | Type::Ref(_) 65133d722a9Sopenharmony_ci | Type::Ptr(_) 65233d722a9Sopenharmony_ci | Type::Str(_) 65333d722a9Sopenharmony_ci | Type::SliceRef(_) => false, 65433d722a9Sopenharmony_ci } 65533d722a9Sopenharmony_ci} 65633d722a9Sopenharmony_ci 65733d722a9Sopenharmony_cifn is_opaque_cxx(cx: &mut Check, ty: &Ident) -> bool { 65833d722a9Sopenharmony_ci cx.types.cxx.contains(ty) 65933d722a9Sopenharmony_ci && !cx.types.structs.contains_key(ty) 66033d722a9Sopenharmony_ci && !cx.types.enums.contains_key(ty) 66133d722a9Sopenharmony_ci && !(cx.types.aliases.contains_key(ty) && cx.types.required_trivial.contains_key(ty)) 66233d722a9Sopenharmony_ci} 66333d722a9Sopenharmony_ci 66433d722a9Sopenharmony_cifn span_for_struct_error(strct: &Struct) -> TokenStream { 66533d722a9Sopenharmony_ci let struct_token = strct.struct_token; 66633d722a9Sopenharmony_ci let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new()); 66733d722a9Sopenharmony_ci brace_token.set_span(strct.brace_token.span.join()); 66833d722a9Sopenharmony_ci quote!(#struct_token #brace_token) 66933d722a9Sopenharmony_ci} 67033d722a9Sopenharmony_ci 67133d722a9Sopenharmony_cifn span_for_enum_error(enm: &Enum) -> TokenStream { 67233d722a9Sopenharmony_ci let enum_token = enm.enum_token; 67333d722a9Sopenharmony_ci let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new()); 67433d722a9Sopenharmony_ci brace_token.set_span(enm.brace_token.span.join()); 67533d722a9Sopenharmony_ci quote!(#enum_token #brace_token) 67633d722a9Sopenharmony_ci} 67733d722a9Sopenharmony_ci 67833d722a9Sopenharmony_cifn span_for_receiver_error(receiver: &Receiver) -> TokenStream { 67933d722a9Sopenharmony_ci let ampersand = receiver.ampersand; 68033d722a9Sopenharmony_ci let lifetime = &receiver.lifetime; 68133d722a9Sopenharmony_ci let mutability = receiver.mutability; 68233d722a9Sopenharmony_ci if receiver.shorthand { 68333d722a9Sopenharmony_ci let var = receiver.var; 68433d722a9Sopenharmony_ci quote!(#ampersand #lifetime #mutability #var) 68533d722a9Sopenharmony_ci } else { 68633d722a9Sopenharmony_ci let ty = &receiver.ty; 68733d722a9Sopenharmony_ci quote!(#ampersand #lifetime #mutability #ty) 68833d722a9Sopenharmony_ci } 68933d722a9Sopenharmony_ci} 69033d722a9Sopenharmony_ci 69133d722a9Sopenharmony_cifn span_for_generics_error(efn: &ExternFn) -> TokenStream { 69233d722a9Sopenharmony_ci let unsafety = efn.unsafety; 69333d722a9Sopenharmony_ci let fn_token = efn.fn_token; 69433d722a9Sopenharmony_ci let generics = &efn.generics; 69533d722a9Sopenharmony_ci quote!(#unsafety #fn_token #generics) 69633d722a9Sopenharmony_ci} 69733d722a9Sopenharmony_ci 69833d722a9Sopenharmony_cifn describe(cx: &mut Check, ty: &Type) -> String { 69933d722a9Sopenharmony_ci match ty { 70033d722a9Sopenharmony_ci Type::Ident(ident) => { 70133d722a9Sopenharmony_ci if cx.types.structs.contains_key(&ident.rust) { 70233d722a9Sopenharmony_ci "struct".to_owned() 70333d722a9Sopenharmony_ci } else if cx.types.enums.contains_key(&ident.rust) { 70433d722a9Sopenharmony_ci "enum".to_owned() 70533d722a9Sopenharmony_ci } else if cx.types.aliases.contains_key(&ident.rust) { 70633d722a9Sopenharmony_ci "C++ type".to_owned() 70733d722a9Sopenharmony_ci } else if cx.types.cxx.contains(&ident.rust) { 70833d722a9Sopenharmony_ci "opaque C++ type".to_owned() 70933d722a9Sopenharmony_ci } else if cx.types.rust.contains(&ident.rust) { 71033d722a9Sopenharmony_ci "opaque Rust type".to_owned() 71133d722a9Sopenharmony_ci } else if Atom::from(&ident.rust) == Some(CxxString) { 71233d722a9Sopenharmony_ci "C++ string".to_owned() 71333d722a9Sopenharmony_ci } else if Atom::from(&ident.rust) == Some(Char) { 71433d722a9Sopenharmony_ci "C char".to_owned() 71533d722a9Sopenharmony_ci } else { 71633d722a9Sopenharmony_ci ident.rust.to_string() 71733d722a9Sopenharmony_ci } 71833d722a9Sopenharmony_ci } 71933d722a9Sopenharmony_ci Type::RustBox(_) => "Box".to_owned(), 72033d722a9Sopenharmony_ci Type::RustVec(_) => "Vec".to_owned(), 72133d722a9Sopenharmony_ci Type::UniquePtr(_) => "unique_ptr".to_owned(), 72233d722a9Sopenharmony_ci Type::SharedPtr(_) => "shared_ptr".to_owned(), 72333d722a9Sopenharmony_ci Type::WeakPtr(_) => "weak_ptr".to_owned(), 72433d722a9Sopenharmony_ci Type::Ref(_) => "reference".to_owned(), 72533d722a9Sopenharmony_ci Type::Ptr(_) => "raw pointer".to_owned(), 72633d722a9Sopenharmony_ci Type::Str(_) => "&str".to_owned(), 72733d722a9Sopenharmony_ci Type::CxxVector(_) => "C++ vector".to_owned(), 72833d722a9Sopenharmony_ci Type::SliceRef(_) => "slice".to_owned(), 72933d722a9Sopenharmony_ci Type::Fn(_) => "function pointer".to_owned(), 73033d722a9Sopenharmony_ci Type::Void(_) => "()".to_owned(), 73133d722a9Sopenharmony_ci Type::Array(_) => "array".to_owned(), 73233d722a9Sopenharmony_ci } 73333d722a9Sopenharmony_ci} 734