-
Notifications
You must be signed in to change notification settings - Fork 28
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
Add informational field type name #30
Conversation
# Conflicts: # test_suite/tests/derive.rs
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.
Two main concerns (really: nitpicks) are:
- the API is a bit less ergonomic to use after this
- not a fan of the
display_name
name; could it be justalias
?
Overall great stuff though.
test_suite/tests/derive.rs
Outdated
|
||
#[test] | ||
fn fields_with_type_alias() { | ||
type BoolAlias = bool; |
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.
Unrelated to this PR, but do you think we could have this work at some point?
#[derive(TypeInfo)]
type BoolAlias = bool;
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.
It's a good idea, it may well be worth experimenting with. This would provide extra information about what aliases are available and may increase the accuracy of the heuristic identifying alias usage.
Ultimately it would also have the same limitation in that there is still no guarantee to identify when a given alias is being used, because the registry is using the underlying type id i.e. any::TypeId::of<BoolAlias>() == any::TypeId::of<bool>()
.
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.
Never thought about this use case. I am not sure it goes too far but making it optional would probably be okay. The question is how to integrate it properly into the current scheme if we actually want ot.
# Conflicts: # derive/src/lib.rs # src/build.rs # src/ty/fields.rs # test_suite/tests/derive.rs # test_suite/tests/json.rs
This will display any valid field type name as specified in the source code.
Updated so it now contains the raw string which is a result of |
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'll give it a proper review, but this real good. :)
test_suite/tests/json.rs
Outdated
{ "type": 2 }, | ||
{ "type": 4, "displayName": ["bool"] }, | ||
{ "type": 1, "typeName": "i32" }, | ||
{ "type": 2, "typeName": "[u8 ; 32]" }, |
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 nice. :)
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.
Note sure we need displayName
or typeName
(why rename btw?) for types such as [u8; 32]
because its primary use case is still to counterfeit type aliases and besides that I cannot think of any other serious use case. Also I am unsure about turning the namespace (array of strings) into a single string since that kinda dictates how 3rd party tools handle namespaces or simply removes namespaces which are kinda important to differentiate between types.
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.
displayName or typeName (why rename btw?)
To make it more general to imply we are not just dealing with paths/aliases now, but whatever type name is in that position.
Note sure we need displayName or typeName (why rename btw?) for types such as [u8; 32]
Indeed it is redundant because you can just look it up on the underlying type. We can easily filter those out, but in this iteration I have decided to always take the type name in the source for simplicity's sake, at the cost of some redundancy.
besides that I cannot think of any other serious use case
I believe we might need this initially if we want to be able to convert to the existing substrate metadata format, though of course it may be possible without, needs some investigation.
Also I am unsure about turning the namespace (array of strings) into a single string since that kinda dictates how 3rd party tools handle namespaces or simply removes namespaces which are kinda important to differentiate between types.
3rd party tools should not be relying on any namespace in the type/display name because it will only be there if the user decides to fully qualify their type e.g. struct S { field: foo::bar::Foo }
, if they just use foo::bar::Foo
then the display/type name will be Foo
.
By not using the Path
type anymore we are just giving an extra indication that this field does not provide any guarantees as to the content of that field other than it is the name of a valid Rust type in the context of the .rs
file where it is defined.
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.
already commented
input | ||
.replace(" ::", "::") | ||
.replace(":: ", "::") | ||
.replace(" ,", ",") | ||
.replace(" ;", ";") | ||
.replace(" [", "[") | ||
.replace("[ ", "[") | ||
.replace(" ]", "]") | ||
.replace(" (", "(") | ||
.replace("( ", "(") | ||
.replace(" )", ")") | ||
.replace(" <", "<") | ||
.replace("< ", "<") | ||
.replace(" >", ">") |
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.
😆
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.
dq: why wouldn't .replace(" ", "");
work here? Is space ever significant?
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.
yes, e.g. something like &'a mut dyn Foo
would become &'amutdynFoo
.
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.
🤦
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'd love to claim credit for this beauty but I stole it from https://github.com/paritytech/substrate/blob/master/frame/support/procedural/tools/src/lib.rs#L96
The only thing that bogs me with this approach that we no longer really support overlapping aliases by replacing the namespace with plain strings. E.g.: mod a {
pub type Foo = i32;
}
mod b {
pub type Foo = i64; // could also be just i32
}
fn do_stuff(foo1: a::Foo, foo2: b::Foo) { ... } We probably would prefer having aliases here but we could no longer differentiate between them really with them being just strings. |
You can still differentiate between the two though, instead of |
But then how is |
For the case of a plain However if we want something a bit more sophisticated it will just require a bit more thought. As an aside, I think it's useful information anyway. We probably don't want to model type in source code being |
ah okay I see. |
Given a complex type which incorporates a field with a type alias, we currently lose the information about the use of a type alias. e.g.
This currently results in the field type being resolved to
u128
in the type registry, and we have no way to distinguish between a plainu128
and an aliasedu128
, which we may want to treat differently, e.g. some custom decoding or display logic for that type.This PR adds the optional
type_name
property toField
, and updates the derive macro to extract the field type names e,g, in the above example the underlying type isu128
but the type name isBalance
.Note that this will add a
type_name
even if it is non-aliased, e.g.a: u32
will still have the type display name"u32"
as part of the field definition. Even though this is redundant, and it is possible to remove non aliased display names (I implemented then removed it), I have left them in for the sake of simplicity and flexibility, leaving it up to consumers to do the lookup to determine whether an alias is being used or not.This is required for use-ink/cargo-contract#79 in order for custom encoding/decoding for aliased
Balance
types.