HNHacker News
TopNewBestAskShowJobs

fluffything

2,917 karma · joined April 21, 2019

submissionscomments
fluffything··on SpaceX Starlink average speedtest is 42.3Mbps down / 9.7 Mbps up
For mobile phone networks, >20ms latency in audio is "unacceptable" from the point-of-view of standards conformance and a client "accepting" the hardware of some vendor.

Up to 100ms is kind of ok-ish barely-sluggish, but over 100ms latency, it becomes extremely annoying to maintain a conversation.

Video conferencing often makes this worse, because it is what people use for meetings, etc. and that involves more than 2 people maintaining a conversation, so latency becomes even more important there.

Otherwise 3-4 people start talking over each other, and none of them notices until they receive what the others are saying. Which is extremely annoying.

fluffything··on Is macOS Becoming Unmaintainable?
Its also really hard to report bugs. So things don't get fixed.

Company policy is more like "it just works, our software has no bugs" (goes ahead and pushes one bug fix update per week).

The irony.

fluffything··on After 48 years, Democrats endorse nuclear energy in platform
The problem with nuclear isn't whether you can build a safe plant, you can.

The problem with nuclear is all the assumptions under which a perfectly safe plant is actually perfectly safe (proper maintenance, training, etc.).

I don't believe those assumptions always hold in practice. At the end of the day, these plants are operated by people, and private companies, who have many interests beyond keeping the plant "perfectly safe" (like making money) and also operate under constraints that prevent them from actually keeping the plant "perfectly safe" even if they wanted to (like lack of money).

The problem with nuclear isn't technological, but social. It allows a relatively small bunch of shitty people and companies to cause tremendous amounts of devastation.

Remove people from the "nuclear energy safety equation" and I'm all in with nuclear. Telling me that new plants are perfectly safe as long as people and private companies don't do shit, reads like these plants aren't safe at all to me.

---

And this is without taking into account all the unknown unknowns, like all the natural disasters we can't even predict or imagine, which all plant designs just assume cannot happen.

Just claiming that modern nuclear plants are safe, for all potential world states is BS, because nobody can imagine, much less know, what all those potential world states are.

Sure coal kills people, but what makes many think its safer than nuclear is that we understand how that happens, we understand where coal goes.

See this John Oliver episode about nuclear waste. After 70 years, we haven't even been able to agree in a location to dispose nuclear waste, much less build one, and use it: https://www.youtube.com/watch?v=ZwY2E0hjGuU&list=PLMJ9OaOo9J...

All the assumptions that nuclear was safer than X over the last 70 year assumed that such a location would exist and be used.

fluffything··on Show HN: Olaf – Acoustic Fingerprinting on the ESP32 and in the Browser
Maybe for other people, not for me.

My free time is very expensive.

An ESP32 costs nothing compared to the cost of my free time, and comes with wifi and bluetooth, which makes many things simpler.

Other solutions whose hardware costs less than an ESP32 cost me a lot of time, and end up being infinitely more expensive than the ESP32 approach.

fluffything··on SpaceX Starlink average speedtest is 42.3Mbps down / 9.7 Mbps up
Anything that requires real-time interaction between a client and a server and other clients, e.g., gaming, stadia/geforce now, videoconferencing, ...

< 100ms is usually the "minimum", > 150ms is often "unusable", and for a smooth experience you might need < 30ms depending on the application (e.g. depending on the game you might need < 90ms or <60ms or <30ms).

fluffything··on TikTok CEO Kevin Mayer to leave the company
I'm not sure I agree.

We have trade-deals across countries, and IMO these trade deals should account for access to markets, e.g., Chinese companies can operate in Europe freely (abiding by our laws) _if_ European companies can operate in China freely as well.

Trade-deals change all the time, and when these change, some companies might get kick off.

I think this is a functional and rational thing to do for the EU.

If you don't have any deals or specific laws about it, then pretty much everything goes. Maybe the EU could have a law that all foreign companies that abide by the EU rules can operate in Europe freely, but I strongly doubt that. Every country does pretty much whatever they want in this regard (e.g. we see it with some countries allowing Huawei to sell 5G equipment, others forbidding it, and others like Germany attempting to forbid it without mentioning Huawei). All these countries have different rules, so they all end up doing their different stuff.

China (+) is buying lots of EU companies, "forcing" them to produce and do engineering in China, with a Chinese partner, and then ripping them completely off, as part of their 2025 program.

TBH I'm very concerned about some of the companies they have bought (e.g. Rukka). I am certain this is good for China, but I don't see how this can be good for the EU in the long term. China is very open that their plan is to acquire and become leaders in the technology, and then flip a switch and cut us out.. but they are the highest bidders today...

(+) these are actually chinese companies, but sponsored and ordered by the Chinese government, with essentially unlimited funds.

fluffything··on The potentially revolutionary Celera 500L aircraft
> had a maximum cruising speed of at least 450 miles per hour and a range of over 4,500 miles

Given the shape of the airplane, I'd guess the 4,500 miles range is not at 450 miles per hour, but much much less. Also, it needs to fly very high, so you need to correct the time it takes to travel with this with the longer take off and landing times.

It wouldn't surprise me if the "effective" velocity of this plane for long distances was more like 200 mph. I hope I'm wrong.

fluffything··on Draft of OCaml Scientific Computing book
I suppose this book exists because somebody developed a scientific computing course at university that uses it.

So I'd expect that every year, there will at least be a class of 30 scientists taking this course.

fluffything··on Draft of OCaml Scientific Computing book
This chapter showcases the problem perfectly.

It gives scientists a lot of information about how to perform low level optimization on code, e.g., if your code is "slow", use SIMD, OpenMP, BLAS, or do this or that trick.

But it does not provide the scientist with even the most basic tools to answer the question: "Is my code fast or slow?" (i.e. should I optimize it at all?), much less "_Why_ is it slow, and what's the best way to address that?" (e.g. if it is slow because its using 100% of the peak FLOPs of the CPU, but your hardware has a GPU, so you end up with 1% total FLOP utilization, then none of the "tricks" there will help).

It also completely avoids the issue that, in practice, a O(N) algorithm beats a OpenMP+SIMD-optimized O(N^2/p) algorithm pretty much all the time.

The chapter kind of assumes that scientists OCaml code will be slow, and gives them a "bag of tricks" that they can try to make it faster.

So we end up with the irony of a book on scientific computing that completely ignores the scientific method.

fluffything··on HPC Systems Special Offer: Two A64FX Nodes in a 2U for $40k
> ... Am I missing something?

Memory BW? Power consumption ? What's the BW and the power consumption of 2 A64FX CPUs, and what's the BW and power consumption of 4x Threadripper 3990X that also deliver 6 TFLOP/s? You might need to add the power for cooling to the comparison as well if you plan to stock a full cluster with these.

Also, if your main metric is TFLOPs, you might want to add a single A100 to the comparison.... it probably crushes the Threadripper and the A64FX from the POV of TFLOPs, memory BW, and power consumption, but maybe not price.

fluffything··on Draft of OCaml Scientific Computing book
Skimming through this book, one thing i was constantly wondering, is how well does this ocaml framework use the hardware.

Leaving ocaml aside, the connection between scientific computing and hardware is the one thing I miss the most in "scientific computing" books and courses, because it sooner or later limits the science that any researcher doing scientific computing can do.

To give an example, earlier this week, one of our scientists was waiting 10 minutes between each interactive iteration of their data-set, so I was called to help, and the only feedback they gave was that "its slow", to which I replied "slow with respect to what? how fast are you expecting this to be and _why_?".

The answer to these questions is the difference between "maybe they just need a faster computer", "maybe they need a different algorithm", or even "maybe this problem cannot be solved today because computers this fast do not exist".

From their facial expression, it looked to me that they actually had never thought about any of this, probably because whatever they did before was always fast enough, but now this issue was limiting their science and they were lacking the bare minimum set of tools to even get proper help.

If you are doing scientific computing, chances are that the problems you are going to be dealing with are going to be getting bigger and harder as you advance in your career. For many scientists, the first problems will actually be big enough for the hardware to matter.

I wish scientific computing courses and books will at least provide the most basic tools to these scientist for them to at least be able to get meaningful help. Having someone on call for when this matters is quite expensive.

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
I think that would be worth doing, but more than the backward compat problem, the main complication I see would be in the syntax/grammar/macro expansion.

Like, say we wanted to make cxx or autocxx macros unsafe. We'd need to allow at item scope writing this:

    mod foo {
        unsafe { my_unsafe_macro!() }
    }
and we'd "somehow" have to check that unsafe macros are only expanded within unsafe "scopes", rejecting the program otherwise (can't be a type error because we can't do type checking before macro expansion). Also, these unsafe scopes would need to export all the items, etc.

I don't know. Seems like a lot of contortion for something that could be solved with just a rename like other have proposed, e.g., unsafe_autocxx_include!(...);

Might be worth opening an internal threads about this. Maybe Centril could shed more like on how hard this would actually be.

Most (all?) macros that I regularly use are sound (the derives, println!, debug!, offset_of!, pin_mut!...). So it might also be worth looking into how common of a problem this is. I've seen soundness bugs in macros before (offset_of!), but these were always bugs. This is the first time I recall a macro that's unsound by design.

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
I agree with you that by controlling both sides of the FFI (the Rust and the C++ code) one can make sure that the types work.

The real problem is, however, that C++ lacks an "unsafe" keyword, so functions like:

    /// # Unsafe
    ///
    /// Must call `bar` after a sequence of calls to `foo`
    unsafe fn foo();
    fn bar();
just look like

    /// note: must call bar after a sequence of calls to foo
    void foo();
    void bar();
You can autogenerate "correct" C++ code from that Rust code (just loose the "unsafe"), but you cannot autogenerate safe Rust code from that C++ code unless you start parsing and understanding documentation comments (which could be possible, e.g., chromium could annotate C++ APIs that should be unsafe in Rust).

To generate Rust from C++, it does not suffice to just "look at the types" like cxx and autocxx do. One also _at least_ need to read all the API documentation comments, check if there are any invariants that must be preserved, and act accordingly.

If the APIs are ok and can be wrapped mechanically, the actual wrapping can be made trivial with tools, but there is no tool today that will tell you whether this is the case.

That is, at the end of the day, if you need to expose 10k C++ APIs from Rust, you will still need to manually inspect those 10k C++ APIs, and _think_ about whether they are safe or not.

That's the time consuming part, and you actually want to only do this once, and write down why an API is safe or not, so that other programmers don't have to repeat this work every time you hit an FFI issue.

So IMO while cxx and autocxx are "ergonomic", they spare you only the easy lest time consuming portion of the work. autocxx also makes it easy for you to either not check, or not write down the result of the check, and this could end up creating a lot more work down the road.

---

Note that this is something one wants to do even when one trusts that the C++ code is correct. In the example above, the C++ APIs can be correct, but one can still UB by using them incorrectly.

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
I think we pretty much agree on everything then.

My only complain about autocxx remains that it does not require `unsafe`, but if they adopt the same fix that the `cxx` crate wants to adopt, that complain is gone. I hope the Chromium devs would be "ok" with such a small amount of unsafe code that condenses the proofs of all APIs being wrapped.

We kind of tossed aside the discussion of unsafe vs safe macros, but I'd understand some people see that differently (macros expand Rust code, but IMO they are not that different from generics, and we do have safe and unsafe generics; right now, AFAICT, we only have safe macros).

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
> "Just use bindgen" is a cop-out, not a solution. It is technically correct, merely by marking all APIs unsafe. But as the Chromium document describes, this introduces a lot of noise that can mask the more involved proofs.

Chromium does not want to use `unsafe` on every call. The solution is simple, write a safe wrapper, that uses `unsafe` once.

> but a way to consolidate large numbers of similar proofs into a single place

That wasn't my read of their comment. If that's what they want, then the patched `cxx` crate which requires `unsafe` would give them exactly this.

The reddit user mentions:

> The key issue that people get worked up about, is that all C++ is unsafe,

This is not what we are talking about here. Lot of C++ code is safe, and writing a safe wrapper over C++ that's obviously safe is a one liner. What's problematic is doing so without checking _and_ without writing unsafe, by assuming that all C++ code is safe, which is what a library that asks you for a path to a headerfile and that will automatically generate safe wrappers in safe rust without asking even if the header file silently changes seems to encourage.

I also worked on one of the largest FFI Rust projects, and what one does is automatically generate thousands of unsafe C bindings, and have a crate exposing safe wrappers. Every time you need to call one FFI you either use the safe wrapper, or you add one if there isn't one. Very often, safe C wrappers weren't trivial, because what the FFI bindings were doing was inherently unsafe, and the amount of abstraction required to make that safe was prohibitive (and many many projects have run into this, Vulkan, wayland, ...). Then you either spend a lot of time into a safe abstraction, or you just use the unsafe API. Automatically generating safe wrappers instead just sounds like a bad idea, one would just be pushing all those issues onto safe Rust, which is not where they belong.

This is exactly what the first reply to that reddit user mentions, and here is your reddit user's reply to that, in which they explain that they were mostly referring to FFI when it comes to splicing Rust into C++: https://www.reddit.com/r/rust/comments/ielvxu/the_cxx_debate...

Calling Rust from C++ is a _very_ different use case from just calling C++ from Rust, which is what the Chromium devs mention is their primary concern:

> we are primarily concerned with the ability for new Rust code to call into existing C++ code

It's so different that one can in fact easily generate "safe" C++ bindings to safe Rust.

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
> There is no such thing as a "safe macro" or an "unsafe macro," so you can't make the usual argument there

From all the soundness issues that have been filled on macros that were not safe in the past, the impression I have is that all exported Rust macros must be safe.

> but "how can we enable people to correctly bind to large C++ APIs?"

This is a solved problem: rust-bindgen, it correctly generates unsafe Rust FFI wrappers for all C++ code.

What the Chromium devs actually want is what I pointed out in my root comment: to automatically generate correct soundness proofs for their C++ code / APIs, so that they can automatically generate safe Rust FFI wrappers for them.

This is an unsolved problem, which is probably impossible to solve.

So I think this is an absurd requirement from the part of the Chromium project, that deserves the absurd solution proposed by the `autocxx` crate, which is to just assume that these proofs exist. The disclaimer "You can only use `autocxx` on those APIs for which those proofs actually exist" isn't very reassuring TBH. They don't appear interested in finding out whether those proofs actually exist, so what's the point really.

They will just start using Rust, continue getting CVEs because "oh, I guess we shouldn't have blidnly wrapped those thousands of APIs", and conclude that Rust isn't more secure than C++.

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
C++ code only needs to be safe according to C++ rules (not Rust rules). So it is possible for the C++ to be safe, and the corresponding Rust code to be unsafe, e.g.,

* int foo(); which returns an uninitialized int is OK according to C++ rules, but would need a MaybeUninit<c_int> according to Rust rules.

* int foo(); could throw an exception, causing UB in Rust, since Rust assumes FFI declarations not to throw according to the spec. Rust can only export `noexcept(true)` C++ FFI declarations, or C functions (since C cannot throw). Apparently, autocxx and the cxx crate ignore this and treat all C++ functions as if they never throw, giving them a safe API. That's unsound. (One can fix that on nightly Rust though).

Unsafety can also be introduced through ABI incompatibilities, but IIUC autocxx usage of rust-bindgen deals with that.

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
This is currently a soundness bug in libstd: https://github.com/rust-lang/rust/issues/32670

(note: the bug was proposed to review by the libs team, but this review never happened, some prominent community members claim there that this is indeed a soundness bug, just one that might not be worth fixing, or would be really hard to fix, but that should be tracked as such).

To me it looks like one should just link the bug to the unsafe code guidelines, so that they can clarify the definition of soundness (and the limits of the rust abstract machine in which soundness is meaningful) to take this into account.

See the linked "mitosis crate" issue at the end for a similar issue.

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
> This was done to deal with remarks Chromium devs had against Rust C++ binding.

I have a hard time believing those Chromium devs know what they want.

Their request allows safe Rust to introduce undefined behavior, making the unsafe Rust keyword meaningless (since now you can't even grep for the places in the code where this UB is introduced), and eliminating the actual reason they want to use Rust in the first place (to avoid undefined behavior, segfaults, CVEs, etc.).

The only thing complying with the request will achieve is hurt the language. Once the chromium devs start hitting the same CVEs and segfaults in Rust that they were hitting in C++, they will just tell the whole world that Rust is as bad as C++ and using it is not worth it.

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
> Even if someone uploads Rust bindings to C or C++ code to crates.io, as a library user you would still need to manually install the C/C++ library on your end, along with a compiler.

Not if the library comes with your system. One can use this macro to generate a more "ergonomic" "safe libc" crate, that just introduces UB in safe Rust.

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
> It is somewhat unfortunate both the proof obligation and proof 'declaration' use the same token.

There have been some RFCs open to improve this situation (e.g. unsafe blocks in unsafe functions comes to mind).

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
#[no_mangle], like many other Rust features, is unsound; that's a fact and not an opinion, there is a bug in the tracker open for it and labelled I-unsound (accepted as an unsound bug). It is a low priority issue, but will be fixed eventually.

> Frankly Rust values being a usable language too much to be 100% sound.

Rust has a really good track record of identifying, prioritizing, and fixing soundness bugs (e.g. it took 4 years of work to fix one floating-point soundness bug!). Many people continuously work on this at the academic, toolchain, and backend (llvm, crane lift) levels. There is also a lot of people continuously working on making sure that new language features like async/await, const generics, specialization, GATs, ... are sound.

TBH i'm surprised to learn that not all Rust core members consider soundness to be a Rust core value. Maybe it isn't a Rust core value? (it is for me; without it, Rust makes no sense as a language to me)

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
> Using cxx does not, in fact, remove any `unsafe` blocks- thus it is not "lying," nor is it "the ultimate evil." (Such hyperbole makes productive discussion in this space rather difficult...)

If I can write an unsound Rust program using autocxx or cxx safe Rust APIs, then these APIs are unsound.

Whether these APIs are macros or function calls does not matter. There is no distinction at the API level about whether incorrect unsafe code is expanded, or called into. The API is safe, and for these crates, the currently-safe API introduces undefined behavior.

cxx will be fixed to require unsafe, but AFAICT autocxx usecase is to satisfy Chromiums requirements which require completely avoiding unsafe.

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
> Do you validate every single unsafe code in every single library you use? Even the standard library? Every time?

We don't need to? Rust's main soundness theorem says that if a safe Rust API is sound, then safe Rust code using it is sound.

So the only thing we need to check is that the unsafe code that _we_ write is sound, and we 100% do this all the way for the standard library. In the standard library _every_ unsafe block has a comment explaining why the "user-provided soundness proof" that they represent is correct. We even have a linter that actually rejects PRs that add unsafe blocks to the standard library without such comments.

> Do you validate every single unsafe code in every single library you use? Even the standard library? Every time?

Soundness is IMO Rust's main feature and its main core value, and is more important than other Rust core values like, e.g., zero-overhead abstractions, which are also extremely important. Soundness is what enables "Hack without fear", "no segfaults", "refactor without fear", cargo ("large scale software without fear"), crates.io ("using other people's libraries without fear")... and it's what sets Rust apart from unsound-by-design languages like D, Nim, Zig, C, C++, etc.

I haven't read the book in a long time, but the documentation I do read (nomicon, spec, unsafe code guidelines, issue tracker, internals) makes it very clear that making sure that unsafe Rust code is correct is critical for the ecosystem and for users to benefit from the main advantages Rust has to offer.

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
I know.

The Rust spec defines "unsound" as "introducing undefined behavior in safe Rust". The API of the cxx crate allows a safe Rust program to have undefined behavior, and it is therefore unsound.

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
> Rewrite everything in Rust in one go?

No? Just do what every good Rust programmer does today instead?

If I have a C++ function like this:

   // If a == nullptr the behavior is undefined 
   void foo(int* a); 
the right way to provide a safe Rust API for it is to write:

   mod ffi { extern "C" { fn foo(a: *mut c_int); } }
   fn foo(a: *mut c_int) { 
      assert!(!a.is_null());
      unsafe { ffi::foo(a) }
   } 
The crates being discussed here generate:

   mod ffi { extern "C" { fn foo(a: *mut c_int); } }
   fn foo(a: *mut c_int) { 
      unsafe { ffi::foo(a) }
   }
instead (notice the missing assert), which is broken Rust code according to the Rust spec, because now `foo` will introduce undefined behavior into safe Rust every time its safely called with a null pointer. That is, doing this makes _all_ Rust safe code "unsafe", making the unsafe Rust keyword essentially meaningless, and negating any advantage that Rust has over C++ (memory safety, thread safety, lacks of segfaults, refactoring without introducing errors, etc.). So you end up with 2 languages in your codebase, + a lot of glue boilerplate, for very little win.

If this is what you want, you are better off just sticking with C++ instead.

What Firefox, Servo, and any other good C++ project that cannot/does not want to review all C++ APIs does is to just write:

   extern "C" { fn foo(a: *mut c_int); }
instead. That's less code, and it is correct code. When a programmer needs to call foo, they need to write "unsafe { foo(a) }", and that often leads to them actually checking "foo"'s API docs, and explaining why the call is safe (maybe the assert is not needed because a cannot be null. The burden of doing the work is on the caller.

Firefox and Servo heavily use `rust-bindgen`, which will automatically generate all these FFI wrappers with a correct ABIs for you. The main difference is that rust-bindgen does not attempt to falsely convey the idea that these APIs are safe to call.

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
I know how cxx works, and I am not misrepresenting anything.

cxx is currently unsound, and the author (dtolnay) has chimed in above with a fix they are considering that fixes it (https://news.ycombinator.com/item?id=24244121)

The API of the cxx crate is safe, and it can cause UB, therefore it is unsound.

It doesn't matter that the cxx crate API is a macro. Yes, this macro expands to unsafe code like you mention, but the problem is that this unsafe code is often "broken" (unsound).

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
> There is no debate about this.

Of course there is, for example, the offset_of! macro was unsound for a long time:

* https://internals.rust-lang.org/t/pre-rfc-add-a-new-offset-o...

* https://github.com/rust-lang/unsafe-code-guidelines/issues/1...

* https://github.com/rust-lang/unsafe-code-guidelines/issues/2...

* https://github.com/rust-lang/rust-memory-model/issues/35

> You didn't really answer my question.

I literally wrote "No.". To your follow up questions starting with "If so ..." i did not reply, because the assumption these questions were based on (that I would reply to the previous question with "yes") did not hold.

To expand on this. Rust does not have "unsafe macros", so all exported macros must be sound. Whether a macro is sound or not is orthogonal to whether the macro itself uses `unsafe` (and your original claim was whether I thought that macros containing unsafe should be rejected by the compiler, to which I replied "No.", `pin_mut!` is an example of a macro that uses `unsafe` and is sound).

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
> Do you think that macros should treat unsafe blocks in their body as a compiler error?

No. Exported macros (as opposed to private ones) are only sound if they do not allow safe Rust to introduce undefined behavior.

Whether these macros use "unsafe" internally or not is irrelevant. For example, `pin_mut!` uses unsafe internally, but it does not allow safe Rust calling it to introduce UB.

A macro that allows safe Rust to introduce undefined behavior is unsound. An example of such an unsound macro would be `offset_of!`.

---

That is, I do not differentiate Rust abstractions when it comes to soundness. Whether its a function, a trait method, a macro, or a function pointer, it does not matter. If an abstraction its safe to use it shall not introduce UB. If it does, it is an unsound abstraction.

fluffything··on AutoCXX: Safely call C++ from Rust with auto generated bindings
> This assertion is always performed in safe Rust code.

Safe Rust code performs these assertions by using the "unsafe" keyword. This library API allows safe Rust to perform these assertions _without_ writing "unsafe".

That's the problem.

← PreviousPage 6 of 31Next →