Справочник отказов
Компилятор отказывает кодом. Код всегда стоит первым словом строки:
FLANG_TYPE в файле type.flang, строка 6, столбец 3: функция «Удвоить» объявлена как число, а тело даёт строка
Найдите свой код на этой странице: одна строка «что это значит», одна «что делать». Коды сгруппированы по слою, на котором отказ рождается: пока не пройден разбор, до типов дело не дойдёт, а пока не сошлись типы — до доказательств.
Коды возврата: 0 — проверено, 1 — есть замечания, 2 — кривой вызов.
Три ловушки, которые стоят дня
Прочитайте их до того, как начнёте искать свой код. Каждая даёт отказ не там, где ошибка.
Постусловие, зовущее функцию своего же модуля, ломает тех, кто ввозит модуль списком
Файл зелёный у себя. Ввозящий падает.
// ядро.flang
модуль «Ядро»
тотальная функция «Двойка»
принимает н: число
возвращает число
н умножить на 2
тотальная функция «Учтено»
принимает н: число
возвращает число
обеспечивает «не меньше двойки» результат не меньше («Двойка» от н)
(«Двойка» от н) плюс 1
// ввоз.flang
модуль «Ввоз»
использует «Ядро» только «Учтено»
тотальная функция «Проба»
принимает н: число
возвращает число
«Учтено» от н
flang check ядро.flang
модуль «Ядро»: функций 2, из них с доказанным завершением 2; типов 0
ядро.flang: проверено — разбор, типы, завершаемость, ядро и примеры; замечаний нет
flang check ввоз.flang
модуль «Ввоз»: функций 2, из них с доказанным завершением 0; типов 0; файлов вместе с импортами 2
без доказанного завершения: «Учтено» «Проба»
FLANG_UNKNOWN_NAME, строка 12, столбец 4: неизвестная функция «Двойка»
FLANG_UNKNOWN_NAME, строка 11, столбец 50: неизвестная функция «Двойка»
FLANG_NOT_TOTAL, строка 12, столбец 4: тотальная функция «Учтено» вызывает неизвестную функцию «Двойка»: завершение доказать нельзя
ввоз.flang: не проверено — замечаний 3
Ввоз только «Учтено» приводит одно имя. Тело и постусловие «Учтено» зовут «Двойку», которой в ввозящем нет. Столбец 50 указывает внутрь постусловия — строка та же, что и в исходном модуле, а файл не назван: проверено два файла.
Что делать — одно из трёх:
| приём | как |
|---|---|
| привести спутника | использует «Ядро» только «Учтено», «Двойка» |
| ввезти модуль целиком | использует «Ядро» |
| убрать вызов из постусловия | сказать то же арифметикой: результат не меньше (н умножить на 2) |
Зелёный вывод не значит, что утверждения доказаны
flang check без ключей проверяет разбор, типы, завершаемость и примеры. Постусловие, которое он не сумел ни доказать, ни опровергнуть, он пропускает молча. Постусловие «меньше двойки» из примера выше ложно — файл зелёный.
Спрашивайте прямо:
flang check ядро.flang --proof
постусловие «меньше двойки» функции «Учтено» — объявлено, не доказано: ни теоремы, ни примеров. Его считает рантайм после каждого возврата — на тех входах, которые придут
Читайте слова буквально: «доказано» — обо всех входах; «сетка N» — посчитано на N значениях, доказательством не является; «объявлено, не доказано» — утверждение высказано, за ним ничего нет.
И второе: пока в проверке стоит FLANG_UNKNOWN_NAME, функция теряет обещание тотальная и её утверждения не доказывает никто. Сначала имена, потом всё остальное.
FLANG_BOUND_ON_NAN: «не число» живёт в типе число и стоит вне порядка
Самый частый ложный испуг. Утверждение выглядит очевидно верным, а ядро отвечает контрпримером.
модуль «Проба»
тотальная функция «Прибавить один»
принимает н: число
возвращает число
обеспечивает «результат больше довода» результат больше н
н плюс 1
FLANG_BOUND_ON_NAN в файле nan.flang, строка 6, столбец 3: постусловие «результат больше довода» функции «Прибавить один» ЛОЖНО, и контрпример назван: «н» объявлен типом «число», а «не число» живёт в этом типе и стоит ВНЕ ПОРЯДКА — оно не больше и не меньше ничего, включая самоё себя.
Причина: тип число содержит «не число», всякая арифметическая операция его переносит, а сравнение с ним ложно в обе стороны. Утверждение о порядке над сырой арифметикой поэтому неверно.
| починка | что писать | кто платит |
|---|---|---|
| сузить тип входа | принимает н: неотрицательное или целое | никто, «не число» не втащить |
| поставить предусловие | требует «вход есть число» (н минус н) равен 0 | вызывающий |
| оговорить границу в самом утверждении | обеспечивает «…» не ((н минус н) равен 0) или (результат больше н) | никто |
Разбор
| код | что значит | что делать |
|---|---|---|
FLANG_LEX | слово не собралось: не закрыта кавычка, чужой знак | закройте кавычку, уберите знак |
FLANG_PARSE | слова разобраны, конструкция — нет | смотрите строку и столбец: чаще всего нет ветки иначе или у функции два тела |
модуль «Проба»
тотальная функция «Удвоить»
принимает н: число
возвращает число
если н больше 0 то н умножить на 2
FLANG_PARSE в файле parse.flang, строка 7, столбец 1: у 'если' нет ветки 'иначе'
FLANG_LEX в файле lex.flang, строка 5, столбец 3: не закрыта кавычка
Имена и ввоз
| код | что значит | что делать |
|---|---|---|
FLANG_UNKNOWN_NAME | имя не связано: нет такой функции или переменной | объявите её, ввезите модуль или проверьте написание |
FLANG_AMBIGUOUS_NAME | имя приводят два ввоза сразу | оставьте один ввоз или сузьте его списком только |
FLANG_BAD_NAME | имя не годится по правилам записи | переименуйте: имя функции — в кавычках-ёлочках, параметр — словом |
FLANG_NAME_TAKEN | имя занято другим объявлением | дайте другое имя |
FLANG_DUPLICATE_NAME | одно и то же имя объявлено дважды в одном месте | уберите второе объявление |
FLANG_IMPORT_NOT_FOUND | модуль не найден | проверьте имя модуля и то, что файл лежит рядом или выше по каталогам |
FLANG_IMPORT_CYCLE | модули ввозят друг друга по кругу | вынесите общее в третий модуль |
FLANG_IMPORT_AMBIGUOUS | одно имя приходит из двух модулей | сузьте ввоз списком только |
FLANG_IMPORT_NAME | в списке только названо имя, которого в модуле нет | сверьте список с объявлениями модуля |
модуль «Проба»
тотальная функция «Удвоить»
принимает н: число
возвращает число
«Утроить» от н
FLANG_UNKNOWN_NAME в файле unknown.flang, строка 6, столбец 3: неизвестная функция «Утроить»
FLANG_NOT_TOTAL в файле unknown.flang, строка 6, столбец 3: тотальная функция «Удвоить» вызывает неизвестную функцию «Утроить»: завершение доказать нельзя
Незнакомое имя всегда тянет за собой второй отказ про завершаемость. Чините первый — второй уходит сам.
Если имя написано как действие, компилятор скажет об этом прямо:
FLANG_UNKNOWN_NAME в файле pr4.flang, строка 10, столбец 14: имя «м» не связано: имя вводят 'принимает', 'пусть' или образец 'случай'; а действия языка ('плюс', 'минус', 'умножить на', 'делить на', 'остаток от') пишутся МЕЖДУ значениями — «3.14 умножить на р», а не «умножить 3.14 на р»
Типы
| код | что значит | что делать |
|---|---|---|
FLANG_TYPE | объявленный тип разошёлся с тем, что даёт тело или довод | приведите одно к другому |
FLANG_TYPE_ARGS | типу даны аргументы, а он их не принимает | уберите аргументы: типы в языке не параметрические |
FLANG_TYPE_PARAM | параметр типа не связан | назовите тип целиком |
FLANG_APPLY | вызов не сходится: не то число доводов или зовут не функцию | сверьте вызов с подписью |
FLANG_BUILTIN_ARGS | встроенному действию дали не столько доводов | сверьте с описанием операции |
FLANG_MATCH_NOT_EXHAUSTIVE | разбор покрывает не все случаи | допишите недостающий случай |
FLANG_MATCH_UNREACHABLE | случай перекрыт предыдущим и никогда не сработает | уберите его или переставьте выше |
FLANG_EXAMPLE | пример не сошёлся с ожидаемым | почините тело или ожидание |
FLANG_TYPE в файле type.flang, строка 6, столбец 3: функция «Удвоить» объявлена как число, а тело даёт строка
FLANG_TYPE в файле dup.flang, строка 8, столбец 1: функция «Удвоить» объявлена дважды
FLANG_MATCH_NOT_EXHAUSTIVE в файле match.flang, строка 6, столбец 3: разбор списка не покрывает «пусто»
FLANG_EXAMPLE: пример «Двойка» функции «Удвоить»: значение не совпало с ожидаемым: ожидалось 5, получено 4
Завершаемость и пределы
| код | что значит | что делать |
|---|---|---|
FLANG_NOT_TOTAL | функция объявлена тотальная, а завершение не доказано | передавайте в рекурсию ЧАСТЬ довода, а не пересчитанное число |
FLANG_MEASURE | объявленная мера не убывает | поправьте убывает или сам вызов |
FLANG_RECURSION_LIMIT | при вычислении кончились шаги или глубина | поднимите --max-steps / --max-depth либо почините рекурсию |
FLANG_STEP_LIMIT | предел шагов кончился внутри примера | тот же ключ --max-steps |
FLANG_BUDGET_EXHAUSTED | кончился запас, отпущенный прогону | увеличьте запас или сузьте задачу |
FLANG_MEMORY | памяти не хватило | уменьшите данные прогона |
FLANG_STOPPED | прогон остановлен снаружи | перезапустите |
модуль «Проба»
тотальная функция «Считать»
принимает н: число
возвращает число
если н равно 0 то 0 иначе («Считать» от (н плюс 1))
FLANG_NOT_TOTAL в файле total.flang, строка 6, столбец 30: тотальная функция «Считать»: рекурсивный вызов «Считать» не убывает — аргумент 1 («н» add 1) увеличивает параметр «н». Передавайте часть аргумента: хвост списка из образца «голова и хвост», поле варианта из образца, поле записи или элемент коллекции
flang run rec.flang --function "Вниз" --args '{"н":100}' --max-steps 5
FLANG_RECURSION_LIMIT: функция «Вниз» исчерпала лимит шагов (5) на глубине вызовов 1
Утверждения и доказательство
Требования, обещания и теоремы.
| код | что значит | что делать |
|---|---|---|
FLANG_PROPERTY | постусловие нарушено при вычислении | утверждение или тело неверны — смотрите вход, на котором сорвалось |
FLANG_PRECONDITION | предусловие записано неверно | сверьте форму требует «имя» <утверждение> |
FLANG_PRECONDITION_CALL | вызывающий не снял предусловие вызываемой | докажите условие в месте вызова или сузьте тип довода |
FLANG_BOUND_ON_NAN | утверждение о порядке ложно из-за «не числа» | см. третью ловушку выше |
FLANG_PROOF | ядро не приняло доказательство | ниже — уточнённые коды FLANG_PROOF_* |
FLANG_PROOF_NO_GOAL | теорема ничего не закрывает: постусловия с таким именем нет | назовите теорему точно так же, как постусловие |
FLANG_PROOF_AMBIGUOUS | теорема закрывала бы сразу два постусловия | дайте постусловиям разные имена |
FLANG_PROOF_CLAIM_MISMATCH | утверждаем не совпало с постусловием слово в слово | скопируйте текст постусловия дословно |
FLANG_PROOF_DUPLICATE | одно постусловие доказывают две теоремы | оставьте одну |
FLANG_PROOF_STEP | шаг не обоснован или шагов нет вовсе | добавьте по свойству «…», по примеру «…» или по предположению |
FLANG_PROOF_UNFINISHED | доказательство не закрыто | допишите следовательно доказано |
FLANG_PROOF_UNKNOWN_VAR | в утверждении стоит несвязанное имя | введите его строкой дано |
FLANG_PROOF_VAR_TYPE | тип переменной теоремы разошёлся с типом параметра | приведите дано к подписи функции |
FLANG_PROOF_INDUCTION_TYPE | по этому типу индукции нет | индукция идёт по объявленной сумме или по отрезку неотрицательное |
FLANG_PROOF_INDUCTION_CASES | разобраны не все случаи принципа | допишите недостающий случай |
FLANG_PROOF_INDUCTION_BRANCH | ветвь случая не сведена к цели | обоснуйте ветвь |
FLANG_PROOF_INDUCTION_STEP | шаг не сведён к предположению | добавьте по предположению и приведите стороны знак в знак |
FLANG_PROOF_INDUCTION_DESCENT | спуск не строгий: шаг не на единицу | сведите шаг ровно к одному вниз |
FLANG_INITIAL_FAILURE | принцип по объявленному типу не породился | проверьте, что тип объявлен суммой вариантов |
FLANG_UNCOVERED_FAILURE | путь отказа не покрыт разбором | добавьте случай на отказ |
модуль «Проба»
тотальная функция «Удвоить»
принимает н: число
возвращает число
обеспечивает «удвоенное неотрицательно» если н не меньше 0 то (результат не меньше 0) иначе да
н умножить на 2
теорема «удвоенное неотрицательно»
дано н: число
утверждаем если н не меньше 0 то (результат не меньше 0) иначе да
следовательно доказано
FLANG_PROOF_STEP: теорема «удвоенное неотрицательно»: ни одного шага
FLANG_PROOF_NO_GOAL в файле pr1.flang, строка 9, столбец 1: теорема «удвоенное неотрицательно» ничего не закрывает: постусловия «удвоенное неотрицательно» нет ни у одной функции модуля. Теорема доказывает названное утверждение, а не утверждение вообще — назовите её так же, как постусловие, которое она закрывает
FLANG_PROOF_AMBIGUOUS в файле pa.flang, строка 15, столбец 1: теорема «неотрицательно» закрывала бы сразу 2 постусловия («Удвоить», «Утроить»), и выбрать нельзя. Дайте постусловиям разные имена
FLANG_PROOF_CLAIM_MISMATCH в файле pm.flang, строка 11, столбец 3: теорема «неотрицательно» утверждает не то, что обещает функция «Удвоить»: утверждение теоремы и постусловие обязаны совпадать слово в слово. Ядро не решает, что два разных утверждения означают одно и то же
Постусловие, пропущенное проверкой, считает рантайм:
flang run prop.flang --function "Половина" --args '{"н":0}'
FLANG_PROPERTY: нарушено свойство «результат меньше довода» функции «Половина»
Законы объявленных структур
Эти законы компилятор СЧИТАЕТ на конечной сетке значений автора, а не доказывает. Отказ означает найденное нарушение — контрпример есть всегда.
| код | какой закон нарушен |
|---|---|
FLANG_EQUALITY_NOT_REFLEXIVE | объявленное равенство не рефлексивно |
FLANG_EQUALITY_NOT_SYMMETRIC | не симметрично |
FLANG_EQUALITY_NOT_TRANSITIVE | не транзитивно |
FLANG_EQUALITY_NOT_CONGRUENT | композиция равенство не уважает |
FLANG_ORDER_NOT_REFLEXIVE | порядок не рефлексивен |
FLANG_ORDER_NOT_ANTISYMMETRIC | не антисимметричен |
FLANG_ORDER_NOT_TRANSITIVE | не транзитивен |
FLANG_CATEGORY_NOT_CLOSED | категория не замкнута под композицией |
FLANG_CATEGORY_NO_IDENTITY | у объекта нет единицы |
FLANG_CATEGORY_NOT_ASSOC | композиция не ассоциативна |
FLANG_COMPOSE_MISMATCH | у композиции не сходятся концы |
FLANG_MORPHISM_SHAPE | морфизм объявлен не так |
FLANG_FUNCTOR_NOT_TOTAL | функтор определён не на всех объектах |
FLANG_FUNCTOR_SQUARE | квадрат функтора не коммутирует |
FLANG_TRANSFORM_SHAPE | преобразование объявлено не так |
FLANG_TRANSFORM_COMPONENT | у преобразования не хватает составляющей |
FLANG_TRANSFORM_NOT_TOTAL | преобразование определено не на всех объектах |
FLANG_TRANSFORM_NOT_NATURAL | квадрат естественного преобразования не коммутирует |
FLANG_ISO_NOT_INVERSE | стрелки круга не обратны друг другу |
FLANG_EMBED_SHAPE | вложение объявлено не так |
FLANG_EMBED_NOT_INJECTIVE | вложение склеивает разные значения |
FLANG_MONOID | объявление моноида неполно |
FLANG_MONOID_ASSOC | действие моноида не ассоциативно |
FLANG_MONOID_IDENTITY | единица моноида не единица |
FLANG_GROUP_INVERSE | обратный элемент не обратен |
FLANG_MONAD | объявление монады неполно |
FLANG_MONAD_ASSOC | связывание не ассоциативно |
FLANG_MONAD_LEFT_UNIT | левая единица не выполняется |
FLANG_MONAD_RIGHT_UNIT | правая единица не выполняется |
FLANG_NOT_COMMUTATIVE | объявленная коммутативность нарушена |
FLANG_NOT_DISTRIBUTIVE | дистрибутивность нарушена |
FLANG_NOT_IDEMPOTENT | идемпотентность нарушена |
FLANG_NOT_MONOTONE | монотонность нарушена |
FLANG_MEET_NAME_TAKEN | имя множества уже занято |
FLANG_MEET_NO_UNIVERSE | у объявленных множеств нет общего носителя |
FLANG_MEET_SAME_SIDE | пересечение объявлено множества с самим собой |
FLANG_MEET_TWICE | одна и та же пара объявлена дважды |
Поручения и ввод-вывод
Отказы команды flang io. План возвращает ОПИСАНИЕ действия, а делает его хозяин; коды семейства FLANG_IO_* говорят, что хозяин делать отказался.
| код | что значит | что делать |
|---|---|---|
FLANG_PLAN | план объявлен неверно | сверьте форму плана |
FLANG_UNKNOWN_PLAN | плана с таким именем в файле нет | назовите существующий: --plan 'Имя' |
FLANG_PLAN_UNSUPPORTED | поручение этого вида прогонщик не исполняет | замените поручение или прогоните версией, где оно есть |
FLANG_IO_NO_HOST | хозяина нет: поручение отдавать некому | запускайте через flang io, а не вычислением функции |
FLANG_IO_NOT_TEXT | текстовое чтение встретило не текст | читайте октетами |
FLANG_IO_UNSUPPORTED | полномочие снято ключом или действие не поддержано | верните полномочие: без --no-read, --no-write, --no-net и прочих |
FLANG_LOCK | замок испорчен или не сходится печатью | пересоберите замок |
FLANG_PACKAGE | пакет испорчен: перечень не сходится с содержимым | пересоберите пакет |
Полномочия сужаются по одному, умолчание — «можно всё»:
flang io план.flang --plan 'Разбор' --no-net --in-dir
Процессы
| код | что значит | что делать |
|---|---|---|
FLANG_PROCESS | процесс объявлен неверно | сверьте объявление процесса |
FLANG_PROCESS_ACCEPTS | процессу пришло сообщение, которого он не принимает | допишите вид сообщения в принимает |
FLANG_PROCESS_LIMIT | упёрлись в предел числа процессов | поднимите предел или порождайте меньше |
FLANG_MAILBOX_FULL | ящик переполнен: читатель не успевает | читайте чаще или ограничьте отправителя |
FLANG_LINK_DOWN | связь с узлом или процессом разорвана | обработайте разрыв в надзоре |
FLANG_CONC_UNSUPPORTED | эта возможность процессов не поддержана | см. страницу о процессах |
FLANG_HOTSWAP_REFUSED | горячая замена кода отклонена | подгоняйте новый код под прежние объявления |
Командная строка и внутреннее
| код | что значит | что делать |
|---|---|---|
FLANG_CLI | вызов кривой: непонятный ключ или нет довода | flang <команда> --help |
FLANG_INTERNAL | сломался сам компилятор | сообщите об этом: это отказ инструмента, не программы |
FLANG_SELF_EVAL_UNSUPPORTED | форма вне того, что умеет вычислять этот путь | вычисляйте обычной командой flang run |
FLANG_SELF_REPL_UNSUPPORTED | оболочка эту форму не принимает — например, использует | положите код в файл и проверьте flang check |
FLANG_FACTCHECK_НЕТ_ОТВЕТА | проверке фактов не дали ответа вычислителя на вызов | дайте ответ в наборе фактов |
flang check --неткого
flang check: непонятный ключ «--неткого»
Код возврата — 2.
Дальше: Ядро отказало: чья это ошибка — как читать отказ доказательства и когда виноват не автор.