factor lifetime determination into its own module

This commit is contained in:
Pat Hickey
2020-02-26 15:25:52 -08:00
committed by Jakub Konka
parent 515b751333
commit 10dcaeeab4
6 changed files with 68 additions and 75 deletions

View File

@@ -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(&param.name);
let name = names.func_param(&param.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(&param.name);

View File

@@ -2,6 +2,7 @@ extern crate proc_macro;
mod config;
mod funcs;
mod lifetimes;
mod module_trait;
mod names;
mod types;

View 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!('_)
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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!('_)
}