Hacker Newsnew | past | comments | ask | show | jobs | submit | tialaramex's commentslogin

Right, it's not considered weird for a C++ compiler to offer C++ 98, C++ 11, C++ 14, C++ 17, C++ 20, C++ 23 and C++ 26 (seven versions) and support its own extra dialects.

It is also usual for the C++ compilers to support all seven standard library versions too. Rust doesn't have this problem, the editions can define their own stdlib "prelude" (the reason why you can just say Vec or println! in Rust rather than their full names, a prelude is a set of use statements offered by default) but they all share the same standard library.

core::mem::uninitialized() is a bad idea and we've known that for many years, but that doesn't mean you can't use it in brand new 2024 Edition Rust code, it just means doing so is still a bad idea. In contrast C++ removes things entirely from its standard library sometimes because they're now frowned on.


Right. A good mental model would be to imagine every crate of Rust source has an associated Edition and there's a sort of "pre-processing" step where we translate that into the latest version of Rust seamlessly, preserving its exact meaning.

So e.g. 2018 Edition said r# at the start of an identifier now marks a "raw" identifier. Keywords promise never to start this way, so r#foo is the same as foo but r#foo even works if some lunatic makes foo a keyword whereas just foo would become a keyword if that happened. As a result if you write

   let async = 5;
... in Rust 1.0 that translator treats it exactly as though you'd written

   let r#async = 5;
... in a modern Rust edition because these days the keyword async exists.

There are several edge cases where that's exactly what happened.

But in all the cases I can think of, when you look at that Rust today, what it meant in say 2018 Edition seems silly, "Oh, that's a daft thing for that to mean, I'm glad it doesn't mean that now"

We can't magically step into a time machine and fix how it worked at the time, any more than we could go back and cancel those minstrel shows which now seem awful. We can only fix it now and Rust's editions enable this, without the cost of making old code not work in old projects.

    for dog in array_of_dogs.into_iter() {
        /* In Rust 1.0 we get an immutable reference to each dog from the array */
        /* But today (since 2021 Edition) we get the actual dogs, not references - thus consuming the array */
    }
One of the changes I'm looking forward to from a future Edition is what happens when I write native ranges like 1..=10 (the integers 1, 2, 3, 4, 5, 6, 7, 8, 9 and 10). Today this means core::ops::RangeInclusive but that type isn't Copy, because it is Iterator. Instead hopefully one day it'll become core::range::RangeInclusive which is Copy, and so can't be Iterator but instead IntoIterator.

So in that future Rust edition (when/if it happens) I can treat 1..=10 the same way as a pair of numbers (1,10) or an array of two numbers [1, 10] which are both Copy, that is, by just copying the bit pattern you are guaranteed to get an object which means the same thing, making life easier for programmers and the compiler. Today, because it isn't Copy, I must do extra busy work, which is slightly annoying and discourages use of this otherwise great type.


You can have data races in "safe" Go. If you race a trivial object [such as an integer] it's just radioactive and so long as you didn't need it to have any particular value (e.g. you were just going to write it to a log anyway, or you just discard it) you're fine. However if you race a non-trivial object then that's immediately Undefined Behaviour.

Of course Go programmers will say "Just don't do that" but that's exactly what C programmers told us about bounds misses, use after free and so on...


> But no other language claims to be faster than C for general-purpose programming, because none are.

The "faster than C for general-purpose programming" is a pretty woolly claim so I'm not entirely surprised nobody claims that, but equally I think to be sure that "because none are" would need some serious caveats to make it true.

In particular you're going to have to say you think it doesn't matter how much developer time is needed. A project where C programmers spend five hours to make it run in 4 seconds is in this caveat "20% faster" than a project where Alt Lang programmers spend five minutes to make it run in 5 seconds - because only those seconds count. This is not how the real world works so it's a pretty nasty caveat.


Of course it's true in the case of sqlite. It's one of the most used pieces of software ever, and user cpu time spent is going to dwarf any developer time.

Your example should instead be:

- 5 hours of developer time to run in 4 seconds * n

- 5 minutes of developer time to run in 5 seconds * n

As long as n <= 17,700, then the developer time is "not worthwhile." This assumes that you value user time as much as developer time.

In the case of sqlite, the user time may as well be infinite for determining that side of the equation. It's just that widely used.


Also battery life. 20% less time, 20% more battery.

But OP is correct, companies don't care as long as it doesn't translate into higher sales (or lower sales because the competitor does better). That's why you see that sort of optimization mainly in FOSS projects, which are not PDD (profits-driven development).


>>A project where C programmers spend five hours to make it run in 4 seconds is in this caveat "20% faster" than a project where Alt Lang programmers spend five minutes to make it run in 5 seconds - because only those seconds count. This is not how the real world works so it's a pretty nasty caveat.

For any project with non-trivial amount of users the C programmer did better. I mean I know companies like to save money and move the costs (time, electricity, hardware costs) to customers but if you care about users any non-trivial speed improvement is worth a lot in aggregate, surely more than your time implementing it.


I see a few people have been caught by this.

Databases are a problem space which can absorb all available effort. So if you spend five hours making thing U as fast as it could be that's five fewer hours you can dedicate to thing V or thing W, not to mention X, Y, Z and so on.


And of course the kernel - which doesn't even use Rust's Vec but has its own entire allocator library because it is the kernel - likewise provides

https://rust.docs.kernel.org/next/kernel/alloc/kvec/struct.V...

Vec::push_within_capacity is a nice API to confront the reality of running out of memory. "Clever" ideas that don't actually work are obviously ineffective once we see this API. We need to do something with this T, we can't just say "Somebody else should ensure I have room to store it" because it's too late now. Here's your T back, there was no more space.


Although Mozilla's reason to pay for Rust R&D was because of problems with C++ it's probably not most helpful to think of Rust (let alone F#) as an attempt to specifically fix those problems.

C is a Worse is Better language (https://en.wikipedia.org/wiki/Worse_is_better). The bet is that if it's simpler to implement then the fact that what you're implementing isn't great will be dwarfed by that ease of implementation. And it worked for decades which is definitely a success.

You can make a similar argument for Go, but not really for Rust. The other side of the Worse is Better coin is that maybe you could make the Right Thing™ instead.

Because implementing C is so easy and implementing the Right Thing™ is very difficult, the only way this would compete is if almost nobody needs to implement the Right Thing™ themselves. In 1970 that's crazy, each Computer is fairly custom. But by 1995 it feels a lot less "out there", the Intel x86 ISA is everywhere, Tim's crap hypermedia experiment is really taking off. And when Rust 1.0 shipped in 2015 most people were able to use it without doing any implementation work, and the Right Thing™ is just better so why not?

Now, for an existing successful project the calculation is very different, though note that Fish is an example of this working in terms of full throated RIIR. But in terms of whether you should use C for new work it comes out pretty strongly against C in my opinion as a fairly expert C programmer who hasn't written any C for years because Rust is better.


Even for China so-called "overblocking" where to censor a small thing you have to block a much larger thing, is a real concern with these technologies. There's a real trade here, you have to expend effort and destroy potential and in some cases the reward isn't worth it. You can interpret ECH as an effort to move the ratio, maybe China was willing to spend $5000 and annoy a thousand people to block a cartoon site criticising their internal policies, but is it willing to sped $50 000 and annoy a ten thousand people? How about half a million and 100K people ?

That requires the client to only emit ECH, even if the ISP-provided (and therefore government controlled) DNS blocks HTTPS/SVCB records. China can easily make the default for a browser in China be to never even try to use ECH as well. Then they'll only annoy people trying to actively circumvent their system. They already do TCP sessionization to extract the SNI domain. Detecting ECH and then just dropping the connection at L3 is functionally equivalent.

In theory, sites could eventually require ECH to serve anything at all. But we're very far from that.


> That requires the client to only emit ECH

So for example, Firefox since version 119. Or Chrome since 117

Now, for most services ECH doesn't have an encrypted target server. But the important choice in ECH was in this case it just fills that space with noise. An encrypted message also looks like noise. So you can block all the noise, in case it's secrets, or you can let through all the noise (some of which might be secrets) or I suppose you can choose randomly, but you can't do what such regimes want, which is to only forbid secrets, that's not a thing.

We've been here before. When sites starting going to TLS 1.3 lots of HN people said oh, China will just block that, easy. But the choice wasn't "Use TLS 1.3 or keep doing whatever China is happy with instead" the choice was "Use TLS 1.3 or don't connect" and turns out for a lot of the Web China wasn't OK with "don't connect" as their choice, so TLS 1.3 is deployed anyway.


The great firewall was updated to support inspection of TLS 1.3. They didn’t just decide it was whatever and let everything through. It was easier to just update their parsing than to force everyone to turn it off, so they did that instead. Perfect forward secrecy was a thing before TLS 1.3, and they’ve found other methodology to accomplish what they want.

For ECH, China can just require you turn it off. Or distribute their own blessed distribution. It’s the more marginal censorship regimes that will be in an interesting spot. Especially ones where the ISPs are mostly responsible for developing the technical measures.


> The great firewall was updated to support inspection of TLS 1.3.

To actually "inspect" TLS 1.3 you need the keys which are chosen randomly for each session by the parties - so either (1) you have a mathematical breakthrough, (2) you have secured co-operation from one or both parties (in which case they could equally tell you what they said) or (3) in fact you don't have inspection.

As you observe forward secrecy was already possible in TLS 1.2 and China's "Great firewall" didn't magically stop that either. In fact what we see is that China blocks IP outright when it doesn't want you to talk to an address, the protocol doesn't come into that. What we changed wasn't whether China can block connections, but how easy it is to snoop those connections.

> For ECH, China can just require you turn it off

So did they? Remember, I'm not talking about some hypothetical future, this technology is actively in use today and has been for some time.


I don’t understand what your point about TLS 1.3 is. It’s only relevant if you’re doing a downgrade attack (or equivalently, using an active middleware box). TLS 1.3 itself is not vulnerable to this because it (a) doesn’t have non-PFS suites to downgrade to and (b) protects the cipher suites by including them in the key exchange material. But if the server supports TLS 1.2, an active MITM can still downgrade to it if the client doesn’t demand TLS 1.3 specifically (which browsers do not by default). It won’t matter to China until there are lots of TLS 1.3-only websites (which hasn’t happened yet).

China was already leaning on passive DPI and L3 blocking before TLS 1.3 complicated (but as I said, did not preclude) downgrading to PFS ciphers. The reason being that for about the last 10 years, many sites (including default CDN settings) used SSL profiles that only allowed PFS ciphers. For such a server, downgrade attacks are already not useful to the Great Firewall, so adding TLS 1.3 to the mix didn’t change anything.

> So did they? Remember, I'm not talking about some hypothetical future, this technology is actively in use today and has been for some time.

Google Chrome (for example) will now use ECH if the website has the relevant DNS record - but it doesn’t use the anti-censorship mechanism in the spec to make requests to servers that haven’t enabled it look like they may be using ECH. This, combined with the fact that China can just not serve the relevant DNS record by default, means it doesn’t really impact the great firewall.

This is actually a good example of the non-technical side of this: Chrome could send a fake ECH on every request, like the spec suggests. This would perhaps make China block all Chrome traffic to prevent widespread ECH. But then Chrome would lose out on the market share, so Google doesn’t do it. Technical solutions are relevant here, but even the most genius anti-censorship mechanism needs to content with political/corporate realities.


> if the server supports TLS 1.2, an active MITM can still downgrade to it

Nope. That's specifically guarded against, so double good news. 1) You get to learn something new about an important network protocol and 2) I get to tell you a story I enjoy telling

Here's the clever trick which is specified in RFC 8446 (the TLS 1.3 RFC)

In TLS we always have this "Random" field in both Client Hello and Server Hello, it's 32 bytes of random noise. At least, that's what it usually is. When a server implements TLS 1.3 but it receives a connection (in your scenario this is from a middlebox, but it might equally be somebody's long obsolete phone) which asks for TLS 1.2 then when it fills out the Random for this connection the last eight bytes aren't actually random, they spell "DOWNGRD" in ASCII and then a 01 byte. If the client seems to ask for any older version of TLS which is supported then the server writes DOWNGRD and then a 00 byte instead.

As you hopefully realise this signals to a client that a MITM is attempting to downgrade them and so they reject the failed attack. You very likely have never seen your web browser's diagnostic for this scenario, but it's very much a failure not some sort of "Danger, Chinese government is spying on you" interstitial, because we know that warning users of danger they can't fix is pointless. So we just fail, the Chinese government could choose to annoy its citizens with this message but, why bother? Just drop the packets entirely, it's cheaper.

You might wonder, why Random ? Or, can't the MITM just replace this value and carry on anyway ? Or if you've got a bit more insight you might guess that these questions answer each other.

In TLS the Client and Server both need to be sure that each connection is different from any others, if they didn't assure themselves of this they'd be subject to trivial replay attacks. They can't trust each other, so to achieve this both parties inject Random data into the stream early, which means they don't care if the other party really used random numbers or just (stupidly) didn't bother. Shortly after this, during setup, the parties agree on a transcript of their whole conversation so far.

So, if the Random value you saw is different from the Random number your conversation partner expected, that transcript won't match, connection fails, nothing is achieved. But if the Random value isn't changed but somehow we ended up with TLS 1.2 it says DOWNGRD and a TLS 1.3 capable client knows that means it is under attack and rejects the connection, same outcome.

Now, I said there was an anecdote. It's about terrible middle boxes, because of course it is. TLS 1.3 was developed to get past terrible middle boxes and it was mostly successful, however shortly after TLS 1.3 non-draft launch (when the anti-downgrade mechanism was enabled, it would not be OK to have anti-downgrade in a draft protocol for reasons that ought to be obvious) Google began to see a significant number of downgrade failures, connected to particular brands of middlebox.

It turns out that these particular brands of middlebox were so crap that although they were proxying the HTTP connection, they were too cheap to generate their own Random data. So your TLS 1.3 capable browser calls their proxy, the proxy calls the TLS 1.3 capable server, and the proxy tells both parties it only speaks TLS 1.2, but it passes this bogus anti-downgrade "Random" value back as if it had made this itself, thus triggering the alarm.

Obviously on the "Last to change gets the blame" basis Google had customers blaming them for an issue caused ultimately by using a crap middlebox. So they actually added a Chrome feature to "switch off" this feature. Why do I mention this? Well, Chrome added that feature for 12 months. In 2018. So, unless it is still 2019 where you are, they in fact have long since removed that switch and all browsers enforce this rule. That 12 months grace gave vendors the chance to fix the bug or, if they were able to, persuade customers to buy a newer crap middlebox without this particular bug, and it gave customers 12 months to buy somebody else's middlebox or (if they were thus enlightened) stop using a middlebox.


> In theory, sites could eventually require ECH to serve anything at all. But we're very far from that.

I doubt the Chinese government would care about that. They don't depend on the west for their online services any more than we depend on them. All that would happen is that the internet would bifurcate to an even greater degree than it already has.

It's extremely helpful at home in the west as a countermeasure against data monetization and dragnet surveillance. It certainly isn't perfect but at least it reduces the ability of ISPs to collect data on end users as well as forcing the government to formally move against the cloud providers if they want the data. Not that I want the cloud providers having my data to begin with but that's a different rant.


That's not what this is about.

HTTPS is the name of a protocol, which is mostly used to make the World Wide Web work, but we do lots of other things with it, such as DNS-over-HTTPS aka DoH.

However HTTPS is also the name of a type of DNS record, this record contains everything you need to best reach the named HTTPS (protocol) server, and this is the type of record your parent didn't previously know about

In the boring case, say, 20 years ago, when you type https://some.name/stuff/hats.html into a web browser your browser goes "Huh, HTTPS to some.name. OK, I will find out the IPv4 address of some.name, and it makes a DNS query asking A? some.name. The DNS server answers with an IPv4 address, and then as the browser connects securely to that IP address, it asks to talk to some.name, and if the remote host can prove it is some.name, the browser says it wants /stuff/hats.html

Notice we have to tell the remote server who we hope they are - and it so happens eavesdroppers can listen in on this. This means Bad Guys can see that you wanted to visit some.name. They can't see that you wanted to read the document about hats, but they might be able to guess that from context, and wouldn't you rather they didn't know more than they need to?

With the HTTPS record, your web browser asks (over secure DNS if you have it) HTTPS? some.name and, maybe it gets a positive answer. If it does, the answer tells it not only where to try to connect, but also it can choose to provide instructions for a cover name to always use, and how to encrypt the real name, this is part of Encrypted Client Hello (or ECH)

Then the web server tells the server that it wants to talk to the cover name and it provides an encrypted version of some.name. Eavesdroppers can't decrypt that, so if many people share the same endpoints then eavesdropper can't tell which site you were visiting.

Now, if the server only contains documents about hats, this doesn't stop the Secret Hat Police from concluding that everybody connecting to that server is a Hat Pervert and needs to go to Hat Jail. But if you're a bulk host then you force such organisations to choose, they can enforce their rules equally for everything (You wanted to read News about Chickens? Too bad, Hat Jail for you) or they can accept that actually they don't know what people are reading (if this seems crazy, keep in mind that's how US Post worked for many years after Comstock failed, if you get a brown paper package posted to you, well, it's your business what is in there, and your state wasn't allowed to insist on ripping open the packaging to see whether it is pornography or communist propaganda)


> so if many people share the same endpoints then eavesdropper can't tell which site you were visiting.

Which is why it is so important/useful to Cloudflare but of much lower utility to most nginx users.


Cloudflare provides a very large haystack for this, but even for an nginx server with no CDN, it's still useful to prevent the hostname from being sent in the clear before the TLS connection is negotiated. This still hides the hostname from casual eavesdroppers, who now only know what IP you're connecting to, and would need need out-of-band information to map the IP back to a hostname. And they couldn't ever be 100% sure of that, because they wouldn't know for certain whether there are additional vhosts running on a given server.

I think you might be surprised at how heavily SNI is leveraged at places like GoDaddy, Bluehost, and other similar providers to host sites from hundreds of completely unrelated businesses on the same IP address.


Indeed to the extent that Casey has a point here (which sure, I think in its original context it was fine, it's just unfortunate if you mistook a clever quip at a party for a life philosophy) C++ is riddled with types explicitly making this uh, choice.

Its not near the top of the list of reasons std::unordered_map is a crap type, but it's certainly on there. If we choose the capacity explicitly knowing we'll want to put no more than 8340 (key,value) pairs into Rust's HashMap we only allocate once, to make enough space for all 8340 pairs because duh, that's what capacity means. But std::unordered_map doesn't take the hint, it merely makes its internal hash table big enough, and each of the 8340 pairs is allocated separately.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: