-
Notifications
You must be signed in to change notification settings - Fork 430
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
Depend on syn
#302
Depend on syn
#302
Conversation
This comment has been minimized.
This comment has been minimized.
Renaming to libmacros allows us to potentially have more procedural macros in the future without introducing additional crates. Signed-off-by: Gary Guo <gary@garyguo.net>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
add `syn` and others as dependencies of `macros` crate, and use cargo to build `macros` crate. Only host-facing `libmacros.so` is built this way, not any of the other crates that are compiled for the target. This cargo invocation has all crate versions locked and has `--offline` option specified, so it won't access Internet during the build. The current `module!` crate already shows it tedious and limited for writing proc macros without `syn`. Pinning and vtable handling could likely be drastically improved with the help of proc macros, and they will require parsing Rust struct/trait/impl blocks. A dependency on `syn` is highly desirable to avoid us essentially reinventing the wheel when building our procedural macros. A `make rust-fetch-deps` command is added and listed in the documentation as a build requirement. Signed-off-by: Gary Guo <gary@garyguo.net>
Should syn be vendored? |
I don't think it should be checked into the kernel's git tree, and kernel don't use submodules. We could let |
I think we need more discussion around this. In general, I think there is consensus that we need to limit dependency on third-party libraries to just what is absolutely necessary. I'm not convinced |
I agree, but proc macros are different from normal "library" dependencies. Because they only run at compile time, and themselves are not compiled into the binary. It's more similar to our dependency on bindgen. Rustc itself depends on
Why? Proc macros are such a powerful tool, and I think we should encourage use of proc macros if it can help with safety or ergonomics, and sometimes it may the only solution feasible.
And these are ones that I think we need right now. I envision that as more bindings are added we will need more proc macros (attributes and derives are only possible with proc macros). If procedural macros can improve safety, reduce boilerplate and improve ergonomics, I think there shouldn't be any reason not to use it. And safety and ergonomics are the key reasons that we want to use Rust in the kernel, right? With proc macros I can eliminate all
I think this really depend on your attitude towards proc macros only. If we need proc macros then we couldn't avoid |
Thanks for the explanation. I am aware of how proc macros work though. Regardless of how/when it is used, it is a dependency nonetheless: we'd depend on it to build Rust code in the kernel, bugs in it would have the potential to affect the final binary. (In case it isn't clear, bindgen is also a dependency I wish we could avoid, it just so happens that we have no alternative option that is practical.)
Because proc macros, in my opinion, should be our last resort: we should only use them when no other reasonable option is available. (If you don't agree with this, please let me know and I can expand on it.) Assuming we agree on the above, the reason to not encourage proc macros is to avoid inviting people (myself included) to go straight to proc macros and not take the time to explore alternatives: you, for example, started the CStr overhaul with proc macros and eventually (and thankfully) noticed that you didn't need them.
When we eliminate unsafety via Rust constructs, we have a framework to reason about how safe abstractions can emerge from unsafe blocks. This is not the case for proc macros: we have a lot of code that is generating other code that we believe (hope?) provides safe abstractions. Of course, one can claim that we already depend on the compiler, so why would additional compiler-like code be bad? My thinking here is that we should leave compiler-like tasks to the compiler folks; and with that, the support and testing that is needed for this sort of thing. In this project, we are the business of writing kernel code. That said, I am not of the opinion that proc macros should be banned outright. I am, however, of the opinion that our use of it should be judicious.
The |
The |
I'm not arguing for the reinvention of |
That's why I mentioned that
If a simple declarative macro is sufficient, sure. Declarative macros can also do complex parsing, but in that case proc macro is even better -- code will be more readable and error reporting would be much better. My opinion is: use whatever method that is more readable and maintainable.
The proc macro version I proposed earlier also accept
We can require proc macros to justify for all
That's exactly the reason to introduce
|
This is the proc macro part of It's just 300+ lines, but would help us get rid of most |
A few general points:
|
Please note this is not about showing people the "power of Rust". In fact, showing too much "power" is likely a mistake. Even "simple" things like RAII and the Furthermore, proc macros are cool in that they allow to do code parsing/generation without the need of extra build steps, tooling, etc. But they are code parsing/generation in the end, with all its pros & cons. In fact, it is easy for someone to see macros as a lack of power in the "base" language: macros to imitate variadic functions, macros as bad const generics, macros to improve the ergonomics of pinning, etc. So let's be careful about thinking people will automatically go "wow, so clever!". Instead, they may go "ugh... this is Rust's solution for this?". |
And to be extra clear (since my messages are sometimes understood as being 100% against something :-P), I am not saying we should not use procedural macros, just that 1) we should weigh carefully their usage and that 2) we need to be particularly careful in the beginning (and even more so before we are in mainline). So the question is not whether proc macros can help with pinning and other bits, but whether we think it is worth "paying the price" right now. Not just in terms of adding |
Why is Cargo and crates.io banned outright? I don't understand why Cargo is banned entirely. I understand and agree that we shouldn't use it for kernel's core and module crates, but proc macros are self-contained. Their only artefact is the .so file. When talking about external dependencies like crates.io, people are concerned about trustworthiness of code downloaded from Internet. That's why I ensured that the build process won't access the Internet via
quote is indeed in the process of being added to
I thought macros are always pitched as one of the best features of Rust, and in Rust community people are using it quite extensively (like serde/thiserror etc). But you are right, I haven't considered these opinions from people who might not be familiar about Rust.
It's inevitable that some people will ugh. But it's really between them:
I understand all the concerns, but in my opinion, better ergonomics are the best approach to get people accept and get involved in using Rust in the kernel. |
Miguel's points about public perception (especially from a kernel C programmer's point of view) are spot on in my opinion (and a concern I've had but hadn't managed to articulate here). |
To be clear, no one is happy with the amount of unsafety involved in pinning. I am of the opinion that this needs to be addressed by the language, see for example #145 (comment) -- my intent is to engage with them to improve this. But since it's going to be a while before we get something, it's lower in my priority list. |
It is not "banned", it is overkill for what we need, which is a single call to If we wanted to use crates.io and download
I am aware of that, but security is not the issue. Library dependencies are not handled like that. Plus going through crates.io on top of that is completely unneeded.
That is great to hear! Then I would suggest we push for Of course, this does not mean we should not start using
Yeah, Rust macros are great and enable many things that otherwise would be cumbersome. But we need to be careful when showing it to other people, specially because it does not look "like Rust". For instance, take C++ template metaprogramming: specially before the modern standards came, things looked particularly horrendous and completely different than "normal C++ code". Yet it was pitched everywhere as a way to show "how powerful C++ is". But, in my opinion, that was a bad way to try to get more people into the language. For instance, some people would show C programmers things like Boost Spirit that lets you write a parser like: xml =
start_tag [at_c<0>(_val) = _1]
>> *node [push_back(at_c<1>(_val), _1)]
>> end_tag(at_c<0>(_val))
; The things inside |
Syn is deliberately not in the standard library as some syntax changes need breaking changes to syn. This is not allowed for the standard library. |
I am not sure I follow. The standard library |
As struct Foo(u8, u8);
fn main() {
Foo {
0: 0,
1: 42,
};
} If this was stabilized after Some rationale on the RFC that introduced proc macros: https://rust-lang.github.io/rfcs/1566-proc-macros.html#alternatives
|
That is only a problem for those that want to access the very latest syntax through the API. For them, it is a given that you need to update your proc macros as you update your compiler. |
i.e. for many use cases, having access to the very latest syntax does not matter (whether accepted or not by the parser). e.g. one approach I have seen (Python bindings for Clang) is having "unknown" nodes in the AST for anything that cannot be expressed in the current API. Another approach would be providing "syntax editions" and keeping support for them, much like the compiler does for Rust editions. |
The existing struct definitions need to get updated for the examples I gave. No new struct definitions (or other definitions) are introduced. |
No, they do not need to get updated. |
I think it's worth pointing out that the Rust standard library is extremely conservative, so even if adding I think the chances of this happening are near zero and it is not worth putting any hopes into that happening when considering tradeoffs here. Not that that means |
Closed in favour of #910 |
Add
syn
and others as dependencies ofmacros
crate, and use cargoto build
macros
crate. Only host-facinglibmacros.so
is built thisway, not any of the other crates that are compiled for the target. This
cargo invocation has all crate versions locked and has
--offline
option specified, so it won't access Internet during the build.
The current
module!
crate already shows it tedious and limited forwriting proc macros without
syn
. Pinning and vtable handling couldlikely be drastically improved with the help of proc macros, and they
will require parsing Rust struct/trait/impl blocks. A dependency on
syn
is highly desirable to avoid us essentially reinventing the wheelwhen building our procedural macros.
A
make rust-fetch-deps
command is added and listed in thedocumentation as a build requirement.
Related #278