Системы статических типов являются разновидностью статического анализа, но есть много статических анализов, которые обычно не кодируются в системах типов. Например:
Проверка модели - это метод анализа и проверки для параллельных систем, который позволяет вам доказать, что ваша программа хорошо себя ведет при всех возможных чередованиях потоков.
Анализ потока данных собирает информацию о возможных значениях переменных, которые могут определить, являются ли некоторые вычисления избыточными или какая-то ошибка не учитывается.
Абстрактная интерпретация консервативно моделирует эффекты программы, обычно таким образом, что анализ гарантированно прекращается - проверки типов могут быть реализованы аналогично абстрактным интерпретаторам.
Логика разделения - это логика программы (используемая, например, в анализаторе Infer ), которую можно использовать для рассуждения о состояниях программы и выявления проблем, таких как разыменование нулевого указателя, недопустимые состояния и утечки ресурсов.
Контрактное программирование - это средство указания предварительных условий, постусловий, побочных эффектов и инвариантов. Ада имеет встроенную поддержку контрактов и может проверять некоторые из них статически.
Оптимизирующие компиляторы выполняют много небольших анализов, чтобы создать промежуточные структуры данных для использования во время оптимизации, такие как SSA, оценки затрат на встраивание, информацию о парах команд и так далее.
Другой пример не декларативного статического анализа можно найти в проверке типов Hack , где обычные конструкции потока управления могут уточнить тип переменной:
$x = get_value();
if ($x !== null) {
$x->method(); // Typechecks because $x is known to be non-null.
} else {
$x->method(); // Does not typecheck.
}
И если говорить об «уточнении», то назад в мире систем типов уточненные типы (используемые в LiquidHaskell ) объединяют типы с предикатами, которые гарантированно сохраняются для экземпляров «уточненного» типа. И зависимые типы идут дальше, позволяя типам зависеть от значений. «Привет мир» зависимой типизации обычно является функцией конкатенации массива:
(++) : (a : Type) -> (m n : Nat) -> Vec a m -> Vec a n -> Vec a (m + n)
Здесь, ++
принимает два операнда типа Vec a m
и Vec a n
, будучи векторы с типом элемента a
и длиной m
и , n
соответственно, которые являются натуральными числами ( Nat
). Возвращает вектор с тем же типом элемента, длина которого равна m + n
. И эта функция доказывает это ограничение абстрактно, не зная конкретных значений m
и n
, поэтому длины векторов могут быть динамическими.