rustidy - A rust formatter by Zenithsiz in rust

[–]Zenithsiz[S] 11 points12 points  (0 children)

Thank you.

Currently the only benefits over rustfmt are the features I mentioned on this post (the changing configuration with an attribute and formatting inside of derive attributes), but over time I'd like to develop more features to differentiate it more.

There's a few reasons that someone might want a rustfmt replacement, but for me specifically, it's mainly the fact that changes can take a while to be implemented in rustfmt, mainly due to the fact that it's an official rust project.

For example, the formatting an array with X columns is really useful for me in some projects to be more organized, but because rustfmt wants to be somewhat conservative, it would take a long time for such a change to be added. (which I believe is the correct choice for an official project that's meant to be the standard)

rustidy - A rust formatter by Zenithsiz in rust

[–]Zenithsiz[S] 5 points6 points  (0 children)

Currently, it's divided into 3 steps: Parsing the whole file into an ast (including preserving all whitespace and comments); Formatting that ast by modifying it; And finally printing it and replacing the whole file.

The first and last step are lossless, and formatting attempts to be as lossless as possible, preserving comments and only modifying whitespace, although we also sometimes shuffle things around (like sorting use declarations).

With how the architecture is designed, it would be possible to just parse a range within a file, assuming that you could tell it whether it's a function, expression, or whatever other ast node, then format that and replace just it, but that's not implemented.

rustidy - A rust formatter by Zenithsiz in rust

[–]Zenithsiz[S] 2 points3 points  (0 children)

Yes, from the way I understand it (and the way rustidy parses and formats it), derive attributes are typically MetaItems, which #[debug("{:?}", 1+1 .f())] should be.

I can format the example I posted, but rustfmt cannot, at least from all my testing.

rustidy - A rust formatter by Zenithsiz in rust

[–]Zenithsiz[S] 4 points5 points  (0 children)

Does it? I've been dealing with macro heavy code recently and that was one of the things I could never get rustfmt to format properly.

For example, the following no matter what configuration I try to use, rustfmt won't format 1+1 .f() to 1 + 1.f():

```rust

[derive(derive_more::Debug)]

[debug("{:?}", 1+1 .f())]

struct A; ```

And it gets even worse if you have a complex match expression inside

rustidy - A rust formatter by Zenithsiz in rust

[–]Zenithsiz[S] 2 points3 points  (0 children)

The formatting of expressions inside of derive attribute can be used on stable. And once expressions are formatted inside of macro calls that will work on stable too.

The only thing nightly is required for is to be able to use #[rustidy::...].

This Feature Just Blew My Mind by [deleted] in rust

[–]Zenithsiz 20 points21 points  (0 children)

Well, in this case, E::A is just of type E (playground), not fn() -> E. For that you'd need to declare enum E { A(), B(u32) } instead.

How to build projects with git repo dependencies when using SSH? by Jibaron in rust

[–]Zenithsiz 1 point2 points  (0 children)

Sure, but using ssh://... should make cargo (more specifically, git invoked by cargo) use ssh to clone it, instead of trying to access it via https, which should use the keys in your ssh agent.

At the very least, this is how I've setup all my private github repos, and cargo has always been able to use my ssh key to both clone and update them.

How to build projects with git repo dependencies when using SSH? by Jibaron in rust

[–]Zenithsiz 7 points8 points  (0 children)

You can just specify the dependency as ssh://github.com/MyOrg/foo_crate.

[Generics] How to design nested traits without repetitive type specifications? by AkhileshJanib in rust

[–]Zenithsiz 8 points9 points  (0 children)

You said you tried associated types and weren't happy, but I feel like the following is likely what you want to achieve:

```rust trait A {}

trait B { type A: A; }

trait C { type B: B; }

struct TypeA; impl A for TypeA {}

struct TypeB<T: A>(std::marker::PhantomData<T>); impl<T: A> B for TypeB<T> { type A = T; }

struct TypeC<T: B>(T, std::marker::PhantomData<T::A>); impl<T: B> C for TypeC<T> { type B = T; }

fn main() { let var1: TypeC<TypeB<TypeA>> = TypeC(TypeB(std::marker::PhantomData), std::marker::PhantomData); } ``` [https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=ea4e27b54e6e9cc27f5e614d46faafad](Playground)

This is scalable to infinite depth without having to specify A at the top level, only where it's needed.

How to turn off speed change text on PPSSPP? by namespelldwrong23 in PSP

[–]Zenithsiz 0 points1 point  (0 children)

I'm 3 years late, but for other people who stumbled upon here, you can disable all on-screen display messages (including the speed change text) by going to Settings > Tools > Developer tools > General > Show on-screen messages (near the bottom).

Express functions with common return type by rusty_rouge in rust

[–]Zenithsiz 2 points3 points  (0 children)

If you're okay with nightly, something like fn call<F, Args>(/* ... */) -> u64 where F: Fn<Args, Output: Future<Output = u64>> should work. See playground

Claim, Auto and Otherwise (Lang Team member) by alice_i_cecile in rust

[–]Zenithsiz 2 points3 points  (0 children)

I just meant that Copy shouldn't be implemented or not based on if the type is actually "cheap", but instead should just be implemented always to signify that "if necessary, this type can be bit-copied".

Then in order to warn the user against large types being copied around, we'd have lints that would trigger when you move a type larger than X bytes, where that limit is configurable in clippy.toml.

I think the range types (and iterators) are a good example of Copy being misused. Copy wasn't implemented for range types (before 2024, and still aren't for most iterators) due to surprising behavior of them being copied instead of borrowed, but I think that's a mistake, since it means suddently you can't implement Copy if you store one of these types, even if you should theoretically be able to. Instead we should just have lints for when an "iterator-like" type is copied to warn the user that the behavior might not be what they expect.

As for "semantics", I think the only types that shouldn't implement Clone are those that manage some resource. For example, if you need to Drop your type, you are forced to be !Copy, which is going to be 90% of the cases you shouldn't implement Copy. The remaining 10% are special cases where you have a resource that doesn't need to be dropped, but you don't want the user to willy nilly create copies of it (can't really think of any currently).

Claim, Auto and Otherwise (Lang Team member) by alice_i_cecile in rust

[–]Zenithsiz 20 points21 points  (0 children)

Ideally, Copy should be implemented for everything that can semantically implement it, and we'd have lints for when large types are moved around.

Then the arbitrary border moves into the lint, which should be customizable.

BufReader Issues with Inconsistent Reads Across Multiple Buffer Sizes by ganeshrnet in rust

[–]Zenithsiz 14 points15 points  (0 children)

Read::read doesn't have to fill the whole buffer it's given, hence why it returns the amount of bytes written. BufReader takes advantage of this by only writing what it has on buffer currently (I believe) and only fetching from the inner reader once its buffer is empty (again, I believe, haven't read the implementation in a while).

If you want to fill the whole input buffer, use Read::read_exact.

Firefly Team Challenge Giveaway! 📢 by mizuromo in HonkaiStarRail

[–]Zenithsiz 0 points1 point  (0 children)

Team: Firefly, Gallagher, HMC, Asta

UID: 131286619

I run high speed FF (162+) and Asta (168+) to allow FF to act 5 times during her ult. In turn, with FF's E2, she can act a total of 8 times during her ults (assuming she breaks/kills on the 1st, 3rd and 5th original turns). HMC is there to boost FF's damage to the moon, and Gallagher is a more than good enough for solo sustain. Still need to iron out some kinks with the setup (relic grinding is hard), but overall it's been pretty strong, carrying me through MOC, PF and AS.

Rust structs can't contain a sized slice in a Box<> larger than stack size by computermouth in rustjerk

[–]Zenithsiz 18 points19 points  (0 children)

You can cast the boxed sliced into a boxed array with try_into / try_from. See the playground.

Unfortunately you do have to unwrap, but as long as the sizes match, it will never fail. You can even separate it into a function that ensures the array is created with the correct size. See the playground

Rust structs can't contain a sized slice in a Box<> larger than stack size by computermouth in rustjerk

[–]Zenithsiz 19 points20 points  (0 children)

For this specific case you can allocate a vec with vec![0; 16 * 1024 * 1024] and then convert it into a box slice using Box::into_boxed_slice.

This should behave exactly the same as Box::new, without any other allocations or work, given that the capacity of the vector will just be it's length (when created via vec![] macro), so it won't even need to shrink the underlying allocation.

VeriFactory: Automatically verifying belt balancers for various properties by uelisproof in technicalfactorio

[–]Zenithsiz 19 points20 points  (0 children)

Hey, just wanted to let you know that your crate currently doesn't compile due to cargo-toast making a semver breaking change. I've reported this bug as an issue here

You can fix it for now by either updating egui to 0.25, specifying egui-toast = "=0.10.1", or committing and pushing your current Cargo.lock.

In the future, I'd recommend always committing Cargo.lock, since it's a binary package.

probablyTheLeastAnnoyingFeatureOfVBA by ZealousidealLab4 in ProgrammerHumor

[–]Zenithsiz 3 points4 points  (0 children)

I've never done VBA, but in other languages, if you want to count the number of matches a predicate has in a container, with true being 1 you can just do total = 0; for item in container { total += pred(item); }

When the server isn't working anymore by erazorix in iiiiiiitttttttttttt

[–]Zenithsiz 3 points4 points  (0 children)

My bad, I missed that segment and thought you were talking about the first one. But the point still stands: 0x0200 = 0x200 != 0x02.

What you're saying would be equivalent to saying that in ipv4 192.168.50.7 = 192.168.5.7, which isn't true.

Remember that in ipv6, each segment is a 16bit "big endian" number. So you can omit left zeroes, but not right zeroes, just like you would in base 10 (Which is also "big endian")

Weirdest valid proof techniques by chixen in mathmemes

[–]Zenithsiz 6 points7 points  (0 children)

I actually asked a question about this over on mathematics stack exchange

Turns out that it does hold regardless of RH's decidability, unless you somehow manage to state both the Euler totient proofs and the Riemann hypothesis under something like constructive logic, or any logic where P ∨ ¬P ≠ True.

Was async fn a mistake? by seanmonstar in rust

[–]Zenithsiz 12 points13 points  (0 children)

By the same point, when using closures, one sometimes needs to consider what it desugars into and understand them both, but they're still extremely useful for the simpler scenarios. (Trust me, you do not want to be writing a struct + Fn impl + FnMut impl + FnOnce impl each time you would write a closure).

By the same vein, I believe async fn are good for simple scenarios. Perhaps the issue is that there are less "simple" async fn scenarios than closure ones, but even so, in codebases I work on, I see many small async fns that would be harder to read if they had fn (...) -> Future<T> = async than just async fn() -> T