LINUX.ORG.RU

Вышел Rust 1.23

 ,


2

9

4 января состоялся плановый релиз компилятора и стандартных средств разработки системного языка программирования Rust — 1.23.

Интересные изменения:

  • За счёт предотвращения ненужного копирования аргументов функций уменьшено потребление памяти. Например сам компилятор rustc стал потреблять на 5-10% меньше памяти.
  • rustdoc перешёл на рендеринг документации при помощи CommonMark. Раньше использовался Hoedown.
  • The Cargo Book переехал с doc.crates.io на doc.rust-lang.org и обновил формат.
  • cargo uninstall научился сразу удалять несколько пакетов. Например, команда cargo uninstall foo bar удалит foo и bar.
  • auto трейты теперь разрешены в трейтовых объектах. Один из коммитов этого изменения также окончательно удалил элемент языка send.
  • Проверки типов операндов бинарных операторов теперь производится относительно левого операнда, что предотвращает путаницу в соответствующих сообщениях об ошибках.
  • Исключена необходимость в T: Sync для RwLock<T>: Send.
  • Исключена необходимость в T: Sized для {<*const T>, <*mut T>}::as_ref и для <*mut T>::as_mut.
  • Оптимизирована реализация Thread::{park, unpark}.
  • Улучшена производительность SliceExt::binary_search.
  • Трейт AsciiExt объявлен устаревшим, а его методы перенесены в примитивные типы.
  • char::escape_debug теперь использует Unicode 10 вместо Unicode 9.
  • Включён LLVM-флаг TrapUnreachable.
  • musl, используемый для сборки musl rustc, обновлён до 1.1.17.
  • Улучшена производительность SliceExt::binary_search.
  • rustfmt включён в основную инсталляцию.
  • Минимальная версия LLVM изменена на 3.9.

Полный перечень изменений

>>> Анонс

★★★★★

Проверено: Shaman007 ()
Последнее исправление: tailgunner (всего исправлений: 5)

Ответ на: комментарий от anonymous

Ok. Пиши тему в разделе job. О цене, сроках, деталях выполнения заказа договоримся там.

Да ты дебил?! Нет обязательного RAII в плюсах, тем более на уровне компилятора. А если ты обосрался с пруфами не надо козырять job'ом.

И даже от переполнения стека, он, например, не защищает.

А напомните хоть один ЯП который защищает от переполнения стека? Может Rust Вас ещё и от гопников в подъезде должен защищать?

Поправьте меня, если я не прав.

Ты попал в парадокс Блаба.

AntonyRF ★★★★
()
Ответ на: комментарий от bbk123

Причём тут boost? Я спрашивал про стандартные средства C++ до C++11.

По-твоему в Boost какой-то особенный С++03?

anonymous
()
Ответ на: комментарий от bbk123

Std::move, не смотря на название, фактически является простым кастингом лвалуе ссылки к рвалуе. Его, если не ошибаюсь, простым const_cast можно заменить. Семантику перемещения реализует автор класса (или компилятор, в случае тривиального конструктора перемещения). Деструктор у пеоемещённого объекта всё равно вызывается. У Раста иначе, перемещение реализуется простым копированием памяти и деструктор у перемещённого объекта не вызывается. Поэтому, возвращаясь к теме, эксклюзивно занятый объект, нельзя переместить, в C++ память перемещённого объекта остаётся в валидном состоянии, в расте перемещённый объект становится невалидным, а сообщить вызывающей стороне о том, что мы объект уже грохнули невозможно.

khrundel ★★★★
()
Ответ на: комментарий от khrundel

Std::move, не смотря на название, фактически является простым кастингом лвалуе ссылки к рвалуе

Да, значению просто приклеивают ярлык - «с этим можно делать что угодно, грабьте, насилуйте». Но при этом значение не превращается в нечто нерабочее, это все то же значение.

если не ошибаюсь, простым const_cast можно заменит

static_cast

anonymous
()
Ответ на: комментарий от AntonyRF

не надо козырять job'ом.

Написать скрипт, который будет статически проверять плюсовый код на соответствие RAII ?

Это работа на несколько дней и разумеется, ей место в job

А напомните хоть один ЯП который защищает от переполнения стека?

Любой декларативный, хоть тот же SQL. И ещё куча функциональщины. By design, тот же хаскель позволяет защищать от переполнения стека.

Но пока что не вижу ответа на свой вопрос.

anonymous
()
Ответ на: комментарий от anonymous

Любой декларативный, хоть тот же SQL. И ещё куча функциональщины.

Prolog говорит, что ты и в этом не разбираешься.

O02eg ★★★★★
()
Ответ на: комментарий от O02eg

В прологе by design есть переполнение стека? С этого момента поподробнее. ЕМНИП, там даже понятия стека, в явном или неявном виде, нет.

anonymous
()
Ответ на: комментарий от anonymous
?- statistics.
% Started at Mon Jan 15 16:20:31 2018
% 0.390 seconds cpu time for 435,012 inferences
% 6,288 atoms, 3,794 functors, 2,742 predicates, 53 modules, 101,326 VM-codes
% 
%                        Limit    Allocated       In use
% Local  stack:    268,435,456       61,440        1,912 Bytes
% Global stack:    268,435,456       61,424       25,168 Bytes
% Trail  stack:    268,435,456       30,712        5,120 Bytes
cat test.pl 
hello(X):-hello(X+1).
hello(0).

?- hello(3).
ERROR: Out of global stack

ЕМНИП, там даже понятия стека, в явном или неявном виде, нет.

А сhoice points хранить тогда где?

anonymous
()
Ответ на: комментарий от anonymous

А сhoice points хранить тогда где?

В хипе. Кстати, всё что можно хранить на стеке (кроме, разве что, совсем малой «обвязки» детерминированного размера) можно хранить в хипе, таким образом уже теоретически избегая проблемы переполнения стека.

Алсо, на самом деле, большинство реализаций пролога так и делают и то что там зовётся стеком является стеком виртуальной машины, а не ОС. Если я правильно помню, тот же SWI-Prolog с определёнными опциями позволяет наращивать этот свой стек до бесконечности.

Другое дело, что в силу рекурсивной природы пролога, если алгоритм упирается в некоторый оптимальный порог, скорее всего, всю оперативку этот алгоритм тоже исчерпает достаточно скоро.

anonymous
()
Ответ на: комментарий от anonymous

В хипе. Кстати, всё что можно хранить на стеке (кроме, разве что, совсем малой «обвязки» детерминированного размера) можно хранить в хипе, таким образом уже теоретически избегая проблемы переполнения стека.

Можно. И из-за необходимости интерпретации даже «нужно». В смысле — нативный стек использовать сложновато.Но по сути это эмуляция стека, со «сдвигом» границы переполнения и опять же, сути ошибки (переполнение) это никак не меняет. А насчет наращивания — в этом смысле можно и для нативного бинарника лимиты поднять.

anonymous
()
Ответ на: комментарий от anonymous

Написать скрипт, который будет статически проверять плюсовый код на соответствие RAII ?

Следуя твоей логике я так же RAII и для Delphi могу сделать. И огорчу тебя, от этих скриптов в самом языке RAII не появиться. А в Rust избавиться от всех его проблем написав за пару дней пару скриптов?! Бред. Ты просто не хочешь признаться, что обосрался перед публикой со своим высказыванием.

хоть тот же SQL

Гугляться следы переполнения стека в разных СУБД, например:

Stack overflow then parsing a lengthy query - весьма понятно, что MS SQL свалился с ошибкой:

A stack overflow occurred in the server while compiling the query. Please simplify the query.

И как же SQL не защитил от переполнения стека? По поводу хаскеля не знаю ни чего.

Но пока что не вижу ответа на свой вопрос.

Возможно, что ты его не мне задавал или я его упустил, можешь повторить?

AntonyRF ★★★★
()
Ответ на: комментарий от AntonyRF

Следуя твоей логике я так же RAII и для Delphi могу сделать.

совершенно верно, RAII - это, вообще говоря, парадигма

Гугляться следы переполнения стека в разных СУБД

В реляционной теории нет понятия «стек», а то чего нет переполниться не может. А то, что вы загуглили - баг компилятора. Бывает.

Вопрос следующий:

«Т.е., полный перечень проблем от которых защищают растоспецифичные механизмы в однопотоке: утечка ресурсов, выход за пределы коллекции, чтение из неинициализированного указателя, чтение по нулевому адресу, освобождение памяти неподходящими средствами (грубо говоря, вызов free() для памяти выделенной через new). Поправьте меня, если я не прав.»

Т.е., я прав?

anonymous
()
Ответ на: комментарий от anonymous

Вопрос следующий:

«Т.е., полный перечень проблем от которых защищают растоспецифичные механизмы в однопотоке: утечка ресурсов, выход за пределы коллекции, чтение из неинициализированного указателя, чтение по нулевому адресу, освобождение памяти неподходящими средствами (грубо говоря, вызов free() для памяти выделенной через new). Поправьте меня, если я не прав.»

Т.е., я прав?

Нет, ты не прав. Список, приведеннвый тобой, говорит о том, что ты не понимаешь, что именно гарантирует Rust. А гарантирует он простую вещь: в safe Rust, программа может обращаться только по валидным адресам.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

совершенно верно, RAII - это, вообще говоря, парадигма

Да ёп твою дивизию, ты издеваешься?! И что теперь парадигма не может быть реализована на уровне компилятора? Или отсутствовать на этом же уровне как в С++? Хватит уже отрицать, выкручиваться и предлагать костыли, в С++ нет RAII.

В реляционной теории нет понятия «стек», а то чего нет переполниться не может.

Ну всё, у меня уже весь монитор в жиру, хватит так толсто тролить))))

Ну а если ты не знал, то переполнение стека - это другими словами переполнение стека вызовов, а не то о чём ты говоришь. А то, что я загуглил это оно и есть. Ни что не защищает в SQL от этого эффекта, если запрос будет иметь достаточное количество вложенных вызовов, то произойдёт переполнение стека. И если есть рекурсия в хаскеле, то вероятно можно получить переполнение стека и там.

Простейший пример переполнения стека на Си:

int foo() 
{
     return foo();
}

И в Rust, приятно, что есть варнинг который говорит о том, что так делать не надо.

Т.е., я прав?

Нет. Но почему тебе ни кто не расскажет, потому что ни кто не хочет пересказывать тебе половину документации Rust'a. Но можешь почитать сам и сравнить.

AntonyRF ★★★★
()
Ответ на: комментарий от anonymous

Ты из C++ перешёл на rust?

Нет. Я пишу на Си++.

Скажи, кто тебя обратил в веру растаманскую.

Почему обязательно «кто»? Я всегда хотел язык системного программирования, который не был бы устаревшим говном вроде Си. Развитие таких языков привело к появлению Rust.

tailgunner ★★★★★
()
Ответ на: комментарий от AntonyRF

И что теперь парадигма не может быть реализована на уровне компилятора?

Нет, конечно. Можно сильно облегчить или затруднить применение какой-либо парадигмы, но не более. Например, можно и на сишке шпилить в ООП (см. gtk), а можно на жабе писать в процедурном стиле.

Но можешь почитать сам и сравнить

почитал, сравнил, выводы озвучил

anonymous
()
Ответ на: комментарий от AntonyRF

это другими словами переполнение стека вызовов

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

Ровно так же обстоят дела и SQL. Хотя, конечно, какая-то из реализаций SQL может упереться в переполнение стека вызовов, но это баг.

anonymous
()
Ответ на: комментарий от anonymous

для случая Пролога разобрали, что ошибки переполнения стека у него есть всего лишь переполнения его внутреннего массива виртуальной машины и к системному стеку вызовов не имеют никакого отношения

То есть если стек не системный, то переполнение - это нещитово?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

А какие существуют примеры невалидных адресов, состояние невалидности которых не может быть определено вышеописанными случаями?

anonymous
()
Ответ на: комментарий от anonymous
{
  int *p = (int *)malloc(sizeof(int)); // инициализируем указатель
  * p= 1; // используем его
  free(p); // ...и
  *p = 2; // получаем инициализированный невалидный указате
}
tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

free(p) провела освобождение указателя и после этого он перестал указывать на инициализированную память, то есть он перестал быть инициализированным валидным адресом

anonymous
()
Ответ на: комментарий от anonymous

Нет, конечно.

Не согласен! Смотрим определение:

Паради́гма программи́рования — это совокупность идей и понятий, определяющих стиль написания компьютерных программ.

Соответственно, наличие RAII на уровне компилятора - это реализация парадигмы в ЯП, т.к. не надо руками крейтить и дестроить объекты ЯП.

Например, можно и на сишке шпилить в ООП

Но это будет костылирование структур и от этого язык не станет поддерживать объекты на уровне компилятора. Java - мультипарадигмальный ЯП тоже пример не корректный.

Вообще, в теории можно сделать всё на любом тюринг-полном языке, НО! нужно понимать, что реализация ручками и by design - это совершенно разные вещи. И мы снова возвращаемся к тому, что by design в С++ нет RAII =) Если так будет понятнее.

почитал, сравнил, выводы озвучил

Молодец, но либо у тебя уровень как программиста слабоват, либо ты прочитал вместо доков - вики

AntonyRF ★★★★
()
Ответ на: комментарий от AntonyRF

Ветку не читал, но можешь все таки объяснить чем деструкторы в C++, которые отрабатывают при выходе из скопа — не RAII, а растовский Drop — RAII?

mersinvald ★★★★★
()
Ответ на: комментарий от mersinvald

Ветку не читал,

Там чел утверждает, что в С++ можно сделать тоже чтобы при выходе из скопа вызывался деструктор автоматически - без необходимости его прописывать ручками. При попытке получить от него пруфы, он сказал, что я должен обратиться в job, потом пояснил что так можно сделать с помощью внешних скриптов, а дальше стал нести какую-то херню про парадигмы.

AntonyRF ★★★★
()
Ответ на: комментарий от AntonyRF

1) Вы меня просили про RAII, а не про деструкторы.

2) Деструкторы в плюсах итак вызываются автоматически. И да, их совершенно необязательно прописывать ручками: деструктор по умолчанию генерирует компилятор.

anonymous
()
Ответ на: комментарий от anonymous

free(p) провела освобождение указателя и после этого он перестал указывать на инициализированную память,

Нет. Память всё еще инициализирована единицей (см. первое присваивание).

то есть он перестал быть инициализированным валидным адресом

Нет. Он не перестал быть инициализированным - его значение не изменилось. Он перестал быть валидным.

Более того:

{
  int *p = (int *)0x12; // тоже инициализированный указатель
}

P.S. присваивание начального значения при объявлении - это инициализация:

«8.5 Initializers

A declarator can specify an initial value for the identifier being declared. The identifier designates a variable being initialized.»

Учи термины.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

для случая Пролога разобрали, что ошибки переполнения стека у него есть всего лишь переполнения его внутреннего массива виртуальной машины и к системному стеку вызовов не имеют никакого отношения

То есть если стек не системный, то переполнение - это нещитово?

за переполнение системного стека не считается, да

И в чем качественная разница? В обоих случаях аварийное завершение.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от anonymous

для случая Пролога разобрали, что ошибки переполнения стека у него есть всего лишь переполнения его внутреннего массива виртуальной машины и к системному стеку вызовов не имеют никакого отношения.

Будто «системный» стек в «нативной» программе принципиально чем-то сильно отличается. Тогда достаточно сделать отдельный «внутренний» массив: маллок + перекидывание SP/BP и все переполнения стека будут у нас лишь переполнением внутреннего массива …

anonymous
()
Ответ на: комментарий от mersinvald

Просто не все знают плюсы на 100%, например, я изучал плюсы, но так сложилось, что моя работа с ними не пересекалась и все уже забыл за 5-7 лет.

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

По этому и прошу пруфы.

AntonyRF ★★★★
()
Ответ на: комментарий от tailgunner

Системный стек организован так, как организован. А вот class stack можно организовать по-разному. Можно взять std::stack, а можно сделать на основе std::list<std::array<T, 1000>> тогда он может расти вплоть до исчерпания оперативной памяти, а не некоторого определённого числа.

anonymous
()
Ответ на: комментарий от tailgunner

Он не перестал быть инициализированным, но перестал содержать в себе адрес выделенной памяти. Потому, что память освободили.

anonymous
()
Ответ на: комментарий от tailgunner

Нет. Память всё еще инициализирована единицей

Нет. Строго говоря, после освобождения памяти, она принимает неопределённое значение.

anonymous
()
Ответ на: комментарий от anonymous

К тому, что его собеседник начал выпендриваться и махать джобом

mersinvald ★★★★★
()
Ответ на: комментарий от anonymous

И в чем качественная разница? В обоих случаях аварийное завершение.

Системный стек организован так [...]. А вот class stack можно организовать [...]

Я об этом не спрашивал.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

Он не перестал быть инициализированным, но перестал содержать в себе адрес выделенной памяти

Да. Теперь обращение по этому инициализированному указателю - ошибка. И чтобы запретить такие обращения, в Rust используется механизм lifetime-ов, а не RAII.

Строго говоря, после освобождения памяти, она принимает неопределённое значение.

Каким-то волшебным образом, не упоминутым в man 3 free.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

И чтобы запретить такие обращения, в Rust используется механизм lifetime-ов, а не RAII.

Совершенно верно, однако RAII также полностью исключает данный класс ошибок.

Например, так как голые указатели отсутствуют, их невозможно инициализировать «мусором». Т.к. объект уничтожается автоматически, по выходу из обл. видимости или по исключению, обращение после его удаления становятся невозможным. А поскольку объект удаляет сам себя и сам «помнит» правильный деаллокатор, то и ошибки вида «x = new X(); free(x);» становятся невозможными.

anonymous
()
Ответ на: комментарий от tailgunner

В целом, изучая раст, я не нашёл классы ошибок, от которых защищали бы его растоспецифичные механизмы, и от которых бы не спасало RAII.

anonymous
()
Ответ на: комментарий от anonymous

Например, так как голые указатели отсутствуют

А, так в Си++ отсутствуют голые указатели? Тогда окей.

В целом, изучая раст, я не нашёл классы ошибок, от которых защищали бы его растоспецифичные механизмы

Раньше ты хотя бы говорил «в однопотоке» - это создавало хотя бы видимость понимания.

tailgunner ★★★★★
()
Ответ на: комментарий от red75prim

Тут 2 основные ошибки. 1-я появляется в результате нарушения ООП, а затем в RAII, а другая - в результате нарушения RAII.

Нарушение ООП - в дизайне вектора, так сделано для удобства, но позволяет выстрелы в ногу. А именно: в процессе push_back, если будет превышение ёмкости вектора, последует реаллокация и ссылка протухнет, т.е. интерфейс вектора небезопасен. ООП запрещает небезопасный интерфейс, а RAII запрещает ссылки на объекты с неконстантным состоянием. 3-я ошибка - доступ к 0-му элементу, который может не существовать имеет ту же природу и её разбор аналогичен 1-й.

Вторая ошибка проще - т.к. вектор vs живёт вплоть до выхода из функции, то возвращаемое значение ф-ции. Опять же: порождённый объект (ссылка ret) в этом коде живёт дольше родителя, (вектора vs), что является грубым нарушением RAII.

anonymous
()
Ответ на: комментарий от tailgunner

«А, так в Си++ отсутствуют голые указатели? Тогда окей.»

не вижу в своём комментарии слово «С++»

голые указатели

в большинстве случаев, RAII их запрещает

Раньше ты хотя бы говорил «в однопотоке»

устал

ну и, может вы всё-таки приведёте пример RAII кода, в котором есть ошибки памяти и которые мог бы отловить раст? начнём с однопотока

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.