Ответ 1
Он имеет несколько применений. Он может использоваться для функций, предназначенных для паники или выхода из программы. panic!()
сама по себе является одной из таких функций, но ее также можно применять к функциям, которые обертывают panic!()
, например, распечатывают более подробную информацию об ошибках и затем паникуют.
Он также может использоваться для функций, которые никогда не возвращаются. Если функция переходит в бесконечный цикл, такой как основной цикл сервера и, таким образом, никогда не возвращается, его можно определить таким образом.
Другим возможным применением будет обертка вокруг семейства функций Unix exec
, в котором текущий процесс заменяется на тот, который выполняется.
Полезно иметь такой тип, потому что он совместим со всеми другими типами. Чтобы быть безопасным по типу, Rust должен обеспечить, чтобы все ветки оператора match
или if
возвращали один и тот же тип. Но если есть какие-то ветки, которые недоступны или указывают на ошибку, вам нужно каким-то образом выбросить ошибку, которая будет унифицирована с типом, возвращаемым другими ветвями. Поскольку !
объединяется со всеми типами, его можно использовать в любом таком случае.
Существует интересный RFC (и обсуждение) на данный момент, который утверждает (частично) для расширение мест, где !
можно использовать, утверждая, что его следует рассматривать как полноценный тип типа ()
is; !
является типом без значений, которые объединяются со всеми другими типами, тогда как ()
является отдельным типом с одним значением. Я не уверен, что согласен с полным RFC, но обсуждение обработки !
как полноценного типа интересно, и я думаю, что это может быть предложено отдельно от остальной части RFC.
Обновление. Поскольку я написал выше, часть RFC о продвижении !
к полноценному типу была split в отдельный RFC и объединяется, и в процессе реализации (в настоящее время доступно в ночных сборках за функциональным затвором). Как полнофункциональный тип, его можно использовать в большем количестве контекстов, например, в Result<T, !>
, указывающем результат, который никогда не может потерпеть неудачу, или Result<!, E>
как тот, который никогда не сможет преуспеть. Они полезны в общих контекстах; если у вас есть какая-то черта, требующая метода для возврата результата, но для этой конкретной реализации это может быть только возможно, вам не нужно заполнять какой-либо фиктивный тип ошибки.