LINUX.ORG.RU

Rust 1.91.0

 ,


0

5

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

Список изменений:

  • aarch64-pc-windows-msvc теперь является платфомой первого уровня поддержки (ранее было второго уровня). По сравнению со вторым уровнем поддержки, первый уровень подразумевает обязательное успешное прохождения всех тестовых наборов на платформе.

  • Добавлена проверка линтера при возвращении из функции «висячего» указателя. Встроенный в компилятор Borrow Checker уже имеет проверку на тот случай, когда возвращается «висячая» ссылка, но это не работало при использовании сырых указателей. Теперь будет сгенерировано предупреждение:

fn f() -> *const u8 {
    let x = 0;
    &x
}
warning: a dangling pointer will be produced because the local variable `x` will be dropped
 --> src/lib.rs:3:5
  |
1 | fn f() -> *const u8 {
  |           --------- return type of the function is `*const u8`
2 |     let x = 0;
  |         - `x` is part the function and will be dropped at the end of the function
3 |     &x
  |     ^^
  |
  = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated
    at the end of the function because nothing is referencing it as far as the type system is
    concerned
  = note: `#[warn(dangling_pointers_from_locals)]` on by default

В разряд стабильного API было переведено:

  • Path::file_prefix
  • AtomicPtr::fetch_ptr_add
  • AtomicPtr::fetch_ptr_sub
  • AtomicPtr::fetch_byte_add
  • AtomicPtr::fetch_byte_sub
  • AtomicPtr::fetch_or
  • AtomicPtr::fetch_and
  • AtomicPtr::fetch_xor
  • {integer}::strict_add
  • {integer}::strict_sub
  • {integer}::strict_mul
  • {integer}::strict_div
  • {integer}::strict_div_euclid
  • {integer}::strict_rem
  • {integer}::strict_rem_euclid
  • {integer}::strict_neg
  • {integer}::strict_shl
  • {integer}::strict_shr
  • {integer}::strict_pow
  • i{N}::strict_add_unsigned
  • i{N}::strict_sub_unsigned
  • i{N}::strict_abs
  • u{N}::strict_add_signed
  • u{N}::strict_sub_signed
  • PanicHookInfo::payload_as_str
  • core::iter::chain
  • u{N}::checked_signed_diff
  • core::array::repeat
  • PathBuf::add_extension
  • PathBuf::with_added_extension
  • Duration::from_mins
  • Duration::from_hours
  • impl PartialEq<str> for PathBuf
  • impl PartialEq<String> for PathBuf
  • impl PartialEq<str> for Path
  • impl PartialEq<String> for Path
  • impl PartialEq<PathBuf> for String
  • impl PartialEq<Path> for String
  • impl PartialEq<PathBuf> for str
  • impl PartialEq<Path> for str
  • Ipv4Addr::from_octets
  • Ipv6Addr::from_octets
  • Ipv6Addr::from_segments
  • impl<T> Default for Pin<Box<T>> where Box<T>: Default, T: ?Sized
  • impl<T> Default for Pin<Rc<T>> where Rc<T>: Default, T: ?Sized
  • impl<T> Default for Pin<Arc<T>> where Arc<T>: Default, T: ?Sized
  • Cell::as_array_of_cells
  • u{N}::carrying_add
  • u{N}::borrowing_sub
  • u{N}::carrying_mul
  • u{N}::carrying_mul_add
  • BTreeMap::extract_if
  • BTreeSet::extract_if
  • impl Debug for windows::ffi::EncodeWide<'_>
  • str::ceil_char_boundary
  • str::floor_char_boundary
  • impl Sum for Saturating<u{N}>
  • impl Sum<&Self> for Saturating<u{N}>
  • impl Product for Saturating<u{N}>
  • impl Product<&Self> for Saturating<u{N}>

Признак const добавлен к следующим функциям:

  • <[T; N]>::each_ref
  • <[T; N]>::each_mut
  • OsString::new
  • PathBuf::new
  • TypeId::of
  • ptr::with_exposed_provenance
  • ptr::with_exposed_provenance_mut

>>> Подробнее

★★★

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

Этим славится только си. Современный C++ позволяет писать безопасный код, если ты не шиз вроде Столярова, который до сих пор пишет на си с классами.

Rust тоже позволяет. И в нем куда меньше UB. Зачем страдать с C++, если можно страдать с Rust, но меньше?

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

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

Только если в любых языках тебе надо осматривать на предмет порчи памяти вообще весь код, то в rust тебе надо смотреть только в unsafe части. Минусы-то где?

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

Код ревью проводится не для всей кодовый базы. А для отдельных MR. Тебе так и так код отсматривать.

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

Код ревью проводится не для всей кодовый базы. А для отдельных MR. Тебе так и так код отсматривать.

И ты пропустил что нарушил инвариант, и это повлияло на код, который в MR вообще не светится. Ну мы сейчас серьезно будем обсуждать что code review не панацея, если инварианты живут только в голове у программиста?

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

Или больше :)

Или больше. А что получится покажет только практика.

tinykey
()

вот что в защиту ржавого дерьма скажу:

fn f() -> *const u8 {

объявление функции в С++ это реально боль для парсера которая досталась от С. Как отличить объявление функции int x(int y) от int x(30); например? нетривиальная задача между прочим потому что можно ведь так написать:

struct somestruct {
};
int z = 5; 
int x(somestruct); //функция
int y(z); //переменная

я кирпичами сру сейчас делая парсер который может похожий синтаксис разбирать. нужны стеки, нужно знать контекст «до» разбираемой строки чтобы различать имена типов и переменных. в этом плане fn это удобно. хотя возвращаемый тип не нравится, некрасиво. вот было бы так:

fn const u8* f() {
}
ckotctvo
()
Ответ на: комментарий от Bad_ptr

Код на Си: pthread_mutex_lock, работа с данными, pthread_mutex_unlock.

Код на Rust: lock на Mutex возвращает ссылку на данные, иными способами недоступную (без unsafe и т п). Дроп ссылки освобождает Mutex.

Соответственно, нельзя забыть захватить Mutex перед доступом к данным. В том числе при всякой сложной вложенности вызовов.

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

Какой инвариант? Что нельзя доставать сырой указатель из smart_ptr? Так его достать можно только в новом коде и только в месте где есть этот самый smart_ptr.

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

Какой инвариант? Что нельзя доставать сырой указатель из smart_ptr? Так его достать можно только в новом коде и только в месте где есть этот самый smart_ptr.

Или достать можно в старом коде, а сломать в новом.

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

Погрози ему пальчиком.

Один C++-программист – проект, два C++-программиста – проект с предаталем. В общем, пока вы там догориваетесь, как таскать надо, боров уже все проверил и выдал ошибку.

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

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

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

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

Нет, спасибо, этих срачей мне и соцсетях хватает. Тошно уже.

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

Ага, особенно когда указатель летит в Си-api :)

Ты кстати пробовал что-нибудь писать на rust’е с гуем? Я ради эксперимента попробовал. На gtk. Пока писал проклял все :)

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

Ты кстати пробовал что-нибудь писать на rust’е с гуем? Я ради эксперимента попробовал. На gtk. Пока писал проклял все :)

Я делал маленькие развлекательны программы на iced, мне, в целом, понравилось.

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

Ты кстати пробовал что-нибудь писать на rust’е с гуем? Я ради эксперимента попробовал. На gtk. Пока писал проклял все :)

А из прям готового софта, кажется Papers в гном уже на Rust. И их Matrix чат. Я мельком смотрел код, тоже неплохо.

tinykey
()

Разница между управлением памятью в современных плюсах и в расте в том, что:

  • в плюсах безопасное управление памятью (shared_ptr и т.д.) - «opt-in» фичи, т.е. можно пользоваться по желанию, но не обязательно, и осуществляется в рантайме;

  • в расте это «opt-out», т.е. обязательно по умолчанию, но можно отключить по желанию, проверяется во время компиляции.

Два очень разных подхода, и есть веские аргументы за и против каждого.

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

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

gtk - это да, так что лучше получается tauri + что то там (yew мне тут понравился, такой реакт), но приходится еще и html css и возможно ts/js знать

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

typedef же есть. А во вторых,

fn (fn* u8(..)) f() {
}

Например вот так. По идее как я делаю парсер там скобки вокруг указателя на функцию не нужны. Там после function может быть имя типа или сразу имя функции. Как в js. Но для красоты я явно запретил такую некрасоту

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

В плюсах боров заменяется ПРОЕКТИРОВАНИЕМ и умными указателями. Всегда когда код течет это от того что кто то на с++ рукоблудит, не использует контейнеры и методы с проверкой индексов, и самое главное - не продумал устройства программы.

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

Vala удобнее. Тот же сэ но ска насколько же с ним проще

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

В плюсах боров заменяется ПРОЕКТИРОВАНИЕМ и умными указателями. Всегда когда код течет это от того что кто то на с++ рукоблудит, не использует контейнеры и методы с проверкой индексов, и самое главное - не продумал устройства программы.

А тут тебе компилятор запрещает писать неправильные программы. Красота.

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

Не запрещает а лишь частично ограничивает твою свободу ошибаться. Это эмулируется в c++ надстройкой над умными указателями. Тривиальной кстати.

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

А тут тебе компилятор запрещает писать неправильные программы. Красота.

Ну это сильно сказано. Компилятор помогает избежать некоторых ошибок.

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

Писал аккуратно на С и продолжу, пожалуй. Никакой rust мозги не заменит.

Переходи на ассемблер. Никакой C мозги не заменит.

yvv1
()

освобождает программиста от ручного управления памятью

А зачем язык вокруг этого городить?

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

страдать с C++

лучше не страдать же

страдать с Rust

Я слышал©, что борьба с borrow checker это секс на уровне Генту.

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

Вот вот. Как обойтись без ручного управления памятью все было сказано еще в трудах Саттера и Александреску еще в конце 90х начале 200х, но ниасиляторы никак не могут осилить, аж язык для этого специальный написали :)

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

Разница есть только на малом числе быстрых современных ядер.

/tmp ❯❯❯ rustc atomic.r -C target-cpu=native -C opt-level=2
/tmp ❯❯❯ gcc -O2 -march=native atomic.c -o atomic-c
/tmp ❯❯❯ taskset -c 31 hyperfine --warmup 20 --runs 50 ./atomic-c ./atomic
Benchmark 1: ./atomic-c
  Time (mean ± σ):      18.5 ms ±   0.0 ms    [User: 18.2 ms, System: 0.4 ms]
  Range (min … max):    18.5 ms …  18.6 ms    50 runs
 
Benchmark 2: ./atomic
  Time (mean ± σ):      18.7 ms ±   0.0 ms    [User: 18.3 ms, System: 0.5 ms]
  Range (min … max):    18.7 ms …  18.8 ms    50 runs
 
Summary
  ./atomic-c ran
    1.01 ± 0.00 times faster than ./atomic
/tmp ❯❯❯ taskset -c 28,29,30,31 hyperfine --warmup 20 --runs 100 ./atomic-c ./atomic
Benchmark 1: ./atomic-c
  Time (mean ± σ):      38.4 ms ±   3.1 ms    [User: 152.9 ms, System: 0.3 ms]
  Range (min … max):    32.5 ms …  42.4 ms    100 runs
 
Benchmark 2: ./atomic
  Time (mean ± σ):      38.5 ms ±   3.2 ms    [User: 152.5 ms, System: 0.6 ms]
  Range (min … max):    32.7 ms …  42.8 ms    100 runs
 
Summary
  ./atomic-c ran
    1.00 ± 0.12 times faster than ./atomic
/tmp ❯❯❯ taskset -c 2,3 hyperfine --warmup 20 --runs 100 ./atomic-c ./atomic
Benchmark 1: ./atomic-c
  Time (mean ± σ):      15.4 ms ±   0.3 ms    [User: 29.5 ms, System: 0.3 ms]
  Range (min … max):    14.9 ms …  16.1 ms    100 runs
 
Benchmark 2: ./atomic
  Time (mean ± σ):      18.8 ms ±   0.2 ms    [User: 36.1 ms, System: 0.4 ms]
  Range (min … max):    18.3 ms …  19.3 ms    100 runs
 
Summary
  ./atomic-c ran
    1.22 ± 0.03 times faster than ./atomic
/tmp ❯❯❯ taskset -c 2,3,4,5 hyperfine --warmup 20 --runs 100 ./atomic-c ./atomic
Benchmark 1: ./atomic-c
  Time (mean ± σ):      36.3 ms ±   5.8 ms    [User: 142.7 ms, System: 0.2 ms]
  Range (min … max):    27.9 ms …  47.9 ms    100 runs
 
Benchmark 2: ./atomic
  Time (mean ± σ):      39.0 ms ±   6.3 ms    [User: 152.3 ms, System: 0.3 ms]
  Range (min … max):    26.8 ms …  49.4 ms    100 runs
 
Summary
  ./atomic-c ran
    1.07 ± 0.25 times faster than ./atomic
/tmp ❯❯❯ taskset -c 2,3,4,5,6,7,8,9,10,11 hyperfine --warmup 20 --runs 100 ./atomic-c ./atomic
Benchmark 1: ./atomic-c
  Time (mean ± σ):      29.9 ms ±   3.2 ms    [User: 112.1 ms, System: 0.3 ms]
  Range (min … max):    24.8 ms …  35.7 ms    100 runs
 
Benchmark 2: ./atomic
  Time (mean ± σ):      31.2 ms ±   2.9 ms    [User: 118.4 ms, System: 0.3 ms]
  Range (min … max):    25.1 ms …  35.7 ms    100 runs
 
Summary
  ./atomic-c ran
    1.04 ± 0.15 times faster than ./atomic
/tmp ❯❯❯ cat atomic.r atomic.c 
use std::sync::atomic::{AtomicU32, Ordering};
use std::thread;

const N: usize = 4;
const ITERS: usize = 1000_000;

static COUNTER: AtomicU32 = AtomicU32::new(0);

fn main() {
    let mut handles = Vec::with_capacity(N);

    for _ in 0..N {
        handles.push(thread::spawn(move || {
            for _ in 0..ITERS {
                COUNTER.fetch_add(1, Ordering::Relaxed);
            }
        }));
    }

    for h in handles {
        h.join().unwrap();
    }

    println!("counter = {}", COUNTER.load(Ordering::Relaxed));
}
#include <pthread.h>
#include <stdio.h>
#include <stdatomic.h>

#define N 4
#define ITERS 1000000

atomic_int counter = 0;

void* worker(void* _) {
    for (int i = 0; i < ITERS; i++) {
                atomic_fetch_add(&counter, 1);
    }
    return NULL;
}

int main(void) {
    pthread_t t[N];
    for (int i = 0; i < N; i++) pthread_create(&t[i], NULL, worker, NULL);
    for (int i = 0; i < N; i++) pthread_join(t[i], NULL);
    printf("counter = %d (expected %d)\n", counter, N * ITERS);
    return 0;
}
BruteForce ★★★
()
Ответ на: комментарий от Reset

Какая-то ложная дилемма. Вы либо «трахаетесь с памятью», либо у вас GC(костыли), либо костыли, либо костыли. А у нас костыли в языке, поэтому вы лохи, а мы политизируем разработку и поляризуем разработчиков.

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

Ох уж эти ваши новомодные навороты. Пробивал перфокарты и продолжу. Никакой си мозги не заменит.

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

А ты видел во что превратились в итоге плюсы с этой их попыткой скрестить обратную совместимость с нововведениями?

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

Умные дядьки говорят, что даже smart_ptr не нужно.

Например тут строка это просто

struct String8
{
  U8 *str;
  U64 size;
};
BruteForce ★★★
()
Последнее исправление: BruteForce (всего исправлений: 1)
Ответ на: комментарий от LightDiver

Да, видел. И раньше всё было плохо, но каждый новый стандарт делает ещё хуже. Причём плохо не только с т.з. реализации или интерфейса, но и со сложностью, что очень важно. Теперь добавят рефлексию, и станет ещё хуже, по всем фронтам) Я ненавижу Си++, конечно, но очень люблю в некотором смысле, потому что там можно делать деньги — компании готовы платить тем, кто может хоть как-то в этом разобраться. :D

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

Так то egui хорош внешне и прост…на этом преимущества заканчиваются и всплывают подводные камни. У егуи покадровая прорисовка (immediate mode). В итоге обычный менеджер аддонов на раст занимает 6мб озу и 60% цпу. То же приложение на электрон метров 200 озу и 0% процессора.

Если ОЗУ у меня много, то засирать процессор я считаю недальновидным. Ну его нахрен. Проще прикрутить к расту Qt сбоку или писать гуи на чем то другом вообще.

Хотя изначально egui мне даже нравился…

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

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

Зачем страдать с C++, если можно страдать с Rust

Обратное верно, да. :)

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

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

Это было жестоко!.. ;P ;)) :)))

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

Я запустил amdgpu_top, но данной проблемы не вижу. При интерактивной отрисовке нагрузка 0.6 - 3.0%.

Притом окно с большим количеством динамических виджетов. Собственно я на этот фреймворк так и наткнулся, вот сижу пилю его для специфического JSON > SparkPlugB шлюза.

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

Ну у тебя процессор не ограничен в частоте. Я тестировал на энергосберегающем режиме. В любом случае нагрузка растет линейно с количеством элементов и подобная отрисовка - такое себе.

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

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

Каждый update() - полный пересчёт UI - CPU-нагрузка.

У Qt событийная модель (retained mode) - гораздо проще сделать модуль с логикой на раст и подклчить куда надо к Qt интерфейсу, чем возиться с egui. Или к тому же электрону. Да куда угодно проще, чем возня с egui в итоге.

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

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

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

А вот гтк, Qt, egui и прочие прочие дают всетаки некоторые ограничения.

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