factor lifetime determination into its own module
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
|
use crate::lifetimes::{anon_lifetime, LifetimeExt};
|
||||||
use crate::names::Names;
|
use crate::names::Names;
|
||||||
use crate::types::{anon_lifetime, struct_is_copy};
|
|
||||||
|
|
||||||
pub fn define_func(names: &Names, func: &witx::InterfaceFunc) -> TokenStream {
|
pub fn define_func(names: &Names, func: &witx::InterfaceFunc) -> TokenStream {
|
||||||
let funcname = func.name.as_str();
|
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 pointee_type = names.type_ref(tref, anon_lifetime());
|
||||||
let arg_name = names.func_ptr_binding(¶m.name);
|
let arg_name = names.func_ptr_binding(¶m.name);
|
||||||
let name = names.func_param(¶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) => {
|
witx::Type::Array(arr) => {
|
||||||
let pointee_type = names.type_ref(arr, anon_lifetime());
|
let pointee_type = names.type_ref(arr, anon_lifetime());
|
||||||
let ptr_name = names.func_ptr_binding(¶m.name);
|
let ptr_name = names.func_ptr_binding(¶m.name);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ extern crate proc_macro;
|
|||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
mod funcs;
|
mod funcs;
|
||||||
|
mod lifetimes;
|
||||||
mod module_trait;
|
mod module_trait;
|
||||||
mod names;
|
mod names;
|
||||||
mod types;
|
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 proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
|
use crate::lifetimes::{anon_lifetime, LifetimeExt};
|
||||||
use crate::names::Names;
|
use crate::names::Names;
|
||||||
use crate::types::{anon_lifetime, type_needs_lifetime};
|
|
||||||
use witx::Module;
|
use witx::Module;
|
||||||
|
|
||||||
pub fn define_module_trait(names: &Names, m: &Module) -> TokenStream {
|
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,
|
// Check if we're returning an entity anotated with a lifetime,
|
||||||
// in which case, we'll need to annotate the function itself, and
|
// in which case, we'll need to annotate the function itself, and
|
||||||
// hence will need an explicit lifetime (rather than anonymous)
|
// 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)
|
(quote!('a), false)
|
||||||
} else {
|
} else {
|
||||||
(anon_lifetime(), true)
|
(anon_lifetime(), true)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use proc_macro2::{Ident, TokenStream};
|
|||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use witx::{AtomType, BuiltinType, Id, TypeRef};
|
use witx::{AtomType, BuiltinType, Id, TypeRef};
|
||||||
|
|
||||||
use crate::types::type_needs_lifetime;
|
use crate::lifetimes::LifetimeExt;
|
||||||
use crate::Config;
|
use crate::Config;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -52,7 +52,7 @@ impl Names {
|
|||||||
match tref {
|
match tref {
|
||||||
TypeRef::Name(nt) => {
|
TypeRef::Name(nt) => {
|
||||||
let ident = self.type_(&nt.name);
|
let ident = self.type_(&nt.name);
|
||||||
if type_needs_lifetime(&nt.tref) {
|
if nt.tref.needs_lifetime() {
|
||||||
quote!(#ident<#lifetime>)
|
quote!(#ident<#lifetime>)
|
||||||
} else {
|
} else {
|
||||||
quote!(#ident)
|
quote!(#ident)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::lifetimes::{anon_lifetime, LifetimeExt};
|
||||||
use crate::names::Names;
|
use crate::names::Names;
|
||||||
|
|
||||||
use proc_macro2::{Literal, TokenStream};
|
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::Int(i) => define_int(names, &namedtype.name, &i),
|
||||||
witx::Type::Flags(f) => define_flags(names, &namedtype.name, &f),
|
witx::Type::Flags(f) => define_flags(names, &namedtype.name, &f),
|
||||||
witx::Type::Struct(s) => {
|
witx::Type::Struct(s) => {
|
||||||
if struct_is_copy(s) {
|
if !s.needs_lifetime() {
|
||||||
define_copy_struct(names, &namedtype.name, &s)
|
define_copy_struct(names, &namedtype.name, &s)
|
||||||
} else {
|
} else {
|
||||||
define_ptr_struct(names, &namedtype.name, &s)
|
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 {
|
fn define_alias(names: &Names, name: &witx::Id, to: &witx::NamedType) -> TokenStream {
|
||||||
let ident = names.type_(name);
|
let ident = names.type_(name);
|
||||||
let rhs = names.type_(&to.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>;)
|
quote!(pub type #ident<'a> = #rhs<'a>;)
|
||||||
} else {
|
} else {
|
||||||
quote!(pub type #ident = #rhs;)
|
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 {
|
fn define_copy_struct(names: &Names, name: &witx::Id, s: &witx::StructDatatype) -> TokenStream {
|
||||||
let ident = names.type_(name);
|
let ident = names.type_(name);
|
||||||
let size = s.mem_size_align().size as u32;
|
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);
|
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:
|
// Type does not have a lifetime parameter:
|
||||||
quote! {
|
quote! {
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
@@ -887,7 +828,3 @@ fn atom_token(atom: witx::AtomType) -> TokenStream {
|
|||||||
witx::AtomType::F64 => quote!(f64),
|
witx::AtomType::F64 => quote!(f64),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn anon_lifetime() -> TokenStream {
|
|
||||||
quote!('_)
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user