Блог им. AndrewBotDeveloper
Суперкомпиляторы призваны исправить бесчисленные ошибки, которые программисты, занимающиеся искусственным интеллектом, до сих пор допускают в реальном программном обеспечении, используемом в промышленной эксплуатации.

В программировании началась новая битва, и, похоже, очень немногие заметили, насколько сильно она может изменить будущее программирования искусственного интеллекта.
Продолжайте читать, и вы недолго останетесь в их числе.
Системы программирования и компиляторы для искусственного интеллекта движутся в одном направлении, но в противоположных направлениях.
Они по-прежнему работают с одними и теми же языками программирования. Программист с искусственным интеллектом может, например, генерировать функции C++26, такие как контракты, концепции, код рефлексии или аннотации, точно так же, как и разработчик-человек.Но именно компилятор знает, что что всё это означает, как всё это взаимосвязано и когда код просто неверен.
Если по ходу чтения захочется быстро разобрать сложную техническую мысль или подобрать формулировку для собственного текста, можно держать под рукой ИИ-помощника в Telegram — удобно задать вопрос прямо в мессенджере и вернуться к статье.
Примечание: C++ — не единственный язык, который так делает. Rust, Swift и Zig играют в свои собственные версии той же игры: дают компилятору больше информации, которую программисты раньше хранили в комментариях, соглашениях, документации или, что хуже всего, в своей голове. Разные языки, разные уловки, одна и та же идея: если компилятор может это увидеть, вам больше не нужно запоминать эту чертову штуку самостоятельно.
Важно не то, что ИИ может записывать эти функции, а то, что компилятор сможет с ними сделать впоследствии.
Безусловно, C++ становится богаче. Но самое интересное заключается в том, что компилятор теперь может делать больше с тем, что ему говорит программист, вместо того чтобы оставлять все эти детали на усмотрение комментариев, соглашений и человеческой памяти.
В этом смысле компилятор начинает заходить на территорию, которую до недавнего времени мы связывали преимущественно с людьми или ИИ-ассистентами программистов.
Но не стоит путать: компилятор не превращается в искусственный интеллект. Он просто получает больше информации о смысле программы, поэтому может улавливать то, что раньше зависело от памяти программиста, помнящего каждую мелочь.
На первый взгляд, у ИИ, кажется, есть преимущество. Можно поставить перед моделью незнакомый код и спросить, что делает функция, откуда берется ошибка, почему тип «взрывается» или можно ли сгенерировать недостающую часть. Иногда это срабатывает на удивление хорошо.
Достаточно хорошо, чтобы начать думать: ну, может быть, программист, использующий ИИ, действительно понимает код.
Поэтому будьте внимательны, потому что здесь вступает в игру одно из важнейших отличий всей этой истории: несмотря на все эти всё более похожие на ИИ функции, проникающие в языки программирования, ИИ по-прежнему сталкивается с двумя совершенно разными проблемами:
Проверка уже существующего кода и генерация кода, которого нет. Второй вариант сложнее для программистов, работающих с ИИ. Для компилятора все гораздо проще, потому что ему не нужно гадать, что означает программа; он применяет правила языка к уже существующему коду.
Искусственный интеллект всё ещё может допускать некоторые ошибки в этой структуре, но, по крайней мере, у него есть конкретная отправная точка. Что касается генерации кода, то многое ещё предстоит продумать с нуля.
Анализ существующего кода → восстановление семантических фактов — по-прежнему затруднен, поскольку такие языки, как C++ и Rust, скрывают множество смыслов за видимым текстом. Модель может неправильно интерпретировать перегрузки, шаблоны, трейты, преобразования, времена жизни, заимствования или поток управления, и это лишь некоторые из наиболее очевидных проблемных мест. Но она всё ещё работает со структурой, которая уже существует.
Однако при генерации кода мы попадаем в совершенно другой мир. Рассмотрим:
Напишите функцию, которая возвращает среднее значение списка показаний датчиков.
Это звучит почти до смешного просто. Но ИИ всё равно должен решить, какой тип входных данных используется, являются ли данные собственными или заимствованными, что происходит, когда список пуст, какой тип накапливает сумму, что происходит при переполнении, как обрабатываются ошибки, можно ли выделить память, насколько универсальной должна быть функция, и все остальные мелочи, о которых в конечном итоге начинают беспокоиться разработчики на C++ и Rust.
Это не просто косметические изменения: они меняют саму программу.
Таким образом, генерацию кода можно представить следующим образом:
Запрос человека → недостаточно определённые требования → выбор недостающих семантических условий → сгенерированный код
Если запрос не определяет эти варианты, модель заполняет их, используя изученные шаблоны, знакомые API и предыдущие примеры. В худшем случае она просто придумывает вариант, который никогда не был указан. Он может сработать. А может скомпилироваться идеально, но все равно оказаться совершенно неподходящим для данной задачи.
Теперь давайте рассмотрим компилятор.
Искусственный интеллект по-прежнему может подсказывать, какой должна быть программа. Задача компилятора другая: он все лучше справляется с тем, чтобы говорить: хорошо, но если вы написали вот это, то эти правила действительно применимы.
Это означает, что компилятор сможет выполнять более сложные проверки: более сложные проверки, меньше скрытых предположений и меньше привычного для C++ ритуала, когда программисту приходится запоминать пятнадцать крошечных семантических ловушек, чтобы не изменить что-то здесь и случайно не сломать что-нибудь в нескольких других файлах.
Частично это преимущество обусловлено тем, что компилятору не приходится преодолевать тот же разрыв, что и программисту, работающему с ИИ, при преобразовании запроса от человека в формальный код. Помните старое проклятие ORM, когда объекты и таблицы базы данных почти совпадают, но никогда не идеально? В программировании для ИИ возникает аналогичное несоответствие.
Таким образом, короткая подсказка на английском языке, адресованная программисту, работающему с ИИ, может соответствовать множеству различных программ: некоторые из них допустимы, некоторые недопустимы, а некоторые совершенно легальны, но все же не соответствуют тому, что программа должна делать на самом деле.
В этом и заключается настоящая проблема: ИИ может создавать совершенно легальный код, но при этом ошибаться в выполнении задачи.
Очевидное решение — сделать запрос более подробным, добавив типы, граничные случаи, правила владения, поведение при возникновении ошибок, ограничения производительности и все остальное, что модели в противном случае пришлось бы угадывать.
Это работает, до определённого момента.
То, что казалось понятным запросом, превращается в минное поле вложенного контекста, который ИИ должен постоянно корректировать.

Когда в подсказке должны содержаться все скрытые правила, написание самой подсказки может стать сложнее, чем написание кода.
Чем точнее становится запрос, тем больше он начинает воспроизводить ту же формальную структуру, для непосредственного выражения которой был разработан язык программирования, за исключением того, что теперь он становится длиннее, менее точным и его легче неправильно понять. Именно поэтому в последнее время при разработке методов генерации кода всё чаще используют сложные структурированные спецификации, а не полагаются только на текстовый запрос.
Если вы часто работаете с идеями, кодом или техническими материалами, иногда выручает чат-бот с ChatGPT в Telegram: можно попросить его объяснить термин простыми словами или помочь наметить структуру, не переключаясь между десятком сервисов.
И тут вы вдруг понимаете, что тратите больше времени на описание программы на английском языке, чем потребовалось бы на написание важных частей кода самостоятельно, и возникает очевидный вопрос: если мне и так приходится объяснять всё это с такой точностью, почему бы мне просто не написать эту чертову программу на C++?
В этом и заключается ловушка.
Предполагалось, что эта подсказка спасет вас от программирования. А теперь вы программируете эту подсказку.
К настоящему моменту характер конкуренции между разработкой программного обеспечения для ИИ и компиляторами должен стать гораздо яснее.
В программировании для ИИ всё большее значение приобретают механизмы, придающие коду его формальное значение: репозитории, абстрактное синтаксическое дерево (AST), типы данных, диагностика компилятора, тесты, ограничения и, всё чаще, сам компилятор.
С другой стороны, компиляторы получают гораздо больше возможностей благодаря современным языкам программирования: более богатые системы типов, концепции, контракты, рефлексия, более строгие рассуждения на этапе компиляции, улучшенная диагностика, большая автоматизация и, в некоторых инструментальных цепочках, даже эвристические алгоритмы, основанные на машинном обучении.
Интересная возможность заключается в том, что ни одна из сторон не выигрывает, заменяя другую. Вместо этого, давление между ними порождает новую архитектуру.
Для ИИ самая сложная задача всё чаще заключается не в создании правдоподобного исходного текста, а в обработке всего семантического контекста, который исходный текст не объясняет напрямую.
Компилятор действует с совершенно иной позиции. Большая часть семантического механизма уже принадлежит ему: типы, разрешение перегрузок, ограничения, преобразования, шаблоны и правила, определяющие корректность программы.
Именно поэтому C++26 является таким полезным примером. Он предоставляет программисту больше способов напрямую выразить эту семантическую информацию, так что программа может более явно показать свою структуру, а компилятор может с ней больше работать.
C++26 — хороший пример того, с чего начинается путь к суперкомпилятору. Этот язык предоставляет компилятору более широкие возможности для представления, анализа и проверки семантики программы, приближая его к той гибкости, которая нам нравится в программировании для ИИ, сохраняя при этом гораздо более сильный контроль компилятора над сложной семантикой языка — именно там, где программисты, занимающиеся ИИ, всё ещё могут потерпеть сокрушительное поражение, когда реальный проект становится достаточно глубоким.
Важно не то, что компилятор однажды утром внезапно просыпается и превращается в искусственный интеллект. Этого не происходит. Он по-прежнему остается компилятором, и это различие имеет значение.
Меняется то, насколько много смысла программы мы можем вложить непосредственно в её содержание, вместо того чтобы оставлять его разбросанным по комментариям, соглашениям, документации, дублированному коду и всему тому, что программист вспомнит, работая уставшим посреди ночи.
C++26 развивает это направление дальше, используя такие вещи, как контракты и рефлексию, одновременно опираясь на уже имеющийся в C++ механизм, например, концепции и вычисление констант. В то же время, инструменты компилятора становятся всё лучше в плане демонстрации того, что компилятор уже знает, вместо того чтобы скрывать весь этот семантический механизм за одним жалким сообщением об ошибке и сотнями строк шаблонной археологии.
Контракты, рефлексия, оценка на этапе компиляции, концепции, более совершенная диагностика и связанные с ними механизмы — всё это ведет в одном направлении: больше смысла в программе становится явным и механически применимым.
Данное направление кратко изложено в таблице ниже.

В C++26 компилятору предоставляется больше семантической структуры для анализа, проверки и повторного использования — именно тот контекст, который иначе пришлось бы восстанавливать программистам, работающим с ИИ.
Взятые по отдельности, эти функции могут показаться постепенными. Однако, если объединить их, компилятор начнет делать гораздо больше, чем предполагает старая картина.
Теперь это не просто то, что ждет в конце, чтобы перевести готовую программу. Больше того, что вы, как программист, имеете в виду, теперь можно выразить в форме, понятной компилятору напрямую, больше аспектов структуры и логики вашего кода становится для него видимым, неудачные комбинации можно отклонить раньше, и больше работы можно автоматически выполнить на основе уже записанной информации.
Именно здесь идея суперкомпилятора начинает выглядеть гораздо менее умозрительной.
Так как же это будет выглядеть на практике, если перейти от теории к реальной системе?
Рассмотрим службу телеметрии, получающую версионированные бинарные пакеты от встроенных устройств. Это тот тип кода, в котором C++ невероятно силён, но при этом начинает взимать плату за каждую мелкую ошибку.
И вы имеете дело не с одной проблемой.
Вы имеете дело сразу с несколькими семантическими уровнями:
двоичная компоновка,
версионирование,
порядок байтов,
допустимые числовые диапазоны,
валидация,
гарантии API,
структура, создаваемая во время компиляции,
а также тот факт, что поле, добавленное сегодня, возможно, придётся поддерживать одновременно с устройствами, которые не будут обновляться в течение многих лет.
Именно в этом скрытом контексте сгенерированный ИИ код начинает представлять опасность.
Задача одна и та же, но отправная точка совершенно разная: ИИ начинает с неоднозначного запроса, в то время как компилятор начинает с явной структуры программы и правил.
Искусственный интеллект легко может создать декодер, который выглядит правдоподобно. Сложность заключается в том, чтобы знать весь скрытый контекст протокола, который делает этот декодер действительно правильным.
Компилятор тоже не знает этот контекст волшебным образом. В этом и заключается важность. C++26 не делает его всезнающим. Он предоставляет лучшие способы включения этих фактов в программу, чтобы компилятор мог с ними работать.
Точный синтаксис менее важен, чем сам сдвиг. Правила по-прежнему определяет программист. Компилятор их не изобретает.
Но как только эти правила записаны в форме, которую компилятор может увидеть, вот тут-то и начинается настоящая магия. Компилятор может их проверить, механизм рефлексии может их повторно использовать, и остальная часть программы может перестать хранить пять немного отличающихся версий одной и той же чертовой истины.
Та же семантическая информация может использоваться декодером, валидатором, инструментом для работы со схемами или другими механизмами компиляции.
Именно в этом и заключается реальное преимущество более совершенного механизма компиляции по сравнению с программированием, осуществляемым ИИ: каждый семантический факт, который компилятор уже может увидеть, — это на один факт меньше, который ИИ должен заново открывать из разрозненного кода, документации или огромного запроса.
Конечно, рефлексия не бесплатна. Вам все равно придется создать универсальный механизм, который будет знать, как использовать всю эту информацию. Но как только вы это сделаете, вы сможете использовать ее повторно, вместо того чтобы заново обучать каждый декодер, валидатор, инструмент и агента ИИ одним и тем же правилам.
И повторное использование — лишь начало.
Как только эти факты станут доступны компилятору, он сможет начать проверку на противоречия между ними.
Например, если два поля перекрываются, это может привести к ошибке компиляции, а не к обнаружению поврежденных данных позже.
Важно учитывать это ограничение: компилятор по-прежнему не знает, действительно ли ваша спецификация протокола корректна. Он знает лишь, могут ли все предоставленные вами факты быть истинными одновременно.
Вы по-прежнему определяете правила. Компилятор лучше выявляет случаи, когда эти правила противоречат друг другу.
Это один из способов сократить разрыв в возможности проверки: вам, другому программисту или специалисту по искусственному интеллекту остаётся меньше важных предположений, которые нужно запоминать или угадывать.
Однако некоторые правила имеют смысл только во время выполнения. Пакет может иметь правильную структуру, но при этом содержать бессмысленные данные, например, температуру 250,0.
Именно здесь начинается следующий слой.
Не все правила можно установить до запуска программы. Пакет может выглядеть совершенно нормально с точки зрения структуры, но при этом содержать полный мусор.
Вот тут-то и пригодятся контракты.
Вы можете разместить важное правило прямо на границе функции, вместо того чтобы надеяться, что каждая будущая реализация его запомнит. Вы по-прежнему сами решаете, что считается допустимым. Компилятор не читает ваши мысли. Но как только правило записано, у функции, созданной с помощью рефакторинга, оптимизации или искусственного интеллекта, остается гораздо меньше возможностей незаметно отклониться от нормы и совершить глупость.
В этом и заключается преимущество, к которому мы стремились с самого начала. Искусственному интеллекту по-прежнему приходится гадать, что вы имели в виду. Компилятору же не нужно гадать о правилах, которые вы уже записали.
Поэтому вместо:
подсказка → сгенерированный код → скрестите пальцы
вы получите нечто гораздо более полезное для здоровья:
намерение → явные правила → сгенерированный код → проверки компилятора
Искусственный интеллект по-прежнему может проявлять творчество. А компилятор остаётся тем надоедливым человеком в комнате, который говорит: «Нет. Это нарушает правила».
В этом и заключается конвергенция: ИИ предлагает решения, а компилятор держит их на поводке.
Осталась ещё одна ловушка.
Если кодировщик и декодер созданы на основе одних и тех же метаданных, они вполне могут признать одну и ту же ошибку.
Именно поэтому анимация также включает данные пакетов, записанные независимо от протокола устройства. Компилятор может показать, совпадают ли правила внутри программы друг с другом; независимый пакет показывает, соответствуют ли эти правила реальному протоколу.
Внутренняя согласованность — это не то же самое, что внешняя истина.
Поначалу это выглядело как соревнование между программистами, занимающимися искусственным интеллектом, и компиляторами, но это не так.
Искусственный интеллект хорошо справляется с предложением вариантов кода, поиском альтернатив и заполнением недостающих элементов. Проблема в том, что ему по-прежнему приходится гадать, когда отсутствует важный контекст.
Компилятор играет совершенно иную роль. Ему не нужно гадать о правилах, которые уже были формально сформулированы. Типы, ограничения, контракты, рефлексия и другая видимая компилятору структура дают ему что-то конкретное для проверки.
Таким образом, архитектура начинает выглядеть не так, как:
подсказка → сгенерированный код → скрестите пальцы
и скорее так:
намерение → явные правила → ИИ генерирует → проверки компилятора
В этом и заключается суть идеи суперкомпилятора.
Искусственный интеллект предлагает. Компилятор возражает. А вы всё равно решаете, что, чёрт возьми, должна означать эта программа.
Однако есть и ограничения. Компилятор может указать на случаи, когда записанные вами правила противоречат друг другу. Он не может сказать, были ли ваши правила изначально правильными. Вы можете построить систему, которая идеально согласована, прекрасно проверена, и при этом точно реализовывать неправильный протокол, неправильное бизнес-правило или одно очень уверенное ошибочное предположение.
Внутренняя согласованность не является внешней истиной.
И это касается не только C++26. Rust, Swift, Zig, Ada/SPARK и другие языки предоставляют своим компиляторам и инструментам различные виды семантической информации. Детали различаются, но направление схожее: дать системе программирования больше смысла программы для анализа, вместо того чтобы оставлять этот смысл скрытым в комментариях, соглашениях, подсказках или в чьей-то голове.
Также стоит отметить один технический нюанс: это не просто один компилятор с заменой языка. Компиляторная инфраструктура может быть общей — LLVM и GCC являются очевидными примерами, — но каждому языку все равно необходимы собственные интерфейсы и семантические правила. Бэкенд может быть общим; смысл программы — нет.
И это приводит нас к главному выводу:
Цель состоит не в том, чтобы сделать ИИ бесконечно лучше в угадывании скрытого контекста. Цель — свести к минимуму количество скрытого контекста, который нужно угадывать. В конечном итоге компиляторы и программирование ИИ должны будут развиваться вместе.
А если после статьи захочется обсудить тему или быстро проверить свою идею, попробуйте ИИ-помощника в Telegram — это простой вариант получить дополнительную подсказку в привычном чате.
#ИИ #ИскусственныйИнтеллект #Программирование #Технологии #Cplusplus
Потрясающий и глубокий технический разбор! Будущее за симбиозом компиляторов и ИИ ⚙️🤖