3 ms·
This is incorrect. C and C++ have aliasing rules; the compiler is allowed to assume that your magic pointer does not alias an object that otherwise you had no
by not2b 4y ago
This is incorrect. C and C++ have aliasing rules; the compiler is allowed to assume that your magic pointer does not alias an object that otherwise you had no reason to believe could be aliased. Google "strict aliasing rule" to learn the details.
Essentially, C and C++ already have a version of provenance for pointers and references, but it isn't identical to the Rust version.
Because some old codebases pull tricks of this kind (messing with pointers, doing casts without going through unions, etc), gcc (and clang) have a flag, -fno-strict-aliasing , to disable some optimizations that would be enabled by taking aliasing/provenance into account.
- steveklabnik 4y agoAs a small point of order here (not saying you're wrong, just to elaborate a bit): * Rust doesn't have strict aliasing/tbaa * Rust does have "restrict" semantics (in C via the keyword and in C++ via common vendor extensions) And yeah, Rust is considering a provenance model that's different than PNVI-ae.
- not2b 4y agoYes, understood. But in Rust (without going through unsafe code), you can't write a program that will produce a reference to a u16 that overlaps with half of a global u32. In C/C++ you could cast a pointer that way and turn it into a reference, but the compiler is allowed to assume, even though you wrote that, that the u16 (unsigned short) reference can't refer to some particular global u32 (unsigned int), and if it has it in a register it won't reload it. The program has undefined behavior (you could use unions and get implementation-defined behavior, which will depend on little-endian vs big-endian).
- tialaramex 4y ago> without going through unsafe code None of this matters in Rust without unsafe. Pointers technically exist outside unsafe, but you can't do very much with them (you cannot, for example, dereference a pointer). And yes, Rust says that the attempted type pun you describe, which you would need unsafe to create, is Undefined Behaviour. > you could use unions and get implementation-defined behavior Type punning with unions is also Undefined Behaviour in C++. The sanctioned way to perform type punning is to memcpy() the data from type A to type B. C++ 20 provides a built-in way to ask for this to be done std::bit_cast
- tialaramex 4y agoI understand the confusion. C and C++ do indeed have aliasing rules and those rules do, as you point out, forbid type punning tricks. But as you can see I wasn't talking about type punning. Our uuencoded value isn't a type pun, and our pointer isn't the wrong type, it's the correct type with, miraculously, the correct value - It's a magic trick! The C++ Standard is OK with this magic trick. Executing this trick in the C++ abstract machine is no problem at all. However in a real world compiler this is a huge problem - because the optimiser assumes I can't possibly have such a pointer. Where would I get it from? This is where provenance comes into the picture. Where did my pointer come from, that's what provenance means. The C++ standard has nothing to say about provenance but your compiler depends on it.
- not2b 4y agoYou are incorrect. The C++ standard says a whole lot about it, and has detailed aliasing rules and rules about which pointers are valid. Your "magic trick", depending on details, isn't a standard conforming program; the standard will say that it has undefined behavior. That's why, as you say, the optimizer assumes you can't possibly have such a pointer, but what you get wrong is that the C++ standard describes the rules, in detail. I've been doing this stuff for a long time, going back to egcs and even before.
- tialaramex 4y ago>> The C++ standard says a whole lot about it Nope, it says nothing whatsoever on the subject of provenance. Periodically people make a run up and try to get this fixed. N2676 is currently in front of WG14 (ie the C standards committee) with the long term hope that if WG14 takes this fix, or something like it, WG21 (C++) could be persuaded to eventually take a similar fix - although lots of people don't like N2676 and want something else (the more vague your "something else" the more popular). If the standard had "a whole lot" to say about provenance you'd be able to quote some of it. but I suggest reading N2676 for an example of what is not yet standard http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2676.pdf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2676.pdf > has detailed aliasing rules and rules about which pointers are valid Aliasing rules forbid some type punning shenanigans, but again, and I will repeat myself, that's not what's going on here. DR260 (Defect Report number 260, about twenty years ago) asks WG14 what their standard says about such magic tricks, and their response basically says well, compilers are allowed to somehow know about provenance, so actually our Standard is correct and this is working as intended. What's working as intended? Well, whatever your compiler actually does. What a great standard! Note that this response isn't incorporated into subsequent versions of the standard, it's just basically known in the industry, oh yeah, that's DR260, don't worry about it. > I've been doing this stuff for a long time, going back to egcs and even before. That's nice, but it's not terribly relevant here, except that it means you remember an era when people didn't even realise this was a problem. It still was a problem, they just didn't know it was a problem yet. And hey, you know about that experience too, because apparently you didn't know this was a problem after 2004 either. Rust would like not to kick this can down the road for 18 years and counting, which is why Aria Beingessner's experiment is happening.