8000 Remove `user_enum` macro by tcharding · Pull Request #1291 · rust-bitcoin/rust-bitcoin · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Remove user_enum macro #1291

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

Merged
merged 2 commits into from
Sep 20, 2022
Merged

Conversation

tcharding
Copy link
Member
@tcharding tcharding commented Sep 20, 2022

Remove the user_enum macro because it is only used once and is unnecessarily complicated.

Patch 1: Add a preparatory unit test to make sure patch 2 maintains the current serde logic.
Patch 2: Simplify Network by removing user_enum

In preparation for patching the `Network` serde impls; add a roundtrip
test for `serde` (de)serializing  the `Network` type.
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
pub enum Network {
/// Classic Bitcoin (mainnet Bitcoin network).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be enough to just say "Mainnet Bitcoin"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's good with me, @apoelstra?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lol, yeah. Since I wrote this a fork of bitcoin core called "bitcoin classic" came out so the exsting text is needlessly confusing..

Signet => "signet",
Regtest => "regtest",
};
f.pad(s)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm afraid pad will cut off letters if someone specifies too low precision.

Copy link
Member Author
@tcharding tcharding Sep 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I should have thought harder and used write!() like normal, right?

Copy link
Collaborator
@Kixunil Kixunil Sep 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, yes. Long term we will need some helper fn to format non-integers without losing precision.

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
pub enum Network {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#[non_exhaustive]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure thing.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤷 "Remove user_enum macro" is the MR and commit message..

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heads up that the "complaining about #[non_exhaustive] on Network" issue is here #2225 and we basically agreed to eliminate any direct use of the enum in the library, and then move the enum itself to another crate where it won't cause breakage (primarily because nobody will use it..) and then we can remove #[non_exhaustive].

Instead this library will receive network params by taking generic Into<Params> or AsRef<Params> arguments, and you can make your own network enum that implements this and describes exactly the set of networks that you support.

Copy link
Member Author
@tcharding tcharding Feb 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be fair, after all the drama introducing this change has caused I was surprised to see it come in so nonchalantly. I will admit that this should have been in a stand alone PR, the repercussions discussed, and a mention in the changelog. I accept responsibility for the lack of all three.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is one of those cases where nobody could predict how much impact it would have. It seemed totally obvious that the enum should be non_exhaustive. Well, it kinda still is obvious to me but I see how also having other shared enums helps people not write a few lines of code. Though now that I think about it, it's super ironic that people here go as far as to NIH something just to avoid dependency and they refuse to write an enum...

To be honest, there were multiple occasions where I was tempted to say "if you don't want strict API, don't use Rust". But I'm pretty sure it'd come off wrong even though I honestly believe Rust is not that useful if you want to write a quick dirty thing and great if you write something security-critical.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rust's lack of dependent types makes it basically impossible to write many of the APIs that we want (in particular APIs surrounding Network, e.g. addresses whose network is tied to them but which can still be parsed as the same type). Its coherence rules are constantly giving us trouble when we try to break crates apart. Rust's lack of inheritance or monkeypatching or anything also makes it impossible to NIH certain things, especially traits but sometimes enums whose job it is to provide interop. So "just write an enum" is not a solution to a lack of a usable Network enum. (But IMHO it is a solution if library crates avoid referring directly to the enum and instead use their interop with Params, since this does enable people to write their own enums.)

So if I wanted a strict API I'd use Idris or something, but Rust is definitely a language for getting work done.

Philosophy aside -- I was also caught off-guard by what a pain in the ass #[non_exhaustive] turned out to be, since it seemed unlikely that people were supporting the existing full set of networks and that they were doing so by exhaustively matching. I think my own code pretty consistently just panics on some networks.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rust's lack of dependent types makes it basically impossible to write many of the APIs that we want

True, unfortunately.

Its coherence rules are constantly giving us trouble when we try to break crates apart.

Sadly, this may be unsolvable. The rules protect against other problems. I was thinking about it many times but couldn't come up with a reasonable solution.

Rust's lack of inheritance

Thank God for it! IME inheritance is just a mess. Though it's true that Rust would benefit from a delegation syntax. There were multiple attempts at RFC but sadly it doesn't seem like it's going anywhere anytime soon.

So if I wanted a strict API I'd use Idris or something

I'd love to but last time I checked Idris was experimental and IDK how good performance of it is.

@tcharding tcharding force-pushed the 09-20-rm-user-enum branch 2 times, most recently from b9d3278 to d4ff254 Compare September 20, 2022 06:53
The `user_enum` macro is only used a single time. The macro includes
custom serde logic which can be trivially derived instead.

Remove the `user_enum` macro and just implement `Network` the old
fashioned way. Doing so simplifies the code.
@tcharding
Copy link
Member Author

Implemented suggestions from @Kixunil (incl. "Mainnet Bitcoin" rustdoc)

8000

Copy link
Collaborator
@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK f429c22

#[cfg(feature = "std")]
let message = format!("Unknown network (type {})", s);
#[cfg(not(feature = "std"))]
let message = "Unknown network";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FTR, I plan to add some helpers to deal with this more cleanly.

Copy link
Member
@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK f429c22

@apoelstra apoelstra merged commit b309f41 into rust-bitcoin:master Sep 20, 2022
@nlanson nlanson mentioned this pull request Sep 20, 2022
@tcharding tcharding deleted the 09-20-rm-user-enum branch September 21, 2022 00:20
apoelstra added a commit that referenced this pull request Apr 3, 2024
f6467ac Minimize usage of Network in public API (Tobin C. Harding)
3ec5eff Add Magic::from_params (Tobin C. Harding)

Pull request description:

  Minimize usage of the `Network` enum in the public API.

  See #2225 for context, and #1291 (comment) for an interpretation of that long discussion.

  Close: #2169

ACKs for top commit:
  sanket1729:
    reACK f6467ac.
  apoelstra:
    ACK f6467ac

Tree-SHA512: f12ecd9578371b3162382a9181f7f982e4d0661915af3cfdc21516192cc4abb745e1ff452649a0862445e91232f74287f98eb7e9fc68ed1581ff1a97b7216b6a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
0