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)

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

Покажите мне статический массив на стеке в swift. Насколько я знаю, компилятор swift сам решает, что размещать в куче, а что нет. Ну и там обязательный RC для кучи. О какой системщине идёт речь?

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

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

Ни разу у меня не приводило ни как к каким проблемам. Может я просто не злоупотребляю. Так что давай попробуем их поискать вместе. Вот Rust:

Some(Pattern::Color(ColorPattern::new(color::new(color.red, color.green, color.blue, color.alpha))))

Вот С++:

ColorPattern(color)

Какие проблемы меня ожидают?

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

Кто тут еще активно Rust защищает?

Я. Но я его не защищаю, так как у него множество проблем. Я же не фанатик, как лисперы. Но если выбирать C++ vs Rust для нового, домашнего проекта - то только Rust.

И да, я пишу на Rust.

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

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

И это замечательно, Правда мне уже не раз доказали, что он ненужен, но я все-равно рад.

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

Покажите мне статический массив на стеке в swift. Насколько я знаю, компилятор swift сам решает, что размещать в куче, а что нет. Ну и там обязательный RC для кучи. О какой системщине идёт речь?

Ты плохо знаешь Swift. Он решает за тебя для объектов. Все остальное - прекрасно ложится на стек. В том числе тебе никто не запрещает работать с кучей через указатели.

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

Ни разу
у меня

О чём и речь. Не все настолько богоподобны как вы. Даже профессионалы совершают ошибки и опечатки. А найти баг с перекрытием локальной переменной очень сложно.

Какие проблемы меня ожидают?

Начнём с того, что я не вижу что такое ColorPattern и color. Если ColorPattern() - это конструктор, то код с Rust не эквивалент, ибо Some там не нужен.

Вы можете написать на Rust так: ColorPattern::new(color) ну или ColorPattern::new(color.red, color.green, color.blue, color.alpha)

Это будет равноценный код.

Но это не тот implicit, о котором я говорил. Я говорил о проблемах, возникающих из-за неявного приведения, так как в c++ нет атрибута explicit для методов.

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

Ты плохо знаешь Swift.

Я его вообще плохо знаю. Только доку читал.

Но это не моя вина, ведь под gentoo его поставить - целый квест, а под винду его всё еще нет. Смысла учить язык, которого нет под 90% десктопа, для меня нет.

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

Не все настолько богоподобны как вы. Даже профессионалы совершают ошибки и опечатки

И таки давай не переводить тему. Я сделал много ошибок, но не из-за того, что при конструировании что-то скастилось не так. Ну или это было так давно и редко, что я уже не помню об этом. Потому и спрашиваю - что может пойти не так. Из того, что могу сам привести в пример, - NULL, но уже есть nullptr и в примере выше он не используется.

Начнём с того, что я не вижу что такое ColorPattern и color. Если ColorPattern() - это конструктор, то код с Rust не эквивалент, ибо Some там не нужен.

Pattern - хранит тип заливки, он может быть цветом, градиентом и пр. ColorPattern - структура, которая лежит под Pattern для того, что хранить информацию про заливку цветом. Можно сказать, что вся конструкция - аналог «QBrush( color )» на плюсах.

Но это не тот implicit, о котором я говорил. Я говорил о проблемах, возникающих из-за неявного приведения, так как в c++ нет атрибута explicit для методов.

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

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

Но если выбирать C++ vs Rust для нового, домашнего проекта - то только Rust.

как раз не так давно выбирал, выбор пал на C++

почему? мой домашний проект требует несколько проверенных и функциональных либ, которых на Rust нет, а тратить лишний год времени как то не хочется.

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

В расте if let конструкция применяется для раскрытия полноценного шаблона:

if let PATTERN = VALUE {} else {}
Но в свифте if let применяется только для раскрытия Option. Если я создам свой Option, то работать не будет. Чувствуешь разницу? Растовская конструкция универсальна.

Прямым аналогом твоего примера будет это:

if let Person {
    residence: Some(Residence {
        adress: Some(Adress {
           street: johns_street
        })
    })
} = john {
    print!("John's street name is {}.", johns_street)
} else {
    print!("Unable to retrieve the address.")
}
Весь код тут.

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

Он говорит про этот кусок https://github.com/servo/servo/blob/master/components/canvas_traits/lib.rs#L204-207

crate azure
crate gfx_traits

fn gfx_traits::color::new(r: AzFloat, g: AzFloat, b: AzFloat, a: AzFloat) -> AzColor;

impl azure::azure_hl::ColorPattern {
    fn new(color: AzColor) -> ColorPattern;
}

enum azure::azure_hl::Pattern {
    Color(ColorPattern),
    ...
}
anonymous
()
Ответ на: комментарий от anonymous

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

Это потому, что плюсах нет лайфтаймов, передачи this по значению и идеологии «явное - лучше неявного».

Покажите как запишите на Rust.

if let Some(johns_street) = john.residence.and_then(|r| r.adress).and_then(|a| a.street) {
    println!("John's street name is {}.", johns_street);
} else {
    println!("Unable to retrieve the address.")
}
Esper
()
Ответ на: комментарий от shaiZaigh

Но в свифте if let применяется только для раскрытия Option. Если я создам свой Option, то работать не будет. Чувствуешь разницу?

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

if case .Some(let x) = someOptional {
    print(x)
}
anonymous
()
Ответ на: комментарий от Esper

if let Some(johns_street) = john.residence.and_then(|r| r.adress).and_then(|a| a.street) {

Спасибо за вариант, но у shaiZaigh красивее. Хотя это субъективно, конечно.

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

но у shaiZaigh красивее

А ещё у него не полный аналог. Полный аналог в его варианте - такой:

if let Person {
    residence: Some(Residence {
        adress: Some(Adress {
            street: Some(johns_street), ..
        }), ..
    }), ..
} = john {
    println!("John's street name is {}.", johns_street);
} else {
    println!("Unable to retrieve the address.")
}

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

tailgunner не пишет, DarkEld3r не пишет. Кто тут еще активно Rust защищает?

И wota не пишет. Кто тут еще активно Rust хейтит?

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

вам повезло, что нету никаких зависимостей без которых эта либа не могла бы существовать :)

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

И wota не пишет. Кто тут еще активно Rust хейтит?

Ты только что соврал. За сегодня я уже написал пару сотен строк кода на Rust, не считая тестов. Пусть это пока и просто обертка над библиотекой, но она мне будет нужна дальше. Это раз. Два - я не хейтер, я хочу обсудить недостатки языка, перед тем как его использовать, ну и как бонус получить примеры правильных решений для различных простых задач. А для этого нужен флейм, а не вялое болото.

П.С. пока впечатления положительные, дойду до более сложных задач - будет новая порция комментариев от «хейтера».

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

Потому и спрашиваю - что может пойти не так.

class MyClass
{
public:
    MyClass()
    {
        MyData *ptr = new MyData;
    }

private:
    MyData *ptr;
}

Такие ошибки на каждом шагу. Да, сейчас начнутся рассказы что в C++11 нужно писать MyData *ptr = nullptr; и всё будет ок и прочие сказки. Но факт остаётся фактом. Это ошибка. И это UB. И компилятор ее проигнорирует.

аналог «QBrush( color )»

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

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

impl Color {
    fn new<T>(value: T) -> Color
        where Color: From<T>
    {
        Color::from(value)
    }
}

impl From<u8> for Color {
    fn from(value: u8) -> Color {
        Color { red: value }
    }
}

impl<'a> From<&'a str> for Color {
    fn from(value: &str) -> Color {
        Color { red: 255 }
    }
}

fn main() {
    println!("{:?}", Color::new(5));
    println!("{:?}", Color::new("red"));
}

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

И wota не пишет. Кто тут еще активно Rust хейтит?

Ты только что соврал. За сегодня я уже написал пару сотен строк кода на Rust.

А до этого ты за несколько недель (или месяцев?) написал пару сотен хейт-комментов. И нет, 200 строк - это не называется «писать». Столько и я написал.

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

Два - я не хейтер

Ты удачно маскируешься.

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

Такие ошибки на каждом шагу. Да, сейчас начнутся рассказы что в C++11 нужно писать MyData *ptr = nullptr; и всё будет ок и прочие сказки. Но факт остаётся фактом. Это ошибка. И это UB. И компилятор ее проигнорирует.

Вообще-то это уже совсем другая история. И тут нужно писать не = nullptr, а использовать unique_ptr.

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

Да, я в курсе. Но даже такой примитивный пример требует много бойлерплейта. Потому в первый раз все просто напишут портянку как выше, так быстрее. А потом и второй раз напишут, и так оно и останется.

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

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

print(Color(red: 5));
print(Color(name: "red"));
anonymous
()
Ответ на: комментарий от tailgunner

А до этого ты за несколько недель (или месяцев?) написал пару сотен хейт-комментов.

Обсуждать язык не только с положительной стороны - не значит хейтить.

И нет, 200 строк - это не называется «писать». Столько и я написал.

Ну так я же не считаю то, что писал на попробовать. Это решение конкретной задачи.

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

Кстати, выше пишут, что в Rust будет ? оператор, как в Swift. Мне кажется, или ты доказывал, что он не нужен, и правильно что его нет?

Ты удачно маскируешься.

На самом деле еще лучше чем ты думаешь. Но не буду раскрывать карты.

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

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

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

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

Не припомню, чтобы я это доказывал. Я считаю оператор ? ненужным уродством, но народу он нравится и в языке будет.

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

Это ошибка. И это UB. И компилятор ее проигнорирует.

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

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

Абсолютно серьезно. Я лично вижу в коде одну явную ошибку (используется ручной вызов new вместо make_unique) и одно подозрительное место (нет начального значения для MyClass::ptr, но это может быть сделано специально из-за соображений производительности). Но вы явно говорите о чем-то другом. О чем?

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

Тогда уж лучше Java.

Это настолько заезженная тема, но люди продолжают писать подобное.

Static
$ gcc -O2 -static hello.c -o static-c
$ g++ -O2 -static hello.cpp -o static-cpp
$ rustc -O --target=x86_64-unknown-linux-gnu hello.rs -o static-rs
$ du -h static-*
792K	static-c
2.4M	static-cpp
632K	static-rs

Dynamic
$ gcc -O2 hello.c -o dynamic-c
$ g++ -O2 hello.cpp -o dynamic-cpp
$ rustc -O -C prefer-dynamic hello.rs -o dynamic-rs
$ du -h dynamic-*
8.0K	dynamic-c
12K	dynamic-cpp
8.0K	dynamic-rs
anonymous
()
Ответ на: комментарий от anonymous

Я ошибся в указании target в Rust, вот правильный результат.

$ rustc -O --target=x86_64-unknown-linux-musl hello.rs -o static-rs
$ du -h static-*
792K	static-c
2.4M	static-cpp
628K	static-rs
anonymous
()
Ответ на: комментарий от RazrFalcon

Вы можете по-русски прямым текстом свою мысль выразить?

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

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

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

Я в первом посте чётко описал причину этой проблемы. Повторю еще раз: количество подобных ошибок довольно высокое у новичков. Но и у спецов может появится подобная ошибка после неудачного рефакторинга. И найти её потом будет очень сложно.

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

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

Я в первом посте чётко описал причину этой проблемы

Причина этой ошибки - элементарная забывчивость. Си++ здесь не причем, Rust от забывчивости тоже не страхует (и, честно говоря, возможность сделать несколько _локальных_ переменных с одним именем в Rust выглядит более серьезным источником путаницы).

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

java для jvm под helloworld тоже около 3Мб всего требует. так что похоже сказки о жабе жрущей память, неактуальны

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

Я в первом посте чётко описал причину этой проблемы.

Нашел разве что вот это: «О чём и речь. Не все настолько богоподобны как вы. Даже профессионалы совершают ошибки и опечатки. А найти баг с перекрытием локальной переменной очень сложно.»

Посему позволю себе задать уточняющий вопрос: правильно ли я понимаю, что в данном случае ваша претензия к С++ состоит в том, что в C++ можно дать локальной переменной метода такое же название, как и у атрибута класса?

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

Си++ здесь не причем

С++ тут при том, что аноним писал, что смысла писать self - нету. Я привел ему пример, где это полезно. Сам я, с подобной ошибкой, сталкивался всего пару раз, тем не менее, наличие self в rust меня радует.

возможность сделать несколько _локальных_ переменных с одним именем в Rust

Лол. Я сначала увидел это в доке, хотел багрепорт послать. Потом был сильно удивлён, когда пример скомпилися, и уже потом разобрался, что это на самом деле так и задумано. Хз зачем. Возможно из-за повсеместного move.

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

правильно ли я понимаю

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

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

Это было выбрано для примера, чтобы показать целесообразность использования self.

Да уж. Даже у меня в проектах счет методов в классах идет на тысячи штук. И это только определения методов, не считая их вызовов. Что уж говорить о проектах объемом в десятки миллионов строк. Передавать везде в этих случаях self для того, чтобы не совершать ошибку, которая элементарно обходится простейшими соглашениями об именовании имен — это сильно.

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

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

Как ветеран Python спрошу - в чем проблема «передачи self»? Ну, кроме как написать лишних 5 символов.

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

Рантайм в 100М не в счет, конечно

в рантайме шревты, часовые пояса, либы для мультимудии, для gui, все это и в расте не 1024байта займет

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

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

в рантайме шревты, часовые пояса, либы для мультимудии, для gui

Ты хотел размерами хелловорлда померяться? Вот и меряйся, не виляй.

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

Как ветеран Python спрошу - в чем проблема «передачи self»?

В том, что нужно делать лишнюю работу, которую можно не делать. Да-да, писать эти лишние символы. Ну и думать, где их писать (в определении нестатических методов), а где не писать (в определении статических методов).

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

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

Передавать везде в этих случаях self для того, чтобы не совершать ошибку,

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

impl Type {
	fn foo() {} // static
	
	fn foo(self) {} // copy or move
	fn foo(mut self) {} // copy or move with mut
	
	fn foo(&self) {} // borrow
	fn foo(&mut self) {} // mutable borrow
}

Представим, что теперь не надо писать self.

impl Type {
	fn foo() {} // static
	
	move fn foo() {} // copy or move
	mut move fn foo() {} // copy or move with mut
	
	ref fn foo() {} // borrow
	mut ref fn foo() {} // mutable borrow
}

Лично мне больше нравиться первый вариант.

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

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

Ну в этом-то хоть есть какой-то смысл. А вовсе не в том, о чем RazrFalcon говорил.

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

хелловорлд жрет 3Мб а рантайма 12Мб rt.jar ему достаточно. можно 88Мб остальных либ поудалять и все будет работать

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

хелловорлд жрет 3Мб

Это вранье.

а рантайма 12Мб rt.jar ему достаточно

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

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