Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Concretes in entry points #276

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion examples/contracts/generics_forwarded/src/bin/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ fn main() {
execute: ContractExecMsg<SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomQuery>,
query: ContractQueryMsg<SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomQuery>,
}
}
}


5 changes: 4 additions & 1 deletion examples/contracts/generics_forwarded/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use sylvia::types::{
};
use sylvia::{contract, schemars};

#[cfg(not(feature = "library"))]
use sylvia::types::SvCustomQuery;

pub struct GenericsForwardedContract<
InstantiateT,
Exec1T,
Expand Down Expand Up @@ -35,7 +38,7 @@ pub struct GenericsForwardedContract<
)>,
}

// TODO: Add entry points call.
#[cfg_attr(not(feature = "library"), sylvia::entry_points(generics<SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, SvCustomMsg, sylvia::types::SvCustomMsg, SvCustomMsg, SvCustomQuery, String>, custom(msg=SvCustomMsg, query=SvCustomQuery)))]
#[contract]
#[messages(generic<Exec1T, Exec2T, Exec3T, Query1T, Query2T, Query3T, SvCustomMsg> as Generic: custom(msg, query))]
#[messages(cw1 as Cw1: custom(msg, query))]
Expand Down
7 changes: 7 additions & 0 deletions examples/interfaces/generic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ mod tests {
let deps = mock_dependencies();
let querier_wrapper: QuerierWrapper = QuerierWrapper::new(&deps.querier);

// TODO: Allow generic querier calls without fully qualified path.
// ISSUE: BoundQuerier is a non generic type. We try to use method from a generic trait
// Querier. Because of that generic values are unknown at the time we call these methods.
// This issue is present when we have multiple queries using different generic types and
// Rust compiler cannot deduce types of these generics while constructing `QueryMsg`.
// FIX: Solution might be to change the `BoundQuerier` to be generic over the same types as
// `Querier`. I think this should be possible with `BoundQuerier` exposed via `InterfaceApi`.
let querier = super::sv::BoundQuerier::borrowed(&contract, &querier_wrapper);
let _: Result<SvCustomMsg, _> =
super::sv::Querier::<_, _, _, SvCustomMsg>::generic_query_one(
Expand Down
16 changes: 14 additions & 2 deletions sylvia-derive/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,13 @@ impl<'a> MsgVariant<'a> {
}
}

// TODO: This could be made msg_type agnostic and stores map of msg_ty/variants.
// This could nicely increase maintainability as we create `MsgVariants` tens of times
// during the macro call.
// Next step would be to create a `Context` type, init it in `input.rs` and then pass
// to messages/multitest.
// It would however require another type to bind the `variants`, `generics` and `predicates`
// and we already have the `MsgVariants` and `MsgVariant`.
#[derive(Debug)]
pub struct MsgVariants<'a, Generic> {
variants: Vec<MsgVariant<'a>>,
Expand Down Expand Up @@ -1651,11 +1658,11 @@ pub struct EntryPoints<'a> {
override_entry_points: OverrideEntryPoints,
generics: Vec<&'a GenericParam>,
where_clause: &'a Option<WhereClause>,
attrs: EntryPointArgs,
attrs: EntryPointArgs<'a>,
}

impl<'a> EntryPoints<'a> {
pub fn new(source: &'a ItemImpl, attrs: EntryPointArgs) -> Self {
pub fn new(source: &'a ItemImpl, attrs: EntryPointArgs<'a>) -> Self {
let sylvia = crate_module();
let name = StripGenerics.fold_type(*source.self_ty.clone());
let override_entry_points = OverrideEntryPoints::new(&source.attrs);
Expand Down Expand Up @@ -1704,6 +1711,11 @@ impl<'a> EntryPoints<'a> {
} = self;
let sylvia = crate_module();

let custom = match &attrs.custom {
Some(custom) => custom,
None => custom,
};

let custom_msg = custom.msg_or_default();
let custom_query = custom.query_or_default();

Expand Down
38 changes: 30 additions & 8 deletions sylvia-derive/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,27 +48,49 @@ impl Parse for ContractArgs {
}

/// Parsed arguments for `entry_points` macro
pub struct EntryPointArgs {
#[derive(Default)]
pub struct EntryPointArgs<'a> {
/// Types used in place of contracts generics.
pub generics: Option<Punctuated<GenericArgument, Token![,]>>,
/// Custom msg/query used in place of contracts generic ones.
pub custom: Option<Custom<'a>>,
}

impl Parse for EntryPointArgs {
impl<'a> Parse for EntryPointArgs<'a> {
fn parse(input: ParseStream) -> Result<Self> {
let mut entry_points_args = Self::default();
if input.is_empty() {
return Ok(Self { generics: None });
return Ok(entry_points_args);
}

let path: Path = input.parse()?;
let generics: Path = input.parse()?;
match generics.segments.last() {
Some(segment) if segment.ident == "generics" => {
entry_points_args.generics = Some(extract_generics_from_path(&generics))
}
_ => return Err(Error::new(generics.span(), "Expected `generics`.")),
};

let generics = match path.segments.last() {
Some(segment) if segment.ident == "generics" => Some(extract_generics_from_path(&path)),
_ => return Err(Error::new(path.span(), "Expected `generics`")),
let comma: Option<Token![,]> = input.parse().ok();
if comma.is_none() {
return Ok(entry_points_args);
}

let custom: Option<Path> = input.parse().ok();
match custom {
Some(custom)
if custom.get_ident().map(|custom| custom.to_string())
== Some("custom".to_owned()) =>
{
entry_points_args.custom = Some(Custom::parse.parse2(input.parse()?)?);
}
Some(attr) => return Err(Error::new(attr.span(), "Expected `custom`.")),
_ => (),
};

let _: Nothing = input.parse()?;

Ok(Self { generics })
Ok(entry_points_args)
}
}

Expand Down