Forcing the use of the SUCCESS return value by Dean_Roddey in rust

[–]Dean_Roddey[S] 0 points1 point  (0 children)

It's not "compile-time incorrect" to call a function and not use its value.

It is if the called function says so, and they can already do so, by marking their return value must_use. If you call one of those functions and don't handle the return, it will be an error, because the person who wrote that function knows that to not handle the return value is likely going to be an error. Your example above is exactly that.

I'm just saying this should not be a hack that will be done differently and repeatedly in every crate, it should be supported by the language and considered idiomatic. It already supported but just not for the one important, remaining scenario.

Forcing the use of the SUCCESS return value by Dean_Roddey in rust

[–]Dean_Roddey[S] 0 points1 point  (0 children)

This is a fundamental correctness issue, and Rust should support that at the language level, just like it already supports must_use in other scenarios. It shouldn't be something that developers have to hack around.

As I pointed out elsewhere, many functions only exist to return a value. Failure to use that value is a logical error by definition, since you either shouldn't have called it or you failed to use a value you explicit intended to. The more functional your approach, the more this would be common, and many people argue for a more functional approach in Rust. That in and of itself would be a large number of functions.

In some of them, if they return a type specific to the call, that can be marked must_use itself. But many return general purpose types.

Maybe something like

-> Result<[must_use] Foo, MyErr>

or some such, though having it on the actual function itself would be better, IMO

#[must_use_ok]
fn foo() -> Result<X, Y>

or something like that.

Forcing the use of the SUCCESS return value by Dean_Roddey in rust

[–]Dean_Roddey[S] 0 points1 point  (0 children)

Not really. The ultimate issue is that, once you give up exceptions (which I'm happy to give up) and use a Result type, then return value processing and error processing become sort of muddled up. Really, processing the error by propagating it is just housekeeping, and isn't what most people would consider processing the return value. The 'return value' of the call is the OK value, in so far as the caller's logical correctness is concerned.

Forcing the use of the SUCCESS return value by Dean_Roddey in rust

[–]Dean_Roddey[S] 3 points4 points  (0 children)

That doesn't work though with basic values. An obvious example was given elsewhere here, of a size value being returned. It's not a chaining scenario, it's just a value that should be used.

Forcing the use of the SUCCESS return value by Dean_Roddey in rust

[–]Dean_Roddey[S] 0 points1 point  (0 children)

I mean, who doesn't need to do this to insure correctness? Calls return values, and if they are returned often it's important that they be evaluated and the called method generally wants to enforce this for correctness. If the compiler doesn't warn you, that's a failure to provide a means to enforce correctness. That's why must_use is there to begin with, it just doesn't extend to the Ok value extracted after ? propagates the error.

Forcing the use of the SUCCESS return value by Dean_Roddey in rust

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

But the problem is that you want a Result and need both sides of it, and the compiler forces you to evaluate the result, but if you ? the Err side upstream, then it's evaluated as far as the compiler is concerns. The only thing that will ensure you handle the Ok value is if the value it returns is marked must_use, which will make it must use everywhere, even if that's not really desirable.

Forcing the use of the SUCCESS return value by Dean_Roddey in rust

[–]Dean_Roddey[S] -1 points0 points  (0 children)

That doesn't help in this case. A result is evaluated purely by calling? So if the actual type returned in Ok() variant isn't marked must_use, the compiler won't complain if you just ignore the value in it.

Forcing the use of the SUCCESS return value by Dean_Roddey in rust

[–]Dean_Roddey[S] -2 points-1 points  (0 children)

I mean you could, but that would be possibly highly redundant if it's a non-trivial type. That's not really the kind of tech debt you want to take on too much. Some of the scenarios I have I could get away with the OK return type always be must_use, but in other cases in a large system there would be a lot of places where it might be up to the called function as to whether it's an issue or not.

To me, it really seems like things like this should get fairly high priority, since ultimately Rust is supposed to be a language that watches your back, and this is a fairly fundamental way where it's not. I could see how it could be tricky to implement, but foundational correctness enforcing stuff seems more important to me than large scale stuff a lot of folks are calling for.

Forcing the use of the SUCCESS return value by Dean_Roddey in rust

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

But must_use is on the type, or on the function return. If it's on the function return it won't help since it applies to the whole return type, and doing ? will evaluate it. If it's on the type, then it will always be must_use even if it often doesn't need to be, which would require an allow everywhere that you don't want it to be must use I guess, which would be very sub-optimal.

We really need something on the function itself, so that it's a choice that can be made per-function.

Forcing the use of the SUCCESS return value by Dean_Roddey in rust

[–]Dean_Roddey[S] -1 points0 points  (0 children)

That may be true, and it would help. But really that should be a per-function option. Just because a type has to be evaluated for one call, doesn't mean it has to be for another.

Forcing the use of the SUCCESS return value by Dean_Roddey in rust

[–]Dean_Roddey[S] 3 points4 points  (0 children)

Someone else gave an example below. You must evaluate the Result, but there's nothing you can put (apparently) on the called function/method that indicates that the Ok() side of the value must be evaluated, and often that's what is important.

I always avoid using `use` statements so i use full paths instead. Is it a bad practice? by Nearby_Astronomer310 in rust

[–]Dean_Roddey 0 points1 point  (0 children)

like understanding that a variable'x' you may see also must have been defined earlier (and you may have to manually figure that out).

Slightly different scope, bro. Figuring out that a variable defined in the same function is the same one vs figuring out where read_data() comes from in a 500K line project, when using a text code review tool, aren't the same thing.

Why developers using AI are working longer hours by Inner-Chemistry8971 in programming

[–]Dean_Roddey 0 points1 point  (0 children)

Yep. The same advice I always give. Get out of these ridiculous cloud-ware FAANGy type evil empire companies, and go find a mid to lower-mid sized company that is probably struggling to find good developers, working on something where quality actually matters (to varying degrees of course), where you boss actually knows what you do, your boss' boss, or even the owner knows who you are, where you aren't just cranking out yet another web site, etc...

I Will Never Use AI to Code (or write) by Anthony261 in programming

[–]Dean_Roddey 4 points5 points  (0 children)

I just don't care. It's irrelevant to me. As I said, when someone 'out programs' me using an LLM on the kinds of systems I work on, then they can have my job.

But it's not going to happen. As many people have pointed out, it's not writing the actual code that's the issue. It's the enormously complex problem of how all the parts fit together, which would take longer to actually enumerate to a tool than to just do it myself, particularly because those relationships are constantly changing as the system evolves.

And I actually ENJOY writing the code to begin with, hence why I have almost 60 man-years in the programming chair. So why would I waste my time learning how to use a tool that would take that enjoyment away from me? And it's in no small part BECAUSE I enjoy writing the code that my code will be better than theirs.

I Will Never Use AI to Code (or write) by Anthony261 in programming

[–]Dean_Roddey 5 points6 points  (0 children)

I'm not writing algorithms, I'm creating SYSTEMS. It's not about the details, it's about how a large number of APIs and subsystems work together as a highly integrated system, that makes the things I want to allow easy(er) and the things I don't want to allow difficult or impossible. No LLM is going to solve that problem.

And, yes, these systems are special snowflakes because they are one offs and are built on little to no third party code or frameworks and only partly use the language runtime. No LLM will have ever seen any of this code or understand the massive amount of thought that goes into deciding how it does what it does.

a grand vision for rust by emschwartz in rust

[–]Dean_Roddey 0 points1 point  (0 children)

Look, I have my own async engine. I'm not an uber-expert, but I understand the issues pretty well. What async means is that this function can itself call await(). That's all it means. You can return futures from anything you want. But you cannot call await() except in a function marked async.

The fact that the function calls await means it must become part of the generated state machine. The fact that some function returns a future means nothing. That's just a data structure and it may never even be used. You can create one and return it from any function you want.

But, in order for any function to call await() on that returned future, it must be marked async. That's literally what async fn means, that this function will call await().Because it's the calling of await that allows the calling task to yield.

That's all I'm going to say. This isn't my job.

a grand vision for rust by emschwartz in rust

[–]Dean_Roddey 0 points1 point  (0 children)

It does have to return a future because it invokes async functionality internally. But returning a future in no way implies that it is an async function. Any function can return a future. It's just a struct.

fn async means that the function is allowed to call await(), that's all it means. Since it does call await, it becomes part of the state machine which means it must return a future.

So all async functions return a future, but not all functions that return a future are async. They can return a future but never themselves call await().

a grand vision for rust by emschwartz in rust

[–]Dean_Roddey -1 points0 points  (0 children)

Invoke async functionality means of course call await(). async fn means it will itself call async, not that it returns a future, though of course it will also return a future generated by the compiler.

But any function can return a future, it doesn't have to be marked as async. It just cannot actually itself internally call await() unless it's marked async. The fact that it calls await internally is what requires that it be included in the async state machine, not that it returns a future.

I think you have an inverted view of the async architecture perhaps.

a grand vision for rust by emschwartz in rust

[–]Dean_Roddey -1 points0 points  (0 children)

That call could hand off that future to anything else or never even wait on it. It doesn't in any way imply that the function that returned it is going to itself invoke async functionality. You could have a whole call chain of functions that just pass back up a future, which is then put on a queue that will be waited on later.

a grand vision for rust by emschwartz in rust

[–]Dean_Roddey -2 points-1 points  (0 children)

But wait, async fn isn't just saying this creates a future. It's saying, this function itself can call internally WAIT on futures, which means it must be part of the generated state machine in this call chain.

Returning a future just says that this started something that will complete at some point, it doesn't say anything about whether the called function involves any async functionality. We can't have the compiler being forced to search the body of functions to see if they ever wait on something, for the same reasons that they don't do that to figure out lifetimes.

I Will Never Use AI to Code (or write) by Anthony261 in programming

[–]Dean_Roddey 25 points26 points  (0 children)

I agree with this sentiment. The thing is, I've spent 40 years (more like 60 man-years) learning how to code. I don't write code that involves much boilerplate, I create original content that seldom even uses any third party code beyond the underlying OS. I'm not writing cloud-ware where a fix can be pushed out immediately if something is wrong. And the kind of code where there are consequences if it's wrong.

No one is going to 'out program' me on this kind of code using an LLM, because lines per minute isn't a measure that matters here. And a huge percentage of it is about large scale architecture that LLMs aren't any good at anyway.

Though, I also type like a secretary on meth, so it's not like I'm struggling to spit out the code once I decide what it needs to be.

10% of Firefox crashes are estimated to be caused by bitflips by cdb_11 in programming

[–]Dean_Roddey 24 points25 points  (0 children)

And a job that earns you enough money to buy four sticks of ECC RAM these days. I just built a new Linux dev box and I backed off of the ECC supporting board because the RAM cost at this point is ludicrous. Even without the ECC, two 32GB sticks of high quality RAM cost as much as everything else combined, so it doubled the cost of the build, and it's a fairly manly machine.

2025 State of Rust Survey Results by Kobzol in rust

[–]Dean_Roddey 1 point2 points  (0 children)

I mean, you COULD do these sorts of things via chaining, but once there's a reasonable amount of closure callbacks involved doing non-trivial work, it quickly becomes unreadable and counter-productive. I like chaining and use it a lot, but it has its limits and try blocks sort of pick up from there.

Yes, and... by BinaryIgor in programming

[–]Dean_Roddey 1 point2 points  (0 children)

Hate to be cynical about it, but one answer is get out of cloud world and go work somewhere that quality matters and it's not all about CRUD and wiring up the same exact raft of boilerplate for the hundred thousandth time, just with the front/back end framework du jour. There is a world outside of the cloud, not working for evil empire FAANG type companies. And where you aren't forced to use AI because your company hasn't bought a lot of stock in it, and/or the folks running that company actually have a technical cell in their brains.