frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

The Ghost in the Ice Cream Machine (2020)

https://gizmodo.com/the-ghost-in-the-ice-cream-machine-1844339832
1•lapetitejort•54s ago•0 comments

AGI-like behavior found in current LLMs via recursive identity pattern

https://substack.com/home/post/p-167937462
1•schwarmhilda•2m ago•1 comments

A Typology of Canadianisms

https://dchp.arts.ubc.ca/how-to-use
3•gnabgib•5m ago•0 comments

Cerebras Enables Notion to Deliver Real-Time Enterprise Search for 100M+ Users

https://siliconcanals.com/cerebras-enables-notion-to-deliver-real-time-enterprise-search-for-100-million-workspace-users/
1•rbanffy•6m ago•0 comments

OCD's Origins Might Not Lie in the Brain Like We Thought

https://www.sciencealert.com/ocds-origins-might-not-lie-in-the-brain-like-we-thought
1•bilsbie•6m ago•0 comments

Longer wavelengths in sunlight pass through improves vision

https://www.nature.com/articles/s41598-025-09785-3
1•bilsbie•6m ago•0 comments

Multi-Region Row Level Security in CockroachDB

https://www.cockroachlabs.com/blog/fine-grained-access-control-row-level-security/
1•rusticwizard•7m ago•0 comments

Microdosing Willpower: My Takeaways from Microdosing Ozempic

https://substack.com/home/post/p-167852405
3•jxmorris12•7m ago•0 comments

Biotech investor Concentra Bio buys 4 Bay Area firms on brink of collapse

https://www.sfgate.com/tech/article/fund-gobbling-bay-area-biotech-20761986.php
1•randycupertino•8m ago•0 comments

Regular Expression Matching Can Be Simple and Fast (2007)

https://swtch.com/~rsc/regexp/regexp1.html
1•malingo•9m ago•0 comments

Mint 0.26.0 Released

https://mint-lang.com/news/exporting-entities
1•gdotdesign•10m ago•0 comments

SEC's 'crypto mom' says tokenized securities are still securities

https://www.aol.com/secs-crypto-mom-says-tokenized-201203237.html
1•Bluestein•13m ago•1 comments

Now I Won That AI Bet

https://www.astralcodexten.com/p/now-i-really-won-that-ai-bet
1•paulpauper•14m ago•0 comments

Balsa Update: Springtime in DC

https://thezvi.substack.com/p/balsa-update-springtime-in-dc
1•paulpauper•15m ago•0 comments

White Noise – secure and private messenger

https://www.whitenoise.chat/
2•onhacker•16m ago•0 comments

Gemini on Google Pixel Watch

https://support.google.com/googlepixelwatch/answer/16393978?hl=en
1•kaycebasques•16m ago•0 comments

Generating prototypes from game design document with Cursor, Zed and LÖVE

https://blog.luden.io/generating-prototypes-from-game-design-document-with-cursor-zed-and-l%C3%B6ve-7b8d932194d7
2•gamescodedogs•16m ago•5 comments

GlobalFoundries to Acquire MIPS

https://liliputing.com/globalfoundries-to-acquire-mips-bringing-together-risc-v-chip-design-and-manufacturing/
1•t-3•17m ago•0 comments

Developing Structural Analysis Tooling for Experimental Aircraft

https://stanleywang.dev/experience/beta-case-study
1•twinfantasyfan•17m ago•0 comments

Agents Are Controllers: Active Agent Brings MVC to AI in Rails

https://www.activeagents.ai/blog/agents-are-controllers-active-agent-brings-mvc-to-ai-in-rails
1•mooreds•18m ago•0 comments

Slow Projects

https://michaelnotebook.com/slow/index.html
2•calvinfo•19m ago•0 comments

A parallel path for GPU restore in CRIU

https://lwn.net/Articles/1024747/
1•rbanffy•19m ago•0 comments

Karmic

https://www.withkarmic.com/
1•handfuloflight•22m ago•0 comments

OpenAI is reportedly releasing an AI browser in the coming weeks

https://techcrunch.com/2025/07/09/openai-is-reportedly-releasing-an-ai-browser-in-the-coming-weeks/
3•valiant-comma•24m ago•0 comments

Allen G. Hassenfeld, former CEO of Hasbro, dies at 76

https://abcnews.go.com/Business/wireStory/allen-hassenfeld-former-ceo-hasbro-family-founded-iconic-123624319
1•Bluestein•25m ago•0 comments

HyAB k-means for color quantization

https://30fps.net/pages/hyab-kmeans/
10•ibobev•25m ago•0 comments

AI Startup Esperanto Winds Down Silicon Business

https://www.eetimes.com/ai-startup-esperanto-winds-down-silicon-business/
1•zekrioca•27m ago•0 comments

Pulse duration tunable ultra-narrow bandwidth mode-locked lasers

https://www.spiedigitallibrary.org/journals/advanced-photonics-nexus/volume-4/issue-03/036016/Pulse-duration-tunable-ultra-narrow-bandwidth-mode-locked-lasers/10.1117/1.APN.4.3.036016.full
1•PaulHoule•28m ago•0 comments

Everything You See Is from 15 Seconds in the Past, Research Suggests

https://www.popularmechanics.com/science/a65291272/why-brain-smooths-visual-chaos/
1•Bluestein•29m ago•3 comments

Apple design team to start reporting directly to Tim Cook later this year

https://9to5mac.com/2025/07/08/apple-design-team-tim-cook/
2•LorenDB•29m ago•0 comments
Open in hackernews

Tree Borrows

https://plf.inf.ethz.ch/research/pldi25-tree-borrows.html
359•zdw•7h ago

Comments

pvg•7h ago
The Stacked Borrows mentioned had threads in 2020 and 2018

https://news.ycombinator.com/item?id=22281205

https://news.ycombinator.com/item?id=17715399

kibwen•6h ago
Recent blog post from Ralf Jung providing some extra context: https://www.ralfj.de/blog/2025/07/07/tree-borrows-paper.html

Bonus: recent talk from Ralf Jung on his group's efforts to precisely specify Rust's operational semantics in executable form in a dialect of Rust: https://youtube.com/watch?v=yoeuW_dSe0o

wavemode•6h ago
From the paper:

> The problem with unsafe code is that it can do things like this:

    fn main() {
        let mut x = 42;
        let ptr = &mut x as *mut i32;
        let val = unsafe { write_both(&mut *ptr, &mut *ptr) };
        println!("{val}");
    }
No it can't? Using pointers to coexist multiple mutable references to the same variable is undefined behavior. Unless I'm just misunderstanding the point they're trying to make here.
seritools•6h ago
"can do things" in this case doesn't mean "is allowed to do things".

"Unsafe code allows to express the following, which is UB:"

ehsanu1•6h ago
I believe that's exactly the point: it's too easy to violate constraints like not allowing multiple mutable references. Unsafe is meant for cases where the validity of the code is difficult to prove with rust's lifetime analysis, but can be abused to do much more than that.
pavpanchekha•6h ago
The point of this work is to pin down the exact boundaries of undefined behavior. Certainly the code above is accepted by the Rust compiler, but it also breaks rules. What rules? In essence, we know that:

- Anything accepted by the borrow checker is legal

- Unsafe can express illegal / undefined behavior

- There's some set of rules, broader than what the borrow checker can check, that is still legal / defined behavior

The goal of this line of work is to precisely specify that set of rules. The outlines are clear (basically, no writable pointers should alias) but the details (interior pointers, invalidation of iterators, is it creating or using bad pointers that's bad, etc) are really hard. The previous paper in this series, on Stacked Borrows, was simpler but more restrictive, and real-world unsafe code often failed its rules (while still seeming correct). Tree Borrows is broader and allows more while still being provably safe.

ralfj•6h ago
> allows more while still being provably safe.

Note that we have not yet proven this. :) I hope to one day prove that every program accepted by the borrow checker is compatible with TB, but right now, that is only a (very well-tested) conjecture.

sunshowers•4h ago
Hi Ralf! Congrats to you all for the PLDI distinguished paper award.
ralfj•3h ago
Thanks :-)
oconnor663•6h ago
You're already getting a lot of replies, and I don't want to pile on, but I think the clearest way to see the intent there is at the start of the following paragraph:

> Given that aliasing optimizations are something that the Rust compiler developers clearly want to support, we need some way of “ruling out” counterexamples like the one above from consideration.

ralfj•6h ago
> Using pointers to coexist multiple mutable references to the same variable is undefined behavior.

Yes, but which exact rule does it violate? What is the exact definition that says that it is UB? Tree Borrows is a proposal for exactly such a definition.

"code can do things like this" here means "you can write this code and compile it and run it and it will do something, and unless we have something like Tree Borrows we have no argument for why there would be anything wrong with this code".

You seem to have already accepted that we need something like Tree Borrows (i.e., we should say code like this is UB). This part of the paper is arguing why we need something like Tree Borrows. :)

GolDDranks•5h ago
> Unless I'm just misunderstanding the point they're trying to make here.

You misunderstand the word "can". Yes, you can, in unsafe code, do that. And yes, that is undefined behaviour ;)

https://play.rust-lang.org/?version=stable&mode=debug&editio...

pil0u•5h ago
Just realised that one of the author, Neven Villani, is Cédric Villani's (Fields Medal 2010) son. Apples don't fall far from the tree, indeed.
tandr•5h ago
> Apples don't fall far from the tree, indeed.

And one could say that they borrow from the tree some of their qualities. Sorry, couldn't resist.

Yoric•4h ago
Hey, I used to have an office close to the dad's :)

That's before he went into politics, though.

fuhsnn•5h ago
I wonder if Rust or future PL would evolve into allowing multiple borrow checker implementations with varying characteristics (compile speed, runtime speed, algorithm flexibility, etc.) that projects can choose from.
speed_spread•5h ago
I cannot imagine how that would work. You couldn't combine code that expect different borrowing rules to be applied. You'd effectively be creating as many sub-dialects as there are borrow checker implementations.
vlovich123•4h ago
FWIW technically the rules are the same. How they go about proving that the rules are upheld for a program is what would be different.
umanwizard•5h ago
What’s wrong with the compile or runtime speed of the current one?
pjmlp•4h ago
We already have that by having multiple approaches via affine types (what Rust uses), linear types, effects, dependent types, formal proofs.

All have different costs and capabilities across implementation, performance and developer experience.

Then we have what everyone else besides Rust is actually going for, the productivity of automatic resource management (regardless of how), coupled with one of the type systems above, only for performance critical code paths.

LelouBil•4h ago
I would love some sort of affine types in languages like Kotlin, it just makes cleaner code organization in my opinion.

Doesn't matter if it's purely "syntaxical" because the language is garbage collected, just the fact of specifying what owns what and be explicit about multiple references is great imo.

Some sort of effects systems can already be simulated with Kotlin features too.

Programming language theory is so interesting!

ChadNauseam•3h ago
> affine types (what Rust uses)

I'd just like to interject for a moment. What you’re referring to as "affine types", is in fact, Uniqueness Types. The difference has to do with how they interact with unrestricted types. In Rust, these "unrestricted types" are references (which can be used multiple times due to implementing Copy).

Uniqueness types allow functions to place a constraint on the caller ("this argument cannot be aliased when you pass it to me"), but places no restriction on the callee. This is useful for Rust, because (among other reasons) if a value is not aliased you can free it and be sure that you're not leaving behind references to freed data.

Affine types are the opposite - they allow the caller to place a restriction on the callee ("I'm passing you this value, but you may use it at most once"), which is not something possible to express in Rust's type system, because the callee is always free to create a reference from its argument and pass that reference to multiple functions..

ralfj•2h ago
I would say it is perfectly accurate to call Rust's type system affine. At its core, "affine" means that the type system has exchange and weakening but not contraction, and that exactly characterizes Rust's type system. See <https://math.stackexchange.com/questions/3356302/substructur...> for an explanation of what those terms mean (that's in the context of a logic, but it's the same for type systems via the Curry-Howard correspondence).

This is often explained via the "do not use more than once rule", but that's not the actual definition, and as your example shows, following that simplified explanation to the letter can cause confusion.

> because the callee is always free to create a reference from its argument and pass that reference to multiple functions..

Passing a reference is not the same thing as passing the actual value, so this does not contradict affinity.

ChadNauseam•2h ago
> Passing a reference is not the same thing as passing the actual value, so this does not contradict affinity.

I agree that passing a reference is not the same thing as passing the actual value. If it were, there would really be no point to references. However, it does contradict affinity. Specifically, the fact that multiple references can be created from the same value, combined with the properties of references, contradicts affinity.

> At its core, "affine" means that the type system has exchange and weakening but not contraction, and that exactly characterizes Rust's type system.

Well, the rust type system certainly does support contraction, as I can use a reference multiple times. So what is that if not contraction? It seems like rust at least does support contraction for references.

But in practice, having absolutely no contraction is not a very useful definition of affine, because no practical programming language would ever satisfy it. It prohibits too much and the language would not even be turing complete. Instead, there is usually an "affine world" and an "exponential world". (Exponential meaning "unrestricted" values that you can do whatever you want with). And the convention is that values can go from the exponential world to the affine world, but not back. So a function taking an affine value can be passed any value, but must use in in an affine way, and meanwhile but a function taking an exponential (unrestricted) value can only be passed exponential and not an affine value.

If you don't believe me, you can try using linear haskell, and notice that a function taking a linear argument can be passed a non-linear argument, but not the other way around.

If you interpret Rust's type system this way, it's natural to interpret references as exponentials. But references have the opposite convention. You can go from owned values to references, but not the other way around, which is precisely the opposite situation as the convention around linear/affine type systems. Because these systems feel very different to use and enforce very different properties, I do think it's important that we have separate names for them rather than referring to both as "affine". And the usual name for the rust-like system is "uniqueness types", see https://docs.idris-lang.org/en/latest/reference/uniqueness-t... or https://en.wikipedia.org/wiki/Uniqueness_type .

ralfj•1h ago
> Well, the rust type system certainly does support contraction, as I can use a reference multiple times. So what is that if not contraction? It seems like rust at least does support contraction for references.

Good question! For shared references, the answer is that they are `Copy`, so they indeed have contraction. Affinity just means that contraction is not a universal property, but some types/propositions may still have contraction. For mutable references, you can't actually use them multiple times. However, there is a desugaring phase going on before affinity gets checked, so uses of mutable references `r` get replaced by `&mut *r` everywhere. That's not using contraction, it's not literally passing `r` somewhere, it is calling a particular (and interesting) operating on `r` ("reborrowing").

Rust is not just an affine system, it is an affine system extended with borrowing. But I think it is still entirely fair to call it an affine system, for the simple fact that the language will prevent you from "using" a variable twice. "reborrowing" is just not a case of "using", it is its own special case with its own rules.

> But in practice, having absolutely no contraction is not a very useful definition of affine,

Obviously Rust has a class of "duplicable" types, called `Copy`. That's besides the point though.

> If you interpret Rust's type system this way, it's natural to interpret references as exponentials.

Why would that be natural? Mutable references are not even duplicable, so what you say makes little sense for references in general. Maybe you mean shared references -- those are just an example of a duplicable type.

Rust doesn't have a modality in its type system that would make every type duplicable, so there is no equivalent to exponentials. (In particular, `&T` isn't a modality around `T`. It's a different type, with a different representation. And as you noted, even if it were a modality, it wouldn't correspond to exponentials.)

But a type system can be affine/linear without having exponentials so I don't understand the point of this remark.

Uniqueness types seem to be all about how many references there are to a value. You can use linear/affine types to enforce such a uniqueness property (and that is indeed what Rust does), but that doesn't take away from the fact that you have a linear/affine type system.

> Because these systems feel very different to use and enforce very different properties,

I can't talk about the "feel" as I never programmed in an affine language (other than Rust ;), but in terms of the properties, what Rust does is extremely closely related to affine logics: the core property being enforced is that things do not get duplicated. My model of Rust, RustBelt, uses an affine separation logic to encode the properties of the Rust type system, and there's a lot of overlap between separation logic and linear logic. So we have further strong evidence here that it makes perfect sense to call Rust an affine language.

caim•31m ago
The main point of Affine logic is that it doesn't allow contraction, and the Rust type system does allow different forms of contraction. How exactly is Rust an "affine language"?

Also, the claims about Curry-Howard correspondence are wrong. It does not prove that rust is an affine language: https://liamoc.net/forest/loc-000S/index.xml

caim•19m ago
Yeah, that makes sense. The Rust type system isn't "affine" as in affine logic. Rust allows different forms of contraction, which affine logic strictly prohibits.

And some people like to claim that the Curry-Howard correspondence proves something about their type system, but this is only true for dependently typed languages.

And the proofs aren't about program behavior.

See, https://liamoc.net/forest/loc-000S/index.xml

0x000xca0xfe•4h ago
As I understand it the borrow checker only has false negatives but no false positives, correct?

Maybe a dumb question but couldn't you just run multiple implementations in parallel threads and whichever finishes first with a positive result wins?

vlovich123•4h ago
This presumes that checking composes which may not if you have orthogonal checker implementations. You might end up risking accepting an invalid program because part of it is valid under one checker, part under another, but the combination isn't actually valid. But maybe that's not actually possible in practice.
afdbcreid•7m ago
Borrow checking is function-local, so if the opsem model is the same and you run the different checkers per-function, there is no such risk.
sunshowers•4h ago
That would result in ecosystem splitting, which isn't great.
pornel•3h ago
Rust already supports switching between borrow checker implementations.

It has migrated from a scope-based borrow checker to non-lexical borrow checker, and has next experimental Polonius implementation as an option. However, once the new implementation becomes production-ready, the old one gets discarded, because there's no reason to choose it. Borrow checking is fast, and the newer ones accept strictly more (correct) programs.

You also have Rc and RefCell types which give you greater flexibility at cost of some runtime checks.

Ericson2314•2h ago
What you actually want is the underlying separation logic, so you can precisely specify function preconditions and prove mid-function conditions, and the the optomizer can take all those "lemmas" and go hog-wiled, right up to but not past what is allowed by the explicitly stated invariants.

"Rust", in this context, is "merely" "the usual invariants that people want" and "a suite of optimizations that assume those usual invariants, but not more or less".

Voultapher•4h ago
Amazing work, I remember reading the Tree Borrows spec? on Nevin's website a couple years ago and being thoroughly impressed by how it solves some pretty gnarly issue quite elegantly. And in my experience [1] [2] it does indeed allow for sensible code that is illegal under Stacked Borrows.

[1] https://github.com/Voultapher/sort-research-rs/blob/main/wri... Miri column

[2] https://github.com/rust-lang/rust/blob/6b3ae3f6e45a33c2d95fa...

vollbrecht•4h ago
Hmm i just tested out the claim that the following rust code would be rejected ( Example 4 in the paper).

And it seams to not be the case on the stable compiler version?

  fn write(x: &mut i32) {*x = 10}
  
  fn main() {
      let x = &mut 0;
      let y = x as *mut i32;
      //write(x); // this should use the mention implicit twophase borrow
      *x = 10; // this should not and therefore be rejected by the compiler
      unsafe {*y = 15 };
  }
Arnavion•4h ago
Stacked borrows is miri's runtime model. Run it under miri and you will see the error reported for the `*x = 10;` version but not the `write(x);` version - "Undefined Behavior: attempting a write access using [...] but that tag does not exist in the borrow stack for this location".

rustc itself has no reason to reject either version, because y is a *mut and thus has no borrow/lifetime relation to the &mut that x is, from a compile-time/typesystem perspective.

vollbrecht•4h ago
Ah that make sense. Thanks for clarifying.
jcalvinowens•3h ago
> On the one hand, compilers would like to exploit the strong guarantees of the type system—particularly those pertaining to aliasing of pointers—in order to unlock powerful intraprocedural optimizations.

How true is this really?

Torvalds has argued for a long time that strict aliasing rules in C are more trouble than they're worth, I find his arguments compelling. Here's one of many examples: https://lore.kernel.org/all/CAHk-=wgq1DvgNVoodk7JKc6BuU1m9Un... (the entire thread worth reading if you find this sort of thing interesting)

Is Rust somehow fundamentally different? Based on limited experience, it seems not (at least, when unsafe is involved...).

ralfj•3h ago
I would agree that C's strict aliasing rules are terrible. The rules we are proposing for Rust are very different. They are both more useful for compilers and, in my opinion, less onerous for programmers. We also have an actual in-language opt-out: use raw pointers. And finally, we have a tool you can use to check your code.

But in the end, it's a trade-off, like everything in language design. (In life, really. ;) We think that in Rust we may have found a new sweet spot for this kind of optimizations. Time will tell whether we are right.

kookamamie•2h ago
Agreed about C's aliasing rules. Fortran had a better set of defaults.
NobodyNada•47m ago
As someone who has been writing a lot of unsafe Rust (mostly in an embedded context), I'm thrilled about and thankful for the work that you, your students, and the opsem team are doing.

When you're working with anything below the application level, C's confusing and underspecified rules about UB are almost impossible to keep track of, especially when it comes to aliasing and volatile/MMIO. The spec is so difficult to read and full of complicated cross-references that to actually get a practical answer you have to look for a random Stack Overflow post that may or may not have a correct interpretation of the spec, and may or may not address your specific problem.

Rust right now feels a lot harder to work with, because the spec isn't done. When you have a concrete question about a piece of code, like "is this conversion from an &mut to a *mut and back sound", and you try to look for documentation on it, you get either "Nobody knows, Rust aliasing model isn't defined"; a hand-wavy explanation that is not rigorous or specific; or a model like Stack Borrows or Tree Borrows that's defined a little too formally for easy digestion :)

But when I really started digging, I realized just how much cleaner Rust's semantics are. References aren't actually hard, Tree Borrows basically boils down to "while an &mut reference is live, you can only access the value through pointers or references derived from that reference". Pointer operations have straightforward semantics, there's no confusing notions of typed memory, and no UB "just because" for random things like integer overflow. It's just so much less complicated to understand than C's abstract machine.

I'm really looking forward to things like MiniRust, and to an aliasing model making it into the Reference / other documentation, because at that point I feel like unsafe Rust will be way* easier to write confidently and correctly than C.

Congrats on the publication, and thanks again for the work you all have put into this.

Asooka•3h ago
While I can't name the product I work on, we also use -fno-strict-aliasing. The problem with these optimisations is that they can only be done safely if you can prove aliasing never happens, which is equivalent to solving the halting problem in C++. In Rust I suspect the stronger type system can actually prove that aliasing doesn't happen in select cases. In any case, I can always manually do the optimisations enabled by strict aliasing in hot code, but I can never undo a customer losing data due to miscompilation.
pornel•3h ago
> actually prove that aliasing doesn't happen in select cases

In the safe subset of Rust it's guaranteed in all cases. Even across libraries. Even in multi-threaded code.

oconnor663•1h ago
To elaborate on that some more, safe Rust can guarantee that mutable aliasing never happens, without solving the halting program, because it forbids some programs that could've been considered legal. Here's an example of a function that's allowed:

    fn foo() {
        let mut x = 42;
        let mut mutable_references = Vec::new();
        let test: bool = rand::random();
        if test {
            mutable_references.push(&mut x);
        } else {
            mutable_references.push(&mut x);
        }
    }
Because only one if/else branch is ever allowed to execute, the compiler can see "lexically" that only one mutable reference to `x` is created, and `foo` compiles. But this other function that's "obviously" equivalent doesn't compile:

    fn bar() {
        let mut x = 42;
        let mut mutable_references = Vec::new();
        let test: bool = rand::random();
        if test {
            mutable_references.push(&mut x);
        }
        if !test {
            mutable_references.push(&mut x); // error: cannot borrow `x` as mutable more than once at a time
        }
    }
The Rust compiler doesn't do the analysis necessary to see that only one of those branches can execute, so it conservatively assumes that both of them can, and it refuses to compile `bar`. To do things like `bar`, you have to either refactor them to look more like `foo`, or else you have to use `unsafe` code.
steveklabnik•3h ago
While both involve aliasing, C's strict aliasing and Rust's aliasing are two different things. Rust pretty explicitly did not adopt the C style.

C's aliasing is based on type alone, hence its other name "type based alias analysis" or TBAA.

dzaima•3h ago
Rust's aliasing rules are very different from C's.

In C you have a nuclear `restrict` that in my experience does anything only when applied to function arguments across clang & gcc, and type-based aliasing which is both not a generally-usable thing (don't have infinite different copies of the int64_t type (and probably wouldn't want such either)), and annoying (forces using memcpy if you want to reinterpret to a different type).

Whereas with Rust references you have finely-bounded lifetimes and spans and mutability, and it doesn't actually care about the "physical" types, so it is possible to reinterpret memory as both `&mut i32`/`&i32` and `&mut i64`/`&i64` and switch between the two for the same memory, writing/reading halves of/multiple values by the most bog standard Rust safe reads & writes, as long as the unsafe abstraction never gives you overlapping `&mut` references at the same time, or split a `&mut` into multiple non-overlapping `&mut`s.

jandrewrogers•2h ago
Strict aliasing rules are useful conditional on them being sufficiently expressive and sensible, otherwise they just create pointless headaches that require kludgy workarounds or they are just disabled altogether. I don't think there is much disagreement that C strict aliasing rules are pretty broken. There is no reason a language like Rust can't be designed with much more sensible strict aliasing rules. Even C++ has invested in providing paths to more flexibility around strict aliasing than C provides.

But like Linus, I've noticed it doesn't seem to make much difference outside of obvious narrow cases.

ivanbakel•1h ago
>How true is this really?

I’d be interested to see a more thorough analysis, but there is a simple way to gauge this - rip out all the parts of the compiler where aliasing information is propagated to LLVM, and see what happens to performance.

I found a claim that noalias contributes about 5% performance improvement in terms of runtimes[0], though the data is obviously very old.

https://github.com/rust-lang/rust/issues/54878#issuecomment-...

jcranmer•37m ago
Take anything Linus says about compilers with a grain of salt--he writes OS kernels, not compilers, and those are pretty different domains.

Alias analysis is extremely important for getting good performance these days--but it should also be remembered that the biggest benefits accrue from the simplest heuristics (like two loads that use the same SSA value as the pointer must alias each other). In LLVM terms, that's BasicAA: a collection of very simple heuristics that primarily amounts to "if we can track down the allocation sites of objects, we can definitively resolve these alias queries; otherwise, we don't know."

The real question that you're trying to ask, though, is what is the value of alias analyses that go beyond the most basic, obvious tests. At the point where the alias queries are no longer trivial to solve, then it's generally the case that what you can do as a result of those queries also shrinks dramatically, pretty much to looking for code motion hazards, and the benefits you get from that are much reduced. One of the experiments I would like to do is measure the total speedup you'd get from a theoretically perfect alias analysis, and my guess is that it's somewhere in the 20% range even on non-HPC code like the Linux kernel [1].

[1] This doesn't account for the heroic optimizations, such as data-layout transformations, that you wouldn't attempt to write without a very high-quality alias analysis. But since we already know that alias analysis doesn't exist in practice, we're not going to attempt those optimizations anyways, so it's not worth including such stuff in prospective speed gains.

tliltocatl•31m ago
It is mostly useful on arrays/numeric code, probably next to useless otherwise. Numerics people was the ones who sponsored much of compiler/optimization work in the first place, that's how strict aliasing came to be.
dzaima•16m ago
I don't think the usefulness is that skewed towards numerics?

Both clang/llvm and gcc can do alias checking at runtime if they can't at compile-time, which makes loops vectorizable without alias info, at the cost of a bit of constant overhead for checking aliasing. (there's the exception of gather loads though, where compile-time aliasing info is basically required)

And on the other hand there's good potential for benefit to normal code (esp. code with layers of abstractions) - if you have a `&i32`, or any other immutable reference, it's pretty useful for compiler to be able to deduplicate/CSE loads/computations from it from across the whole function regardless of what intermediate writes to potentially-other things there are.

gavinhoward•3h ago
This looks excellent. I will probably implement this model for my own language.
Nurbek-F•1h ago
It can't be a dejavu. I keep seeing this post every 2-3 months...
steveklabnik•1h ago
The paper is years in the making. This is it finally being published.
olddustytrail•1h ago
_Tree Borrows_

"I want my fuckin' money back."

"Hoom, hmm, let us not be hasty!"

"You got 48 hours to deliver or the sapling gets it, Treebeard."