LINUX.ORG.RU

Rust 1.10

 ,


0

4

Анонсирована очередная версия языка программирования Rust 1.10, разрабатываемого Mozilla совместно с сообществом.

Улучшения компилятора:

  • Добавлен новый тип крейта cdylib, предназначенный для экспорта C API. Основные отличия от dylib:
    • отсутствие метаданных;
    • разрешено LTO;
    • все библиотеки должны быть статически слинкованы;
    • экспортируются лишь те символы, которые помечены как extern. Например:
      pub fn foo() {} // не экспортируется
      #[no_mangle] pub extern fn bar() {} // экспортируется
    Для сравнения: «hello world» cdylib занимает 7.2КБ, а dylib - 2.4МБ.
  • Добавлена поддержка платформ i586-unknown-linux-gnu, i686-unknown-linux-musl, и armv7-linux-androideabi;
  • Снижено потребление памяти на ~100МБ при проверке типов;
  • Ускорена проверка T: Sized на 15%;
  • Улучшена кодогенерация при #[derive(Copy, Clone)].

Изменения в стандартной библиотеке:

Breaking changes!

  • AtomicBool теперь преобразуется в bool, а не isize. Демонстрация:
    use std::sync::atomic::AtomicBool;
    use std::mem::transmute;
    
    fn main() {
        let foo: bool = unsafe { transmute(AtomicBool::new(true)) };
    }
    
    На старых версиях компилятора будет ошибка;
  • time::Duration::new теперь будет паниковать при переполнении;
  • String::truncate теперь будет паниковать чуть меньше;
  • Небольшое изменение поведения макросов на этапе их парсинга: из :ty и :path следует :block;
  • Исправлен баг, связанный с гигиеной макросов. Следующий код будет валидным в устаревших версиях компилятора:
    fn main() {
        let x = true;
        macro_rules! foo { () => {
            let x = 0;
            macro_rules! bar { () => {x} }
            let _: bool = bar!();
            //^ `bar!()` использует первый `x` (который bool),
            //| а должен использовать второй `x` (который i32).
        }}
        foo! {};
    }
  • Переименование платформ:
    • arm-unknown-linux-gnueabi => arm-unknown-linux-gnu;
    • arm-unknown-linux-gnueabihf => arm-unknown-linux-gnu;
    • armv7-unknown-linux-gnueabihf => armv7-unknown-linux-gnu.
    Другими словами, изменены target_env, применяемые в conditional compilation.

Изменения в менеджере зависимостей Cargo:

  • Добавлен флаг --force, -f для подкоманды cargo install, предназначенной для загрузки исходных текстов из crates.io, их компиляции и установки в каталог ~/.cargo/bin. Это нововведение теперь позволит писать:
    cargo install FOO -f
    вместо:
    cargo uninstall FOO
    cargo install FOO
    Однако всё еще невозможно узнать, а требуется ли обновление вообще?
  • Диагностические сообщения теперь отправляются в stderr, а не в stdout;
  • С помощью флагов cargo doc --bin и cargo doc --lib можно выбрать: генерировать html документацию для проекта-приложения src/main.rs или проекта-библиотеки src/lib.rs;
  • В конфигурационном файле Cargo.toml, который можно встретить в корневом каталоге каждого проекта, теперь можно указать, каким образом макрос panic!() будет завершать приложение: unwind (по умолчанию) или abort;
  • Добавлен флаг cargo --explain FOO, поведение которого идентично rustc --explain FOO: показывает документацию по номеру ошибки;
  • В черный список имен крейтов добавлены ключевые слова раста, такие как fn, unsafe, let и прочее.

>>> Подробности



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

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

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

В том, что придётся писать «лишний» код?

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

Так ведь можно наткнуться на какие-то системно-зависимые вещи, которые начинаются, почему-то, с одного подчеркивания. Вроде _cdecl

Да, но по ссылке присутствует и вариант без нижнего подчёркивания вообще. То есть, авторы таких вот расширений могут вообще на стандарт.

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

Попробую объяснить еще раз

Да я мысль, кажется, понял, просто не разделяю «апелляцию к количеству». Если слепо подражать мейнстриму, то что-то принципиально новое и, возможно, более удачное (а может и нет) придумать не получится. Разумеется, это идёт вместе с бонусом в виде «привычности».

Особенно, если говорить про языки с более-менее нормальным ООП (вроде C++ или Eiffel).

Не думаю, что тут принципиально именно ООП. Если в раст добавить «недостающие» части типа наследования данных и т.д., то мне кажется, выбранный подход всё равно будет смотреться в языке удачнее. И дело не (только) в «явности», а ещё и в единообразии (с переменными и лайфтаймами).

С тем, что С++ ничего не выиграл бы, если позаимствовал (только) эту штуку спорить не буду.

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

По-моему, они хотят оставить текущую, легкую генерацию capi, для чего его большинство и использует. А всё эти фичи с перегрузкой, исключениями и подобным, убьют всю эту затею, и превратят раст в очередной C++, который нельзя использовать извне (не считая ipc).

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

Ну от возможности нормально делегировать членам структуры реализацию трейтов я бы не отказался.

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

Да я мысль, кажется, понял, просто не разделяю «апелляцию к количеству»

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

Вот, например, в Python есть и self, и структурирование кода пробелами. Среди прочего эти были причины, по которым в качестве скриптового языка я для себя лично выбрал Ruby, а не Python. А вот будь Python более похож на C, глядишь, база пользователей у него была бы еще больше ;)

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

Среди прочего эти были причины, по которым в качестве скриптового языка я для себя лично выбрал Ruby, а не Python

При этом Python куда популярнее.

Да и вообще озвученные особенности, как по мне, весьма незначительны. Так и до выбора по названию можно докатиться.

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

При этом Python куда популярнее.

У Ruby старт был в других условиях, как минимум.

Да и вообще озвученные особенности, как по мне, весьма незначительны.

Из незначительных особенностей может сложиться большое отвращение от языка.

Хотя вот отсутствие структурирование кода пробелами в Ruby, например, упрощает кодогенерацию.

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

Из незначительных особенностей может сложиться большое отвращение от языка.

Всё может быть. Я просто вспоминаю как сам из-за такой ерунды заморачивался, а теперь оно кажется ужасно незначительным. Связываю это с «взрослением», набором опыта, расширениям кругозора и прочим «профессиональным ростом». Однако, допускаю, что у других людей опыт может различаться.

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

А вот будь Python более похож на C

from __future__ import braces

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

В чём разница?

Ruby вышел в свет позже Python-а. По сути, когда ниша новых скриптовых языков уже была поделена между Perl-ом и Python-ом. Плюс, что еще более важно, он вышел в Японии, а не в США или, хотя бы, в Западной Европе. Из-за этого до начала 2000-х он был известен, в основном, только в Азии. Где был популярнее Python-а (а может и продолжает таковым быть).

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

Ruby вышел в свет позже Python-а. По сути, когда ниша новых скриптовых языков уже была поделена между Perl-ом и Python-ом.

Питон вышел в свет позже Perl'а. Ниша скриптовых язаков была поделена между Bash'ем и Perl'ом. PHP Вышел в свет позже Питона. Ниша скриптовых языков была поделена между Perl'ом и Питоном. JavaScript вышел в свет... Ну ты понел.

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

Ну ты понел.

Да, понял на кого не нужно тратить время.

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

Я просто вспоминаю как сам из-за такой ерунды заморачивался

Ну не знаю ерунда ли. В нормальных языках ставишь курсор на { и видишь нужную }. А в луа, например, только end, сходу непонять чему соответствующий. И это очень вымораживает порой

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

В нормальных языках ставишь курсор на { и видишь нужную }. А в луа, например, только end, сходу непонять чему соответствующий.

С Lua практически не сталкивался, но есть подозрение, что дело не в языке. Пример из википедии:

function factorial(n)
  local x = 1
  for i = 2, n do
    x = x * i
  end
  return x
end
Что мешает IDE подсвечивать строку к которой относится соответствующий end? Разве что отсутствие IDE, но ведь это и к скобковым языкам относиться может.

Да и по отступам и так ведь видно? Или речь о случаях когда имеется большой уровень вложенности? В таком и с IDE неудобно разбираться.

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

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

Тупое философствующее быдло. Не «в принципе», а в общем случае. Во многих частных случаях такой анализ вполне возможен. Более того, экземпляров программ, для которых статический затруднен, на практике следует избегать. Потому что отлаживать глюкодром свой будешь до усрачки.

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

Тупое философствующее быдло. Не «в принципе», а в общем случае. Во многих частных случаях такой анализ вполне возможен. Более того, экземпляров программ, для которых статический затруднен, на практике следует избегать. Потому что отлаживать глюкодром свой будешь до усрачки.

Ути-пути. Не в общем случае, а в любой, более-менее серьёзной программе. Как только появляется цикл с более-менее сложным условием или рекурсивный вызов и всё, компилятор вынужден будет пасовать. В принципе есть способы понять что может происходить, типа range propagation и вариативный анализ, но в реальности это срабатывает только в примитивных случаях. И как ты, прикажешь действовать компилятору, когда он не может доказать безопасность программы? Просто довериться программисту? Тогда ещё хуже чем вообще без анализа. Сообщать об ошибке, если он не может статически доказать, что буфер/стек не переполнится? Т.е. программа будет компилироваться в одной версии и не компилироваться в другой, или, например если там в выражение добавится один xor и у компилятора RP сломается? Если же вернуться к практике, то всё ещё хуже. Во первых, в отличие от условия теоремы Тьюринга, компилятору неизвестны входные данные, с которыми будет работать программа. Во-вторых, свободного хипа и места в стеке очень мало, так что даже если статически ясно, что рекурсия завершится, это вовсе не значит, что пары мегабайтов стека ей хватит. Возьмём для примера наивную рекурсивную реализацию quicksort. Умный компилятор может увидеть, что интервал сортировки для каждого рекурсивного вызова сокращается по крайней мере на 1 элемент, это значит, что алгоритм завершится. Но, если quicksort выбирает первый, последний или срединный элемент (наивные любители предлагают именно такой подход), при определённых последовательностях глубина рекурсии будет сравнима с размером последовательности, что означает ой. Решением является выбор индекса элемента для разбиения случайным образом. И вот теперь представь, умный компилятор должен понять, что вариант «берём первый, последний и срединный элементы, находим средний по значению и используем его» - это плохо, это stack overflow, а «index = rnd.get(right - left)» - это хорошо?

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

Тогда подавляющее большинство давно и успешно используемых языков просто сосут :)

верно

template< typename T > class derived_from_param : public T {

хороший вопрос

я было хотел написать, затем поленился, но написать придется:

фича «импорт пространства имен класса в локальное пространство имен метода класса» прибита гвоздями, и поэтому из удобства иногда превращается в неудобство (как в случае derived_from_param — если класс Т предполагается произвольным, то может быть удобным из его пространства имен ничего не импортировать *вообще*)

нормально было бы иметь эту фичу в рамках стандартных средств работы с пространствами имен; тогда можно было бы импортировать пространство имен класса не только в методы, но и во внешние функции; это был бы и плюс к удобству рефакторинга — если мы из метода делаем внешнюю функцию (или наоборот, или сначала так, а через месяц наоборот), то меньше придется делать идиотской работы по переписыванию

так же не было бы давления на программиста «да, внешние функции безопаснее, но метод получается короче и читабельнее, дай-ка я лучше сделаю метод!»

www_linux_org_ru ★★★★★
()
Последнее исправление: www_linux_org_ru (всего исправлений: 5)
Ответ на: комментарий от eao197

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

Пожалуй, это одна из самых странных претензий к C++, которые доводилось видеть.

где-то у меня была интересная ошибка из-за похожего

я обычно пишу

class Point
{
public:
  Point(float x, float y): x(x), y(y) {}
private:
  float x;
  float y;
};

но при чуть более хитрой инициализации закралась ошибка

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

этой проблемы нет, пока не требуется детерминированное освобождение

Поправь меня, но на практике оно требуется только для инородных по отношению к рантайму языка ресурсов, например для файловых дескрипторов или каких-то FFI буферов. Больше что-то ничего в голову не приходит. Но пользоваться GC для них в принципе неправильно, будут утечки, знакомые по печально известному Lazy IO в Haskell.

В функциональщине в простейшем случае используется старый паттерн «RAII для бедных»

withMyHandle $ \handle -> do
  stuff handle

Его достаточно в большинстве случаев, причём нестить подобные выражения можно не опасаясь stack overflow (GHC использует стек несколько своеобразно, его переполнить можно, но не просто вложенными вызовами, а умудрившись создать «санк смерти», в котором много вложенных сравнений с образцом). В более сложных случаях (совместное владение дескриптором и т.д.) код что с GC, что без, будет специфическим для задачи.

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

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

Да. И это не редкость, в том же .net картинки в виде дескрипторов из GDI+ хранятся. Вот, предположим, есть у нас сложное дерево, где есть абстрактная нода и все её потомки могут иметь разное количество и разный тип детей. Всё более-менее хорошо, пока не понадобилось в один из дочерних типов, который может в 1% случаев встречается, добавить картинку. Ну и, чтоб дескрипторы не утекали, добавляем IDisposable в базовый класс и вроде даже всё работает, пока не попадётся дерево с одной глубокой веткой.

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

Там, где нужен GUI - не согласен. Нет внятных биндингов ни Qt, ни GTK под Go. Ну и где динамическая линковка по дефолту?

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