LINUX.ORG.RU

Rust 1.88.0

 

Rust 1.88.0

0

4

Опубликован следующий стабильный релиз компилятора и стандарта языка Rust.

В этой версии добавлены следующие возможности:

  1. Синтаксис для описания функций без пролога и эпилога. Тело таких функций обязано состоять из naked_asm! блока :
#[unsafe(naked)]
pub unsafe extern "sysv64" fn wrapping_add(a: u64, b: u64) -> u64 {
    // Equivalent to `a.wrapping_add(b)`.
    core::arch::naked_asm!(
        "lea rax, [rdi + rsi]",
        "ret"
    );
}
  1. Возможность объявлять две и более переменных в условных выражениях if / while:
if let Channel::Stable(v) = release_info()
    && let Semver { major, minor, .. } = v
    && major == 1
    && minor == 88
{
    println!("`let_chains` was stabilized in this version");
}
  1. В DSL для условной компиляции cfg добавлены константы true и false, которые так же стали доступны в макросе cfg!.

  2. Добавлено предупреждение о попытке обращения к нулевому указателю для функций, чьи инварианты корректной работы требуют не нулевых адресов. К примеру попытка сконструировать объект std::slice по нулевому адресу:

// Undefined behavior
unsafe { std::slice::from_raw_parts(ptr::null(), 1); }

приведёт к выдаче сообщения. По умолчанию это предупреждение имеет уровень deny-by-default, то есть будет рассмотрено компилятором как ошибка.

Все нововведения перечислены в списке изменений.

>>> Announcing Rust 1.88.0

★★★★★

Проверено: dataman ()
Последнее исправление: dataman (всего исправлений: 3)
Ответ на: комментарий от MOPKOBKA

Вообще, странный пример. Можно же намного проще:

if let Channel::Stable(Semver { 1, 88, .. }) = release_info()
{
    println!("`let_chains` was stabilized in this version");
}

Хотя, понятное дело, иллюстративная составляющая пропадает.

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

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

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

когда заявлено прямое взаимодействие с C++

Исключений нет как минимум. Значит нет никакой STL даже в С++98 варианте.

sarumeister
()

Посмотрел на календарь. Вроде не первое апреля. Или это меня глючит. Чтоб в раст добавили qol фичу, да еще и такую вкусную? Эко я знатно в коме полежал

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

А в Rust так можно? Ужас. А если порядок полей поменяется в структуре? Надо было сделать требование указывать имя поля.

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

Во-первых, так тоже можно if let User{name: username, addr: mail, ..} = user { ... }
А во-вторых, а какое имя ты будешь писать, если там не структура, а кортеж?

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

Как в OCaml. Если кортеж то имя не пишется. Если структура, то имя поле пишется. А обращение без указания поля приведет рано или поздно к ужасным ошибкам, они бы еще додумались через val[int] сделать обращение.

Теперь когда ты рассказал что имя поля вписывается опционально, можно сделать честное сравнение с матчингом:

if let Channel::Stable(Semver { major: 1, minor: 88, .. }) = release_info()
{
    println!("`let_chains` was stabilized in this version");
}
struct semver v = release_info();
if (info.major == 1 && info.minor == 88) 
  printf("c was stabilized");

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

честное сравнение с матчингом

В честном сравнении отсутствует аналог Channel::Stable. Ну и если уж на то пошло, засирается область видимости структурой v и неизвестно откуда взявшейся info.

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

Не вижу там union, уж очень запутанный синтаксис у этого вашего Rust. Определения функции тоже не нашел, если оно существует.

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

Первая же сточка, if let Channel::Stable(v) = release_info(). Тип результата release_info() это сумма, а if let это проверка того, что значение является конкретным вариантом, и одновременно извлечение значения из этого варианта.

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

В Ada это было бы нечто вроде

ri := release_info();
if ri.kind = Channel.Stable and ri.major = 1 and ri.minor = 88 then
    ...
end if;

Ada проверяет в рантайме, обратился ли ты к существующим полям, когда же раст энфорсит это дело синтаксически. Отсюда потребность в сахарке.

quantum-troll ★★★★★
()
Последнее исправление: quantum-troll (всего исправлений: 1)
Ответ на: комментарий от MOPKOBKA
struct semver v = release_info();
if (info.major == 1 && info.minor == 88) 
  printf("c was stabilized");

Что за переменная info, откуда взялась? v наверное?

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

У плюсов фичи 26 стандарта уже определены. А следующий стандарт будет не раньше 29 года. Ну можно не торопиться, ага.

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

И почему же?

Потому что за приравнивания и создания переменных в if надо бы бить ссаными тряпками по морде. Ибо с какого перепугу тот кто читает этот код должен думать, а это у вас приравнивание или вы просто забыли добавить ещё =.

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

В случае сишечки это скорее было бы так:

semver v = release_info();
if(v.kind == STABLE && v.stable.major == 1 && v.stable.minor == 88)
 printf("c was stabilized");

где release_info возвращает что-то типа этого:

typedef enum { BETA, STABLE } kind;

typedef struct { int major; int minor; } Beta;
typedef struct { int major; int minor; } Stable;

typedef struct {
    kind kind;
    union{
        Beta beta;
        Stable stable;
    };
} semver;
WatchCat ★★★★★
()
Ответ на: комментарий от WatchCat

где release_info возвращает что-то типа этого

Больные ублюдки.

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

Нормальные программисты «ещё =» не забывают. Если там написано приравнивание - значит это приравнивание.

firkax ★★★★★
()
Ответ на: комментарий от rk-d

Именно поэтому пишется if let a = … . Вы не сможете здесь перепутать = и ==

А давайте вы будете создавать переменные вне блока проверки условий if, чтобы не думалось?!

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

А с чем же связано такое острое желание вынести переменную за иф?

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

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

{
  semver v = release_info();
  if(v.kind == STABLE && v.stable.major == 1 && v.stable.minor == 88)
    printf("c was stabilized");
}
unC0Rr ★★★★★
()
Ответ на: комментарий от Ygor

Найди тут создание переменной, назови её идентификатор:

if let Channel::Stable(Semver { 1, 88, .. }) = release_info()
{
    println!("`let_chains` was stabilized in this version");
}
unC0Rr ★★★★★
()
Ответ на: комментарий от Ygor

Условие не сработает если release_info() не возвращает Channel::Stable, и не сработает если версия не 1 и 88.

Выше понятно переписали на С:

struct semver {
    enum { BETA, STABLE } kind;
    int major, minor;
};

struct semver v = release_info();
if (v.kind == STABLE && v.major == 1 && v.minor == 88)
 printf("c was stabilized");

Как видишь AND(&&) идет по трем проверкам.

Еще проще, синтаксис let X = Y, это не синтаксис int X = Y из С. Это не let NAME = VALUE, это let PATTERN = VALUE, где VALUE проверяется на PATTERN.

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 5)
Ответ на: комментарий от quantum-troll

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

struct semver {
    enum { BETA, STABLE } kind;
    union {
      struct { int major, minor; };
      struct { int revision; };
    };
};
MOPKOBKA ★★★★★
()
Ответ на: комментарий от Ygor

Давай рассахарю:

match release_info() {
    Channel::Stable(v) =>
        match v {
            Semver {1, 88, ..} => {
                println!("`let_chains` was stabilized in this version");
            }
            _ => {}
        }
    _ => {}
}


Работает так:

Разберём результат функции release_info():

- Пусть результатом является значение вида `Channel::Stable(v)`, где v некоторое значение
    - Разберём v
        - Пусть v совпадает со значением `Semver {1, 88, ..}`
            - Тогда будет выполнено `println!(...)`
        - Пусть v это иное значение
            - Тогда ничего не будет выполнено
- Пусть результатом является иное значение
    - Тогда ничего не будет выполнено


`if let PATTERN = EXPR {...}` это буквально сахар для `match EXPR { PATTERN => ..., _ => {} }`.

quantum-troll ★★★★★
()
Последнее исправление: quantum-troll (всего исправлений: 2)
Ответ на: комментарий от MOPKOBKA

В Rust нельзя добавить if на каждый or в match, не ожидаешь такого от «современного» языка.

enum Color {
    Green(i32),
    Black(f32)
}

fn test(color: Color) {
    match color {
        Color::Green(x) if x > 10 | Color::Black(y) if y > 10.0 => {
            println!("Hello World");
        }
        _ => println!("_")
    }
} 

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

Кстати, смотри, в Rust даже abs() функция не работает!

https://godbolt.org/z/M898djbno

Ну язык так язык... Справа внизу вывод:

abs(int) = -2147483648

Очень безопасно, это вам не сишка.

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

Играл с переполнениями @ проиграл.

Норм троллинг, смешной.

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

Интересно, а как ты ожидаешь твои x и y будут вести себя внутри блока, если только один из них разматчивается, а один и тот же идентификатор невозможно использовать, потому что типы разные?

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

Это не let NAME = VALUE, это let PATTERN = VALUE

Это, конечно, le classique как делают язык "с у чётом опыта си / с++" и тут же кидаются отчебучивать чечётку на граблях с переиспользованием одного и того же ключевого слова в разных контекстах для абсолютно не связанной семантики.

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

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

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

Нету никакого переиспользования в разном значении, let x = 10 это тоже let PATTERN = VALUE, а не let NAME = VALUE, просто тут нету деструктуризации, а сразу вся правая часть матчится на имя слева.

Например mut относится к имени которое забирает значение из правой части:

let x = (10, 20);
let (mut y, z) = x;

Или вот еще пример, аргументы функций, можно вот так определить один аргумент принимающий кортеж из двух чисел, и распаковать сразу такой аргумент по переменным:

fn get_sum((x, y): (i32, i32)) -> i32 {
  return x + y;
}

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

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

let x = 10 это тоже let PATTERN = VALUE

Постой, постой. Rust book меня уверяет, что

let x = 5;

создаёт константу x со значением 5 (и типом, производным от литерала).

Он что же это, обманывает меня?!?

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

x это тоже паттерн. Только совсем простой.
Да, в результате патматчинга ты получаешь свою константу с нужным значением.

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

Нету никакого обмана, проводится сопоставление x :: 5, и на основе этого создается константа x.

Можно создать две константы сразу:

let (x, (y, _, _)) = (5, (10, 20, 30));

Советую рассмотреть диаграмму: https://doc.rust-lang.org/reference/statements.html#r-statement.item.outer-ge...

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

В OCaml еще можно написать:

let 10 = 10
Но в Rust специально для такого случая ввели дополнительный, ненужный синтаксис (хотя он условный, а в OCaml это как assert):
if let 10 = 10 {}
Вот он как раз в ОП-посте.

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 2)
Ответ на: комментарий от quantum-troll

в результате патматчинга ты получаешь свою константу с нужным значением

А почему в результате ’if let’а я её не получаю?

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

Получаешь:

if let x = 10 { println!("{}", x) };
Этот код всегда будет выводить x, потому что он НЕ проверяет x == 10, а выполняет сопоставление, и оно всегда будет проводится успешно, так же как и в случае let x = 10.

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 3)
Ответ на: комментарий от quantum-troll

Полезно, я хотел выбрать некие значения, но оказалось что это невозможно, пусть язык сразу выдаст ошибку. Для if let который завершается без ошибки, есть match, хотя если match неполный то ошибка в runtime все равно будет, хотя компилятор проверяет полноту match, поэтому это на совести программиста.

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 2)

Опубликован следующий стабильный релиз заменителя языка С для дегенератов, так и не осиливших рабoту с памятью.

fixed

Myp3ik ★★★
()
Последнее исправление: Myp3ik (всего исправлений: 2)
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.