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

fix: prohibit NEAR function generics #980

Merged
merged 12 commits into from
Jan 23, 2023
8 changes: 3 additions & 5 deletions near-sdk-macros/src/core_impl/abi/abi_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@ use crate::core_impl::{
};

pub fn generate(i: &ItemImplInfo) -> TokenStream2 {
let public_functions: Vec<&ImplItemMethodInfo> =
i.methods.iter().filter(|m| m.is_public || i.is_trait_impl).collect();
if public_functions.is_empty() {
if i.methods.is_empty() {
// Short-circuit if there are no public functions to export to ABI
return TokenStream2::new();
}

let functions: Vec<TokenStream2> = public_functions.iter().map(|m| m.abi_struct()).collect();
let first_function_name = &public_functions[0].attr_signature_info.ident;
let functions: Vec<TokenStream2> = i.methods.iter().map(|m| m.abi_struct()).collect();
let first_function_name = &i.methods[0].attr_signature_info.ident;
let near_abi_symbol = format_ident!("__near_abi_{}", first_function_name);
quote! {
#[cfg(not(target_arch = "wasm32"))]
Expand Down
6 changes: 3 additions & 3 deletions near-sdk-macros/src/core_impl/code_generator/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ mod tests {
#[warn(unused)]
pub fn method(&self) { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false,impl_type).unwrap().unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curious, doesn't look like cargo-fmt acted on these..

Suggested change
let method_info = ImplItemMethodInfo::new(&mut method, false,impl_type).unwrap().unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, that's interesting. Looks like a bug, wondering if I can create a minimal reproduction.

let actual = generate_ext_function(&method_info.attr_signature_info);

// Note: only whitelisted non-bindgen attributes are forwarded.
Expand All @@ -267,7 +267,7 @@ mod tests {
let mut method: ImplItemMethod = parse_quote! {
pub fn method(&self, k: &String) { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false,impl_type).unwrap().unwrap();
itegulov marked this conversation as resolved.
Show resolved Hide resolved
let actual = generate_ext_function(&method_info.attr_signature_info);
let expected = quote!(
pub fn method(self, k: &String,) -> near_sdk::Promise {
Expand Down Expand Up @@ -298,7 +298,7 @@ mod tests {
let mut method: ImplItemMethod = parse_quote! {
pub fn borsh_test(&mut self, #[serializer(borsh)] a: String) {}
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false,impl_type).unwrap().unwrap();
itegulov marked this conversation as resolved.
Show resolved Hide resolved
let actual = generate_ext_function(&method_info.attr_signature_info);
let expected = quote!(
pub fn borsh_test(self, a: String,) -> near_sdk::Promise {
Expand Down
67 changes: 31 additions & 36 deletions near-sdk-macros/src/core_impl/code_generator/item_impl_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ impl ItemImplInfo {
pub fn wrapper_code(&self) -> TokenStream2 {
let mut res = TokenStream2::new();
for method in &self.methods {
if method.is_public || self.is_trait_impl {
res.extend(method.method_wrapper());
}
res.extend(method.method_wrapper());
}
res
}
Expand All @@ -20,10 +18,7 @@ impl ItemImplInfo {
match syn::parse::<Ident>(self.ty.to_token_stream().into()) {
Ok(n) => generate_ext_function_wrappers(
&n,
self.methods
.iter()
.filter(|m| m.is_public || self.is_trait_impl)
.map(|m| &m.attr_signature_info),
self.methods.iter().map(|m| &m.attr_signature_info),
),
Err(e) => syn::Error::new(self.ty.span(), e).to_compile_error(),
}
Expand All @@ -42,7 +37,7 @@ mod tests {
fn trait_implt() {
let impl_type: Type = syn::parse_str("Hello").unwrap();
let mut method: ImplItemMethod = syn::parse_str("fn method(&self) { }").unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, true, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand All @@ -60,7 +55,7 @@ mod tests {
fn no_args_no_return_no_mut() {
let impl_type: Type = syn::parse_str("Hello").unwrap();
let mut method: ImplItemMethod = syn::parse_str("pub fn method(&self) { }").unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand All @@ -78,7 +73,7 @@ mod tests {
fn owned_no_args_no_return_no_mut() {
let impl_type: Type = syn::parse_str("Hello").unwrap();
let mut method: ImplItemMethod = syn::parse_str("pub fn method(self) { }").unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand All @@ -97,7 +92,7 @@ mod tests {
fn mut_owned_no_args_no_return() {
let impl_type: Type = syn::parse_str("Hello").unwrap();
let mut method: ImplItemMethod = syn::parse_str("pub fn method(mut self) { }").unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand All @@ -115,7 +110,7 @@ mod tests {
fn no_args_no_return_mut() {
let impl_type: Type = syn::parse_str("Hello").unwrap();
let mut method: ImplItemMethod = syn::parse_str("pub fn method(&mut self) { }").unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand All @@ -137,7 +132,7 @@ mod tests {
fn arg_no_return_no_mut() {
let impl_type: Type = syn::parse_str("Hello").unwrap();
let mut method: ImplItemMethod = syn::parse_str("pub fn method(&self, k: u64) { }").unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -165,7 +160,7 @@ mod tests {
let impl_type: Type = syn::parse_str("Hello").unwrap();
let mut method: ImplItemMethod =
syn::parse_str("pub fn method(&mut self, k: u64, m: Bar) { }").unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -198,7 +193,7 @@ mod tests {
let impl_type: Type = syn::parse_str("Hello").unwrap();
let mut method: ImplItemMethod =
syn::parse_str("pub fn method(&mut self, k: u64, m: Bar) -> Option<u64> { }").unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -234,7 +229,7 @@ mod tests {
let impl_type: Type = syn::parse_str("Hello").unwrap();
let mut method: ImplItemMethod =
syn::parse_str("pub fn method(&self) -> &Option<u64> { }").unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand All @@ -255,7 +250,7 @@ mod tests {
fn arg_ref() {
let impl_type: Type = syn::parse_str("Hello").unwrap();
let mut method: ImplItemMethod = syn::parse_str("pub fn method(&self, k: &u64) { }").unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -283,7 +278,7 @@ mod tests {
let impl_type: Type = syn::parse_str("Hello").unwrap();
let mut method: ImplItemMethod =
syn::parse_str("pub fn method(&self, k: &mut u64) { }").unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -312,7 +307,7 @@ mod tests {
let mut method: ImplItemMethod = parse_quote! {
#[private] pub fn method(&self, #[callback_unwrap] x: &mut u64, y: String, #[callback_unwrap] z: Vec<u8>) { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -356,7 +351,7 @@ mod tests {
let mut method: ImplItemMethod = parse_quote! {
#[private] pub fn method(&self, #[callback_unwrap] x: &mut u64, #[callback_unwrap] y: String) { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -392,7 +387,7 @@ mod tests {
let mut method: ImplItemMethod = parse_quote! {
#[private] pub fn method(&self, #[callback_result] x: &mut Result<u64, PromiseError>, #[callback_result] y: Result<String, PromiseError>) { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -426,7 +421,7 @@ mod tests {
let mut method: ImplItemMethod = parse_quote! {
#[private] pub fn method(&self, #[callback_vec] x: Vec<String>, y: String) { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -468,7 +463,7 @@ mod tests {
#[init]
pub fn method(k: &mut u64) -> Self { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -504,7 +499,7 @@ mod tests {
#[init]
pub fn method(k: &mut u64) { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
compile_error! { "Init methods must return the contract state" }
Expand All @@ -519,7 +514,7 @@ mod tests {
#[init(ignore_state)]
pub fn method(k: &mut u64) -> Self { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -553,7 +548,7 @@ mod tests {
#[payable]
pub fn method(k: &mut u64) -> Self { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -586,7 +581,7 @@ mod tests {
#[result_serializer(borsh)]
pub fn method(&mut self, #[serializer(borsh)] k: u64, #[serializer(borsh)]m: Bar) -> Option<u64> { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -622,7 +617,7 @@ mod tests {
let mut method: ImplItemMethod = parse_quote! {
#[private] pub fn method(&self, #[callback_unwrap] #[serializer(borsh)] x: &mut u64, #[serializer(borsh)] y: String, #[callback_unwrap] #[serializer(json)] z: Vec<u8>) { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -663,7 +658,7 @@ mod tests {
fn no_args_no_return_mut_payable() {
let impl_type: Type = syn::parse_str("Hello").unwrap();
let mut method: ImplItemMethod = syn::parse_str("#[payable] pub fn method(&mut self) { }").unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand All @@ -682,7 +677,7 @@ mod tests {
fn private_method() {
let impl_type: Type = syn::parse_str("Hello").unwrap();
let mut method: ImplItemMethod = syn::parse_str("#[private] pub fn private_method(&mut self) { }").unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -710,7 +705,7 @@ mod tests {
#[handle_result]
pub fn method(&self) -> Result<u64, &'static str> { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -740,7 +735,7 @@ mod tests {
#[result_serializer(borsh)]
pub fn method(&self) -> Result<u64, &'static str> { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -770,7 +765,7 @@ mod tests {
#[handle_result]
pub fn new() -> Result<Self, &'static str> { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -801,7 +796,7 @@ mod tests {
#[handle_result]
pub fn new() -> Result<Self, &'static str> { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
#[cfg(target_arch = "wasm32")]
Expand All @@ -828,7 +823,7 @@ mod tests {
#[handle_result]
pub fn method(&self) -> &'static str { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
compile_error! {
Expand All @@ -844,7 +839,7 @@ mod tests {
let mut method: ImplItemMethod = parse_quote! {
pub fn method(&self) -> Result<u64, &'static str> { }
};
let method_info = ImplItemMethodInfo::new(&mut method, impl_type).unwrap();
let method_info = ImplItemMethodInfo::new(&mut method, false, impl_type).unwrap().unwrap();
let actual = method_info.method_wrapper();
let expected = quote!(
compile_error! {
Expand Down
21 changes: 4 additions & 17 deletions near-sdk-macros/src/core_impl/info_extractor/attr_sig_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::{ArgInfo, BindgenArgType, InitAttr, MethodType, SerializerAttr, Seria
use proc_macro2::Span;
use quote::ToTokens;
use syn::spanned::Spanned;
use syn::{Attribute, Error, FnArg, Ident, Receiver, ReturnType, Signature};
use syn::{Attribute, Error, FnArg, GenericParam, Ident, Receiver, ReturnType, Signature};

/// Information extracted from method attributes and signature.
pub struct AttrSigInfo {
Expand Down Expand Up @@ -38,25 +38,12 @@ impl AttrSigInfo {
original_attrs: &mut Vec<Attribute>,
original_sig: &mut Signature,
) -> syn::Result<Self> {
if original_sig.asyncness.is_some() {
if original_sig.generics.params.iter().any(|g| matches!(g, GenericParam::Type(_))) {
itegulov marked this conversation as resolved.
Show resolved Hide resolved
return Err(Error::new(
original_sig.span(),
"Contract API is not allowed to be async.",
original_sig.generics.span(),
"Contract API is not allowed to have generics.",
));
}
if original_sig.abi.is_some() {
return Err(Error::new(
original_sig.span(),
"Contract API is not allowed to have binary interface.",
));
}
if original_sig.variadic.is_some() {
return Err(Error::new(
original_sig.span(),
"Contract API is not allowed to have variadic arguments.",
));
}

let ident = original_sig.ident.clone();
let mut non_bindgen_attrs = vec![];
let mut args = vec![];
Expand Down
Loading