I think the most classically cited problem is the learning curve. Understanding ownership and lifetimes, and understanding how to satisfy the borrow checker can be quite daunting.
Here are a few that I think about personally and which are probably a little more unusual to see:
* Batteries not included: the standard library's been pretty stripped down in favor of moving things out into external crates. The justification is that packages included in the standard library tend to ossify and become liabilities as they outlive their usefulness [1]. I buy the argument, but am a little worried that it's going to result in a fractured ecosystem where even extremely common functions like HTTP don't have "one true path" so we get a dozen different packages that try to handle it.
* Tunnel vision focus on Tokio: to my eye the community seems a little obsessed with Tokio and zero-cost futures. It's really nice how performant it is, but I'm not crazy about how futures-based concurrency spreads into your code through huge amounts of necessary boilerplate (`.and_then(...).and_then(...).and_then(...)`). I think that for most cases where performance is not an absolute mission critical necessity, a light runtime that manages asynchronous operations for you (say like Go's) is probably the way to go because it unlocks far better productivity. I'm cautiously optimistic about the possible inclusion of something like an `await/async` construct.
How is that more boilerplate than any other way to have concurrency?
To give one specific example, WinRT uses futures, and there you can write async code that flows from C++ through C# to JavaScript and back, with mapping to a common ABI type done transparently at the interop layers (https://docs.microsoft.com/en-us/uwp/api/windows.foundation....).
If and when we standardize on a higher-level ABI that includes fibers or something similar, then the other approach might make more sense. Of course, the problem is that there isn't a single consensus design to standardize on...