This has been my experience also. I've written at least 40kloc of rust over the past couple years (including complex graphs with cycles, low-level DSP) and I could probably count the number of unsafe blocks I've needed on one hand.
Excluding FFI I might just be able to count the number on unsafe blocks I’ve needed on one hand. But honesty compels me to declare that for reasons of performance micro-optimisation, I’ve written a lot more.
I tend to use petgraph[1] when I need a graph-like data structure (the only time I've needed cycles). Super fast, distinguishes `Node`s from `Edge`s, lots of useful items for different kinds of traversal.
stdlib has plenty of unsafe blocks inside it, as do many crates. Claiming one doesn't use unsafe blocks because none are visible in one's lib.rs or whatever doesn't mean they aren't there.
If you're going to consider unsafe blocks in other libraries (and especially the standard library) as just as "bad" as ones in your own, you have to include the compiler itself too ("oh your compiler generates machine code, that's unsafe!!!"). This logic of course applies to every language, as everything bottoms out in machine code/hardware, and thus it is a fairly uninteresting point.
The power of Rust is the ability to wrap dangerous code into safe abstractions without cost, and unsafe blocks are essentially a flag for "this is dangerous, make sure it's contained".
I think of libstd as basically what would be part of the compiler or runtime in other languages. In some languages (e.g. Go), things like hash maps are in the language and implemented directly with unsafe code, and nobody thinks the language is less safe because of it.
Every language that exists, compiled or interpreted, typed or untyped, ultimately relies on code which could violate every guarantee that language makes. Most often, that code is written in C or C++, and is a part of the language's runtime or compiler toolchain.
There's certainly a difference between writing one's own unsafe blocks and relying on functionality which was implemented using unsafe in a community project (which has hopefully been vetted by some community members).
Most projects use c bindings; it's not unfair to say that the quality of many of the c bindings on crates.io doesn't match the quality of stuff in the standard library.
(ie sure, maybe you're not writing unsafe yourself, but you'll quite possibly hit an issue where you have to dig into a crate that does)
edit: This is not counting FFI though.