upvote
For a long time `loop {}` was undefined behavior. Lots of l-unsounds are really nuts but a few are not.

The reality is that if this were actually code that people wrote, well, it wouldn't have sat around for a decade.

reply
Afaik loop {} has never been UB, however because llvm started as a c++ compiled where it is, this has been causing miscompilations in rust and C for… nearly two decades (llvm issue 965).
reply
Sure, I think it was still under the same unsound tag regardless.
reply
Unsoundness and UB are very different things, UB tells users of the language "don't do that it's wrong", unsoundness tells users of the language "be careful we need to fix that", it's a bug.
reply
Since the Rust language is defined by the Rust compiler and has no other specification, if it's UB in the compiler then it's UB in the language.
reply
And this, kids, is how you get called Billy Madison.

May god have mercy on your soul, cowlevel1.

reply
Rust has no formal spec? Really?
reply
It's a work in progress. The Reference (https://doc.rust-lang.org/reference) is slowly getting more complete over time. Other ongoing efforts include a-mir-formality (https://github.com/rust-lang/a-mir-formality), minirust (https://github.com/minirust/minirust), the FLS (https://github.com/rust-lang/fls), and Rust via Desugarings (https://nadrieril.github.io/rust-via-desugarings/). But writing a 100% complete and correct formal spec is hard! Not even C gets this right, the C standard has holes which lead to miscompilations and UB in practice: https://www.ralfj.de/blog/2020/12/14/provenance.html
reply
> is definitely something you'd easily come across in normal code.

The fact that nobody reported this before means it's not, by definition.

reply
Not at all. There are way more valid lifetimes than the lifetime system of Rust can express. There are countless scenarios where you could accidentally use the unsound behaviour while not producing a segmentation fault because the lifetimes happens to be arranged such that no invalid memory access actually happened.

A program isn't invalid just because it violates the ownership and borrowing rules of Rust. There are tons of programs in the world with shared, mutable access, devoid of Mutexes, Arcs and Locks that nonetheless are completely valid.

reply
I think you are talking about a different problem and that has nothing to do with my comment.
reply
Simplified, the point is that a lot of badly typed code that this bug lets through might be mostly harmless (or even fully semantically correct, in some instances). So you can't conclude that 'normal' code wouldn't trigger this bug just because no-one's noticed it until now. The bad code could could be happily executing and performing as expected.
reply
I wonder if the reason it works is because you'd easily come across it in normal code, and someone didn't realize that saving the effort of implementing a check for this would result in unsoundness.
reply
That's not how it works. rustc doesn't "check" for specific cases explicitly, the borrow checker (apparently at fault here by reports) has a set of rules that should reject invalid programs. So either one of the fundamental rules was broken (unlikely here from what I've heard), or some optimization caused the rules to not be implemented correctly.
reply
I know the borrow checker uses rules, but I don't know enough about the internal implementation details to use fully precise terminology. I don't mean borrow checking is just a chain of if-statements or something. I meant check in the abstract.

From the GitHub thread: "I think unification just generally doesn't check lifetime bounds of the type." [0]

There are steps, or rules or whatever, that perform soundness (or well-formedness or whatever) checks. And clearly one was missing.

My guess was just that maybe someone didn't think it was necessary for soundness.

[0]: https://github.com/rust-lang/rust/issues/164250#issuecomment...

reply
Not really. I've worked with rust for 4 years, systems side, and never had to write a custom drop implementation. That's the gotcha here, not the rigamarole with the static+Send option type (which _would_ be something you'd encounter in prod).
reply
I've written dozens of custom Drop implementations. Well, many of them are named cleanup because of the async Drop mess in Rust, but...
reply
How many of them only conditionally implement Drop, based on a generic param lifetime?
reply
Why would you ever conditionally custom impl Drop? I don't think I've ever seen that pattern, and I can't think of a use case.
reply
Therefore explaining why the bug hadn't been hit in practice for 11 years.
reply
The bug in the OP is about UNconditional impl. And honestly, looks like very standard code, definitely something that could've been written for real. I can't even explain why it passes checks, it clearly shouldn't.
reply
This code, from the bug submission?

  impl<T: 'static + Send> Drop for Q<T> {
      fn drop(&mut self) { if let Some(t) = self.0.take() { KEPT.lock().unwrap().push(Box::new(t)); } }
  }
The bound on T in the Drop impl means Drop is not implemented for all T, only where T: 'static + Send. Q<T> also having the same bound doesn't make a difference to the Drop impl.
reply
You cannot write a type which conditionally implements Drop: https://play.rust-lang.org/?version=stable&mode=debug&editio...

    struct Q<T>(Option<T>);

    impl<T: 'static> Drop for Q<T> {
        fn drop(&mut self) {}
    }


    error[E0367]: `Drop` impl requires `T: 'static` but the struct it is implemented for does not
     --> src/main.rs:3:9
      |
    3 | impl<T: 'static> Drop for Q<T> {
      |         ^^^^^^^
      |
    note: the implementor must specify the same requirement
     --> src/main.rs:1:1
      |
    1 | struct Q<T>(Option<T>);
      | ^^^^^^^^^^^
reply
Even if the bounds are the same on the struct and the impl, it's still true that placing bounds on the Drop impl means it's not implemented for all T (just all T that also satisfy Q).

You also don't have to place those bounds on the Drop impl just because they're on Q, that's not an error.

reply
OK. That's good to know. I'm not sure why sharing our professional experience with this type of code is controversial, but here we are.
reply
That's easily the exception rather than the rule. I've seen custom `Drop` implementations in almost every non-trivial Rust codebase I worked on.
reply
A custom `Drop` appears very quickly with FFI code. Suppose for example you interface with some C library that expects you to call a function to release some resources.
reply
deleted
reply
Now we are at the phase where, Rust is “safe” but only if you use it “correctly” and without using X language feature or a custom Y feature.

This is the problem when a language advertises with “guarantees” and it turns out it never had any due to many false assumptions by their promoters.

So what other soundness bugs are there in the language that we need to know about?

reply
I'm not defending rust here - a correctness bug invalidates the premise. But I am saying that I've never seen a custom drop in production.

For some reason this is controversial, but it remains true.

reply
You said/implied 2 things:

- you've never written a custom Drop

- "Not really". Implying that your experience generalizes

I've written a bunch of rust programs without custom Drop. I believe your first statement. There are large classes of programs that don't need it. There are also many that do. I think your statement says a lot more about what kind of programs you work on than about custom Drop not being common. People are downvoting the implication that custom Drop is not a common pattern.

reply
Custom drops are all over the place. As others have said.

But not custom drops that are doing variadic type stuff like this, usually.

reply
No we're in a situation where a bug in the type checker was found and will be fixed and a new release will be made.

That it took 11 years for someone to come across this is a fairly intense counterargument to your attempt to paint this as a language with dangerous footguns.

reply
[flagged]
reply
A gun in a glass case with a warning label reading "do not aim at foot"?
reply