> Если проблему с памятью можно ещё как-то решить придумав Rust, то остальные 95% сами себя не смогут излечить."Сами себя" не смогут. Но если ты приложишь чутка усилий, то ты сможешь заставить своих программистов не совершать ошибок типа "забыл проверить входящие данные". Система типов ведь для специально для этого и дана, чтобы описывать в ней требования по работе с данными.
У тебя есть два варианта, либо создать тип Checked<T>, либо тип Unchecked<T>. За каждым из типов прячутся разные стратегии. За первым -- отказываться работать с T, если он не был завёрнут в обёртку Checked -- но это надо переделать все API за которыми прячется код работающий с T. За вторым -- заворачивать все входящие T в Unchecked<T>, и обрезать все возможности для программиста добраться до T, кроме как вызвав метод Unchecked::check(&self) -> &T. Этот вариант не требует кардинальных изменений API, но надо будет отследить все места, где данные входят в программу.
Есть ещё подход -- принудительно проверять всё в момент создания T, и это хорошо, но ровно до тех пор, пока у тебя нет возможности столкнутся со 100500 инстансами T, из которых реально нужны лишь парочка. Раст, кстати, так делает со строками: он проверяет валидность utf8-строк на входе, программер может отложить эту проверку на потом, жонглируя &[u8] слайсами, но ежели он хочет API для работы с черектерами и строками из них, ему придётся вызывать конструктор str, а тот проверит валидность utf8.
Твои проблемы решаются даже без раста, если по-хорошему. И они решались ещё до появления раста именно таким образом. Я подцепил идею, по-моему, из cl-sql, который давал API для сборки строк SQL-запросов, при этом проверял и экранировал все непроверенные/неотэкранированные ещё строки, при этом не проверяя и неэкранируя то, что не нужно экранировать.