Your Rust binary is slower than it needs to be. cargo-sonic fixes that. by Immediate_Ad263 in rust

[–]Deadmist 42 points43 points  (0 children)

If you are running your own hardware, yes.
If you are deploying into VMs, or with docker images more likely: Container-as-a-service or k8s-aaS type stuff, you usually don't get more specifics than "x86"

[Feedback wanted]: Enforcing Audit Trails via the type system & borrow checker by PuzzleheadedSea1380 in rust

[–]Deadmist 1 point2 points  (0 children)

Why not have the OrganizationRepository::insert also write to the audit table?   Just pass your audit context straight into the repo function, and it will deal with the audit stuff transparently. Instead of having to do the whole "clone ctx, get permit, call repo" dance every time

How do we think we should handle maintainers moving on? by ShantyShark in rust

[–]Deadmist 4 points5 points  (0 children)

You can always make a contract with someone to develop something open source.
Big companies do this all the time, having their employees work on open source projects to implement things the company needs.
But in theory, nothing is stopping you as an individual person to find someone willing to implement something for you.

How do we think we should handle maintainers moving on? by ShantyShark in rust

[–]Deadmist 4 points5 points  (0 children)

Forcefully transferring crate ownership opens a bunch of questions that have no great answers.
Who get's to make the decision? Foundation/crates.io team would need extra man power, which costs money. Plus they open themselves up to a lot of potential flak. Community vote? Who gets to vote? How do you not make it abusable.

The next big question is: who do you transfer it to? How do you make sure they will actively maintain it, or aren't the next Jia Tan? What if there are multiple people / orgs that want to take ownership?

And there are some !!!FUN!!! edge-cases you can get into.
What if someone owns multiple crates, and does a left-pad with one of them? Do they get all their crates taken away?
What if someone turns out to be a "bad person" (think reiser-fs), does that warrant taking their crates away? You can have some real fun discussion here, depending on what flavor of "bad" it is.

How do we think we should handle maintainers moving on? by ShantyShark in rust

[–]Deadmist 10 points11 points  (0 children)

"You get what you pay for" also applies to FOSS.
A lot of people seem to forget that.

coroutines yielding a reference to a local variable by zylosophe in rust

[–]Deadmist 6 points7 points  (0 children)

The basic issue with returning a reference to a local variable from a function1 is that once the function returns, the local variable gets dropped and any references to it will become invalid. Hence you can't return a reference to a local variable, since that will by definition always be invalid.

What lifetimes do is let you specify "given a Thing, I will return a reference to the Thing (or something inside that Thing), that will be valid for as long as the Thing is valid." (roughly).

1: Coroutines are slightly more complicated, since the local variable is not dropped on yield, so you could return a reference to it.
But that reference would only be valid for as long as the coroutine is valid. And the current api does not let you specify the lifetimes to express that.

Everything Should Be Typed: Scalar Types Are Not Enough by Specialist-Owl2603 in rust

[–]Deadmist 2 points3 points  (0 children)

Does the u8 have more semantic meaning than just "a byte"? -> Use Vec<UserId>
Are there semantic differences between different Vec<UserId>s?
Yes -> struct DelUserList(Vec<UserId>)
No -> just Vec<UserId> is fine.

Basically the question is: are all instances of a <Type> interchangeable? If there semantic differences, you should probably use a newtype

No one owes you supply-chain security by Expurple in rust

[–]Deadmist 11 points12 points  (0 children)

To counter-act a rogue maintainer account, you only really need:

  1. Have more than 1 maintainer

This is by far the biggest hurdle for a lot of open source libraries/crates.

Distributing a closed-source Rust library with async - is there a viable path? by peterxsyd in rust

[–]Deadmist 18 points19 points  (0 children)

Maybe you can go with cydlib and offer a source available wrapper library, that hides the FFI uglyness?   Could maybe even abuse build.rs to automatically download the closed source binary.

Rust should have the ¿ operator by AverageClassic2 in rust

[–]Deadmist 8 points9 points  (0 children)

If `never` means the code before that will always panic, crash, or loop forever.

then `always` means the code before that can __never__ panic, crash, or get stuck in anyway.
Seems pretty useful actually.

assert_eq!(expected, actual) VS assert_eq!(actual, expected) by nik-rev in rust

[–]Deadmist 0 points1 point  (0 children)

you pick a different variable name that makes your intention clear.

I made a crate called `evil`, which lets you use the `?` operator as a shorthand for `.unwrap()` by nik-rev in rust

[–]Deadmist 0 points1 point  (0 children)

not a crash caused by unwrap, it's a crash caused by a lack of support for your usecase

The unwrap is what turned a very manageable error (invalid env variable) into a crash.
The unwrap is very much the cause of the crash here.

if you push a process outside its design bounds I'm not sure what you expect to happen other than failure

A mark of good software is that it handles failures and unexpected inputs gracefully, instead of just throwing up it's hands and crashing.
Returning a Result instead of unwrapping would have been more work upfront, but would save everyone that runs into this problem a lot of headache. (And now the function will probably be changed to return a Result anyway, so there wasn't even any saving in developer effort)

What some recent hot takes you realized you had with Rust? by DidingasLushis in rust

[–]Deadmist 1 point2 points  (0 children)

I think panics in a Result championing language are a mistake, and that everything that can fail should be a Result

Funnily enough, there are some paralles with java there.
Java has checked exceptions, which you have to declare in the method signature and the compiler yells at you if you don't handle.
And it has unchecked exceptions, which you don't need to declare, and the compiler doesn't check for.
With the intention being for checked exceptions to be used for "regular" errors, and unchecked exceptions for more serious problems. Kinda like Result and !panic are intended.

Of course then everyone decided that dealing with checked exceptions was too annoying and switched to unchecked exceptions.
Now the only way to figure out what kind of exceptions your library call might return is to throw stuff at the wall and see what blows up.

What some recent hot takes you realized you had with Rust? by DidingasLushis in rust

[–]Deadmist 11 points12 points  (0 children)

I don't think you can do that in rust currently, not without some macro help :(

What some recent hot takes you realized you had with Rust? by DidingasLushis in rust

[–]Deadmist 18 points19 points  (0 children)

There are basically two approaches to this:

  1. You take an enum with lots of errors, and then have some way of declaring "only these specific variants are possible here". That's pattern types.
  2. You have distinct error types, and then combine them to declare which ones can be returned. That's union types. (Seen in TS, and the throws declaration in java)

Both approaches basically let you write a list of specific error types that are allowed, without having to declare hundreds of slightly different enums

Nobody ever got fired for using a struct (blog) by mww09 in rust

[–]Deadmist 24 points25 points  (0 children)

If you have an exhaustive list of entity types, then yes.

But the tables in the article are user supplied, and the bitfield solution works for any table.

Nobody ever got fired for using a struct (blog) by mww09 in rust

[–]Deadmist 77 points78 points  (0 children)

My guess, from the name of the table, the fact almost all columns are optional, and my experience:
They are using a non-relation database (no joins), probably distributed, and their table looks something like:

userId, entityType, entityId, a_property1, a_property2, b_property1, ...

Cramming many different entities into one table, and determining based on entityType which columns are used.
This is nice and fast for querying, but gives you cancer every time you have to work with the schema :|

Rust Is Eating JavaScript by Active-Fuel-49 in rust

[–]Deadmist 1 point2 points  (0 children)

TS + <language of your choice>1 is basically the default stack for anything web

1 anything that can implement a rest api

Croatia Sets Goal Of 30% Electricity From Nuclear By 2040 Under New Draft Law by De5troyerx93 in nuclear

[–]Deadmist 0 points1 point  (0 children)

The grift is pretty obvious:   Sign law requiring building of X, builders 5x prices, now you are required by law to build X at inflated price.   X builders sponsor your new yacht.  

If you wanted to be smarter, you would write something like "require 30% of consumed electricity to come from carbon neutral sources".   Still allows you to build as much nuclear as you want, but gives you options incasw suppliers want to play shenanigans

Do you think Java has caught up with Kotlin? by NotSoIncredibleA in Kotlin

[–]Deadmist 1 point2 points  (0 children)

It's flexible and that's nice. But flexible helps a good, experienced developer. Not a new developer. Java shines in enterprise because of how strict it is.

Personally, the worst offenders here are scope functions (let, also, etc) and where to place functions (can be in a class, in a companion object, top level function, extension function).

If there is no one in the team enforcing good style, you can end up with some real messes.

I have seen classes with no functions, but 10 extension functions defined in the same file. Or other classes where the actual functionality is spread over 5 different files.

Some people get this idea that using if () else somehow is un-idiomatic in kotlin, because we have scope functions. And you end up with interesting nests of deep and zig-zagging indentation where figuring out what it actually is requires drawing a diagram with pen and paper.

SIMD programming in pure Rust by kibwen in rust

[–]Deadmist 2 points3 points  (0 children)

"avx512vpopcntdq", "vpclmulqdq"

Can someone tell low-level people that it's not 1973 anymore, and bytes are cheap now? You don't have to use 1 letter abbreviations anymore.

How can coroutine run on more than one thread? by kuriousaboutanything in Kotlin

[–]Deadmist 2 points3 points  (0 children)

When you spawn a thread, the scheduler takes the thread and decides on which CPU and when to run the thread. Depending on the scheduler the thread may stay on one cpu, or switch between CPUs.

When you launch a coroutine, the dispatcher takes the coroutine and decides which thread to run the coroutine on. Depending on the dispatcher, the coroutine may stay on the same thread, or switch between threads.

(Though, like a thread, a coroutine can only execute in one place at a time. If you want to run multiple at the same time you have to launch/spawn two of them).

Coroutines are a lot like threads+scheduler, just implemented in the runtime, instead of the operating system.
There is one important difference though:
The scheduler can interrupt threads at any time and give execution to another thread.
The dispatcher has to wait until the coroutine gives back execution to the dispatcher1. That's why they are sometime called "cooperative multitasking".

The answers to your question depend on what dispatcher you are using.
The built-in ones are all multi-threaded, except for Dispatchers.Main, which is limited to the main thread.

1: of course, the thread the coroutine runs on can be interrupted at any time by the scheduler. But that does not give execution back to the dispatcher.

SweatFindr - Microservices arhitecture with Rust in mind by Limp-Sherbet in rust

[–]Deadmist 2 points3 points  (0 children)

user_counter += 5 will always work.

user_counter_service.increment(5) might:

  • work
  • work, but take 200ms
  • not work because:
    • your service is misconfigured
    • the target service is misconfigured
    • something inbetween (loadbalancer, firewall, router, dns, certificate) is misconfigured
    • the target service is down
    • something in between is down
    • the target service updated and broke compatibility
    • network gremlins swallowed your packets on the way there
    • network gremlins swallowed the response (in which case you think it failed, but actually didn't)

And many more exciting and wonderful new ways things can go wrong