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)
Ответ на: комментарий от eao197

В том, что нужно делать лишнюю работу, которую можно не делать

Не совсем так. В Си++ принято вешать на переменные-члены уродские префиксы - тоже работа. Так что я определенно предпочитаю явный self.

есть ли какой-нибудь статически-типизированный ООЯ, в котором бы для нестатических методов приходилось явно прописывать аргумент self?

Не знаю такого. Но, опять же, все статически типизированные ООП-языки в большей или меньше степени скопированы с Си++.

Хотя вроде в Ocaml тоже явный self.

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

А хелловорлд на Rust нужно 600к самого бинаря. Всего-то в 20 раз меньше.

Вообще-то 350 Кб если сделать strip.

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

Напиши да померяй. Пустой запуск:

$ /usr/bin/time java
...
0.06user 0.01system 0:00.07elapsed 101%CPU (0avgtext+0avgdata 17480maxresident)k
0inputs+64outputs (0major+1777minor)pagefaults 0swaps
tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

В Си++ принято вешать на переменные-члены уродские префиксы - тоже работа. Так что я определенно предпочитаю явный self.

Открой для себя суффиксы.

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

Self передаётся не для этого, а для того чтобы показать как используется объект.

Там ещё можно указывать лайфтайм:

fn foo<'a>(&'a self) -> &'a Bar {}
fn foo<'a>(&'a mut self) -> &'a Bar {}

Зачем это надо, ХЗ, но вдруг когда-нибудь пригодится.

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

есть ли какой-нибудь статически-типизированный ООЯ, в котором бы для нестатических методов приходилось явно прописывать аргумент self?

Go. Правда там не self, его можно называть как угодно. Ну, и его ООПэшность - спорный вопрос, но с растом то же.

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

Суффиксы компактнее, чем использование self. Кроме того, если человеку нравится писать self.x вместо m_x или x_, то не ему говорить про уродскость.

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

Ну, и его ООПэшность - спорный вопрос

Я спрашивал про ООЯ. Go и Rust к таковым относить можно только, если с нормальными ООЯ никогда не сталкивался.

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

Суффиксы компактнее, чем использование self

А, эти суффиксы... то же, что и префиксы, но с другой стороны.

если человеку нравится писать self.x вместо m_x или x_, то не ему говорить про уродскость.

Этот человек писал и суффиксы, и префиксы, и self, и сделал выбор. Так что ему говорить, ему.

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

Этот человек писал и суффиксы, и префиксы, и self, и сделал выбор. Так что ему говорить, ему.

Так ты же то на C, то на Python-е писал. Ассортимент так себе.

Или ты и в C++ пишешь this->x вместо x_?

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

Меньше жрёт память и не подвисает, когда GC решит таки убрать мусор.

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

А, эти суффиксы... то же, что и префиксы, но с другой стороны.

Ну расскажи, пожалуйста, как ты себе видишь обязательный аргумент self в статически-типизированном ООЯ. Не в Rust-е, с которым разговор особый, а в языках типа Eiffel или C++?

Вот есть у меня, скажем:

class basic_io {
public :
  virtual void read(buffer &to) = 0;
  ...
};
...
class localfs_file_io : public basic_io {
public :
  virtual void read(buffer &to) = 0;
  ...
};
Вот какие типы у self-а ты предлагаешь вписывать в методах read?

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

Ты уверен, что лучше менять код каждый месяц, чем переписывать всё с нуля раз в 10 лет? Тем более, что за 10 лет обычно многое меняется и переписывание с нуля может даже пойти на пользу, чем тащить legacy. К тому же сколько C++ лет? И он живее всех живых.

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

Раз Linux выстрелил - значит в нём была потребность. Была потребность в чём-нибудь открытом и POSIX-совместимым. Linux оказался наиболее привлекателен в тот исторический период. А вот потребности в двух ОС с такими параметрами не было, поэтому фряха и не взлетела.

Есть две поговорки - «свято место пусто не бывает» и «незаменимых людей нет». К софту это тоже применимо. Не было бы Linux, то взлетела бы FreeBSD. Не было бы FreeBSD, взлетела бы какая-нибудь другая ОС. Не было бы ничего - написали бы.

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

Вот какие типы у self-а ты предлагаешь вписывать в методах read?

basic_io* и localfs_file_io* соответственно. В чём проблема? Ну и в целом, непонятно, зачем ты собрался вписывать какие-то там типы у self'а.

Esper
()

Моё впечатление о Rust как о низкоуровневом языке: из низкоуровневого языка должна легко выпиливаться стандартная библиотека, чтобы начать писать прошивку под МК или ядро ОС. Например, достаточно передать GCC опцию -ffreestanding, а линкеру -nostdlib и всё - в бинарник попадёт лишь код, которые явно мною написан. При этом в принципе все конструкции языка продолжат адекватно работать (лишь пропадёт какой-нибудь malloc или strlen, но их легко запилить свои, либо взять готовый newlib, который специально спроектирован для работы без ОС, и слинковать с ним).

В Rust с этим не так всё просто, одних ключей компилятора мало, нужно ещё вставлять всякие экспериментальные директивы в исходник (а ещё желательно создать пустую стандартную библиотеку), а знающие люди говорят, что тогда половина фич языка отвалятся.

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

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

basic_io* и localfs_file_io* соответственно. В чём проблема?

Например, в том, что придется править дофига объявлений, если поменяется имя типа.

Ну и в целом, непонятно, зачем ты собрался вписывать какие-то там типы у self'а.

Я вообще не собирался, меня вполне устраивает то, что есть в большинстве нормальных ООЯ. Пытаюсь понять, что хотят видеть отдельные личности в «языках их мечты».

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

У вас тысячи методов у одного класса?!

Суммарно во всех классах какого-нибудь проекта на пару десятков тысяч строк вполне может оказаться несколько тысяча-полторы методов. В проектах на сотни тысяч строк методов гораздо больше. Указывать в их сигнатурах какой-нибудь self только для того, чтобы вам или tailgunner-у было приятно писать что-то вроде (self.x+self.y) мне бы лично ну очень не хотелось бы.

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

как о низкоуровневом языке

Понятие о «низкоуровневом языке» у всех своё. Вам нужно программирование железяк, в то время как раст, сейчас, нацелен на прикладное. Тем не менее пилится Rust Core Library, который нужен вам.

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

Всего - это понятно. Я про количество методов у одно единственного класса.

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

GIMP на GTK+

Масло масляное, шо то шо то в винде место занимает, в отличие от линуха

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

Так ты же то на C, то на Python-е писал. Ассортимент так себе.

Это последние 15 лет. До того я писал на Си++ и немного на Java, сейчас - на Си++. Ассортимент не очень, но для вывода о self хватает.

Или ты и в C++ пишешь this->x вместо x_?

Я бы писал, если бы можно было заставить компилятор это проверять.

как ты себе видишь обязательный аргумент self в статически-типизированном ООЯ. Не в Rust-е, с которым разговор особый, а в языках типа Eiffel или C++?

В особом разговоре о Rust нет необходимости - его решение напрямую переносится в Си++:

class localfs_file_io : public basic_io {
public :
  virtual void read(self, buffer &to) = 0;
  ...
};

Тип писать не нужно, он автоматически назначается.

P.S. а еще явный self в Ada95.

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

В Rust с этим не так всё просто, одних ключей компилятора мало, нужно ещё вставлять всякие экспериментальные директивы в исходник (а ещё желательно создать пустую стандартную библиотеку), а знающие люди говорят, что тогда половина фич языка отвалятся.

#![feature(lang_items)]
#![feature(asm)]
#![feature(core_intrinsics)]

#![no_std]
#![no_main]

use core::intrinsics::unreachable;

macro_rules! syscall {
    ($i:expr, $a0:expr) => ({
        let ret: i64;
        asm!("syscall"
            : "={rax}"(ret)
            : "{rax}"($i), "{rdi}"($a0)
            :
            : "volatile"
        );
        ret
    });
    ($i:expr, $a0:expr, $a1:expr, $a2:expr) => ({
        let ret: i64;
        asm!("syscall"
            : "={rax}"(ret)
            : "{rax}"($i), "{rdi}"($a0), "{rsi}"($a1), "{rdx}"($a2)
            :
            : "volatile"
        );
        ret
    });
}

const SYS_WRITE: u64 = 1;
const SYS_EXIT: u64 = 60;

unsafe fn sys_write(fd: u64, buf: &[u8]) -> i64 {
    syscall!(SYS_WRITE, fd, buf.as_ptr(), buf.len() as u64)
}

unsafe fn sys_exit(code: u64) -> ! {
    syscall!(SYS_EXIT, code);
    unreachable();
}

#[no_mangle]
pub extern fn _start() -> ! {
    let msg = b"Hello, world!\n";
    
    unsafe {
        sys_write(0, msg);
        sys_exit(0);
    }
}

#[lang = "panic_fmt"]
extern fn panic_fmt() -> ! {
    unsafe { sys_exit(1); }
}

#[lang = "eh_personality"]
extern fn eh_personality() {}
$ rustc -O -C link-args="-nostdlib" lib.rs -o app
$ ldd app
	statically linked
$ objdump  -d app 

app:     file format elf64-x86-64


Disassembly of section .text:

0000000000000320 <_ZN3lib8sys_exit17hbd2adf697519b0adE>:
 320:	b8 3c 00 00 00       	mov    $0x3c,%eax
 325:	0f 05                	syscall 
 327:	66 0f 1f 84 00 00 00 	nopw   0x0(%rax,%rax,1)
 32e:	00 00 

0000000000000330 <_start>:
 330:	50                   	push   %rax
 331:	48 8d 35 15 00 00 00 	lea    0x15(%rip),%rsi        # 34d <byte_str2140>
 338:	b8 01 00 00 00       	mov    $0x1,%eax
 33d:	31 ff                	xor    %edi,%edi
 33f:	ba 0e 00 00 00       	mov    $0xe,%edx
 344:	0f 05                	syscall 
 346:	31 ff                	xor    %edi,%edi
 348:	e8 d3 ff ff ff       	callq  320 <_ZN3lib8sys_exit17hbd2adf697519b0adE>
$ ./app
Hello, world!

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

По крайней мере до того пока не стабилизируют некоторые вещи.

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

Тип писать не нужно, он автоматически назначается.

Как хорошо, что ты не занимаешься разработкой языков программирования.

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

Тип писать не нужно, он автоматически назначается.

Как хорошо, что ты не занимаешься разработкой языков программирования.

Более того - я и не хочу ей заниматься, потому что представляю сложность задачи. Но всё же хотелось узнать - в чем претензия к конкретному решению? Кроме эстетики.

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

Но всё же хотелось узнать - в чем претензия к конкретному решению?

Есть устоявшаяся практика, которой этот подход противопоставляется. Хотелось бы видеть какие-то аргументы «за», но пока он всего один: редкие ошибки с перекрытием области видимости. Платить за эти ошибки указанием self в каждой декларации, а затем запись self.x при каждом обращении к x внутри метода — это, на мой взгляд, слишком большая цена.

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

Есть устоявшаяся практика, которой этот подход противопоставляется.

На самом деле, есть 2 устоявшиеся практики. Просто ты работаешь в рамках одной.

Хотелось бы видеть какие-то аргументы «за», но пока он всего один: редкие ошибки с перекрытием области видимости

Не думаю, что аргумент с ошибками кто-то воспринимает серьезно. Настоящий аргумент один - explicit vs implicit.

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

На самом деле, есть 2 устоявшиеся практики.

Да ладно. Ты вот смог вспомнить только OCaml и Ada95. Причем оба можно рассматривать как попытку прилепить ООП к не-ООП-шным изначально языкам.

А так получается только пример динамически типизированного Питона против кучи как статически, так и динамически типизированных ООЯ. Взять хотя бы статику: С++, Java, C#, Scala, Eiffel... Что этому опыту противопоставить? Go, Rust, OCaml и Ada95?

Настоящий аргумент один - explicit vs implicit.

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

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

На самом деле, есть 2 устоявшиеся практики.

Да ладно. Ты вот смог вспомнить только OCaml и Ada95

Потому что ты поставил ограничение «Ъ-ООП и статика». А это ограничение нерелевантно - неявный self используется в двух широко распространенных языках, он уже вполне обычен.

Ну так ты попробуй в том же C++ писать везде в телах методов this->, увидишь, как быстро тебе это надоест

Еще раз: я делал это в Python. Ничего страшного в этом нет, а понятности прибавляется. Мне не хватает этого в Си++.

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

Потому что ты поставил ограничение «Ъ-ООП и статика»

Это потому, что когда есть ООП и статика правила игры несколько другие.

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

В каких? OCaml и Python? Так широко распространен только один из них. Плюс к тому динамически-типизированный.

Еще раз: я делал это в Python. Ничего страшного в этом нет, а понятности прибавляется. Мне не хватает этого в Си++.

Рискну предположить, что объем твоих программ на Python-е не измерялся сотнями тысяч строк кода. Ну и в C++ ты имеешь возможность писать this->, но ведь не пользуешься ей. Попробуй воспользоваться, уверен, тебя ждут удивительные открытия.

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

Ты уверен, что лучше менять код каждый месяц, чем переписывать всё с нуля раз в 10 лет? Тем более, что за 10 лет обычно многое меняется и переписывание с нуля может даже пойти на пользу, чем тащить legacy. К тому же сколько C++ лет? И он живее всех живых.

Готов переписывать тулзы вроде Git каждые десять лет?

kirk_johnson ★☆
()
Ответ на: комментарий от quantum-troll

На фоне сотен тысяч строк кода мелочи вроде явного `self` особой погоды не играют.

То, какой объем кода был написан без этой мелочи, намекает, что мелочь эта никому не нужна. А раз не нужна, то не следует тянуть ее в новые языки программирования.

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

когда есть ООП и статика правила игры несколько другие.

Да нет же. Традиция Си++ другая, но Си++ - это еще не вся статика и не всё ООП.

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

В каких? OCaml и Python?

Python и Go.

Рискну предположить, что объем твоих программ на Python-е не измерялся сотнями тысяч строк кода.

Нет, ну и что? Их хватало, чтобы занять меня на полный рабочий день. Большие программы писались бы коллективами (и пишутся, и там тоже явный self). Проблемы _нет_.

Ну и в C++ ты имеешь возможность писать this->, но ведь не пользуешься ей.

И я даже сказал, почему.

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

Не ждут.

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

Да нет же. Традиция Си++ другая, но Си++ - это еще не вся статика и не всё ООП.

Остальное — маргинальщина.

Python и Go.

О, да, Go — это просто образец ООП.

Нет, ну и что?

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

self.x = self.prepare_x(self.y, self.z);
self.r = self.do_something(self.x, self.other_params);
То ты очень быстро придешь к выводу, что даже префиксы и суффиксы — это гораздо меньше зло.

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

Зачем метод запрашивает поле из self?

Ну так ту же агитируют за поголовный explicit. А ну как x — это локальная переменная? Это ж гарантированные баги у новичков :)

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

Python и Go.

О, да, Go — это просто образец ООП.

«Ъ-ООП» - это такое же нерелевантное ограничение, как статическая типизация.

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

Да хоть миллиарды строк. Я буду работать с ней 8 часов в день, а насчет этого см. выше.

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

Я имею в виду другое. Строчкой выше `self.x` присваивается новое значение. Так зачем передавать `self.x` методу, если метод и сам может обратиться к `self.x`? А если метод `do_something` не использует внутри `self.x`, то зачем делать присваивание здесь?

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

«Ъ-ООП» - это такое же нерелевантное ограничение, как статическая типизация.

Ты для себя можешь выставлять какие хочешь ограничения. Меня интересуют именно такие.

Да хоть миллиарды строк.

Понятно. Когда на языке вроде Rust-а напишешь первую сотню тысяч строк, тогда вернешься и расскажешь про свои ощущения.

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

do_something может быть унаследованным из базового класса методом, который ничего не знает про self.x.

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

Когда на языке вроде Rust-а напишешь первую сотню тысяч строк

Я бы спросил, почему засчитывается только сотня тысяч строк, и чем Python хуже Rust в отношении explicit, но спор уже стал пустым.

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

Так я же не про Rust. Я хочу понять, что бы из себя представляли «языки мечты» у RazrFalcon, tailgunner-а и пр. сторонников чрезмерного стремления к explicit.

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

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

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

Я бы спросил, почему засчитывается только сотня тысяч строк

Потому что на таких объемах всякие неудачные эксперименты завершаются ничем и люди возвращаются к тому, что считается более-менее общепринятым.

Даже любители писать this-> в C++ довольно быстро прекращают это делать, когда им приходится писать, например, большие объемы вычислительного кода.

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

Я хочу понять, что бы из себя представляли «языки мечты»

Нет, ты проецируешь отдельно вырванные вещи из Rust на свои привычки.

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