Yeah motivation is the bigger factor (why would Mozilla care about the system APIs of an OS, of all things?) but also it doesn't hurt that Apple is one of the richest companies in the world (depending on the day).
It's literally true that Rust tried and failed in the sense that Rust's early design was extremely similar to Swift's, polymorphic compilation and all, and it was thrown out when it didn't seem to work. Swift pushed on it harder, and got it to work.
But it's less so true in the sense that the two teams had different use cases, and simply took divergent paths. Rust took the "easier"* path that limited expressivity in favour of a simple execution model that requires a minimal runtime, which in turn enabled them to focus on more interesting static analyses. Swift took the other path.
* This may sound like a slight against Rust, but both the Swift and Rust folks who worked on this stuff agree that what Swift did is a comically huge amount of work in pursuit of a relatively niche use case (idiomatic-feeling system apis). There's only so much time in the world, and Rust spent its time on other problems.
More accurately I worked on stdlib stuff for both, with a focus on collections. It's just that this naturally pushes you into minoring in language design and majoring in the low-level details of the language. Plus it's hard to not pick this stuff up if you have to hang out with compiler people all day.
Yeah the smearing approach is the only one that merits a callout from my position in the pipeline, because the other approaches are handled by your shaper or rasterizer, which are usually 3rd party libs that can be mostly regarded as black boxes.
I mainly prioritize making my pages work reasonably with different zooms and window sizes, since all I really know for certain is that there's no ideal for everyone.
The font settings are just from a copy of bootstrap from like 6 years ago, because I have absolutely no eye for this sort of thing.
Yeah there's a reason all my examples use the same ~3 languages, and only a few random fragments from them. You just need a few examples that demonstrate that something can happen. Everything actually works pretty uniformly, so as long as you have a few examples that cover the interesting cases and handle those cases in a general way, everything tends to work fine. The actual font formats are much more nasty and corner-casey. (Thank god you don't need to deal with that, eh Patrick?)
Same reason I prefer to use imperfect terms that capture the important aspects of the problem-space from an english-speaking perspective. Are ligatures the right word for how arabic and marathi get shaped into glyphs? Maybe not, but as long as you get that the æ ligature can be synthesized from ae by a font, and that this is super important for some languages, you're on the right path.
I don't even know what the fragments I use mean, lol. I like to assume I'm just copy-pasting Arabic swears around. Apparently at least one is just Manish's name?
To elaborate on the float example, see JSON, where text-based representations of numbers has led to massive incompatibilities among different parsers and generators. The original "spec" didn't even define if numbers were doubles or infinite precision or what. This is much harder to mess up with a binary format.
Ultimately it boils down to the fact that there's basically no interesting difference between an immutable reference to a primitive and the primitive itself in Rust. It can't dangle. The immutability can't be casted away. They just have a different ABI if the references don't get completely optimized away. You could do pointer equality checks on them if you really want?
Swift has taken the observation further and is investigating ways to avoid ever having a immutable+shared-reference-to-primitive vs primitive distinction in the language, while still introducing this distinction for types where it is interesting. (e.g. reference counted classes or atomics)
webrender is "the stuff that works pretty ok and we can run through CI". In principle enabling webrender should get you the ~same results as not having it on, visually, modulo a few known bugs.
webrendest is "everything we're working on, no matter how broken"
It's a pretty big project so there's lots of stuff in tree that's barely functional (especially true with the layers-free pivot).
Yeah when we do named args it will very likely be based on Swift, but a bit different due to backwards compat and the desire to integrate it into existing methods like Vec::from_raw_parts and ptr::copy.
* All unsafe operations exist, but the literal unsafe keyword and its machinery doesn't exist
The latter is how most ostensibly safe languages work. See Haskell's UnsafePerformIO, Swift's UnsafePointer, and Java's JNI for 3 examples off the top of my head.
The former is just a really gimped language that would have been a pain in the neck to implement libraries for (see other replies for examples).
Re: parameterized unsafe -- I think it's been discussed and rejected, I don't remember where. I think it was mostly a matter of "yes this would be more powerful, but the complexity isn't worth it".
That's probably how we intend to solve these kinds of problem in the future.
Re: aliasing -- if it's a serious enough problem, one of two things will happen:
* Someone will develop a version of asan/ubsan for Rust.
* The Rust devs will be forced to reduce the extent to which they apply alias analysis by default (possibly with a flag to opt into it). At least temporarily.
The rust devs have backed off optimizations in the past when they break stuff in the ecosystem (struct layout optimization). But they also work with the affected devs to fix those bugs so they can turn the optimization on.
Note that a lot of these optimizations aren't necessary in Rust -- e.g. list fusion is only valuable in Haskell because mapping over lists is exposed as a one-shot operation that produces a new list. So `map map map list` is conceptually building 2 whole lists of temporaries you don't care about (and you often don't actually care about the last one either, in cases where you just iterate over it and discard it).
Meanwhile mapping in Rust generally takes an iterator and produces another iterator that will apply the given closure to the current element as it's yielded. So the naive codegen for iter().map().map().map().collect() is exactly what list fusion is trying to produce -- no temporary lists.
TL;DR: making "map" having the monadic `T[U] -> T[V]` signature is really expensive. ¯\_(ツ)_/¯
Yeah the only thing that Rust might have over C, in terms of really optimized implementations, is low-level idioms that C declares to be UB, but Rust declares to be defined (generally to be what x64 hardware does).
Maybe something that leverages signed overflow, overlong shifts, or type punning.
But if you have enough control over your codebase to mandate the compiler/flags its built with, then you can generally tell the major C compilers to act like Rust in these cases.
That said, the expected win for Rust over C(++) in practice is that you can be more "reckless", because you have a stronger type system protecting you from messing things up. A production-quality C(++) codebase might rightly do more copies, use more reference counting, and use less concurrency just because the risk of doing otherwise isn't worth the potential performance wins.
Organizations have limited resources to commit to optimizing/verifying code. Rust is intended to get you more bang for your buck.
Yeah dropck is a fun little gem, which has received several post-1.0 revisions due to soundness problems.
I agree the system you propose would be simpler in terms of spec and effort, but I don't know about simpler to use. Much like removing mutable references in favour of `foo(X) -> X` would be a simpler type system, but awful to use compared to `foo(&mut X)`.
This is really ignoring how relevant and affine types interact with different features. For example, unwinding makes perfect sense with affine, not so with relevant. Rust has unwinding, and no effect system to track whether something can or can't unwind.
I also make it very clear that the implementation is mostly free. It's just using tools we already have with minor tweaks. Most of my issues are exactly the pragmatic matters: your standard library isn't built to handle it, nothing in the ecosystem is built to handle it, and it everyone has to opt into support for backwards compatibility reasons.