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

macros: Add #[main] macro #2920

Open
MabezDev opened this issue Jan 9, 2025 · 6 comments
Open

macros: Add #[main] macro #2920

MabezDev opened this issue Jan 9, 2025 · 6 comments

Comments

@MabezDev
Copy link
Member

MabezDev commented Jan 9, 2025

Description of work required is available here: #2900 (comment)

@playfulFence
Copy link
Contributor

playfulFence commented Jan 9, 2025

I want to discuss it a little bit more.

From my point of view and understanding of a comment (linked in an initial issue comment) the suggestion is to "hide" and mask those runtime crates/macros.
User doesn't interact with them directly - yes, but it still sounds like being dependant on unstable crate for me 🤔
Like, every application will still use unstable functionality to define main function.

Again, just my point of view for now (which might be wrong though 😄 ) and I'm looking forward to get some feedback! <3

@MabezDev
Copy link
Member Author

MabezDev commented Jan 9, 2025

Good question, thanks for asking! I addressed this a bit in this point:

A new main macro that uses the hidden rt crates, basically #[main] will simply expand to #[arch_rt::entry]
because users don't interact with code generated by these macros, we can use them as long as we don't change the behavior of them.

but I'll expand a bit further why I think it's okay to do this.

API stability is about "can a user upgrade from 1.x to 1.y without having to make code changes?". Whilst we may depend on fundamentally unstable crates to create the #[main] macro, we have the flexibility here to do so because:

  • Users can't (or atleast shouldn't be able) interact with code generated by the #[main] macro, all it should do is setup an entry point for users to run their code.
  • Less important, but also a factor here: we are in control the unstable crates in question

Further more, there is some precedence for this both in the embedded space, and in rust generally.

Precedence 1: RTIC - rtic currently has support for two major versions, and has had stability for a number of years. However, the underlying crates, namely cortex-m-rt for ARM users, are still not stable. The code generation backends for the esp32c3/c6 are also built on unstable PAC crates, but through careful use and an internal API for macros they can achieve stability.

Precedence 2: Rust its self does this all the time, async itself depends (internally) on unstable features of the compiler, but to give a more accurate example the core library addr_of! macro has used (the now stable, but for many years unstable) &raw syntax because the rust project understood that they users of this macro won't interact with the generated code, and therefore the API stability stops with the macro itself.

@playfulFence
Copy link
Contributor

On the other hand, the only option that I see is making users export entry by themselves. Which also sucks, because every application will still inevitably contain unstable macro, but just from outside of our crate, but there's no another option.

So, from this point of view, adding #[main] macro seems reasonable then, as what I suggested above is way more ugly 😄

Other words, I'm a bit confused 😆.

@playfulFence
Copy link
Contributor

playfulFence commented Jan 9, 2025

Thanks for clarifying, agreed, it's probably the best way how to keep things user-friendly, others (which I described above) are really, really ugly 😄

@bugadani
Copy link
Contributor

bugadani commented Jan 9, 2025

So this is the third issue we have that is related to unstable crate dependencies in some way.

API stability is about "can a user upgrade from 1.x to 1.y without having to make code changes?"

What counts as code change? PACs, RT crates are "singleton crates", i.e. a single version can exist in a project. If we release a breaking change to them, and hide that breaking change behind a semver-compatible HAL change, users that directly depend on those crates will need to make code changes. In the best case, that code change is just a version bump in Cargo.toml, but it can be much more.

Precedence 2

If we are talking about std-related precedence, we should bring up the c_char redefinition and the pain it caused in the name of a "bugfix".

@MabezDev
Copy link
Member Author

MabezDev commented Jan 9, 2025

What counts as code change? PACs, RT crates are "singleton crates", i.e. a single version can exist in a project. If we release a breaking change to them, and hide that breaking change behind a semver-compatible HAL change, users that directly depend on those crates will need to make code changes.

This is exactly what I want to explore in the first linked issue - do they need to be "singletons"? What happens when two semver compatible, but different with rt crates, esp-hal versions are in the same dependency tree?

If we are talking about std-related precedence, we should bring up the c_char redefinition and the pain it caused in the name of a "bugfix".

Good point, we shouldn't follow them blindly, but in general they have good stability guarantees. Imo that was a process failure on their end, and they should learn from that. The fact the PR got merged before everyone pinged replied was not only strange, but at that point they were asking for breaking changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Todo
Development

No branches or pull requests

3 participants