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)

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

Сейчас такие штуки через build-скрипт проворачивают.

Каким образом?

Имхо, намного удобнее, чем CTFE.

Трудно представить что-то более удобное, чем правильное CTFE.

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

https://github.com/sfackler/rust-phf

Это какой-то кодогенератор. Юзать такое для задач уровня сложности «посчитать факториал в компайл-тайме» - явная наркомания.

С кучей ограничений?

Отсутствие непортабельной хрени и обращений к глобальным переменным? Жосткие ограничения, ога.

Для мелочёвки - да. Для сложного - не очень.

CTFE и нужно для «мелочёвки».

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

Единственный CTFE который я видел, это в C++11. И он там способен на сущие мелочи. Шаг в сторону - и получаем 100500 строк не читаемой лапши на шаблонах.

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

Единственный CTFE который я видел, это в C++11.

Расширяй кругозор.

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

Единственный CTFE который я видел, это в C++11. И он там способен на сущие мелочи. Шаг в сторону - и получаем 100500 строк не читаемой лапши на шаблонах.

CTFE в C++11, как и метапрограммирование на шаблонах, — это побочный эффект от инструментов, предназначенных для совсем других целей. Соответственно, нужно десять раз подумать, прежде чем браться за CTFE в C++.

Вот тот же D если взять, который более-менее похож на С++ (С#/Java), то в нем CTFE на совсем другом уровне.

eao197 ★★★★★
()

Ребят, а что в расте с многопоточностью? Как там будет выглядеть программа сложения миллиарда 8-байтных интов наподобие https://play.golang.org/p/99CNE3wtIW С растом не знаком, но интересно.

anonymous
()

И снова я здесь с вопросом. Мне надо реализовать трейт Index, но при этом возвращать новое значение, а не ссылку. Как это правильно сделать?

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

Я вкурсе.
Но эрэфцэ это эрэфцэ, когда имплементация пока не ясно.

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

Ты не понял. Мне нужно именно имплементация уже имеющегося трейта.
Не моего.
Т.е. всяких Clone, Copy и пр. которые вовсю используются в языке.

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

Мне нужно именно имплементация уже имеющегося трейта.

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

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

Ты не понял. Мне нужно именно имплементация уже имеющегося трейта. Не моего. Т.е. всяких Clone, Copy и пр. которые вовсю используются в языке.

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

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

А если еще точнее - в index мне нужно создать новую структуру и вернуть ее наверх.

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

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

Нет. Я хочу реализовать Clone и Copy для массива больше чем 32 элемента.

Временное ограничение языка, используй вектор.

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

Ну да, так и приходится делать.

Вот только вместо

struct MyStruct{
    field1: i32,
    field2: [u16;48]
}

let s:MyStruct = some_fun();
let b = s.field1[1];


Приходится писать
struct MyArrU16([u16;48]);

struct MyStruct{
    field1: i32,
    field2: MyArrU16
}

let s:MyStruct = some_fun();
let b = s.field2.0[1];



Оно конечно работает и всё-такое. Но какта ниочинь.

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

Да там вектор по сути это излишество.
к тому же нужен постоянный размер.
проще свой struct MyArrU16([u16;48]); использовать.

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

Как-то так:

extern crate rayon;

use std::time::SystemTime;
use rayon::par_iter::{IntoParallelIterator, ParallelIterator};

fn main() {
    let start_time = SystemTime::now();
    let ints = vec![0i64; 1000000000];
    let sum = ints.into_par_iter().sum();
    println!("sum {}", sum);
    println!("time {:?}", start_time.elapsed().unwrap());
}

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

Но какта ниочинь.

А зачем ты хранишь MyArrU16? Храни [u16; 48] и оборачивай только там, где нужно клонировать:

struct MyStruct{
    field1: i32,
    field2: [u16; 48],
}

let s = MyStruct {field1: 10, field2: [0; 48]};
let Array(a) = Array(s.field2).clone();
let b = s.field2[1];
Esper
()
Ответ на: комментарий от eao197

И в чем же ошибка? Разработчик захотел локальную переменную с тем же именем, что и атрибут класса. Захотел — сделал. Ошибка-то где?

ошибка в том, что язык не требует для этого случая указать явно [[override]] или че-то в этом духе

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

А зачем ты хранишь MyArrU16? Храни [u16; 48] и оборачивай только там, где нужно клонировать:

let Array(a) = Array(s.field2).clone();
let b = s.field2[1];

Как это вообще работает? Слайс фиксированного размера подставляется по значению, поэтому и копироваться должен по значению. И он не имплементит Copy, соответственно при присваивании должен перемещаться во временный Array() и уничтожаться после завершения метода clone.

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

ошибка в том, что язык не требует для этого случая указать явно [[override]] или че-то в этом духе

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

template< typename T >
class derived_from_param : public T {
  public :
    derived_from_param() {
      auto attr = make_unique<Sample>(...);
      ...
    }
  ...
};
В этом случае никакого криминала не будет:
struct First {
  unique_ptr<Sample> m_attr;
  ...
};
using FirstDemo = derived_from_param<First>;
А вот в этом уже будет:
struct Second {
  unique_ptr<Sample> attr;
  ...
}
using SecondDemo = derived_from_param<Second>;

Ну и как здесь должен себя вести «правильный язык»?

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

И в чем же ошибка? Разработчик захотел локальную переменную с тем же именем, что и атрибут класса. Захотел — сделал. Ошибка-то где?

Разработчик случайно создал внутри конструктора переменную, которая выглядит как поле. В итоге поле оказалось непроинициализировано, что с++ разрешено, но означает неопределённое поведение. Собственно, тут 2 мелкие претензии к языку, которые в сумме дают большую проблему.

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

Так мне структуру целиком надо клонировать.

Реализуй Clone для структуры ручками. Конечно, получится не так красиво, как #[derive(Clone)], зато избавишься от уродского field2.0 на протяжении остального кода. Ну и да, не понимаю, в чём проблема заюзать Box<[u16]>/Vec<u16>/whatever.

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

Как это вообще работает?

Легко и непринуждённо.

Слайс фиксированного размера

Вообще, массив, но это мелочи.

И он не имплементит Copy

Имплементит.

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

Реализуй Clone для структуры ручками.

Ну разве что. Только кода чуть побольше будет.

Ну и да, не понимаю, в чём проблема заюзать Box<[u16]>/Vec<u16>/whatever.

Потому что #[repr(C)] и FFI во все поля.

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

Согласно доке и даже исходникам растовой либы, trait Copy наследуетcя от Clone.

Всем пофиг. В доке написано, что массив реализует Copy, если элементы реализуют Copy - и пусть хоть обнаследуется. Если авторам языка пофиг, нам-то что париться?

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

Ну и в плюсах не нужно писать this первым параметром для методов.

Зато нужно писать явно static или const (после). Просто другие умолчания. Пожалуй, в итоге получится слегка более многословно из-за того, что «обычных методов», как правило, больше. Но тут опять «более очевидно». Вместо неявной передачи this, явно передаётся self. Как по мне, так это не принципиально, хотя наличие «единого подхода», в моих глазах, оправдывает необходимость писать на пару букв больше.

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

Сейчас - по уродски или через try!. Но вы не переживайте - оператор ? уже в RFC и скоро будет в языке.

Разве он поможет в приведённом примере? «Оператор ?», как и try! делают ранний return, а там нужно продолжать вызовы или отдать None.

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

Это опять же - сахар:

Я не совсем уловил. Так что будет работать со своим Option или нет?

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

П.С. аналог на Swift:

struct Color {
    var r: UInt8
    
    init(red: UInt8) { r = red; }
    init(name: String) { r = 255; }
}

print(Color(red: 5));
print(Color(name: "red"));

Как по мне, то аналогим на расте будет не вариант с From, а вот это:

#[derive(Debug)]
struct Color {
    r: u8,
}

impl Color {
    fn new(red: u8) -> Color { Color{ r: red } }
    fn from_string(name: &str) -> Color { Color { r: 255 } }
}

println!("{:?}", Color::new(5));
println!("{:?}", Color::from_string("red"));
И кода получается не особо больше.

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

fn foo(mut self) {} // copy or move with mut

Кстати, в этой штуке вообще смысл какой-то есть?

struct S { a: i32 }

fn foo(s: S) {
    //s.a = 20; // cannot assign to immutable fiel
    let mut s = s;
    s.a = 20; // OK
}

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

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

А чем суффиксы лучше префиксов? У префиксов есть хотя бы (очень небольшое) удобство в том, что после того как набрал его, ИДЕ покажет именно члены-данные, отсеяв функции.

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

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

Дык, скорее наоборот - это краткая форма позволяет не указывать лайфтайм, который просто автоматически выводится. Так что это ещё один плюс к однородности синтаксиса: мы просто выкидываем лайфтаймы, а база остаётся обычной. Если бы выбрали подход «как в С++», то в варианте с лайфтаймом его непонятно куда впихивать пришлось бы.

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

А чем суффиксы лучше префиксов?

У некоторых разработчиков есть аллергия на префиксы :) Они будут писать x_, но никогда не напишут m_x.

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

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

Именно поэтому есть тип Self.

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

Как по мне, то аналогим на расте будет не вариант с From, а вот это:

А почему для u8 - new, а для str - from? Тогда уж from_rgb/from_rgba/from_hsl/from_string/....

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

У некоторых разработчиков есть аллергия на префиксы :) Они будут писать x_, но никогда не напишут m_x.

Так ведь писать _x для членов класса - «законно»? В смысле, имена начинающиеся с одного подчёркивания зарезервированы только в глобальном пространстве имён. По количеству символов получится одинаково, неужели аллергия так сильна? (:

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

А почему для u8 - new, а для str - from? Тогда уж from_rgb/from_rgba/from_hsl/from_string/....

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

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

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

Не собираюсь доказывать полезность явного self, как по мне, он уместен в расте по нескольким причинам и далеко не все имеют смысл в других языках. Но вот конкретно этот аргумент весьма так себе.

По большому счёту, новые языки (или их обновленные версии) привносили дополнительные удобства. Есть, конечно, спорные моменты, но можем взглянуть хотя бы на unique_ptr из плюсов - без него ведь как-то код писали. На С вон даже нельзя свой аналог сделать и тоже живут как-то. Так что отбрасывать новое с аргументов «раньше без него обходились, значит и дальше обойдёмся» не самая лучшая идея.

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

Так ведь писать _x для членов класса - «законно»?

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

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

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

Попробую объяснить еще раз: я не утверждал, что self в Rust-е — это плохо для Rust-а. Просто когда люди начинают говорить, что нечто подобное они хотели бы видеть вне Rust-а, тут уж хочется понять зачем и какие от этого будут выгоды. Особенно, если говорить про языки с более-менее нормальным ООП (вроде C++ или Eiffel).

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

ли менее популярных haskell, ну или еще менее популярный lisp. Они ни разу не похожи на C.

Дык, оригинальный синтаксис этих языков «хейтеры», зачастую, записывают в причины их «провала».

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

если хочется еще добавить возможность сделать вызов Color::new() без аргументов для создания дефолтного объекта

Не совсем по теме, но «дефолтный» объект принято создавать через реализацию трейта Default.

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

А в планах они есть?

Конечно. Если ничего не путаю (лень перечитывать), то отложили просто потому что целенаправленно шли к 1.0, а сделать это можно и потом и, в принципе, без поломки совместимости. Последние аргументы против «реализации в лоб»: так можно проще ломать АПИ библиотек. Как по мне, удобство того стоит, но тут опять подключаются «борцы за явность». В результате предлагаются монструозные конструкции, где надо каждый такой аргумент помечать как pub.

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