-
Notifications
You must be signed in to change notification settings - Fork 14
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
Generate custom responses #156
Conversation
Codecov Report
@@ Coverage Diff @@
## custom_msg_support #156 +/- ##
======================================================
- Coverage 81.79% 81.64% -0.15%
======================================================
Files 36 36
Lines 1774 1776 +2
======================================================
- Hits 1451 1450 -1
- Misses 323 326 +3
... and 5 files with indirect coverage changes 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
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.
That is more or less right, but there are three problems:
- Custom messages do not work for traits at all. I am pretty sure you cannot implement any trait for contracts using
ExecC
. If I am wrong, please at least prove mi wrong by creating a test with a contract usingExecC
and the interface implemented on it via trait. This is critical, and we cannot merge it for now. I will come back to that at the end of the comment as it is not trivial. App
which is notBasicApp
will not work with those proxies. The solution for that is delivered in the comments, and it is fairly easy, so I expect it to be fixed in this PR.- If a contract has
ExecC
defined, it is impossible to return a non-customizedResponse
from it, which I find an inconvenience - you previously implemented conversion forResponse
types just to provide this functionality so we want it to be implemented. I am Ok with creating a separate issue for that and implementing it later, but we want this.
Now we need to understand how custom messages relate to interfaces. We need to recognize cases:
- Contract uses
Empty
ExecC
(not defines it at all), and the interface usesEmpty
ExecC
(wherever that means for now). The contract should be able to implement this interface. - Contract uses some custom
ExecC
, and it wants to implement the trait which is not usingExecC
at all (defaults it toEmpty
). Such a contract should be able to implement his interface, and allResponse
s returned from interface functions should be converted to contractResponse<ExecC>
somewhere in the dispatcher. - We want to create a trait using a particular
ExecC
(most probably designed for a specific chain) in its messages. For now, we want only contracts with the very sameExecC
to implement such an interface. In the future, we will introduce the notion of compatibility betweenExecC
so we will make it possible to implement such trait by any contract which we can convertExecC
properly, but it is for the future only. - We may want to implement the trait which uses the
ExecC
being sort of "configurable" by chain, so for example have it as an associated type. In such a case there should be a possibility to determine by Sylvia what is the final type we are working with, and it would be delivered via[sv::custom(...)]
on the trait impl block.
For now, we need at least 1 or 2 workings and tested, so we fully support custom types on contract (we can support it on traits on separate PR). 1 should be working with now. My intuition is, that if you provide the #[custom(...)]
on the trait impl block, and then try to convert the result from functions to the contract response in the contract level impl block (when the trait level dispatcher is called). Possibly we would need to additionally add the #[sv::custom(...)]on the
#[interface]if one wants to use a non-empty
ExecCinterface (it would be useable either by very concrete type for 3, the
Self::AssociatedCustomTypefor 4, and even generics for some strange cases I don't see) - however we can add this in another PR (so, for now, we would "support" traits using
ExecC`, except with no possibility of creating them).
2fbd042
to
fea6fac
Compare
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.
Almost ok, with some minor comments.
My biggest issue is commit history - to detail, it would look bad both in the changelog and in the commit history. Avoid using chore
, test
and refactor
commits. Those are most probably changes to be done either:
- as part of the bigger change (eg. test of the feature should go with the feature)
- in a completely separated review (eg. if it is a big refactor, then we create the whole refactor pr).
In this case - all of your test
commits are to be squashed with parents, and chore
commits should come with the next non-chore commit.
We will use those test
, refactor
and chore
when we for example create a single PR filling up some more missing regression in a single PR not adding any new functionality, etc.
I am ok you working on small changes yourself, but then rebase it to keep clean commit history before PR.
sylvia-derive/src/parser.rs
Outdated
@@ -389,13 +383,21 @@ impl Custom { | |||
1 => custom.into_iter().next().unwrap(), | |||
_ => { | |||
emit_error!( | |||
source.span(), | |||
span, |
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 should probably spot it in the previous PR, but I did not so we will fix it here.
Now you are giving a short error, passing the span to the whole entity (created from the whole trait!). Misleading.
Also, it doesn't exactly match how similar errors are returned in Rust. E.g., you create a function with a name already existing, Rust error:
error[[E0428]](https://doc.rust-lang.org/stable/error_codes/E0428.html): the name `foo` is defined multiple times
--> src/main.rs:2:1
|
1 | fn foo() {}
| -------- previous definition of the value `foo` here
2 | fn foo() {}
| ^^^^^^^^ `foo` redefined here
|
= note: `foo` must be defined only once in the value namespace of this module
Do similar:
| #[custom(...)]
| ------------ The attribute `custom` is redefined
=note:
| #[custom(...)]
|------------- Previous definition of the attribute `custom`
=note: Only one `custom` attribute can exist on a single sylvia entity
You can achieve that with more advanced usage of emit_error
. I imagine something like this:
emit_error!(
// `attr` is the whole `attr` attribute which is not "first" (obsolete)
attr, "The attribute `custom` is redefined";
// `custom` here is the first "proper" `custom` attribute defined
note = custom => "Previous definition of the attribute `custom`";
note = "Only one `custom` attribute can exist on a single sylvia entity"
)
I know that custom spans are working only on Rust nightly, but it is still beneficial - if I am struggling I will often use nightly for my day-2-day builds because of better error reporting.
One thing to check how those errors look on stable; if there are some artifacts we can always make "spanned" notes optional (with =?
) and remove them under some nightly
feature flag (but I would leave it enabled-by-default if errors don't look too bad on stable).
Also, we need some way of testing if the errors are reasonably readable - you suggested a solution, but I rejected it because I don't like error message testing too much. However, I was wrong - here it is too critical to maintain them as clearly as possible - please create an issue about using the tool you suggested before; we will try how it works for us.
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.
Additional hint on how to implement this:
let mut customs = attrs
.iter()
.filter(|attr| ...)
.filter_map(|attr| ...);
let custom = match customs
.next()
.unwrap_or_default();
for redefined in customs {
emit_error!(
redefined, "The attribute `custom` is redefined";
note = custom => "Previous definition of the attribute `custom`";
note = "Only one `custom` attribute can exist on a single sylvia entity";
);
}
custom
Benefit: I just got rid of the collection to vec!
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 should probably spot it in the previous PR, but I did not so we will fix it here.
Now you are giving a short error, passing the span to the whole entity (created from the whole trait!). Misleading.
Also, it doesn't exactly match how similar errors are returned in Rust. E.g., you create a function with a name already existing, Rust error:
error[[E0428]](https://doc.rust-lang.org/stable/error_codes/E0428.html): the name `foo` is defined multiple times --> src/main.rs:2:1 | 1 | fn foo() {} | -------- previous definition of the value `foo` here 2 | fn foo() {} | ^^^^^^^^ `foo` redefined here | = note: `foo` must be defined only once in the value namespace of this module
Do similar:
| #[custom(...)] | ------------ The attribute `custom` is redefined =note: | #[custom(...)] |------------- Previous definition of the attribute `custom` =note: Only one `custom` attribute can exist on a single sylvia entity
You can achieve that with more advanced usage of
emit_error
. I imagine something like this:emit_error!( // `attr` is the whole `attr` attribute which is not "first" (obsolete) attr, "The attribute `custom` is redefined"; // `custom` here is the first "proper" `custom` attribute defined note = custom => "Previous definition of the attribute `custom`"; note = "Only one `custom` attribute can exist on a single sylvia entity" )I know that custom spans are working only on Rust nightly, but it is still beneficial - if I am struggling I will often use nightly for my day-2-day builds because of better error reporting.
One thing to check how those errors look on stable; if there are some artifacts we can always make "spanned" notes optional (with
=?
) and remove them under somenightly
feature flag (but I would leave it enabled-by-default if errors don't look too bad on stable).Also, we need some way of testing if the errors are reasonably readable - you suggested a solution, but I rejected it because I don't like error message testing too much. However, I was wrong - here it is too critical to maintain them as clearly as possible - please create an issue about using the tool you suggested before; we will try how it works for us.
Issue to consider trybuild
#98
There is a pending PR.
For examples of usage in real projects you can check its use in serde
@@ -248,7 +258,7 @@ impl<'a> MultitestHelpers<'a> { | |||
#sylvia ::multitest::MigrateProxy::new(&self.contract_addr, msg, &self.app) | |||
} | |||
} | |||
} else { | |||
} else if msg_ty == &MsgType::Query { |
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 am not a fan of this if-else chain. I am pretty sure it should be a match or even a function like MsgType::generate_message_variant(...)
(not sure about this one, as maybe it is not the best place to put this).
Here you did only minimal changes on this, but let's fix it up in some later refactor (I'll create a task).
Especially since those things look identical. Really. I see the difference, but I think we could simplify it. Not mentioning last else is bullcrap here, I don't see which patterns are not covered; it frustrates me.
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.
.github/workflows/ci.yml
Outdated
# TODO: Remove when custom_msg_support will be merged to main | ||
# Later name feature branches with `feat_` prefix | ||
- custom_msg_support | ||
- feat_* |
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.
Nice, but I will avoid any _
prefixing in branch names - /
feels far more natural (and I am pretty sure it is allowed in branch names). I will go either with feat/*
or shorter ll/
(long-living - potentially not only for features but maybe bigger refactors or something`,
.github/workflows/ci.yml
Outdated
branches: | ||
- main | ||
# TODO: Remove when custom_msg_support will be merged to main | ||
# Later name feature branches with `feat_` prefix | ||
- custom_msg_support | ||
- feat_* |
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.
Here I would altogether remove the branches
filter. All pull requests should trigger CI flow. We could potentially do a quick CI flow if we have some long-running non-critical CI flows on all PRs, and the full CI only for PRs to main
, but I think we don't have this kind of split for now.
7081d77
to
0e1f3eb
Compare
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, minor docs wording hints.
.github/workflows/ci.yml
Outdated
@@ -4,9 +4,11 @@ on: | |||
push: | |||
branches: | |||
- main | |||
# TODO: Remove when custom_msg_support will be merged to main | |||
# Later name feature branches with `feat_` prefix |
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.
# Later name feature branches with `feat_` prefix | |
# Later name feature branches with `feat/` prefix |
README.md
Outdated
@@ -842,5 +842,7 @@ features for you. Here is a rough roadmap for the incoming months: | |||
|
|||
## Troubleshooting | |||
|
|||
For more descriptive error messages consider using +nightly toolchain. |
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.
For more descriptive error messages consider using +nightly toolchain. | |
For more descriptive error messages, consider using the nightly toolchain (add `+nightly` argument for cargo) |
0e1f3eb
to
5379712
Compare
Closes #155