LINUX.ORG.RU

Rust 1.26

 


5

11

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

Обновить Rust можно с помощью команды:

curl https://sh.rustup.rs -sSf | sh # если у вас еще не установлен rustup
rustup update stable

Основные изменения:

  • Вторая редакция книги «The Rust Programming Language» (почти) готова, и теперь рекомендована по умолчанию для ознакомления вместо первой версии. Также готовится к выходу бумажное издание книги.
  • impl Trait в заголовках функций

    Стало возможно указывать Trait в заголовке функции в качестве типа возвращаемого значения:

    fn foo() -> impl Iterator<Item = i32> {
        // ...
    }
    
    Это позволяет не указывать полный тип в заголовке функции, если с точки зрения API конкретный тип не имеет значения. Такой синтаксис подразумевает статическую диспетчеризацию, в отличие от Box<Trait>.

    Также эта возможность удобна для использования с замыканиями (closures):

    fn foo() -> impl Fn(i32) -> i32 {
        |x| x + 1
    }
    

    Новый синтаксис теперь можно использовать и для типов аргументов фунции:

    // раньше нужно было писать так:
    fn foo<T: Trait>(x: T) {
    
    // сейчас можно так:
    fn foo(x: impl Trait) {
    

  • Неявное разыменование ссылок в сопоставлении с образцом (match, if let, ...)

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

    fn hello(arg: &Option<String>) {
        match arg {
            Some(name) => println!("Hello {}!", name),
            None => println!("I don't know who you are."),
        }
    }
    
    и эквивалентен такому:
    fn hello(arg: &Option<String>) {
        match arg {
            &Some(ref name) => println!("Hello {}!", name),
            &None => println!("I don't know who you are."),
        }
    }
    
    То же работает и для &mut + ref mut.

  • Раскрытие срезов (slice) в сопоставлении с образцом
    fn foo(s: &[u8]) {
        match s {
            [a, b] => (),
            [1, _, _] => (),
            _ => (),
        }
    }
    
  • Закрытые интервалы вида 0..=4, включающие обе границы в диапазон перечисления
        for i in 0..=4 {
            println!("i: {}", i); // выведет 0, 1, 2, 3 и 4
        }
    
  • Новые целочисленные типы i128 и u128
  • Функция main() теперь может возвращать тип Result
    use std::fs::File;
    
    fn main() -> Result<(), std::io::Error> {
        let f = File::open("bar.txt")?;
    
        Ok(())
    }
    
  • Ускорения в работе компилятора
  • Стабилизирована функция std::fs::read_to_string
  • При форматировании через trait Debug теперь можно выводить целочисленные значения в шестнадцатеричном виде:
    assert!(format!("{:02x?}", b"Foo\0") == "[46, 6f, 6f, 00]")
    
  • Номер версии Cargo, начиная с этого релиза, изменяется синхронно с номером версии Rust

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

★★★★★

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

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

Позже, на этапе связывания функций будет выяснен настоящий тип переменной и сгенерирован код для конкретного этого типа.

https://play.rust-lang.org/?gist=8402bcb104f360a9f592bf5ec7137f59&version...

Рядом с кнопкой «Run» есть кнопка с тремя точками, потом «MIR». Никакого этапа связывания.

Больше всего это похоже на ассоциированный тип трейта. В принципе, можно назвать и дженериком, если в очень больших кавычках.

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

Лол, раст - как квантовая механика. Никто в ней не разбирается, но все не прочь о ней многословно порассуждать. impl Trait - не дженерик, иди читай мануал, пока не просветлишься.

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

Ну так что, реальный тип переменной b можно вывести?

Да.

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

Ты точно в состоянии измененного сознания, если думаешь, что умеешь читать мысли.

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

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

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

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

go крутит свои треды которые значительно быстрее системных

вопрос был не в очередном холиваре, а в поиске возможности превзойти go в данном аспекте

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

Рядом с кнопкой «Run» есть кнопка с тремя точками, потом «MIR». Никакого этапа связывания.

фейспалм.jpg.

Т.е. если компилятор C++ идёт с препроцессором в виде отдельной тулзы, то можно говорить об этапе препроцессинга, но как только препроцессор интегрируют внутрь компилятора, то говорить об этом этапе сразу становится нельзя и любые слова о различии #define XXX 1 и constexpr int XXX = 1 становятся ересью?

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

Лол, раст - как квантовая механика. Никто в ней не разбирается, но все не прочь о ней многословно порассуждать. impl Trait - не дженерик, иди читай мануал, пока не просветлишься.

Ты-то точно не разбираешься. Но это полбеды. Ты неспособен не только освоить мануал, но и простой короткий текст. Я с самого начала писал, что impl trait - это не дженерик. Внезапно, да?

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

Господи, почему все гоферы такие тупые?

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

Да.

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

Сразу предупреждаю, не пытайся впарить замыкания: они внутри одной функции пишутся.

Ты точно в состоянии измененного сознания, если думаешь, что умеешь читать мысли.

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

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

в чем отличие «дешевле» от «быстрее»? меньше грузят проц?

Расходы ОС меньше - один стек на несколько нитей, более короткие очереди планировщика (M:N threading). Но, ЕМНИП, результаты тестов на Linux отличаются не сильно.

tailgunner ★★★★★
()
Ответ на: комментарий от khrundel
trait MyTrait {}

impl MyTrait for i32 {}

fn get_my_trait() -> impl MyTrait + std::ops::Add {
    1
}

fn main() {
    let a = 1;
    println!("a + 1 == {}", a + 1);
    let b = get_my_trait();
    println!("b + 1 == {}", b + 1);
}

Вывод:

error[E0308]: mismatched types
  --> src/main.rs:10:35
   |
10 |     println!("b + 1 == {}", b + 1);
   |                                   ^ expected anonymized type, found integral variable
   |
   = note: expected type `impl MyTrait+std::ops::Add`
              found type `{integer}`

Компилятор тоже думает, что на выходе функции описан анонимный тип.

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

Ну так что, реальный тип переменной b можно вывести?

Да.

Продемонстрируй.

Но ведь тебе это уже продемонстрировали. ЧСВ мешает по ссылкам ходить? Окей, вот:

#[inline(never)]
fn foo() -> impl Debug {
    1u32
}

Вот сгенерированный MIR:

fn foo() -> u32{
    let mut _0: u32;                     // return place

    bb0: {                              
        _0 = const 1u32;                 // bb0[0]: scope 0 at src/main.rs:5:5: 5:9
                                         // ty::Const
                                         // + ty: u32
                                         // + val: Value(ByVal(Bytes(1)))
                                         // mir::Constant
                                         // + span: src/main.rs:5:5: 5:9
                                         // + ty: u32
                                         // + literal: const 1u32
        return;                          // bb0[1]: scope 0 at src/main.rs:6:2: 6:2
    }
}

Видишь возвращаемый тип foo? А теперь иди проспись.

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

Компилятор тоже думает, что на выходе функции описан анонимный тип.

Я чёт малёха запутался, это возражение на тему анонимности или что? Если анонимность, то анонимный на языке псоглавых будет anonymous, а не anonymized.

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

Но ведь тебе это уже продемонстрировали. ЧСВ мешает по ссылкам ходить? Окей, вот:
Вот сгенерированный MIR:

LOL. А чё сразу дизассемблированный код не написал?

Ты задание прочитал? Ты утверждал, что возможен вывод типа за границами функций. Я жду подтверждения. Не надо мне ни MIR, ни LLVM IR, ни ассемблера, ни машинных кодов, мне нужен текст программы на Расте, в которой компилятор выведет настоящий тип переменной не из прототипа функции, а из её тела, и на основании этого знания позволит или не позволит выполнить операцию. Т.е. нужно чтоб я, изменив только внутри тела твоей функции foo 1u32 на, например, 1i32 или на строку, получил ошибку компиляции в функции main, которая твою foo() вызывает.

Вот подобный код внутри одной функции я написать могу. Можно не указать параметр типа вектора и сделать пуш 2х переменных в него, тип которых также явно не указан, в итоге успешность компиляции будет зависеть от того, вывелся ли у обеих переменных одинаковый тип или разный.

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

А чё сразу дизассемблированный код не написал?

Необходимости не было.

Ты утверждал, что возможен вывод типа за границами функций.

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

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

Я чёт малёха запутался, это возражение на тему анонимности или что?

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

Если анонимность, то анонимный на языке псоглавых будет anonymous, а не anonymized.

https://translate.google.com/m/translate#auto/ru/anonymized

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

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

Ну вот, пошли отмазки. Не пытайся сделать вид, что тут как-то привязан дженерик в кавычках, мы о другом. Ты мне лично пообещал вывод типа в случае impl trait такого же качества, как для варианта внутри функции. Чтоб было одинаково хорошо с let a = 1; и let b = foo();, где foo возвращает impl trait, но реально i32. Вот это и показывай. Не юли, не пытайся выдать MIR или ещё чего, я и без тебя знаю, что в конце концов в бинарнике будет статически правильный тип.

Ну либо признай, что был не прав, что вывод типа (тот самый вывод типа, определённый в спецификации языка) в случае impl trait даёт не реальный тип, а некий плейсхолдер, реальный же тип либо выясняется где-то на более позднем этапе (но до непосредственной кодогенерации), либо rustc делает вид, что не знает, когда анализирует функцию.

Вообще, вынужден добавить, что это конкретный идиотизм на MIR ссылаться: MIR - это внутренняя кухня rustc, он относительно недавно появился вообще, и он вовсе необязателен, ты в любой момент можешь взять да написать альтернативный компилятор rust, который вместо MIR будет другую хрень использовать, может в новой версии rustc mir заменят на что-то другое и у тебя там будет стоять не i32, а impl Debug.

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

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

Не, мужык, это не _мы_ о другом - это ты о чем-то своем, причем то об одном, то о другом. А я говорю, что компилятор знает настоящий тип значения, возвращаемого через impl Trait, причем знает его и в месте определения функции, и в месте ее вызова. А в остальном ты споришь с голосами в своей голове.

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

Не, мужык, это не _мы_ о другом - это ты о чем-то своем, причем то об одном, то о другом. А я говорю, что компилятор знает настоящий тип значения, возвращаемого через impl Trait, причем знает его и в месте определения функции, и в месте ее вызова. А в остальном ты споришь с голосами в своей голове.

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

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

Ещё раз, я тебя спросил, можно ли вывести реальный тип. Ты ответил что да.

Да, и он выведен компилятором.

Я с тебя тяну пример вывода типа. «Вывод типа» если что - это такая фича языка Rust.

Анонимные типы - тоже (ах да, анонимизированные, anonymized). Если ты «тянул пример» вывода анонимизированного типа - кто ж тебе доктор.

Вопрос что там знает компилятор rustc во время вызова функции или чего не знает нерелевантен вообще никак.

А что релевантно? Что ты хочешь знать - настоящий тип значения анонимизированного типа? Серьезно?

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

А я думал что я единственный кто про какие-то «монады», «моноиды » читает. Теория категорий там и все такое. Но это я вижу только функцинальных языках программирования.

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

Это он наверное об этом:

go крутит свои треды которые значительно быстрее системных

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

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

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

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

А еще гошные супер-треды могут размер своего стека менять при необходимости. Жалкому расту до го как до луны

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

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

это какие, например?

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

мы же про safety говорим, не про security?

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

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

Тот, кто платит, далеко не всегда сможет отличить молоток от отвертки. Не то что бы я считал, что это хорошо

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

я имел в виду в вебе, а то по сути это обсуждение не форум а чат, телеграм надо ставить, я им не пользуюсь, irc опять ставить, джаббер - хз

а тут просто комната ткнул и ты там, даже регаться ненадо https://www.lonje.com/chatroom/lor/

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

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

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

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

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

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

Если тебе всё понятно, то бы не назвал уродцами языки семейства ML.

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

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

Попрошу кефир из треда.

Ещё раз: если ты не осилил, то это твои проблемы.

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