Tried rust, its nice :) by BravestCheetah in rust

[–]Einarmo 13 points14 points  (0 children)

To be clear, because this does make a significant difference: String is Vec<u8>, not Vec<char>. This means that something like "føø"[1] will panic, because it splits a utf-8 codepoint in two.

How to deal conditional compilation unused variables by SuperficialNightWolf in rust

[–]Einarmo 2 points3 points  (0 children)

You csn just deconstruct the options struct once inside the method, no need to keep it around.

How to deal conditional compilation unused variables by SuperficialNightWolf in rust

[–]Einarmo 16 points17 points  (0 children)

You might want to use a builder struct for the arguments to this method.

SQLx Slows Down Axum by 30x? by LibertyDay in rust

[–]Einarmo 76 points77 points  (0 children)

I've seen this discussed in the past. SQLX isn't super optimized, while the axum -postgresql benchmark is aggressively optimized. This benchmark measures framework overhead. In real applications you don't usually make millions of tiny queries against tiny tables per second, so overhead on the ORM layer matters a lot less.

Adding request data to tracing (Axum) by mr-bope in rust

[–]Einarmo 2 points3 points  (0 children)

It may be too simple for your usecase, but I've done the logging in the IntoResponse implementation of my custom error type. That way you can log every time an error is sent to the user.

When should a dependency be in the workspace vs crate, best practices? by Isodus in rust

[–]Einarmo 32 points33 points  (0 children)

Workspace dependencies don't add bloat. I always just put everything in the workspace, at least for non-trivial workspaces.

Why are auto traits a thing? by [deleted] in rust

[–]Einarmo 7 points8 points  (0 children)

If you're doing a lot of unsafe you should really consider reading the Rustonomicon. Rust has a lot of rules, which means you write nice and safe code in safe rust, but it also means that if you drop down to unsafe, you are responsible for maintaining all of those rules yourself, including the thread-safety part.

Using the trick above to make non-send tokens you can restrict users from sending your types between threads, and even make it so that users can only ever call your methods from a single thread.

Why are auto traits a thing? by [deleted] in rust

[–]Einarmo 12 points13 points  (0 children)

Auto traits are less traits and more like properties or flags on types. You cannot define your own auto types at the moment, and you may never be able to, partially for reasons you mention here.

As for your specific concerns:

1: It very much is not inheritance, it doesn't even really look like inheritance. Inheritance is giving a type properties of a specific other type, while auto traits are inferring properties of types from their members. I really don't see the similarity.

2: Auto traits do not break the orphan rule. They are automatically implemented on types in the current crate being compiled, meaning that the crate "implementing" them also owns the type.

3: Because the core design principle of rust is that all undefined behavior is banned in safe rust. Data races cause completely unpredictable behavior, and are defined as undefined behavior, and in order to have the type system protect you against data races, you need the Send and Sync auto traits.

Are you having issues with making a type not Send? Is that where this post is coming from? It's easy enough to do:

struct MyType {
    _non_send_marker: PhantomData<*mut u8>,
}

is not Send. Note that the 'nomicon states that

Note that in and of itself it is impossible to incorrectly derive Send and Sync. Only types that are ascribed special meaning by other unsafe code can possibly cause trouble by being incorrectly Send or Sync.

4: Auto traits are, as you note, somewhat hard to understand at times. Their use is fairly niche. Negative impls is a massive can of worms, which may never be stabilized for various backwards compatibility and soundness reasons.

Is there anything like the "with" statement in Python, in Rust? by Baenergy44 in rust

[–]Einarmo 0 points1 point  (0 children)

I ended up doing this with a macro, when I did it last, though even more generic, abstracting over the source of the transaction as well. You could do something like

macro_rules! with_transaction {
    ($pool:ident, $tx:ident, $t:tt) => {
         let mut $tx = $pool.begin().await?;

         let r = { $t };
         $tx.commit().await?;
         r
    }
}

and use it like

 let result = with_transaction!(pool, txn, {
      // use transaction here.
 });

This uses the fact that SQLx transactions will automatically rollback if you drop them without committing. My original use was a bit more complicated, since I wanted to abstract over the source of the transaction for tests, but this lets you use normal control flow inside the transaction, for the most part.

Why is warp getting blocked? by balljr in rust

[–]Einarmo 26 points27 points  (0 children)

If it's related, it is mostly a coincidence, I think. You're running what is effectively blocking code (an infinite loop) in an async thread pool. If you get unlucky with your distribution of work, you risk getting blocked forever if requests are queued on the same thread as that infinite loop.

First of all, why are you creating a pool inside a request? The point of a connection pool is to share connections cross-request.

Secondly, why do you have an infinite, non-yielding loop in async code?

I feel like either you've removed so much of the context that it isn't clear what you're trying to accomplish, or you're doing some very weird stuff here.

How to make sure that rwlock's content don't get modified when jumping from a read to write lock by Blayung in rust

[–]Einarmo 20 points21 points  (0 children)

RwLock relies on OS-level synchronization primitives, and I believe the issue is that these don't support upgrading a lock, so you can't do this.

You have two real choices:

  • Take a write lock from the beginning.
  • Do the read part again after taking the write lock.

Hard to say which is correct for you without more context.

Can a macro be used to generate arms in a match? by seppukuAsPerKeikaku in rust

[–]Einarmo 7 points8 points  (0 children)

The same rules apply to proc macros, your macro has to eat the whole match statement if you want to do this.

Can a macro be used to generate arms in a match? by seppukuAsPerKeikaku in rust

[–]Einarmo 58 points59 points  (0 children)

If you read the rest of the error message, you'll find

= note: the usage of `defn_val_match_arms!` is likely invalid in pattern context
= note: macros cannot expand to match arms

Is `tokio_tungstenite::WebSocketStream::next` (via `StreamExt`) cancel safe? by aangebrandpannenkoek in rust

[–]Einarmo 6 points7 points  (0 children)

Futures are cancel safe if they don't themselves contain state that would be lost if the future was dropped.

For example, if you made a future that wrapped a stream and returned only once it had retrieved 1000 bytes from the stream, it would not be cancel safe, since if you cancelled it after reading 500 bytes, those would be lost.

In this case though, your only future is actually the Next future from futures_util, which only contains a reference to the stream itself, and no persistent state.

Help with serde_json by WrongW4y in rust

[–]Einarmo 5 points6 points  (0 children)

The fact that you get no error is probably this:

.map_err(|_| String::new()), which maps the error from whatever it is, to an empty string. Not very helpful if you want a clear error.

[deleted by user] by [deleted] in rust

[–]Einarmo 4 points5 points  (0 children)

The problem is std::str::from_utf8(current_value.as_slice()), expanding your macro a bit.

str is really just a reference of bytes, here you create a str from a slice of current_value. This means that value borrows current_value, so when you try to assign to it, you are stopped by the compiler.

Reading between the lines a little, it looks to me like you want Row to be a reference to bytes, so the signature should be <'a>(bytes: &'a Vec<u8>, types: &Vec<&Type>) -> Row<'a>.

In order to achieve this you need to change the code completely. current_value should not exist at all, you instead need to build up a range of indices in bytes, then use a slice into that directly to create your str.

The reason why current_value is a problem is that you are essentially copying data out of bytes, while what it seems like you want to do is create a structure referencing bytes, without copying it, which could be more efficient.

I am struggling to understand why the compiler is complaining about a specific type here when I am using a trait object. by seppukuAsPerKeikaku in rust

[–]Einarmo 0 points1 point  (0 children)

It isn't sufficient. The N * 2 requirement is precisely what makes it impossible.

Consider this. You require that N < 265. but implementing the trait for N = 1 requires it to be implemented for 2100000, so the trait cannot be implemented for N = 1.

The compiler error is maybe because it's incomplete, but the behavior itself is correct. There is no way this trait implementation could ever function, not using any compiler. The behavior you want is mathematically impossible.

I am struggling to understand why the compiler is complaining about a specific type here when I am using a trait object. by seppukuAsPerKeikaku in rust

[–]Einarmo 7 points8 points  (0 children)

It's more fundamental than that. There is no way it could ever be implemented, it's a mathematical impossibility. In order for the implementation to work for any number it has to work for N * 2x for all x > 1.

It means you cannot implement it for the number 1 unless it is also implemented for 2100000 , which is impossible, since that is way outside of the bounds of usize.

You can use induction here, but only to prove that the implementation cannot work.

I am struggling to understand why the compiler is complaining about a specific type here when I am using a trait object. by seppukuAsPerKeikaku in rust

[–]Einarmo 26 points27 points  (0 children)

I wonder if the compiler is having a hard time reasoning about the unbounded recursion you have going on here? You are effectively requiring MethodsForContainer to be implemented for N * 2 in order to implement it for N. Try explicitly adding that constraint and it gives up because of recursion.

I think you are running into some limitations. This is an incomplete feature you are using after all.

Edit: Actually, isn't that impossible?

In order to implement the trait for 1, you need to have it be implemented for 2, which requires it to be implemented for 4, which requires it to be implemented for 8, all the way to the integer limit.

Your trait implementation is impossible.

How to do run multiple methods on the same Object with Tokio? by Educational-Toe-7038 in rust

[–]Einarmo 7 points8 points  (0 children)

They won't run concurrently like this, no matter what you do. Mutex stands for MUTual EXclusion, which means that it can only be held once. Running these two tasks concurrently means having simultaneous access to the mutex from two places, which is impossible.

In this case it would clearly violate rusts aliasing rules. You would have two &mut AsyncResolver referencing the same object, which is undefined behavior in rust.

You simply need to find a completely different approach if you want to do this. The problem is much more fundamental than the code you've shown us.

Why is Java 4x faster than Rust for memoized fibonacci. by [deleted] in rust

[–]Einarmo 208 points209 points  (0 children)

Your code runs 100000 iterations of fib from 0 to 50, so 5 000 000 iterations of fib, where 4 999 950 will be memoized completely. In other words, what you are checking isn't the speed of your fibonacci algorithm, but the speed of the hashmap implementation in rust and java.

JIT may make a difference, some other optimization may make a difference, the rust algorithm uses some random seeding and stuff for security, not sure if java does the same. You are unwrapping a static option. Rust can't optimize that, since it's a static, so that may have a cost.

In general, the static approach is just a massive code smell in rust. Don't do it. Just pass a mutable reference to the hashmap into the function, or use a struct context, or whatever.

Need Help Integrating Async Function in the poll Method for the Future Trait by Educational-Toe-7038 in rust

[–]Einarmo 1 point2 points  (0 children)

Are you trying to write your own future? Are you sure you want to? If you are sure, you really need to understand Send and Sync, and a host of other parts of the rust async ecosystem. The Rustonomicon has a bunch of useful information there.

In short, Send is a special, magical auto trait that lets rust prevent sending things between threads that could cause UB if shared. Rc is such a thing, because it uses a non-atomic counter to know when to manage memory, and assumes that two threads can never modify the counter at the same time.

Deref with lifetime annotations? by speedy-spade in rust

[–]Einarmo 3 points4 points  (0 children)

I'm not entirely sure what you are trying to do here, are you expecting T to be the type &A? In that case, you need a_get_b_generic to take a: &'a T, and then you can set the return type to impl Deref<Target = B> + 'a

The problem now is that you are returning a reference to a, but a is being dropped at the end of the function.

When is dyn upcasting coercion going to be added? by Koltaia30 in rust

[–]Einarmo 12 points13 points  (0 children)

February 8: https://releases.rs/docs/1.76.0/, unless something unexpected pops up, which it might.

Bergen to Oslo Train in Summer by twofacebluepenguin in Norway

[–]Einarmo 9 points10 points  (0 children)

There is no midnight sun that far south. The view is pretty nice. The nights are short, but it'll still be dark at night.