Skip to content

Commit

Permalink
Use composite_type! lifetimes in pgrx-sql-entity-graph (#1463)
Browse files Browse the repository at this point in the history
I was working on fixing the auto-staticizing lifetime issues and noticed
this likely would be landable on its own. This moves out `struct
CompositeTypeMacro` into its own file and starts to actually modularize
the code around it a little, to start actually preserving the lifetimes
in their usage during macro expansion. Because we need to also generate
wrapping types, it doesn't count as much of a cleanup on its own, but
that's why I'm landing it separately.
  • Loading branch information
workingjubilee authored Jan 6, 2024
1 parent 684b4c3 commit 7df371d
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 29 deletions.
38 changes: 38 additions & 0 deletions pgrx-sql-entity-graph/src/composite_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/// Innards of a `composite_type!`
///
/// For SQL generation and further expansion.
/// Use this so you don't drop the span on the floor.
#[derive(Debug, Clone)]
pub struct CompositeTypeMacro {
pub(crate) lifetime: Option<syn::Lifetime>,
pub(crate) expr: syn::Expr,
pub(crate) span: proc_macro2::Span,
}

impl syn::parse::Parse for CompositeTypeMacro {
fn parse(input: syn::parse::ParseStream) -> Result<Self, syn::Error> {
let span = input.span();
let lifetime: Option<syn::Lifetime> = input.parse().ok();
let _comma: Option<syn::Token![,]> = input.parse().ok();
let expr = input.parse()?;
Ok(Self { lifetime, expr, span })
}
}

/// Take a `composite_type!` from a macro
pub fn handle_composite_type_macro(mac: &syn::Macro) -> syn::Result<CompositeTypeMacro> {
let out: CompositeTypeMacro = mac.parse_body()?;
Ok(out)
}

impl CompositeTypeMacro {
/// Expands into the implementing type, explicitly eliding the lifetime
/// if none is actually given.
pub fn expand_with_lifetime(&self) -> syn::Type {
let CompositeTypeMacro { lifetime, span, .. } = self.clone();
let lifetime = lifetime.unwrap_or_else(|| syn::Lifetime::new("'_", span));
syn::parse_quote! {
::pgrx::heap_tuple::PgHeapTuple<#lifetime, ::pgrx::pgbox::AllocatedByRust>
}
}
}
1 change: 1 addition & 0 deletions pgrx-sql-entity-graph/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub use to_sql::{ToSql, ToSqlConfig};
pub use used_type::{UsedType, UsedTypeEntity};

pub(crate) mod aggregate;
pub(crate) mod composite_type;
pub(crate) mod control_file;
pub(crate) mod enrich;
pub(crate) mod extension_sql;
Expand Down
46 changes: 17 additions & 29 deletions pgrx-sql-entity-graph/src/used_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ to the `pgrx` framework and very subject to change between versions. While you m
*/
use std::ops::Deref;

use crate::composite_type::{handle_composite_type_macro, CompositeTypeMacro};
use crate::lifetimes::staticize_lifetimes;
use proc_macro2::Span;
use quote::ToTokens;
Expand Down Expand Up @@ -381,9 +382,11 @@ fn resolve_vec_inner(
Err(syn::Error::new(mac.span(), "`Vec<default!(T, default)>` not supported, choose `default!(Vec<T>, ident)` instead"))
}
"composite_type" => {
let sql = Some(handle_composite_type_macro(mac)?);
let composite_mac = handle_composite_type_macro(mac)?;
let comp_ty = composite_mac.expand_with_lifetime();
let sql = Some(composite_mac);
let ty = syn::parse_quote! {
Vec<::pgrx::heap_tuple::PgHeapTuple<'static, ::pgrx::pgbox::AllocatedByRust>>
Vec<#comp_ty>
};
Ok((ty, sql))
}
Expand Down Expand Up @@ -442,9 +445,11 @@ fn resolve_variadic_array_inner(
Err(syn::Error::new(mac.span(), "`VariadicArray<default!(T, default)>` not supported, choose `default!(VariadicArray<T>, ident)` instead"))
}
"composite_type" => {
let sql = Some(handle_composite_type_macro(mac)?);
let composite_mac = handle_composite_type_macro(mac)?;
let comp_ty = composite_mac.expand_with_lifetime();
let sql = Some(composite_mac);
let ty = syn::parse_quote! {
::pgrx::datum::VariadicArray<'static, ::pgrx::heap_tuple::PgHeapTuple<'static, ::pgrx::pgbox::AllocatedByRust>>
::pgrx::datum::VariadicArray<'static, #comp_ty>
};
Ok((ty, sql))
}
Expand Down Expand Up @@ -503,9 +508,11 @@ fn resolve_array_inner(
Err(syn::Error::new(mac.span(), "`VariadicArray<default!(T, default)>` not supported, choose `default!(VariadicArray<T>, ident)` instead"))
}
"composite_type" => {
let sql = Some(handle_composite_type_macro(mac)?);
let composite_mac = handle_composite_type_macro(mac)?;
let comp_ty = composite_mac.expand_with_lifetime();
let sql = Some(composite_mac);
let ty = syn::parse_quote! {
::pgrx::datum::Array<'static, ::pgrx::heap_tuple::PgHeapTuple<'static, ::pgrx::pgbox::AllocatedByRust>>
::pgrx::datum::Array<'static, #comp_ty>
};
Ok((ty, sql))
}
Expand Down Expand Up @@ -556,9 +563,11 @@ fn resolve_option_inner(
match archetype.ident.to_string().as_str() {
// Option<composite_type!(..)>
"composite_type" => {
let sql = Some(handle_composite_type_macro(mac)?);
let composite_mac = handle_composite_type_macro(mac)?;
let comp_ty = composite_mac.expand_with_lifetime();
let sql = Some(composite_mac);
let ty = syn::parse_quote! {
Option<::pgrx::heap_tuple::PgHeapTuple<'static, ::pgrx::pgbox::AllocatedByRust>>
Option<#comp_ty>
};
Ok((ty, sql))
},
Expand Down Expand Up @@ -613,11 +622,6 @@ fn resolve_option_inner(
}
}

fn handle_composite_type_macro(mac: &syn::Macro) -> syn::Result<CompositeTypeMacro> {
let out: CompositeTypeMacro = mac.parse_body()?;
Ok(out)
}

fn handle_default_macro(mac: &syn::Macro) -> syn::Result<(syn::Type, Option<String>)> {
let out: DefaultMacro = mac.parse_body()?;
let true_ty = out.ty;
Expand Down Expand Up @@ -705,19 +709,3 @@ impl Parse for DefaultMacro {
Ok(Self { ty, expr })
}
}

#[derive(Debug, Clone)]
pub struct CompositeTypeMacro {
#[allow(dead_code)]
pub(crate) lifetime: Option<syn::Lifetime>,
pub(crate) expr: syn::Expr,
}

impl Parse for CompositeTypeMacro {
fn parse(input: ParseStream) -> Result<Self, syn::Error> {
let lifetime: Option<syn::Lifetime> = input.parse().ok();
let _comma: Option<Token![,]> = input.parse().ok();
let expr = input.parse()?;
Ok(Self { lifetime, expr })
}
}

0 comments on commit 7df371d

Please sign in to comment.