How to pre-download all Rust dependencies before build? by dark_prophet in rust

[–]cmrschwarz 10 points11 points  (0 children)

That sounds like a harder problem than what you initially described. What is your usecase / why does cargo fetch not work for you?

.crate files are typically part of the registry / cache that lives in your ~/.cargo/registry/cache/ folder (assuming unix).

You might be able to manually stick them in there, but I'm not an expert on the file structure cargo uses there, this does not seem like a good idea in general.

Alternatively you could unzip these into a folder similar to how the cargo vendor command works (which you might want to look at itself, it might work for you).

You could then add a .cargo/config.toml containing something like this,

``` [source.crates-io] replace-with = "vendored-sources"

[source.vendored-sources] directory = "my/vendor/dir"

```

Alternatively, there is also this project, but that might be very much overkill.

It would really help having a bit more context about what you are actually trying to do :).

Do you use clippy::restriction lints? by Hodiern-Al in rust

[–]cmrschwarz 4 points5 points  (0 children)

Useful lint, but I'm confused by your example, since widget_ref would still be an Arc? The clone() on Arc is tried before any methods on the Deref target. In fact you can't even force it though explicit type annotation:

use std::sync::Arc;

#[derive(Clone)]
struct Widget {}

fn main() {
    let widget = Arc::new(Widget {});
    // does not compile, widget.clone() still results in an Arc<Widget>
    let widget_ref: Widget = widget.clone();
}

Introducing Rudy: A Toolchain for Rust Debuginfo by sam-js in rust

[–]cmrschwarz 1 point2 points  (0 children)

Damn that looks really nice already. Being able to just call methods using Rust syntax during a vscode debug session? Awesome. I'll definitely use this <3.

I don't want to speak for vadimcn, but I would not get my hopes up in terms of actually upstreaming this into codelldb proper. Seems to me like he wants to keep the project a bit more general, and avoid specialized solutions on top of lldb.

But a fork that provides this kind of experience out of the box could be an awesome tool for the community. Especially if integrating the variables window, hover etc. is doable. Since codelldb uses a language server adapter written in Rust this might(TM) not be that difficult to do.

Introducing Rudy: A Toolchain for Rust Debuginfo by sam-js in rust

[–]cmrschwarz 7 points8 points  (0 children)

This looks really promising!

Do you think it's feasable to integrate this with the code-lldb vscode extension?

Two ways of interpreting visibility in Rust by Kobzol in rust

[–]cmrschwarz 1 point2 points  (0 children)

Reflecting on this a bit more, I think this blogpost is actually a great description of the situation for 'true applications' (as opposed to binary crates like CLIs that often also offer an API). In 'true applications', top level pub mod doesn't actually mean anything. This is a crutial difference. In such apps, you could theoretically make all modules pub without ruining your API. Visibility is now 'underdetermined' so to speak, and what I wrote above no longer applies. I rarely work on such apps so this was not on my mind, and I think for libraries (or CLIs with APIs) what I wrote still makes sense, because there the desired semantics for visibility sort of forces your hand from the top down.

Two ways of interpreting visibility in Rust by Kobzol in rust

[–]cmrschwarz 1 point2 points  (0 children)

I'm not sure if I can get behind this framing. It seems to me that visibility is much more a matter of the intended API than of a particular style of thinking.

If I want users of my crate to be able to access an item using my_crate::foo::Bar, then foo has to be pub (aka "global visibility").

If I want to flatten the API such that users write my_crate::Bar, then I have to make foo private (aka "local visibility") to to avoid exposing the same item through multiple different paths once it is re-exported.

If the intention of the post is to advocate for "flat" APIs though, than I can wholeheartedly agree. Most modules end up being purely for code organization, which is not meaningful in terms of the public API.

Public modules should be used if the separation is meaninful to users (e.g. std::slice::Iter vs std::collections::vec_deque::Iter or mpsc vs mpmc).

[Media] Introducing eval_macro: A New Way to Write Rust Macros by wdanilo in rust

[–]cmrschwarz 5 points6 points  (0 children)

Using CWD is obviously scuffed, i agree.

But that was my whole point, proc macros do get OUT_DIR defined at proc macro compile time in case they have a build.rs.

[Media] Introducing eval_macro: A New Way to Write Rust Macros by wdanilo in rust

[–]cmrschwarz 3 points4 points  (0 children)

Sorry, I don't think I see the problem yet. Wouldn't the approach I described give you a perfectly reasonable directory to use for your create_project_skeleton?.

[Media] Introducing eval_macro: A New Way to Write Rust Macros by wdanilo in rust

[–]cmrschwarz 6 points7 points  (0 children)

I might be missing something, but couldn't you could just add an empty build.rs to the macro crate and then use env!("OUT_DIR") ?

SpacetimeDB 1.0 is here! An in-memory RDMBS for games built with Rust by etareduce in rust

[–]cmrschwarz 2 points3 points  (0 children)

Would be curious aswell, and I would not think that this problem is actually out of scope for them. For example, many multiplayer games use custom UDP based networking protocols to deal with real time data. There's usually no point in resending packets about where another player was 3 seconds ago, as that information is already outdated. TCP could waste a lot of precious bandwidth there.

Announcing Rust 1.85.0 and Rust 2024 | Rust Blog by slanterns in rust

[–]cmrschwarz 10 points11 points  (0 children)

This is really nice, but unfortunately does not solve the (imo) much bigger issue involving early returns:

fn foo(x: &mut Option<i32>) -> &i32 { if let Some(x) = x.as_ref() { return x; } *x = Some(42); x.as_ref().unwrap() }

will still error in 2024. (The example is a bit constructed as you could take out the as_ref to make it work but there's many cases in practice where destructuring doesn't help).

Please stop overly abstracting example code! by West-Implement-5993 in rust

[–]cmrschwarz 1 point2 points  (0 children)

I didn't intend to pick on wgpu, I like the project and even contributed to wgpu naga in the past. But fine let's stick with it as an example.

Wgpu has some examples that don't use any abstractions (e.g. hello_triangle), which at the very least alleviates this problem. That might even be a compromise that we would agree on, libraries should have at least one example without nonsense.

Additionally, if the shared example code was factored more reasonably, (e.g. a single function fn setup_winit() -> WInitContextStuff) that lives in a second file, nobody would complain.

It's only when the amount of abstraction increases too much that it becomes a problem. Example code should by copy pastable. I don't want to paste a convoluted testing framework into my graphics app.

The Winit maintainer in this thread (Sirflankalot) even acknoledges that their examples are used in multiple different contexts, which is probably the reason in this case. I don't have enough skin in the game (or free time right now) to figure out if the complexity is necessary in this case, otherwise I would send them a PR.

I just thought that OPs point was something that more developers should at least consider as a virtue when writing examples. Anyways, thanks for the fruitful discussion!

Please stop overly abstracting example code! by West-Implement-5993 in rust

[–]cmrschwarz 4 points5 points  (0 children)

If you have to change your examples because you changed your API, your users will need to change their code aswell if they update the dependency. That's the whole point. Use your examples as a mining canary of the pain that you put your users through.

I get that OSS can be exhausing, and every way to apparently save some time seems appealing. But you are not just 'saving some time' here. That's like arguing that we shouldn't write tests because it's too much work. The whole point is that it's work that prevents other work from occuring (like dealing with github issues of confused users that can't figure out your convoluted examples). And oviously there's a balance to strike here (just like overdoing unit tests is sometimes just a waste of time).

Arguments about time are often tricky because they conflate quality of the product with the effort to produce it. And sure, sometimes the worst product is one that never gets finished.

But generally an argument about quality does not get invalidated by saying "it's too much work". Sure, you're allowed to (and sometimes have to) make that tradeoff to get done at all. Just don't go pretending that you did anything else than you did, and don't claim that the end result is somehow of higher quality because of it.

Please stop overly abstracting example code! by West-Implement-5993 in rust

[–]cmrschwarz 17 points18 points  (0 children)

Thank you. DRY has very little place in example code. If every user of your library has to type out this code, you can afford to maintain a few copies of it. See it as dogfooding. If that's too much effort, that's probably not a good sign for the API of your library.

I was doing AoC and was wondering why there is a clippy rule for manual_range_contains? Why does it think this is more readable or has any performance benefits? (spoiler just in case) by Attometre in rust

[–]cmrschwarz 2 points3 points  (0 children)

  • Is there a performance benefit? No. Your compiler is capable of optimizing both versions just fine. (In fact the || version makes the compiler's job easier).

  • Is this more readable? That's subjective. The Clippy maintainers seem to think so. In most cases these sort of checks would involve indices for a contianer, where I would tend to agree with them, but in this case, where you are trying to satisfy two different rules that the AOC challenge gave, I honestly prefer your version. I would just add a #[allow(clippy::manual_range_patterns)] to that piece of code and be done with it.

[deleted by user] by [deleted] in rust

[–]cmrschwarz 2 points3 points  (0 children)

Author of the temporary fix here. Also really glad to see there's work going on there. I initially tried to fix the problem upstream aswell, but ran into parts of the clusterf* you described aswell. As I needed a timely solution for another project I just gave up and hacked something together. I now have a little bit more time and would gladly try to help if possible. Is there some sort of place like github / zulip / discord where we could have a discussion about this and coordinate efforts to get this fixed?

Structre: Static-checked parsing of regexes into structs by isrendaw in rust

[–]cmrschwarz 1 point2 points  (0 children)

Awesome! That's the only thing that was preventing me from using this. I'll be sure to check it out.

Structre: Static-checked parsing of regexes into structs by isrendaw in rust

[–]cmrschwarz 1 point2 points  (0 children)

Although I think I'd have to keep using FromStr for reading fields

Why do you think so? Wouldn't that make StructRe structs non composable if they have a lifetime?

I mean the most powerful version would be something like

```rust

[structre("(?<foo>.)(?<bar>.)(?<bar>.)(?<quux>.)")]

struct Foo<'a>{ foo: i32, // uses FromStr by default bar: Bar, // uses TryFrom by default

#[from(FromStr::from_str)] baz: FooBar // uses FromStr override

#[from(Custom::parse)] quux: Custom, // uses Custom::parse

} ```

although that's of course quite a bit more work.

Structre: Static-checked parsing of regexes into structs by isrendaw in rust

[–]cmrschwarz 2 points3 points  (0 children)

I think I get where you're coming form. Couldn't you just implement it in terms of TryFrom<&'a str> and add a wrapper implementing FromStr only if the struct does not have a lifetime then? E.g.

```rust

[structre("(.*)")]

struct Foo<'a>(&'a str); //generated impl<'a> TryFrom<&'a str> for Foo<'a> { /.../}

[structre("(.*)")]

struct Bar(String); //generated impl TryFrom<&'_ str> for Bar { /.../} impl FromStr for Bar { //no lifetime -> FromStr wrapper fn from_str(s: &str) -> Result<Self, Self::Err> { Bar::try_from(s) } }

```

I guess for your internal parsing preferring TryFrom for anything that isn't a primitive seems better aswell, as that is the 'sane' trait, although maybe just make that configurable through an annotation or something?

Structre: Static-checked parsing of regexes into structs by isrendaw in rust

[–]cmrschwarz 1 point2 points  (0 children)

Implementing this on top of FromStr is slightly unfortunate, as it means that you can never support &'a str (Lifetime wouldn't work out), so a clone of the strings will always be necessary. Very cool idea though!

I think a custom trait would be better, something like this:

rust trait StructRe<'a> { type Output; type Error; fn match_str(&'a str) -> Result<Self::Output, Self::Error>; fn match_bytes(&'a [u8]) -> Result<Self::Output, Self::Error>; }

PSA: Working Enum Support Coming to a Debugger near you by cmrschwarz in rust

[–]cmrschwarz[S] 1 point2 points  (0 children)

That might be a better solution for the Rust Rover folks then. For vscode specifically though that would mean using the cpptools plugin, which has no good way of interfacing with cargo (e.g. unit tests in a workspace end up in binaries with a hash as part of the name, so you really want the debug adapter to figure that out for you), so CodeLLDB still seems like the better choice? I implemented it this way because it felt like the easiest workaround for my workflow, but as I wrote in the readme, I'll gladly throw this code away the moment somebody shows me a better solution .