LINUX.ORG.RU

Rust и типобезопасность

 ,


3

7

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

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

Почитав документацию:

The as keyword does safe casting

Набросал такой примерчик:

fn main() {
        let a: f64 = std::f64::MAX;  // данное значение просто пример "большого числа"
        let b = a as i64;
        println!("{}", b);
}

Вопросы:

1) С какой стати это вообще компилируется?

2) Да, f64 и i64 нужно одно и то же количество битов для хранения значения, ну и что?

3) Почему результат меняет знак?

Представьте, что какой-то тех. процесс идет, и определенный параметр нельзя изменять скачкообразно, иначе физически система (по крайней мере, один из компонентов) выйдет из строя (встанет в раскоряку, взорвется, выпустит токсичный газ, убивающий 100тыс. населения; нужное подчеркнуть). И вот значение в f64 положительное и увеличивается постепенно, с i64 все вроде в порядке (и тестирование проходит на тестовых значениях), и вдруг хренак! и уже -9223372036854775808

Как так?

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

Проверки в расте - как в haskell: на соответствие ограничениям (type class constraints).

Тут либо раст надо знать, либо haskell. У меня сейчас нет времени расписывать. Могу сказать, что это очень крутая штука. В C++ что-то такое то ли будет скоро, то ли уже где-то можно увидеть, но выглядит как ужас-ужас, тогда как в rust и haskell изящно и лаконично. Кажется, я к этому начинаю уже привыкать.

dave ★★★★★
()

Важно отличие Rust от С в том, что такое не компилируется. А в С даже с волшебной комбинацией -Wall -Wextra -Werror компилируется и даже иногда будет работать.

andalevor ★★★
()
Ответ на: комментарий от RazrFalcon
#include <iostream>
#include <vector>
#include <concepts>
#include <algorithm>

struct MyType { int d; };

template<std::totally_ordered T>
void max_value(const std::vector<T>& items)
{
    std::cout << std::max_element(items.begin(), items.end()) << std::endl;
}

int main(int argc, char* argv[])
{
    const std::vector<MyType> items{ {1}, {2}, {3} };
    max_value(items);
    return 0;
}

Вывод копипасть не будут, ибо не влезет.

Вывод:

Ошибка	C7602	"max_value": связанные ограничения не соблюдаются	
fsb4000 ★★★★★
()
Ответ на: комментарий от fsb4000

Это, конечно, здорово. Но осталось подождать лет 10 и можно будет юзать эти концепты в коде за пределами своей личной «песочницы».

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

Но сообщение об ошибке все равно слишком гроздкое :( Будем надеяться, что поправят в дальнейшем.

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

А остальное кто будет копипастить, Печкин?

Кажется кто-то пропустил появление концептов. Да ты и сам должен понимать, что в общем случае дженерики Rust не ровня шаблонам С++.

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

А остальное кто будет копипастить, Печкин?

Шарик, ты балбес. С первых строк сообщения об ошибке уже все предельно ясно.

Разорванный Флакон

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

И много народу сидит на свежих версиях? Я недавно «откатывал» свой код до C++11 варианта, т.к. на одной из систем, где считать пришлось (выч. кластер), стоит CentOS 7.3.1611 с очень «свежим» gcc 4.8.5. И обновлять эту систему будут примерно через бесконечность :(

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

Кто-то пропустил суть сообщения и пытался сыграть в дурачка.

Кто и где? По ссылке fsb4000 текст ошибки не намного больше чем у Rust.

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

И много народу сидит на свежих версиях?

Очнись, в этом же треде твоя секта советует людям для решения проблемы собирать код только nightly компилятором (и то с костылями) Rust и типобезопасность (комментарий), а как C++, то сразу надо брать только C++ 1917, игнорируя все последние версии? Вся суть форумных военов.

Разорванный Флакон

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

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

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

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

Все там локанично и просто - вы просто придираетесь. Я бы даже сказал что вывод удобнее в Си++, потому что он выше получается и сразу видно проблему. Компилял на годболт-онлайн-компиллер-сайте последним гцц…

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

т.к. на одной из систем, где считать пришлось (выч. кластер), стоит CentOS 7.3.1611 с очень «свежим» gcc 4.8.5. И обновлять эту систему будут примерно через бесконечность :(

Я для подобного взял Ubuntu 14.04 (можно даже 12.04 было), поставил там gcc 9 и пользуюсь С++17.

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

Что ты хочешь сделать этим идиотизмом из сишечки и прочего скама? Взять целую часть числа? Так используй соответсвующие функции.

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

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

Вот и я о том что в отличии от раста вывода там в первых строчках видна проблема, что нельзя итератор в поток выводить, далее идёт исправление ошибки (которую любой новичек знает как исправить)

просто разоменовать итератор:

-std::cout << std::max_element(items.begin(), items.end()) << std::endl;
+std::cout << *(std::max_element(items.begin(), items.end())) << std::endl;

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

<source>:10:15: error: no match for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'const MyType')

иными словами в такой то строе для объекта типа «std::ostream» (проинстанцированного std::basic_ostream<char>) и объекта типа const MyType не определен оператор вывода в поток <<

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

компилировать всякий небезопасный шлак и в си можно. заче тогда нужен "типа"безопасный язык?

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

Разница только в том, что Rust на ту же центось ставится в одну команду, а свежий gcc надо руками конпелять.

Вся суть форумных военов.

Я, вообще-то, не растоман, а вполне себе плюсовик. А вот почему у тебя так бомбит, мне не совсем понятно :)

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

Вы буковки считаете или полезную нагрузку?

Если говорить про «полезную нагрузку», то у меня clang выделил красным место ошибки:

/usr/include/c++/8/bits/predefined_ops.h:43:23: error: no match for ‘operator<’ (operand types are ‘const MyType’ and ‘const MyType’) { return *__it1 < *__it2; } 

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

П.С. опять же, если бы в Rust были бы возможности шаблонов, дедукции и перегрузки как в С++, то и сообщения об ошибках пришлось бы значительно расширить. Ну или заставить пользователя самому искать эту информацию.

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

зачем тогда нужен "типа"безопасный язык?

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

Разорванный Флакон

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

является UB

обана. как так? в расте же нет UB

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

опять же, если бы в Rust были бы возможности шаблонов, дедукции и перегрузки как в С++

Зачем все эти возможности в Rust’е? Mozilla сказала «ненужно», значит «ненужно», зато это самое безопасное «ненужно» в мире.

Разорванный Флакон

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

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

Ж*па только в том, что этого «мусора» часто на порядки больше, чем действительно полезной информации.

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

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

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

А теперь прочитай этот тред и хорошенько так подумай (это unsafe операция, а то, мало ли, что тебе там в голову взбредет)

LLVM 10.0

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

в отличии от раста вывода там в первых строчках видна проблема

Что именно в выводе rustc кажется непонятным? Он же внятно говорит, что тип T должен реализовывать std::cmp::Ord и std::fmt::Debug. И при этом не генерирует километр дополнительной «полезной» информации. Меня, как пишущего на C++, выхлоп плюсового компилятора в таких ситуациях нихрена не радует.

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

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

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

Вы не могли бы более внятно изложить - о чем именно я должен подумать? И как ваша ссылка связана с текущей темой?

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

строго говоря, тут еще надо обложить концептами функцию operator<<. А в целом да, концепты в C++ куда более мощная штука, чем трейты в расте.

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

Ну может, я пока концепты не применяю, раз прочитал о них, понял что штука хорошая, но если честно даже синтаксис забыл, т.к. пока не применяю.

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

Ж*па только в том, что этого «мусора» часто на порядки больше, чем действительно полезной информации.

Бывает, ждем внедрения концептов.

но, например, при компиляции на удалённой системе парсить эти портянки часто приходится «глазами».

У нас сборки на виртуалках. Есть отдельная копия для таких случаев, с IDE, блэкджеком и куртизанками.

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

И при этом умудряются в коде из 3-х строк делать ошибки? Да, это круто и перспективно :))))

Такие неучи, как Эдик, «осилили» только «святую сишку», а всё остальное для них - г*вно. Считают себя «илитариями», будучи ПТУшниками по сути.

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

Очень частая ситуация

Лично я такое чаще всего вижу у недоученных сишников, которые ещё по граблям не попрыгали как следует, и у лисперов-неофитов. Те вообще невменяемые :)

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

Что именно в выводе rustc кажется непонятным?

грубо говоря почти все. Т.к. синтаксиса его не знаю. Вот ++-ый вывод я читаю легко и быстро, раставский посмотрел минуту, что вывод что код и ничего не понял))

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

В расте какая-то нечитаемая штуковина для меня (т.е. нужно изучать чтобы понять) но как бы на самом деле не нужно, потому что есть другие ЯП, не раст :)

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

Ну это очень легко в такое свалиться, Линус тоже свалился, он хороший эксперт в своей области, хорошо знает Си, но на Плюсах он даже ничего не писали и вряд ли их понимает, но имеет своё авторитетное мнение например :)

К тому же я думаю что в расте тоже в трех строках ошибку можно сделать…

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

Такие неучи, как Эдик

Про Эдика нам хоть что-то известно, а вот про тебя – ничего. Но если для тебя такие люди, как он, неучи, то ты, наверное, можешь похвастаться чем-то большим? Или не можешь?

Я не Эдик ни разу, я обычный Флакон.

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

грубо говоря почти все. Т.к. синтаксиса его не знаю. Вот ++-ый вывод я читаю легко и быстро, раставский посмотрел минуту, что вывод что код и ничего не понял))

Это дело привычки (опыта) - никакого rocket-science тут нет :) Я сам раст тыкаю палочкой иногда из любопытства и во многих аспектах он мне вполне симпатичен. Полностью C/C++ он вряд ли заменит, но свою нишу займёт, я думаю.

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

Мне ничего не известно. Кто это. Я тут хоть и давно а местных знаменитостей пожалуй и не знаю…

Царя то хоть знаешь? (Его, кстати, в этом треде не хватает).

Разорванный Флакон

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

Линус тоже свалился, он хороший эксперт в своей области, хорошо знает Си, но на Плюсах он даже ничего не писал

https://github.com/Subsurface-divelog/subsurface

но имеет своё авторитетное мнение например :)

В том, что С++ слишком сложен, дает слишком много путей и делает поведение кода менее очевидным. И он прав. Но, если он познакомится с Rust, то скорее всего сделает такой же вывод, потому как Rust тоже не образец очевидности, и становится все больше и сложнее.

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

тут еще надо обложить концептами функцию operator<<

Согласен, вот чуть поправил тот пример, теперь компилируется

https://godbolt.org/z/zXhNLS

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