-
Notifications
You must be signed in to change notification settings - Fork 78
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
Refactor proc macros #164
Refactor proc macros #164
Conversation
These tests are important before upgrading alloy to avoid misuing their API and causing errors.
This alloy version includes generic integer types, so instead of implementing those on our end, we special case the built-in integer sizes so they work with both primitive ints and alloy generics.
This is a rather large refactor of the stylus proc macros with the main goal of improving maintainability, testability, and documentation of these macros. The following changes have been made: - Operate on AST nodes instead of raw tokens. This allows testing of smaller parts of the macros as unit tests. This also allows some composibility within the implementations. - Use the visitor pattern in several places to avoid confusing nesting of for-loops. - Separation of export-abi code using "extention" traits so that it is easy to reason about export-abi when needed, and otherwise ignore it. - Improved error reporting. The main change here is the ability to report multiple errors when compilation fails, allowing the user to see all errors at once. There is also some small changes with regards to consistency between the macros. - Unit tests for utilities and macro generation at the AST level. This includes a `assert_ast_eq()` function which can be used to compare two ASTs of the same type. If an error occurs, the ASTs are pretty printed and a diff is output so that the issue can be easily addressed. - Integration tests in the `stylus-proc/tests` directory. These allow compiled macros to be tested as working correctly. Additionally the `stylus-proc/tests/fail` directory will contain failing integration tests. These all fail to compile and include expected stderr outputs. - Modify code snippets within docstrings so that they are not ignored, and pass as part of the `cargo test` process. - A `README.md` which will contain information about developing and maintaining these proc macros. - Support for `solidity.path.separator` to `rust::path::separator` for custom structs within `sol_interface!` definitions. - Change the folder structure to have all macro implementations in a `macros` module. Easier to find the macro implementation you are looking for. - Docstrings within the macro implementations for developer reference. - Utilities for handing inner attributes including those which contain tokens which need to be parsed. A little more work is going to be done before this is ready for merge, but it will be good to get this out for review since it is such a large set of changes.
stylus-proc/src/consts.rs
Outdated
use proc_macro2::{Span, TokenStream}; | ||
use quote::ToTokens; | ||
|
||
/// Name of the entrypoint funciton that is generated for struct-based contracts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo on function
|
||
use crate::imports::ConstPath; | ||
|
||
pub const Address: ConstPath = ConstPath("stylus_sdk::alloy_sol_types::sol_data::Address"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is cool, why stop at Address
though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now I just have the imports that were declared as constants before for easy interpolation. Could potentially add more in the future as needed.
use syn::{parse_macro_input, parse_quote}; | ||
|
||
use crate::imports::stylus_sdk::abi::AbiType; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really nice!
self.match_arms.push(parse_quote! { | ||
#self_name::#name(e) => stylus_sdk::call::MethodError::encode(e), | ||
}); | ||
self._ext.add_variant(field); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is throwing odd warnings. I guess since the SolidityErrorExtension
trait is implemented for ()
you can just remove the self._ext
part?
What is meaning of
impl SolidityErrorExtension for () {
type Ast = Nothing;
fn add_variant(&mut self, _field: syn::Field) {}
fn codegen(_err: &DeriveSolidityError<Self>) -> Self::Ast {
Nothing
}
}
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the warning I get from clippy:
passing a unit value to a function
for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg
#[warn(clippy::unit_arg)]
on by defaultclippyClick for full compiler diagnostic
mod.rs(56, 9): move the expression in front of the call and replace it with the unit literal()
:self._ext; ().add_variant(field)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the extension here (and in public macro), is designed to do nothing by default. That's why the default impl uses a ()
and returns Nothing
. When the export-abi
feature is enabled the Extension
type alias points to a type that actually provides the logic. This just avoids having #[cfg(feature = "export-abi")]
in a bunch of different places
{ | ||
T::SolType::abi_encode(value) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have encode
and encode_params
, and we've got decode_params
, should we also add a decode
wrapper?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not quite sure yet, it wasn't needed for these changes but I do want to take a broader look at how we handle abi encoding/decoding and revisit then.
stylus-sdk/src/abi/mod.rs
Outdated
let encoded = encode_params(&value); | ||
assert_eq!(encoded, buffer.as_ref()); | ||
// TODO: debug this assertion for test encode_decode_bytes_tuple() | ||
// assert_eq!(abi::encoded_size(&value), encoded.len()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is failing on the encode_decode_bytes_tuple
test from abi/bytes.rs
. Is there a bug here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that I am aware of. I haven't had a chance to dig into this but bytes have been working correctly. I'll revisit this with some other abi encoding/decoding changes mentioned above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Description
This is a rather large refactor of the stylus proc macros with the main goal of improving maintainability, testability, and documentation of these macros. The following changes have been made:
assert_ast_eq()
function which can be used to compare two ASTs of the same type. If an error occurs, the ASTs are pretty printed and a diff is output so that the issue can be easily addressed.stylus-proc/tests
directory. These allow compiled macros to be tested as working correctly. Additionally thestylus-proc/tests/fail
directory will contain failing integration tests. These all fail to compile and include expected stderr outputs.cargo test
process.README.md
which will contain information about developing and maintaining these proc macros.solidity.path.separator
torust::path::separator
for custom structs withinsol_interface!
definitions.macros
module. Easier to find the macro implementation you are looking for.A little more work is going to be done before this is ready for merge, but it will be good to get this out for review since it is such a large set of changes.
Checklist