What Rust provides is a way to build safe abstractions over unsafe code.
Rust's type system (including ownership and borrowing, Sync/Send, etc), along with it's privacy features (allowing types to have private fields that can only be accessed by code in the module that defined them) allows you to create fully safe interfaces around code that uses unsafe; there is provably no combination of uses of the interface which lead to undefined behavior.
Now, yeah, it's possible to also use unsafe in Rust just for applying a local optimisation. And that has fewer benefits than a fully encapsulated safe interface, though is still easier to audit for potential UB than C.
So you're right that it's on a continuum, but the distinction between safe and unsafe code means you can more easily find the specific places where UB could occur, and the encapsulation and type system makes it possible to create safe abstractions over unsafe code.
So, it's true that unsafe code can depend on preconditions that need to be upheld by safe code.
But using ordinary module encapsulation and private fields, you can scope the code that needs to uphold those preconditions to a particular module.
So the "trusted computing base" for the unsafe code can still be scoped and limited, allowing you to reduce the amount of code you need to audit and be particularly careful about for upholding safety guarantees.
Basically, when writing unsafe code, the actual unsafe operations are scoped to only the unsafe blocks, and they have preconditions that you need to scope to a particular module boundary to ensure that there's a limited amount of code that needs to be audited to ensure it upholds all of the safety invariants.
Ralf Jung has written a number of good papers and blog posts on this topic.
And you think one can not modularize C code and encapsulate critical buffer operations in much safer APIs? One can, the problem is that a lot of legacy C code was not written this way. Also lot of newly written C code is not written this way, but the reason is often that people cut corners when they need to get things done with limited time and resources. The same you will see with Rust.
There is no distinction between safe and unsafe code in C, so it's not possible to make that same distinction that you can in Rust.
And even if you try to provide some kind of safer abstraction, you're limited by the much more primitive type system, that can't distinguish between owned types, unique borrows, and shared borrows, nor can it distinguish thread safety properties.
So you're left to convention and documentation for that kind of information, but nothing checking that you're getting it right, making it easy to make mistakes. And even if you get it right at first, a refactor could change your invariants, and without a type system enforcing them, you never know until someone comes along with a fuzzer and figures out that they can pwn you
There is definitely a distinction between safe and unsafe code in C, it is just not a simple binary distinction. But this does not make it impossible to screen C for unsafe constructions and it also does not mean that detecting unsafe issues in Rust is always trivial.
I assume you are hinting at 'int' is signed here? And, that signed overflow is UB in C? Real question: Ignoring what the ISO C language spec says, are there any modern hardware platforms (say: ARM64 and X86-64) that do not use two's complement to implement signed integers? I don't know any. As I understand, two's complement correctly supports overflow for signed arithmetic.
I might be old, but more than 10 years ago, hardly anyone talked about UB in C and C++ programming. In the last 10 years, it is all the rage, but seems to add very little to the conversation. For example, if you program C or C++ with the Win32 API, there are loads of weird UB-ish things that seem to work fine.
> Ignoring what the ISO C language spec says, are there any modern hardware platforms (say: ARM64 and X86-64) that do not use two's complement to implement signed integers?
This is not how compilers work. Optimization happens based on language semantics, not on what platforms do.
At least in recent C++ standards, integers are defined as two’s complement. As a practical matter what hardware like that may still exist doesn’t have a modern C++ compiler, rendering it a moot point.
UB in C is often found where different real hardware architectures had incompatible behavior. Rather than biasing the language for or against different architectures they left it to the compiler to figure out how to optimize for the cases where instruction behavior diverge. This is still true on current architectures e.g. shift overflow behavior which is why shift overflow is UB.
int average(int x, int y) {
long sum = (long)x + y;
if(sum > INT_MAX || sum < INT_MIN)
return -1; // or any value that indicates an error/overflow
return (int)(sum / 2);
}
There is no guarantee that sizeof(long) > sizeof(int), in fact the GNU libc documentation states that int and long have the same size on the majority of supported platforms.
> return -1; // or any value that indicates an error/overflow
-1 is a perfectly valid average for various inputs. You could return the larger type to encode an error value that is not a valid output or just output the error and average in two distinct variables.
> There is no guarantee that sizeof(long) > sizeof(int), in fact the GNU libc documentation states that int and long have the same size on the majority of supported platforms.
That used to be the case for 32-bit platforms, but most 64-bit platforms in which GNU libc runs use the LP64 model, which has 32-bit int and 64-bit long. That documentation seems to be a bit outdated.
(One notable 64-bit platform which uses 32-bit for both int and long is Microsoft Windows, but that's not one of the target platforms for GNU libc.)
I don't know why this answer was downvoted. It adds valuable information to this discussion. Yes, I know that someone already pointed out that sizeof(int) is not guaranteed on all platforms to be smaller than sizeof(long). Meh. Just change the type to long long, and it works well.
Copypasting a comment into an LLM, and then copypasting its response back is not a useful contribution to a discussion, especially without even checking to be sure it got the answer right. If I wanted to know what an LLM had to say, I can go ask it myself; I'm on HN because I want to know what people have to say.
average(INT_MAX,INTMAX) should return INT_MAX, but it will get that wrong and return -1.
average(0,-2) should not return a special error-code value, but this code will do just that, making -1 an ambiguous output value.
Even its comment is wrong. We can see from the signature of the function that there can be no value that indicates an error, as every possible value of int may be a legitimate output value.
It's possible to implement this function in a portable and standard way though, along the lines of [0].
Too late for me to edit: as josefx pointed out, it also fails to properly address the undefined behavior. The sums INT_MAX + INT_MAX and INT_MIN + INT_MIN may still overflow despite being done using the long type.
That won't occur on an 'LP64' platform, [0] but we should aim for proper portability and conformance to the C language standard.
But this is also easy to protect against if you use the tools available to C programmers. It is part of the Rust hype that we would be completely helpless here, but this is far from the truth.
sorting floats with NaN ? almost anything involving threading and mutation where people either don't realise how important locks are, or don't realise their code has suddenly been threaded?
You're a lot more limited more limited to the kinds of APIs you can safely encapsulate in C. For example, you can't safely encapsulate an interface that shares memory between the library and the caller in C. So you're forced into either:
- Exposing an unsafe API and relying on the caller to manually uphold invariants
- Doing things like defensive copying at a performance cost
In many cases Rust gives you the best of both worlds: sharing memory liberally while still having the compiler enforce correctness.
Which is just a convoluted way of saying that it is possible to write bugs in any language. Still, it's undeniable that some languages make a better job at helping you avoid certain bugs than others.
There's also "white" which is naturally occurring pure hydrogen.
Mostly it's seen as being economically infeasible to extract, though there is one working well in the world, and some other potential sources that may be feasible to extract discovered recently.
But the big problem with hydrogen is that right now, the majority of the supply is grey/brown/black, which all emit CO2 to produce. Green is far more expensive, and the carbon capture needed for blue is also expensive and the methods of storage are dodgy.
The thing about green hydrogen is that it's more efficient to transmit and store electricity than convert it to hydrogen and distribute and store that, so it's basically just a worse way of utilizing green energy sources. The only reason hydrogen is at all economical is that grey/brown/black are cheap, and it's hard to see any path for green or blue to become competitive (and truly zero emissions for blue).
It's possible that we'll find reserves of white hydrogen and efficient ways to extract it, but that's purely speculative right now, while building renewable energy sources, electric distribution, and batteries can be done right now.
I'm kind of puzzled by your first point. In my experience, parking apps require you to pay in larger chunks of hours than paying with coins used to; many times I have to pay for a minimum of 2 hours of parking with the app when I could pay for just 10 or 15 minutes of parking with coins.
The parking app I use in Berlin, easy park, works in the sense that I pre-select a timeframe I think im going to park which then gives me an estimate for how much it'll cost and reserve that amount using my CC. When I end the parking before that timer ends, the actual time I've parked will be taken and only that amount is charged.
It used to be even better in the sense that you'd only start and then end parking without having to pre select a time. But I think too many people, me included, forgot to end the parking when taking off and paid way more than they actually parked for.
Of course the apps could easily detect that parking has ended. They could note your location when you park. When the phone returns to that location, and then moves at driving speed, parking has ended.
But they don't because they make more money by profiting from people who forget to "clock out" when they are done parking.
> Of course the apps could easily detect that parking has ended. They could note your location when you park. When the phone returns to that location, and then moves at driving speed, parking has ended.
They could at least start with adding proper CarPlay and Android Auto support so you can just end the parking from the infotainment. But I think there can be at most a single engineer working on this app if at all. Up until a couple months ago it didn't even have the option for a persistent notification to remind you that you had an ongoing parking...
> But they don't because they make more money by profiting from people who forget to "clock out" when they are done parking.
fwiw, at least in this case, the app that profited from you not clocking out got shut down and bought out by the app that asks you to pre-set your parking time. Which I guess is still not great, but at least somewhat of a step up.
> But I think there can be at most a single engineer working on this app if at all.
I assume they’re contracted out to the lowest bidder.
In my city the payment schedule on the app significantly lags the meters/official rates. Fine when prices go up, but pretty annoying to app-users when the app charges more than the official parking rates. Maybe if they get their merchant account sanctioned for too many chargebacks someone will take notice.
All of the parking apps I’ve used offer this “drive away detection” optionally.
One of them wanted me to sign up to a parking subscription of some sort to be able to access it which was a bit insane. I just don’t turn on the feature because I don’t really think its worth sending my precise location for the next however many hours to some random small time app developer.
>In my experience, parking apps require you to pay in larger chunks of hours than paying with coins used to;
Here in Nashville, they sold out our public street parking to a private company. Now instead of coins in a meter for the time you want, you have to buy at least an hour for $1.75 (or more), pay by scanning a QR code (which is misprinted on the signs) unless you're in one of the spots where there's a working pay machine, and it now is enforced 24/7 instead of having holidays and weekends off (IIRC it was also free after 6, which was great). Also they had two hour limits where you can't simply move your car, you have to park somewhere they don't check for an indeterminate amount of time. How is any of this an improvement unless you get a cut of the money?
Parking apps requires registration. I arrive, park my car then
(1) via machine: insert my card into the machine, get ticket, leave
(2) via app: spend 10 minutes registering an account, email, password, phone number, wants verification via email or phone number, wants me to register my credit card and the agree to them selling all my data.
IF on the other hand, they just made it use some kind of common e-cash and no registration, no tracking, no account, I'd be 100% for it.
If you pay with a card, then they can track you, so it doesn't really matter if you put that card into a machine or into an app account.
For places where I don't expect to return (or only rarely), sure, having to do an app is annoying. But for places where you expect to use it often enough, it can be a time-saver, after the initial time cost of setup.
Strange, I only have experience with two parking apps, but they both let you pay in 15-minute increments.
I have seen meters that have smaller increments, like sub-10-minutes, but when the increments cost something like 50 cents, it's hard to really care that much.
On public transport I can tap in and tap out with the wallet on phone or any bank card. Car parks could work in exactly the same way, but instead there are 15 apps.
DC fast chargers tend to cost much more than level 2 chargers. They have expensive equipment, more expensive electricity (intermittent high load is more expensive than more continuous lower levels, even for the same total power), and there tends to be a limited number of them so you want to encourage people to do level 2 charging when possible, and only DC fast charging on road trips when they really need it.
So prices are much higher than for normal AC charging. Most of the charging you do should be AC charging at your home or work.
Even when charging on pure fossil fuels, generating in large plants with efficient turbines and delivering it to efficient electric motors is more efficient than pumping, refining, and delivering gasoline to millions of tiny piston engines.
But we don't charge on pure fossil fuels. The grid is increasingly powered by renewables and nuclear, which are less harmful to the environment than fossil fuels. Anthropogenic climate change could lead to mass catastrophe if we don't get it under control; it's already costing us billions and killing people worldwide.
And while our electric grid couldn't handle everyone switching to electric vehicles over night, the transition takes time, and we can invest in grid improvements as energy demand moves towards greater electric usage due vehicles.
Very true. I've seen some tech companies doing this in conjunction with adding roof solar to get tax breaks. Are other industries stepping up as well?
Of course in hind-sight I recall we had about 16 chargers at the time we had over 20k employees. There were a lot of Tesla's in the parking lot but many of those people were older and had homes. Those chargers also caused a lot of drama. People would unplug other peoples cars, the other people would send videos from their Tesla to corporate security. I would just park my old ICE truck near the front door since I got to work early.
In 2014 or 2015 I worked with a guy who wanted charging at the office. We didn't have it, so he just started running an extension cord from his car into the building. IIRC they got mad at him not for taking the electricity but because he was leaving the door ajar to do it.
Honestly, it's kind of blatantly transparent that corporate climate change initiatives are meaningless when they insist workers commute to the office when we just spent the last few years proving we would work from home. I'm thankful my employer still lets us WFH and it greatly helps our recruitment and retention.
Agreed. I assumed the push for EV's was to buy the US and EU time to refine their processes around CNG refinement, storage and transport and to avoid dependence on Saudi (for US)/Russian (for EU) oil. That's nearly a done deal in the US. CNG not far from me is $2.25/gallon. No idea how far along the EU is or if the plan is for the US to sell CNG to the EU.
All climate change initiatives that don't directly reduce either mass or reducing the distance the mass is moved are meaningless.
Which means, the only initiative for climate change that ever needed to happen is a higher and higher taxes on fossil fuels, and everything would flow downhill from that.
But that was never on the table, so it was always all just lip service.
> Which means, the only initiative for climate change that ever needed to happen is a higher and higher taxes on fossil fuels, and everything would flow downhill from that.
We effectively managed it in Canada, but it’s become political poison.
> The team looked for a fermenting agent that could remain reactive in substances with a temperature of up to 37 degrees Celsius* and alcohol of the recommended 16 per cent per volume.
> This article was edited on 29/01 to correct the temperature for fermenting to 37 degrees Celsius.
The fire is still burning, is only partially contained, has gotten close to the Center, and the winds are forecast to pick up again tomorrow. So there's still a chance it will be at risk.
Now, they've had days to prepare for this, and apparently have plenty of contingencies in place, but this is still relevant the fire could get there.
Rust's type system (including ownership and borrowing, Sync/Send, etc), along with it's privacy features (allowing types to have private fields that can only be accessed by code in the module that defined them) allows you to create fully safe interfaces around code that uses unsafe; there is provably no combination of uses of the interface which lead to undefined behavior.
Now, yeah, it's possible to also use unsafe in Rust just for applying a local optimisation. And that has fewer benefits than a fully encapsulated safe interface, though is still easier to audit for potential UB than C.
So you're right that it's on a continuum, but the distinction between safe and unsafe code means you can more easily find the specific places where UB could occur, and the encapsulation and type system makes it possible to create safe abstractions over unsafe code.