Collection: cast to concrete type

Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
Luca Fulchir 2024-12-13 16:57:46 +01:00
parent 0c9bd1948f
commit 7beea1a36b
Signed by: luca.fulchir
GPG Key ID: 8F6440603D13A78E
8 changed files with 89 additions and 35 deletions

View File

@ -60,6 +60,7 @@ pub(crate) fn collection(
* *
#(#[::bok_macro::collection_dep(#all_deps_builder)]) #(#[::bok_macro::collection_dep(#all_deps_builder)])
* *
#[derive(::core::fmt::Debug)]
pub struct Collection { pub struct Collection {
repo: ::std::sync::Arc<#name>, repo: ::std::sync::Arc<#name>,
pkgs: ::std::sync::RwLock< pkgs: ::std::sync::RwLock<

View File

@ -58,7 +58,7 @@ pub(crate) fn package(attrs: TokenStream, input: TokenStream) -> TokenStream {
|| path.segments[1].ident.to_string() != "PkgEmpty" || path.segments[1].ident.to_string() != "PkgEmpty"
{ {
let repo_argument = { let repo_argument = {
let generic_id: ::syn::Path = ::syn::parse_quote!(id<R>); let generic_id: ::syn::Path = ::syn::parse_quote!(id<R, C>);
generic_id.segments.last().unwrap().arguments.clone() generic_id.segments.last().unwrap().arguments.clone()
}; };
path.segments.last_mut().unwrap().arguments = repo_argument; path.segments.last_mut().unwrap().arguments = repo_argument;
@ -103,7 +103,11 @@ pub(crate) fn package_path(
.into(); .into();
}; };
let generic_struct: ::syn::ItemStruct = ::syn::parse_quote! { let generic_struct: ::syn::ItemStruct = ::syn::parse_quote! {
pub struct test<R> where R: ::bok::Repository + 'static {} pub struct test<R, C>
where
R: ::bok::Repository + 'static,
C: ::bok::Collection,
{}
}; };
let (_, generics, where_clause) = generic_struct.generics.split_for_impl(); let (_, generics, where_clause) = generic_struct.generics.split_for_impl();
@ -142,9 +146,15 @@ pub(crate) fn package_path(
_bok_repo: ::std::marker::PhantomData<R> _bok_repo: ::std::marker::PhantomData<R>
}) })
.unwrap(); .unwrap();
let collection_marker = ::syn::Field::parse_named
.parse2(quote! {
_bok_collection: ::std::marker::PhantomData<C>
})
.unwrap();
base_fields_extra.push(pkg_version); base_fields_extra.push(pkg_version);
base_fields_extra.push(base_marker); base_fields_extra.push(base_marker);
base_fields_extra.push(repo_marker); base_fields_extra.push(repo_marker);
base_fields_extra.push(collection_marker);
} }
None => { None => {
return ::syn::Error::new( return ::syn::Error::new(
@ -165,6 +175,7 @@ pub(crate) fn package_path(
if id.to_string() == "version" if id.to_string() == "version"
|| id.to_string() == "_bok_base" || id.to_string() == "_bok_base"
|| id.to_string() == "_bok_repo" || id.to_string() == "_bok_repo"
|| id.to_string() == "_bok_collection"
{ {
continue; continue;
} }
@ -359,8 +370,16 @@ pub(crate) fn package_impl(
"BokDeps{}", "BokDeps{}",
t_id.path.segments.last().unwrap().ident t_id.path.segments.last().unwrap().ident
); );
let trait_deps_builder = ::quote::format_ident!(
"BokBuilderDeps{}",
t_id.path.segments.last().unwrap().ident
);
let g: ::syn::ItemImpl = ::syn::parse_quote! { let g: ::syn::ItemImpl = ::syn::parse_quote! {
impl<R> trait_name for #t_id<R> where R: ::bok::Repository + #trait_deps {} impl<R, C> trait_name for #t_id<R, C>
where
R: #trait_deps,
C: #trait_deps_builder,
{}
}; };
ast.generics = g.generics; ast.generics = g.generics;
ast.self_ty = g.self_ty; ast.self_ty = g.self_ty;
@ -638,16 +657,30 @@ pub(crate) fn package_impl_builder(
}; };
Ok(actual_repo) Ok(actual_repo)
}?; }?;
/*
let #arg_build = { let #arg_build = {
let build_any = #arg_build.0.as_any(); let build_any = #arg_build.0.as_any();
let Some(actual_build) = let Some(actual_build) =
build_any.downcast_ref::<#trait_deps_builder>() else { build_any.downcast_ref::<C>() else {
return Err(()); return Err(());
}; };
Ok(::bok::deps::Build(actual_build)) Ok(actual_build)
}?;
let #arg_runtime = {
let runtime_any = #arg_runtime.0.as_any();
let Some(actual_runtime) =
runtime_any.downcast_ref::<C>() else {
return Err(());
};
Ok(actual_runtime)
}?;
let #arg_test = {
let test_any = #arg_test.0.as_any();
let Some(actual_test) =
test_any.downcast_ref::<C>() else {
return Err(());
};
Ok(actual_test)
}?; }?;
*/
Ok(()) Ok(())
} }
}; };
@ -675,6 +708,7 @@ pub(crate) fn package_impl_builder(
if id.to_string() == "version" if id.to_string() == "version"
|| id.to_string() == "_bok_base" || id.to_string() == "_bok_base"
|| id.to_string() == "_bok_repo" || id.to_string() == "_bok_repo"
|| id.to_string() == "_bok_collection"
{ {
return None; return None;
} }
@ -705,6 +739,7 @@ pub(crate) fn package_impl_builder(
if id.to_string() == "version" if id.to_string() == "version"
|| id.to_string() == "_bok_base" || id.to_string() == "_bok_base"
|| id.to_string() == "_bok_repo" || id.to_string() == "_bok_repo"
|| id.to_string() == "_bok_collection"
{ {
return None; return None;
} }
@ -735,6 +770,7 @@ pub(crate) fn package_impl_builder(
if id.to_string() == "version" if id.to_string() == "version"
|| id.to_string() == "_bok_base" || id.to_string() == "_bok_base"
|| id.to_string() == "_bok_repo" || id.to_string() == "_bok_repo"
|| id.to_string() == "_bok_collection"
{ {
return None; return None;
} }
@ -765,6 +801,7 @@ pub(crate) fn package_impl_builder(
if id.to_string() == "version" if id.to_string() == "version"
|| id.to_string() == "_bok_base" || id.to_string() == "_bok_base"
|| id.to_string() == "_bok_repo" || id.to_string() == "_bok_repo"
|| id.to_string() == "_bok_collection"
{ {
return None; return None;
} }
@ -822,30 +859,33 @@ pub(crate) fn package_impl_builder(
quote! { quote! {
#[derive(::std::default::Default, ::std::fmt::Debug)] #[derive(::std::default::Default, ::std::fmt::Debug)]
pub struct #name_builder<R> pub struct #name_builder<R, C>
where where
R: ::bok::Repository + 'static + #trait_deps, R: 'static + #trait_deps,
C: 'static + #trait_deps_builder
{ {
_bok_repo: ::std::marker::PhantomData<R>, _bok_repo: ::std::marker::PhantomData<R>,
_bok_collection: ::std::marker::PhantomData<C>,
#(#non_opt_fields: ::std::option::Option<#non_opt_types>,)* #(#non_opt_fields: ::std::option::Option<#non_opt_types>,)*
#(#opt_fields: ::std::option::Option<#opt_types>,)* #(#opt_fields: ::std::option::Option<#opt_types>,)*
} }
#[::macro_magic::export_tokens(#full_export_path_name)] #[::macro_magic::export_tokens(#full_export_path_name)]
impl<R> ::bok::PkgBuilder for #name_builder<R> impl<R, C> ::bok::PkgBuilder for #name_builder<R, C>
where where
R: ::bok::Repository + 'static + #trait_deps, R: 'static + #trait_deps,
C: 'static + #trait_deps_builder,
{ {
fn name(&self) -> ::bok::PkgName { fn name(&self) -> ::bok::PkgName {
use ::bok::Pkg; use ::bok::Pkg;
#pkg_name::<R>::default().name() #pkg_name::<R,C>::default().name()
} }
fn path(&self) -> ::bok::Path<::bok::PkgName> { fn path(&self) -> ::bok::Path<::bok::PkgName> {
use ::bok::Pkg; use ::bok::Pkg;
#pkg_name::<R>::default().path() #pkg_name::<R,C>::default().path()
} }
fn version(&self) -> ::bok::Version { fn version(&self) -> ::bok::Version {
use ::bok::Pkg; use ::bok::Pkg;
#pkg_name::<R>::default().version() #pkg_name::<R,C>::default().version()
} }
fn as_any(&self) -> &dyn ::std::any::Any { fn as_any(&self) -> &dyn ::std::any::Any {
self self
@ -854,7 +894,7 @@ pub(crate) fn package_impl_builder(
self self
} }
fn default_unused(&mut self) -> &mut dyn ::bok::PkgBuilder { fn default_unused(&mut self) -> &mut dyn ::bok::PkgBuilder {
let def = #pkg_name::<R>::default(); let def = #pkg_name::<R,C>::default();
#(if self.#non_opt_fields5.is_none() { #(if self.#non_opt_fields5.is_none() {
self.#non_opt_fields5 = Some(def.#non_opt_fields5); self.#non_opt_fields5 = Some(def.#non_opt_fields5);
})* })*
@ -869,7 +909,7 @@ pub(crate) fn package_impl_builder(
#(if self.#non_opt_fields2.is_none() { #(if self.#non_opt_fields2.is_none() {
return ::std::result::Result::Err("unset field".into()); return ::std::result::Result::Err("unset field".into());
})* })*
let mut pkg = ::std::boxed::Box::new(#pkg_name::<R>::default()); let mut pkg = ::std::boxed::Box::new(#pkg_name::<R,C>::default());
#(pkg.#non_opt_fields3 = self.#non_opt_fields3.clone().unwrap();) #(pkg.#non_opt_fields3 = self.#non_opt_fields3.clone().unwrap();)
* *
#(pkg.#opt_fields2 = self.#opt_fields2.clone();) #(pkg.#opt_fields2 = self.#opt_fields2.clone();)
@ -879,13 +919,16 @@ pub(crate) fn package_impl_builder(
#(#local_funcs) #(#local_funcs)
* *
} }
impl<R> #name_builder<R> impl<R, C> #name_builder<R, C>
where where
R: ::bok::Repository +'static + #trait_deps, R: 'static + #trait_deps,
C: 'static + #trait_deps_builder,
{ {
// FIXME: difference from `::default()`?
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
_bok_repo: ::std::marker::PhantomData::default(), _bok_repo: ::std::marker::PhantomData::default(),
_bok_collection: ::std::marker::PhantomData::default(),
#(#non_opt_fields6: None,)* #(#non_opt_fields6: None,)*
#(#opt_fields4: None,)* #(#opt_fields4: None,)*
} }
@ -937,9 +980,10 @@ pub(crate) fn package_impl_builder(
-> ::std::result::Result<(),()>;) -> ::std::result::Result<(),()>;)
* *
} }
impl<R> #trait_options for #name_builder<R> impl<R, C> #trait_options for #name_builder<R, C>
where where
R: ::bok::Repository +'static + #trait_deps, R: 'static + #trait_deps,
C: 'static + #trait_deps_builder,
{ {
#(fn #non_opt_fields8 (&mut self, val : #non_opt_types4) #(fn #non_opt_fields8 (&mut self, val : #non_opt_types4)
-> ::std::result::Result<(),()> { -> ::std::result::Result<(),()> {
@ -1044,10 +1088,13 @@ pub(crate) fn package_impl_base_add(
} }
let trait_deps = ::quote::format_ident!("BokDeps{}", name_pkg); let trait_deps = ::quote::format_ident!("BokDeps{}", name_pkg);
let trait_deps_builder =
::quote::format_ident!("BokBuilderDeps{}", name_pkg);
let generic_struct: ::syn::ItemImpl = ::syn::parse_quote! { let generic_struct: ::syn::ItemImpl = ::syn::parse_quote! {
impl<R> test for #name_pkg <R> impl<R, C> test for #name_pkg<R, C>
where where
R: ::bok::Repository + 'static + #trait_deps, R: 'static + #trait_deps,
C: 'static + #trait_deps_builder,
{} {}
}; };
@ -1156,21 +1203,24 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
} }
let trait_deps = ::quote::format_ident!("BokDeps{}", name); let trait_deps = ::quote::format_ident!("BokDeps{}", name);
let trait_deps_builder = ::quote::format_ident!("BokBuilderDeps{}", name);
let expanded = quote! { let expanded = quote! {
impl<R> ::core::fmt::Display for #name<R> impl<R, C> ::core::fmt::Display for #name<R, C>
where where
R: ::bok::Repository + #trait_deps, R: #trait_deps,
C: #trait_deps_builder,
{ {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>)
->::core::fmt::Result ->::core::fmt::Result
{ {
<#name<R> as ::bok::PkgCode>::fmt(self, f) <#name<R, C> as ::bok::PkgCode>::fmt(self, f)
} }
} }
impl<R> ::bok::PkgCode for #name<R> impl<R, C> ::bok::PkgCode for #name<R, C>
where where
R: ::bok::Repository + 'static + #trait_deps, R: 'static + #trait_deps,
C: 'static + #trait_deps_builder,
{ {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>)
->::core::fmt::Result ->::core::fmt::Result
@ -1231,9 +1281,10 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
f.write_str(&formatted) f.write_str(&formatted)
} }
} }
impl<R> #name<R> impl<R, C> #name<R, C>
where where
R: ::bok::Repository + 'static + #trait_deps + ::core::default::Default, R: 'static + #trait_deps + ::core::default::Default,
C: 'static + #trait_deps_builder,
{ {
pub fn as_any(&self) -> &dyn ::std::any::Any { pub fn as_any(&self) -> &dyn ::std::any::Any {
self self

View File

@ -279,7 +279,7 @@ pub(crate) fn repo_packages(
// "#[repo_packages(my::pkg)]" -->> "#[repo_packages(my::pkg<Self>)])" // "#[repo_packages(my::pkg)]" -->> "#[repo_packages(my::pkg<Self>)])"
let mut rewrite = false; let mut rewrite = false;
let repo_argument = { let repo_argument = {
let generic_id: ::syn::Path = ::syn::parse_quote!(id<Self>); let generic_id: ::syn::Path = ::syn::parse_quote!(id<Self, Collection>);
generic_id.segments.last().unwrap().arguments.clone() generic_id.segments.last().unwrap().arguments.clone()
}; };
for p in packages.0.iter_mut() { for p in packages.0.iter_mut() {

View File

@ -16,6 +16,7 @@
*/ */
mod conf; mod conf;
//mod expanded;
mod repos; mod repos;
fn main() { fn main() {

View File

@ -32,6 +32,7 @@ impl ::std::default::Default for One {
One { One {
_bok_base: ::std::marker::PhantomData::default(), _bok_base: ::std::marker::PhantomData::default(),
_bok_repo: ::std::marker::PhantomData::default(), _bok_repo: ::std::marker::PhantomData::default(),
_bok_collection: ::std::marker::PhantomData::default(),
my_attr: 1, my_attr: 1,
version: ::bok::Version { version: ::bok::Version {
major: 0, major: 0,

View File

@ -22,14 +22,13 @@ pub struct Three {
pub my_attr: u32, pub my_attr: u32,
} }
impl<R> ::std::default::Default for Three<R> #[::bok::package_impl]
where impl ::std::default::Default for Three {
R: ::bok::Repository,
{
fn default() -> Self { fn default() -> Self {
Three { Three {
_bok_base: ::std::marker::PhantomData::default(), _bok_base: ::std::marker::PhantomData::default(),
_bok_repo: ::std::marker::PhantomData::default(), _bok_repo: ::std::marker::PhantomData::default(),
_bok_collection: ::std::marker::PhantomData::default(),
version: ::bok::Version { version: ::bok::Version {
major: 0, major: 0,
minor: 0, minor: 0,

View File

@ -28,6 +28,7 @@ impl ::std::default::Default for Two {
Two { Two {
_bok_base: ::std::marker::PhantomData::default(), _bok_base: ::std::marker::PhantomData::default(),
_bok_repo: ::std::marker::PhantomData::default(), _bok_repo: ::std::marker::PhantomData::default(),
_bok_collection: ::std::marker::PhantomData::default(),
my_attr: 2, my_attr: 2,
my_attr2: 2, my_attr2: 2,
version: ::bok::Version { version: ::bok::Version {

View File

@ -33,7 +33,7 @@ pub type PkgMap =
BTreeMap<Path<PkgName>, (Arc<dyn Repository>, ArcLock<dyn PkgBuilder>)>; BTreeMap<Path<PkgName>, (Arc<dyn Repository>, ArcLock<dyn PkgBuilder>)>;
*/ */
pub trait Collection: ::std::any::Any { pub trait Collection: ::std::any::Any + ::core::fmt::Debug {
fn as_any(&self) -> &dyn ::std::any::Any; fn as_any(&self) -> &dyn ::std::any::Any;
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any; fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any;
} }