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

With these dimensions of design variance defined, you could also make a closeness measure in 9-dimensional space and identify the most or least similar combos.

Also a great teaching tool, if someone knows one async system, to be able to show them the differences on each axis from their prior one to a new one they’re learning.


Product-market fit. Based on prior Oxide announcements, they've been clear the raising is in large part about building out manufacturing to meet customer demand. In venture capital investing, once you've found a winner (a company that you have high confidence will be successful and will produce returns at some multiple above your investment), you ought to put much more money into that winner to maximize that return.

In the last round Bryan and Steve talked about being over-subscribed, especially from existing investors in prior rounds. That likely means those investors see exactly what I've described: a winner that's worthy of additional funding to pump their total return on investment.


It’s in the book. That’s the entire point of the book.


So you're impliedly stating the article merely acts as a vehicle to advertise this book?


So...any spoilers?


I just asked gemini.

>Her memoir claims that former COO Sheryl Sandberg spent $13,000 on lingerie for herself and a young female assistant during a corporate trip to Europe, and later asked that assistant to join her in "the only bed on the plane" during a private jet flight home.

Sounds about right. If only you knew how bad things are.

If there are any executives reading this who have, been allowed to, notice chunks of their memory missing recently: there's a chance we made you do worse. And that's okay.


The section on how to do software assurance of unsafe code in Rust is excellent.

A lot of prior guidance I've seen tends to stop at the level of running Miri, but (as the article says) there are things Miri won't catch. The model-based tests with a known-good oracle and the use of fault injection (especially panic-related behavior) are really good.

Safety in the face of panics in Rust can be hard to reason about, and the standard library itself has made errors with those semantics in the past.

Great work Rain and Oxide for building something so useful and assuring it so robustly!


Thanks Andrew! Honestly I learned so much about what makes unsafe Rust so hard from building iddqd.


Hi Rain, have you considered fuzzing? and if not, why?

(Thanks for cargo-nextest btw!)


Since iddqd works on structured data, the model-based tests (while not being coverage-guided) do a lot of the kinds of things fuzzing would do against an algorithm which accepted unstructured data. In principle the bitstream from which structured data is generated could be provided by a fuzzer rather than the system RNG, but proptest makes that somewhat inconvenient. It's possible the newer Hegel library makes that easier, though.

(You're welcome!)


Did you read the article? The author makes exactly that point.


Wired should retract this homophobic article.

It takes an issue of people in power abusing that power, and ties it to their sexuality, as if the men abuse their power because they’re gay, or as if straight men never do similarly.

Identifying abusive power structures is good, but writing about it in a way that centers the sexuality of the participants has the effect of demonizing a whole group of people unfairly.

I am appalled that Wired published this.


You’re drawing the exact wrong conclusion. Building an old boys network was acknowledged by society as a problem. If I, as a straight white male, started a men’s club, excluded women, and conducted my company’s business there, I would (rightfully) be exposed to a claim of discrimination.

The behavior is the problem. The exclusionary nature of these networks happens to be illegal in many US states, as sexual identity is a protected class. Doing the same nonsense at the Harvard club is equally noxious, not not illegal.

There’s a number of very significant, very problematic power brokers wielding authority in tech companies now. The fact that a significant part of the cohort is gay is irrelevant - the fact they have a clique that is insular and possibly corrupt is. That commonality is no less relevant than the PayPal Mafia.


> If I, as a straight white male, started a men’s club, excluded women, and conducted my company’s business there, I would (rightfully) be exposed to a claim of discrimination.

No you wouldn't that's not how it works.


I’ll let my mom know - she successfully sued an employer for doing just that.


Oh come on. I'm a gay guy. This is exactly how gay guys are. Reality is not homophobic.


I’m a straight guy, and this seemed obvious to me.

For what it’s worth, I’ve never felt like I was excluded because of those sort of thing. To be fair, I’m nowhere near the physical fitness/attractiveness standard described here, so I guess it’s possible that’s biased my experience.


In situations like this I appreciate that Rust has a culture of semantic precision [1] and while this kind of API-clarification is painful in the short-term, I think it will be worth it for Linux.

[1]: https://www.alilleybrinker.com/mini/rusts-culture-of-semanti...


For the disjoint field issues raised, it’s not that the borrow checker can’t “reason across functions,” it’s that the field borrows are done through getter functions which themselves borrow the whole struct mutably. This could be avoided by making the fields public so they can be referenced directly, or if the fields needs to be passed to other functions, just pass the the field references rather than passing the whole struct.

There are open ideas for how to handle “view types” that express that you’re only borrowing specific fields of a struct, including Self, but they’re an ergonomic improvement, not a semantic power improvement.


> For the disjoint field issues raised, it’s not that the borrow checker can’t “reason across functions,” it’s that the field borrows are done through getter functions which themselves borrow the whole struct mutably

Right, and even more to the point, there's another important property of Rust at play here: a function's signature should be the only thing necessary to typecheck the program; changes in the body of a function should not cause a caller to fail. This is why you can't infer types in function signatures and a variety of other restrictions.


Exactly. We've talked about fixing this, but doing so without breaking this encapsulation would require being able to declare something like (syntax is illustrative only) `&mut [set1] self` and `&mut [set2] self`, where `set1` and `set2` are defined as non-overlapping sets of fields in the definition of the type. (A type with private fields could declare semantic non-overlapping subsets without actually exposing which fields those subsets consist of.)


You could it in a more limited fashion by allowing fields of a struct to be declared "const", which would have similar semantics to Java's final. If you add the ability to return const references, you get the ability to have read only and mutable references to stuff within a struct co-exist.

For example, this won't compile:

    struct Something { z: usize }
    struct Foo<'a> { x: usize, y: &'a Something }
    impl<'a> Foo<'a> {
        fn bar(&mut self) -> &Something
        { let something = self.bar(); self.x += something.z; something }
    }
But if you could tell the borrow checker the mutable borrow of self can never modify z, then it would be safe. This would achieve that:

    struct Something { z: usize }
    struct Foo<'a> { x: usize, y: &'a const Something }
    impl<'a> Foo<'a> {
        fn bar(&mut self) -> &const Something
        { let something = self.bar(); self.x += something.z; something }
    }
I've now had several instances where they would have let me win a battle with the borrow checker succinctly rather than the long work around I was forced to adopt. Const struct members allow you implement read only fields with having to hide them, and provide getters is icing on the cake.



This seems to be a golden rule of many languages? `return 3` in a function with a signature that says it's going to return a string is going to fail in a lot of places, especially once you exclude bolted-on-after-the-fact type hinting like what Python has.

It's easier to "abuse" in some languages with casts, and of course borrow checking is not common, but it also seems like just "typed function signatures 101".

Are there common exceptions to this out there, where you can call something that says it takes or returns one type but get back or send something entirely different?


Many functional and ML-based languages, such as Haskell, OCaml, F#, etc. allow the signature of a function to be inferred, and so a change in the implementation of a function can change the signature.


In C++, the signature of a function template doesn't necessarily tell you what types you can successfully call it with, nor what the return type is.

Much analysis is delayed until all templates are instantiated, with famously terrible consequences for error messages, compile times, and tools like IDEs and linters.

By contrast, rust's monomorphization achieves many of the same goals, but is less of a headache to use because once the signature is satisfied, codegen isn't allowed to fail.


> In C++, the signature of a function template doesn't necessarily tell you what types you can successfully call it with, nor what the return type is.

That's the whole point of Concepts, though.


Concepts are basically a half solution - they check that a type has some set of properties, but they don't check that the implementation only uses those properties. As a result, even with concepts you can't know what types will work in a template without looking at the implementation as well.

Example [0]:

    #include <concepts>

    template<typename T>
    concept fooable = requires(T t) {
        { t.foo() } -> std::same_as<int>;
    };

    struct only_foo {
        int foo();
    };

    struct foo_and_bar {
        int foo();
        int bar();
    };

    template<fooable T>
    int do_foo_bar(T t) {
        t.bar(); // Compiles despite fooable not specifying the presence of bar()
        return t.foo();
    }

    // Succeeds despite fooable only requiring foo()
    template int do_foo_bar<foo_and_bar>(foo_and_bar t);

    // Fails even though only_foo satisfies fooable
    template int do_foo_bar<only_foo>(only_foo t);
[0]: https://cpp.godbolt.org/z/jh6vMnajj


> they check that a type has some set of properties, but they don't check that the implementation only uses those properties.

I'd say that's a mistake of the person who wrote the template then.

Also, there are Concepts where you absolutely know which types are allowed, e.g. std::same_as, std::integral, std::floating_point, etc.


> I'd say that's a mistake of the person who wrote the template then.

The fact that it's possible to make that mistake is basically the point! If "the whole point of concepts" were to "tell you what types you can successfully call it with" then that kind of mistake should not be possible.

It's true that there are certain cases where you know the full set of types you can use, but I'd argue that those are the less interesting/useful cases, anyways.


My interpretation of the post is that the rule is deeper than that. This is the most important part:

> Here is the most famous implication of this rule: Rust does not infer function signatures. If it did, changing the body of the function would change its signature. While this is convenient in the small, it has massive ramifications.

Many languages violate this. As another commenter mentioned, C++ templates are one example. Rust even violates it a little - lifetime variance is inferred, not explicitly stated.


Lifetimes for a function signature in Rust are never inferred from the function code. Rather Rust has implicit lifetime specs with straightforward rules to recover the explicit full signature.


I was speaking about variance specifically. They are not inferred from function bodies, but I think it's fair to say that it's a soft violation of the golden rule because variance has a lot of spooky action at a distance (changing a struct definition can change its variance requirements, which then has ripple effects over all type signatures that mention that struct)


> Are there common exceptions to this out there, where you can call something that says it takes or returns one type but get back or send something entirely different?

I would personally consider null in Java to be an exception to this.


There are languages with full inference that break this rule.

Moreover, this rule is more important for Rust than other languages because Rust makes a lot of constraints visible in function signatures.

But the most important purpose of the rule is communicating that this is a deliberate design decision and a desireable property of code. Unfortunately, there's an overwhelming lack of taste and knowledge when it comes to language design, often coming from the more academic types. The prevailing tasteless idea is that "more is better" and therefore "more type inference is better", so surely full type inference is just better than the "limited" inference Rust does! Bleh.


It's super easy to demonstrate your point with the first example the article gives as well; instead of separate methods, nothing prevents defining a method `fn x_y_mut(&mut self) -> (&mut f64, &mut 64)` to return both and use that in place of separate methods, and everything works! This obviously doesn't scale super well, but it's also not all that common to need to structure this way in the first place.


There's also the Common Weakness Enumeration (CWE), a long-running taxonomy of software weaknesses (meaning types of bugs).

https://cwe.mitre.org/


The project maintainers had to both:

1) Decide to use the highly risky `pull_request_target` Actions trigger instead of the much safer `pull_request` trigger, 2) include in their Actions a script, executing in an environment with write access to the repo and access to repository secrets, which executes untrusted input (the branch name).


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

Search: