factor lifetime determination into its own module
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
use crate::lifetimes::{anon_lifetime, LifetimeExt};
|
||||
use crate::names::Names;
|
||||
use crate::types::{anon_lifetime, struct_is_copy};
|
||||
|
||||
pub fn define_func(names: &Names, func: &witx::InterfaceFunc) -> TokenStream {
|
||||
let funcname = func.name.as_str();
|
||||
@@ -258,7 +258,7 @@ fn marshal_arg(
|
||||
};
|
||||
}
|
||||
}
|
||||
witx::Type::Struct(s) if struct_is_copy(&s) => {
|
||||
witx::Type::Struct(s) if !s.needs_lifetime() => {
|
||||
let pointee_type = names.type_ref(tref, anon_lifetime());
|
||||
let arg_name = names.func_ptr_binding(¶m.name);
|
||||
let name = names.func_param(¶m.name);
|
||||
@@ -276,7 +276,7 @@ fn marshal_arg(
|
||||
};
|
||||
}
|
||||
}
|
||||
witx::Type::Struct(s) if !struct_is_copy(&s) => read_conversion,
|
||||
witx::Type::Struct(s) if s.needs_lifetime() => read_conversion,
|
||||
witx::Type::Array(arr) => {
|
||||
let pointee_type = names.type_ref(arr, anon_lifetime());
|
||||
let ptr_name = names.func_ptr_binding(¶m.name);
|
||||
|
||||
@@ -2,6 +2,7 @@ extern crate proc_macro;
|
||||
|
||||
mod config;
|
||||
mod funcs;
|
||||
mod lifetimes;
|
||||
mod module_trait;
|
||||
mod names;
|
||||
mod types;
|
||||
|
||||
56
crates/generate/src/lifetimes.rs
Normal file
56
crates/generate/src/lifetimes.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
pub trait LifetimeExt {
|
||||
fn needs_lifetime(&self) -> bool;
|
||||
}
|
||||
|
||||
impl LifetimeExt for witx::TypeRef {
|
||||
fn needs_lifetime(&self) -> bool {
|
||||
self.type_().needs_lifetime()
|
||||
}
|
||||
}
|
||||
|
||||
impl LifetimeExt for witx::Type {
|
||||
fn needs_lifetime(&self) -> bool {
|
||||
match self {
|
||||
witx::Type::Builtin(b) => b.needs_lifetime(),
|
||||
witx::Type::Struct(s) => s.needs_lifetime(),
|
||||
witx::Type::Union(u) => u.needs_lifetime(),
|
||||
witx::Type::Enum { .. }
|
||||
| witx::Type::Flags { .. }
|
||||
| witx::Type::Int { .. }
|
||||
| witx::Type::Handle { .. } => false,
|
||||
witx::Type::Pointer { .. }
|
||||
| witx::Type::ConstPointer { .. }
|
||||
| witx::Type::Array { .. } => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LifetimeExt for witx::BuiltinType {
|
||||
fn needs_lifetime(&self) -> bool {
|
||||
match self {
|
||||
witx::BuiltinType::String => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LifetimeExt for witx::StructDatatype {
|
||||
fn needs_lifetime(&self) -> bool {
|
||||
self.members.iter().any(|m| m.tref.needs_lifetime())
|
||||
}
|
||||
}
|
||||
|
||||
impl LifetimeExt for witx::UnionDatatype {
|
||||
fn needs_lifetime(&self) -> bool {
|
||||
self.variants
|
||||
.iter()
|
||||
.any(|m| m.tref.as_ref().map(|t| t.needs_lifetime()).unwrap_or(false))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn anon_lifetime() -> TokenStream {
|
||||
quote!('_)
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
use crate::lifetimes::{anon_lifetime, LifetimeExt};
|
||||
use crate::names::Names;
|
||||
use crate::types::{anon_lifetime, type_needs_lifetime};
|
||||
use witx::Module;
|
||||
|
||||
pub fn define_module_trait(names: &Names, m: &Module) -> TokenStream {
|
||||
@@ -11,8 +11,7 @@ pub fn define_module_trait(names: &Names, m: &Module) -> TokenStream {
|
||||
// Check if we're returning an entity anotated with a lifetime,
|
||||
// in which case, we'll need to annotate the function itself, and
|
||||
// hence will need an explicit lifetime (rather than anonymous)
|
||||
let (lifetime, is_anonymous) = if f.results.iter().any(|ret| type_needs_lifetime(&ret.tref))
|
||||
{
|
||||
let (lifetime, is_anonymous) = if f.results.iter().any(|ret| ret.tref.needs_lifetime()) {
|
||||
(quote!('a), false)
|
||||
} else {
|
||||
(anon_lifetime(), true)
|
||||
|
||||
@@ -3,7 +3,7 @@ use proc_macro2::{Ident, TokenStream};
|
||||
use quote::{format_ident, quote};
|
||||
use witx::{AtomType, BuiltinType, Id, TypeRef};
|
||||
|
||||
use crate::types::type_needs_lifetime;
|
||||
use crate::lifetimes::LifetimeExt;
|
||||
use crate::Config;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -52,7 +52,7 @@ impl Names {
|
||||
match tref {
|
||||
TypeRef::Name(nt) => {
|
||||
let ident = self.type_(&nt.name);
|
||||
if type_needs_lifetime(&nt.tref) {
|
||||
if nt.tref.needs_lifetime() {
|
||||
quote!(#ident<#lifetime>)
|
||||
} else {
|
||||
quote!(#ident)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::lifetimes::{anon_lifetime, LifetimeExt};
|
||||
use crate::names::Names;
|
||||
|
||||
use proc_macro2::{Literal, TokenStream};
|
||||
@@ -13,7 +14,7 @@ pub fn define_datatype(names: &Names, namedtype: &witx::NamedType) -> TokenStrea
|
||||
witx::Type::Int(i) => define_int(names, &namedtype.name, &i),
|
||||
witx::Type::Flags(f) => define_flags(names, &namedtype.name, &f),
|
||||
witx::Type::Struct(s) => {
|
||||
if struct_is_copy(s) {
|
||||
if !s.needs_lifetime() {
|
||||
define_copy_struct(names, &namedtype.name, &s)
|
||||
} else {
|
||||
define_ptr_struct(names, &namedtype.name, &s)
|
||||
@@ -39,7 +40,7 @@ pub fn define_datatype(names: &Names, namedtype: &witx::NamedType) -> TokenStrea
|
||||
fn define_alias(names: &Names, name: &witx::Id, to: &witx::NamedType) -> TokenStream {
|
||||
let ident = names.type_(name);
|
||||
let rhs = names.type_(&to.name);
|
||||
if type_needs_lifetime(&to.tref) {
|
||||
if to.tref.needs_lifetime() {
|
||||
quote!(pub type #ident<'a> = #rhs<'a>;)
|
||||
} else {
|
||||
quote!(pub type #ident = #rhs;)
|
||||
@@ -407,66 +408,6 @@ fn define_builtin(names: &Names, name: &witx::Id, builtin: witx::BuiltinType) ->
|
||||
}
|
||||
}
|
||||
|
||||
// XXX DRY - should move these funcs to be a trait that Type, BuiltinType, StructDatatype,
|
||||
// UnionDatatype all implement
|
||||
pub fn type_needs_lifetime(tref: &witx::TypeRef) -> bool {
|
||||
match &*tref.type_() {
|
||||
witx::Type::Builtin(b) => match b {
|
||||
witx::BuiltinType::String => true,
|
||||
_ => false,
|
||||
},
|
||||
witx::Type::Enum { .. }
|
||||
| witx::Type::Flags { .. }
|
||||
| witx::Type::Int { .. }
|
||||
| witx::Type::Handle { .. } => false,
|
||||
witx::Type::Struct(s) => !struct_is_copy(&s),
|
||||
witx::Type::Union(u) => !union_is_copy(&u),
|
||||
witx::Type::Pointer { .. } | witx::Type::ConstPointer { .. } => true,
|
||||
witx::Type::Array { .. } => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn struct_is_copy(s: &witx::StructDatatype) -> bool {
|
||||
s.members.iter().all(|m| match &*m.tref.type_() {
|
||||
witx::Type::Struct(s) => struct_is_copy(&s),
|
||||
witx::Type::Builtin(b) => match &*b {
|
||||
witx::BuiltinType::String => false,
|
||||
_ => true,
|
||||
},
|
||||
witx::Type::ConstPointer { .. } | witx::Type::Pointer { .. } | witx::Type::Array { .. } => {
|
||||
false
|
||||
}
|
||||
witx::Type::Union(u) => union_is_copy(u),
|
||||
witx::Type::Enum { .. }
|
||||
| witx::Type::Int { .. }
|
||||
| witx::Type::Flags { .. }
|
||||
| witx::Type::Handle { .. } => true,
|
||||
})
|
||||
}
|
||||
pub fn union_is_copy(u: &witx::UnionDatatype) -> bool {
|
||||
u.variants.iter().all(|m| {
|
||||
if let Some(tref) = &m.tref {
|
||||
match &*tref.type_() {
|
||||
witx::Type::Struct(s) => struct_is_copy(&s),
|
||||
witx::Type::Builtin(b) => match &*b {
|
||||
witx::BuiltinType::String => false,
|
||||
_ => true,
|
||||
},
|
||||
witx::Type::ConstPointer { .. }
|
||||
| witx::Type::Pointer { .. }
|
||||
| witx::Type::Array { .. } => false,
|
||||
witx::Type::Union(u) => union_is_copy(u),
|
||||
witx::Type::Enum { .. }
|
||||
| witx::Type::Int { .. }
|
||||
| witx::Type::Flags { .. }
|
||||
| witx::Type::Handle { .. } => true,
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn define_copy_struct(names: &Names, name: &witx::Id, s: &witx::StructDatatype) -> TokenStream {
|
||||
let ident = names.type_(name);
|
||||
let size = s.mem_size_align().size as u32;
|
||||
@@ -774,7 +715,7 @@ fn define_union(names: &Names, name: &witx::Id, u: &witx::UnionDatatype) -> Toke
|
||||
});
|
||||
let validate = union_validate(names, ident.clone(), u, &ulayout);
|
||||
|
||||
if union_is_copy(u) {
|
||||
if !u.needs_lifetime() {
|
||||
// Type does not have a lifetime parameter:
|
||||
quote! {
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
@@ -887,7 +828,3 @@ fn atom_token(atom: witx::AtomType) -> TokenStream {
|
||||
witx::AtomType::F64 => quote!(f64),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn anon_lifetime() -> TokenStream {
|
||||
quote!('_)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user