If you are thinking about general programming tasks, then I don't think Rust is "bad" at doing any of them. The language is designed to be correct, safe, and fast; the build system is sensible, and dependency management is easy and robust. There are libraries under active development for several areas, including "the web", whatever that means to people – templating libraries, HTTP clients/servers, database management, you name it. Rust has probably the smoothest WebAssembly support for its league.
I have no idea why people keep mentioning "prototyping"; there is no such thing as prototyping. It will end up in production anyway, because no management will ever acknowledge that they need to burn money to build the whole system all over again because of CoDE QUaLiTy and similar purely academic (in their eye) needs.
If you are thinking about areas outside of the tasks of most software engineers, then yeah, Rust won't fulfill the role of specialized DSLs, for example. You probably won't be able to perform interactive theorem proving in the way you would in Agda or Coq or Prolog. You wouldn't use Rust directly to write CSS. You can't use it as a drop-in replacement for a children's visual programming environment. You won't query a SQL database directly using Rust.
So there are non-goals, and unsurprisingly, there are better specialized languages for purposes that Rust isn't even trying to work for. But listing them is probably an exercise in futility. You shouldn't be asking yourself (and us), "what's the wrong tool for this job?", you should be asking what the right tool is.
Things that would usually be done with named arguments can be somewhat troublesome to provide. I still have not found a pattern that is always suitable, and it mostly depends on a case-by-case decision which pattern(s) seem to work best (struct with pub fields, one of the various builder patterns, or macros).
It's hard to write plugin systems in Rust. I imagine something like Spring Boot, which allows to dynamically construct your application from separate components linked via an xml manifest, would be also very hard to write. I don't think a system like that is reasonable without a garbage collector.
Anything which uses self-referential types is hard to impossible to do in Rust (, and there are various soundness issues with those solutions). In particular, if you are trying to reproduce an OOP arbitrary graph of objects, then you are in for big trouble. This also includes various types of callback-based interfaces, where you pass around handler functions with unclear captures and life cycle. It is a separate question whether such architecture is a good thing to reproduce. It's extremely popular in GC-based languages, but there are valid arguments against, and Rust likely can solve the same problems via a different approach. ECS-based solutions are currently popular both in games and in GUI applications.
One thing I struggled with was that I wanted to write an xhtml and html5 generation library that would mimic the behavior of an existing library. We have a stack of libraries for dynamically generating pages. At the very bottom I wanted to model the different element types, and I also wanted to constrain adding child elements based on their proper context (i.e. statically well-formed and mostly-valid documents).
This is one of those cases where inheritance can be very helpful, and the old code used inheritance.
My rewrite-in-Rust strategy has largely been to first do a "straight" port, then focus on properly Rustifying it afterwards. This project taught me that there are cases where this is just a massive waste of time. Our new solution looks nothing like the original, but I'm happy with it.
With regards to prototyping: I find Rust to be very ergonomic for prototyping. The thing that makes a language prototype-friendly to me is, roughly in order:
No manual resource management (free memory, closing files, etc).
It has ergonomic collections for vectors (Vec<T>), sets (HashSet) and maps (HashMap).
It has good support for print formatting.
Project management is easy (adding new files to the project, pulling in dependencies, etc).
Rust fulfills all of these criteria, and in addition it makes refactoring (which tends to happen a lot when I prototyping) less scary.
If your plugin system is not designed to run untrusted code then Rust is perfectly capable (although lack of stable ABI hinders it a bit).
That's why there are so much talks about WASM: it promises safe plugin system, finally (and works well with Rust from what I have heard).
Ohh, forgot about these. That's true. It's also hard to write unstructured code with arbitrary GOTOs which go from the middle of one routine point to another.
IMNSHO that's an advantage, not deficiency. OOP is not needed for small projects and I'm yet to see any big project which haven't ended up with memory leaks unless it employs rigid Rust-like ownership system. At which point translation it to Rust is trivial.
Yeah. That's how simple UI with three knobs like track.net may consume gigabytes of RAM if you don't close the tab for the night.
Often it's pretty easy to solve the “business task”, but if you want similar API… you are in trouble.
It's structural programming all over again! Just this time with data, not code.
Yes. That's both advantage and disadvantage of Rust. Because it's so hard to write any other language in Rust it becomes much easier to read someone's else code in Rust (it's all similar and uses similar idioms), but it's endless source of initial frustrations.
If that happens then think seriously about your design again. Because very often it's sign that you production code is designed wrongly.
Like: my code have hardcoded database name but I want to mock it for test to make sure tests wouldn't ruin user's code.
No: it's not the time to think about mocking, but time to think about how you can ensure database name can be specified in production, too! Hardcoding it is bad practice and it would bit you, sooner or later.
The strong type system means Rust is really bad at those once-off hacky scripts you throw together in a Jupyter notebook for exploration or a temporary fix.
A couple weeks ago, I needed to take some data from a spreadsheet on Google Sheets and upload it to an in-house website for a particular event. This involved reading in a CSV, doing a bunch of selecting and manipulation to get the arguments in the right form, then sending a POST request to the website.
With Python, I spent longer reverse-engineering how the website's frontend communicated with the backend than I did writing the data manipulation code. In this case, the lack of static typing, the introspectability you get from a REPL/notebook, and not needing to deal with async/await meant I could be sloppy and just get the job done... Which was good, because I ended up hacking this together about 4 hours before the event.
Yeah, forgot about this. Rust is terrible for scripting. Technically there is evcxr, but my experiments with using it ended up with a strong determination never to use it again. For example, Rust's great type inference, which derives types from both function arguments and result usage, can't work when there are no uses of result because the following lines are not yet written. Neither is the boilerplate of all basic trait implementations (Debug, Clone, Ord etc) acceptable in a scripting interactive environment. Or the explicit typing of all function signatures.
You might want to look into F# for tasks where you want the dynamism/interactivity of Python but with static, but heavily inferred, typing. Can also run in REPL/Jupyter Notebooks. It shares some syntactical and feature similarity with Rust, being ML-based.
One of its secret weapons is Type Providers. E.g., you can read in data from a csv file and it strongly infers the types, complete with IntelliSense and completion, from the column data. Ditto for operations such as web page scraping.
Computations (Fortran will always be the best), scripting (Rust is really not suitable for scripting), GUI (we don’t have an ultimate framework for all platforms yet) and there’s a lack of metaprogramming IMHO (Rust is still one of the best in it tho).
P.S. I didn’t mean that Rust is bad at something, I meant that not all the tools that Rust ecosystem needs are built yet.
I get your point, that temporary software solutions often last longer than anticipated and turn into technical debt, but I think it's far too strong to say that "there is no such thing as prototyping". I worked a bit with some hardware prototypes a while back, and it's quite common to hack up some quick Python scripts to test the wire interface of poorly-documented or otherwise unintuitive hardware.
These scripts often stick around, collecting dust in an abandoned repo, but they're (by their construction) very difficult to integrate into the final software stack, and just reimplementing the protocol using the obtained knowledge is often the simpler option. Perhaps this goes back to the distinction between "prototyping" and "experimenting"; we could be using the same term to refer to different things.
Hardware prototypes are very different. They don't suffer from the iceberg secret. I dealt with quite a few hardware prototypes and none of them looked beautiful. Most of them looked downright ugly.
That one part is incredibly important and extremely under-appreciated by programmers:
If you show a nonprogrammer a screen which has a user interface which is 100% beautiful, they will think the program is almost done.
Businesses are ready to invest plenty into making something good, but you have to show them that their investment is well-spent.
If your prototype works but looks ugly — you would get budget to make it beautiful, if you would show prototype which looks beautiful — businessperson would start preparing sales booklets.
There's hilarious story when Steve Ballmer organised extremely clever and impressive sales campaign for Windows.
In year 1983.
When Windows was ready to ship in 1985.
And Microsoft lost smartphones market for the exact same reason 40 years later.
When your boss is Bill Gates you can get away with showing the exact some presentation after year of development — where first one was “smoke and mirrors make-believe” and second one was “now OLE works like we promised” (also true story, apparently).
But when you boss is normal person with no programming background you have to ensure GUI completeness matches project completeness. You can even get away with making GUI worse than everything else (although this may prompt questions of where money have went), but never, just never-never make it better.
And then prototypes stay prototypes.
It's just so very hard to do with software, temptation to finish GUI and then start doing everything else is just so tempting…