Skip to content

Commit

Permalink
use lifetimes on types that require it
Browse files Browse the repository at this point in the history
  • Loading branch information
Pat Hickey committed Jan 31, 2020
1 parent 29c3ef9 commit f321f05
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 31 deletions.
18 changes: 9 additions & 9 deletions crates/generate/src/funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use proc_macro2::TokenStream;
use quote::quote;

use crate::names::Names;
use crate::types::struct_is_copy;
use crate::types::{anon_lifetime, struct_is_copy};

pub fn define_func(names: &Names, func: &witx::InterfaceFunc) -> TokenStream {
let ident = names.func(&func.name);
Expand Down Expand Up @@ -58,7 +58,7 @@ pub fn define_func(names: &Names, func: &witx::InterfaceFunc) -> TokenStream {
witx::TypePassedBy::Value(atom) => names.atom_type(atom),
_ => unreachable!("err should always be passed by value"),
};
let err_typename = names.type_ref(&tref);
let err_typename = names.type_ref(&tref, anon_lifetime());
quote! {
let err: #err_typename = ::memory::GuestErrorType::from_error(e, ctx);
return #abi_ret::from(err);
Expand Down Expand Up @@ -106,7 +106,7 @@ pub fn define_func(names: &Names, func: &witx::InterfaceFunc) -> TokenStream {
let marshal_rets_post = marshal_rets.map(|(_pre, post)| post);

let success = if let Some(err_type) = err_type {
let err_typename = names.type_ref(&err_type);
let err_typename = names.type_ref(&err_type, anon_lifetime());
quote! {
let success:#err_typename = ::memory::GuestErrorType::success();
#abi_ret::from(success)
Expand All @@ -133,7 +133,7 @@ fn marshal_arg(
error_handling: TokenStream,
) -> TokenStream {
let tref = &param.tref;
let interface_typename = names.type_ref(&tref);
let interface_typename = names.type_ref(&tref, anon_lifetime());

let try_into_conversion = {
let name = names.func_param(&param.name);
Expand Down Expand Up @@ -180,7 +180,7 @@ fn marshal_arg(
witx::BuiltinType::String => unimplemented!("string types unimplemented"),
},
witx::Type::Pointer(pointee) => {
let pointee_type = names.type_ref(pointee);
let pointee_type = names.type_ref(pointee, anon_lifetime());
let name = names.func_param(&param.name);
quote! {
let #name = match memory.ptr_mut::<#pointee_type>(#name as u32) {
Expand All @@ -192,7 +192,7 @@ fn marshal_arg(
}
}
witx::Type::ConstPointer(pointee) => {
let pointee_type = names.type_ref(pointee);
let pointee_type = names.type_ref(pointee, anon_lifetime());
let name = names.func_param(&param.name);
quote! {
let #name = match memory.ptr::<#pointee_type>(#name as u32) {
Expand All @@ -204,7 +204,7 @@ fn marshal_arg(
}
}
witx::Type::Struct(s) if struct_is_copy(&s) => {
let pointee_type = names.type_ref(tref);
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);
quote! {
Expand All @@ -222,7 +222,7 @@ fn marshal_arg(
}
}
witx::Type::Struct(s) if !struct_is_copy(&s) => {
let pointee_type = names.type_ref(tref);
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);
quote! {
Expand Down Expand Up @@ -251,7 +251,7 @@ fn marshal_result(
let tref = &result.tref;

let write_val_to_ptr = {
let pointee_type = names.type_ref(tref);
let pointee_type = names.type_ref(tref, anon_lifetime());
// core type is given func_ptr_binding name.
let ptr_name = names.func_ptr_binding(&result.name);
let pre = quote! {
Expand Down
7 changes: 4 additions & 3 deletions crates/generate/src/module_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use proc_macro2::TokenStream;
use quote::quote;

use crate::names::Names;
use crate::types::anon_lifetime;
use witx::Module;

pub fn define_module_trait(names: &Names, m: &Module) -> TokenStream {
Expand All @@ -10,7 +11,7 @@ pub fn define_module_trait(names: &Names, m: &Module) -> TokenStream {
let funcname = names.func(&f.name);
let args = f.params.iter().map(|arg| {
let arg_name = names.func_param(&arg.name);
let arg_typename = names.type_ref(&arg.tref);
let arg_typename = names.type_ref(&arg.tref, anon_lifetime());
let arg_type = match arg.tref.type_().passed_by() {
witx::TypePassedBy::Value { .. } => quote!(#arg_typename),
witx::TypePassedBy::Pointer { .. } => quote!(&#arg_typename),
Expand All @@ -22,11 +23,11 @@ pub fn define_module_trait(names: &Names, m: &Module) -> TokenStream {
.results
.iter()
.skip(1)
.map(|ret| names.type_ref(&ret.tref));
.map(|ret| names.type_ref(&ret.tref, anon_lifetime()));
let err = f
.results
.get(0)
.map(|err_result| names.type_ref(&err_result.tref))
.map(|err_result| names.type_ref(&err_result.tref, anon_lifetime()))
.unwrap_or(quote!(()));
quote!(fn #funcname(&mut self, #(#args),*) -> Result<(#(#rets),*), #err>;)
});
Expand Down
17 changes: 11 additions & 6 deletions crates/generate/src/names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +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::Config;

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -47,21 +48,25 @@ impl Names {
}
}

pub fn type_ref(&self, tref: &TypeRef) -> TokenStream {
pub fn type_ref(&self, tref: &TypeRef, lifetime: TokenStream) -> TokenStream {
match tref {
TypeRef::Name(nt) => {
let ident = self.type_(&nt.name);
quote!(#ident)
if type_needs_lifetime(&nt.tref) {
quote!(#ident<#lifetime>)
} else {
quote!(#ident)
}
}
TypeRef::Value(ty) => match &**ty {
witx::Type::Builtin(builtin) => self.builtin_type(*builtin),
witx::Type::Pointer(pointee) => {
let pointee_type = self.type_ref(&pointee);
quote!(::memory::GuestPtrMut<#pointee_type>)
let pointee_type = self.type_ref(&pointee, lifetime.clone());
quote!(::memory::GuestPtrMut<#lifetime, #pointee_type>)
}
witx::Type::ConstPointer(pointee) => {
let pointee_type = self.type_ref(&pointee);
quote!(::memory::GuestPtr<#pointee_type>)
let pointee_type = self.type_ref(&pointee, lifetime.clone());
quote!(::memory::GuestPtr<#lifetime, #pointee_type>)
}
_ => unimplemented!("anonymous type ref"),
},
Expand Down
67 changes: 54 additions & 13 deletions crates/generate/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,25 @@ pub fn define_datatype(names: &Names, namedtype: &witx::NamedType) -> TokenStrea
witx::Type::Union(_) => unimplemented!("union types"),
witx::Type::Handle(_h) => unimplemented!("handle types"),
witx::Type::Builtin(b) => define_builtin(names, &namedtype.name, *b),
witx::Type::Pointer { .. } => unimplemented!("pointer types"),
witx::Type::ConstPointer { .. } => unimplemented!("constpointer types"),
witx::Type::Pointer(p) => {
define_witx_pointer(names, &namedtype.name, quote!(::memory::GuestPtrMut), p)
}
witx::Type::ConstPointer(p) => {
define_witx_pointer(names, &namedtype.name, quote!(::memory::GuestPtr), p)
}
witx::Type::Array { .. } => unimplemented!("array types"),
},
}
}

fn define_alias(names: &Names, name: &witx::Id, to: &witx::NamedType) -> TokenStream {
let ident = names.type_(name);
let to = names.type_(&to.name);

quote!(pub type #ident = #to;)
let rhs = names.type_(&to.name);
if type_needs_lifetime(&to.tref) {
quote!(pub type #ident<'a> = #rhs<'a>;)
} else {
quote!(pub type #ident = #rhs;)
}
}

fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenStream {
Expand Down Expand Up @@ -133,6 +140,23 @@ fn define_builtin(names: &Names, name: &witx::Id, builtin: witx::BuiltinType) ->
quote!(pub type #ident = #built;)
}

pub fn type_needs_lifetime(tref: &witx::TypeRef) -> bool {
match &*tref.type_() {
witx::Type::Builtin(b) => match b {
witx::BuiltinType::String => unimplemented!(),
_ => 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 { .. } => true,
witx::Type::Pointer { .. } | witx::Type::ConstPointer { .. } => true,
witx::Type::Array { .. } => unimplemented!(),
}
}

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),
Expand All @@ -158,11 +182,11 @@ fn define_copy_struct(names: &Names, name: &witx::Id, s: &witx::StructDatatype)

let member_decls = s.members.iter().map(|m| {
let name = names.struct_member(&m.name);
let type_ = names.type_ref(&m.tref);
let type_ = names.type_ref(&m.tref, anon_lifetime());
quote!(pub #name: #type_)
});
let member_valids = s.member_layout().into_iter().map(|ml| {
let type_ = names.type_ref(&ml.member.tref);
let type_ = names.type_ref(&ml.member.tref, anon_lifetime());
let offset = ml.offset as u32;
let fieldname = names.struct_member(&ml.member.name);
quote! {
Expand Down Expand Up @@ -221,11 +245,11 @@ fn define_ptr_struct(names: &Names, name: &witx::Id, s: &witx::StructDatatype) -
witx::TypeRef::Value(ty) => match &**ty {
witx::Type::Builtin(builtin) => names.builtin_type(*builtin),
witx::Type::Pointer(pointee) => {
let pointee_type = names.type_ref(&pointee);
let pointee_type = names.type_ref(&pointee, quote!('a));
quote!(::memory::GuestPtrMut<'a, #pointee_type>)
}
witx::Type::ConstPointer(pointee) => {
let pointee_type = names.type_ref(&pointee);
let pointee_type = names.type_ref(&pointee, quote!('a));
quote!(::memory::GuestPtr<'a, #pointee_type>)
}
_ => unimplemented!("other anonymous struct members"),
Expand All @@ -239,11 +263,11 @@ fn define_ptr_struct(names: &Names, name: &witx::Id, s: &witx::StructDatatype) -
witx::TypeRef::Value(ty) => match &**ty {
witx::Type::Builtin(builtin) => names.builtin_type(*builtin),
witx::Type::Pointer(pointee) => {
let pointee_type = names.type_ref(&pointee);
let pointee_type = names.type_ref(&pointee, anon_lifetime());
quote!(::memory::GuestPtrMut::<#pointee_type>)
}
witx::Type::ConstPointer(pointee) => {
let pointee_type = names.type_ref(&pointee);
let pointee_type = names.type_ref(&pointee, anon_lifetime());
quote!(::memory::GuestPtr::<#pointee_type>)
}
_ => unimplemented!("other anonymous struct members"),
Expand Down Expand Up @@ -286,13 +310,13 @@ fn define_ptr_struct(names: &Names, name: &witx::Id, s: &witx::StructDatatype) -
}
}
witx::Type::Pointer(pointee) => {
let pointee_type = names.type_ref(&pointee);
let pointee_type = names.type_ref(&pointee, anon_lifetime());
quote! {
let #name = ::memory::GuestPtrMut::<#pointee_type>::read_from_guest(&location.cast(#offset)?)?;
}
}
witx::Type::ConstPointer(pointee) => {
let pointee_type = names.type_ref(&pointee);
let pointee_type = names.type_ref(&pointee, anon_lifetime());
quote! {
let #name = ::memory::GuestPtr::<#pointee_type>::read_from_guest(&location.cast(#offset)?)?;
}
Expand Down Expand Up @@ -340,6 +364,19 @@ fn define_ptr_struct(names: &Names, name: &witx::Id, s: &witx::StructDatatype) -
}
}
}

fn define_witx_pointer(
names: &Names,
name: &witx::Id,
pointer_type: TokenStream,
pointee: &witx::TypeRef,
) -> TokenStream {
let ident = names.type_(name);
let pointee_type = names.type_ref(pointee, quote!('a));

quote!(pub type #ident<'a> = #pointer_type<'a, #pointee_type>;)
}

fn int_repr_tokens(int_repr: witx::IntRepr) -> TokenStream {
match int_repr {
witx::IntRepr::U8 => quote!(u8),
Expand All @@ -356,3 +393,7 @@ fn atom_token(atom: witx::AtomType) -> TokenStream {
witx::AtomType::F64 => quote!(f64),
}
}

pub fn anon_lifetime() -> TokenStream {
quote!('_)
}
3 changes: 3 additions & 0 deletions test.witx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
(field $first (@witx const_pointer s32))
(field $second (@witx const_pointer s32))))

(typename $named_ptr (@witx pointer f32))
(typename $named_ptr_to_ptr (@witx pointer (@witx pointer f64)))

(module $foo
(@interface func (export "bar")
(param $an_int u32)
Expand Down

0 comments on commit f321f05

Please sign in to comment.