Comments 37
http://www.ncameron.org/blog/rustfmt-changes
Хочу отметить что для своего проекта уже почти месяц как пользуюсь rustfmt-nightly и в целом оно вполне хорошо уже и сейчас работает. А nrc еще и активно его пилит — с каждой новой версией единый стиль форматирования ржавого кода становится все ближе и ближе.
Кстати, с удивлением понимаю что даже в рамках ржавого сообщества совершенно не известна такая отличная штука как cargo-apk, которая сама из обычного графического glutin-приложения собирает apk под андроид. Для ее работы надо или просто поставить sdk/ndk, или использовать стандартный докер-образ. Очень рекомендую ознакомиться :)
Мы тоже форматом пользуемся, хотя по поводу форматирования массивов были жаркиe споры.
Тут вопрос в том что сложо формализовать четкие и простые правила разбиения аргументов. Конкретно в этом примере и вертикальное форматирование терпимо сомтрится, кмк, особенно если вставить пустые строчки между блоками и комментарии на отдельной строке перед ними.
Ну и #[cfg_attr(rustfmt, rustfmt_skip)]
никто не отменял, особенно если требуется еще большие массивы вставить :)
Да меня тоже дефолтный вариант вполне устраивает, а вот rustfmt_skip
как раз не особо нравится: его на целую функцию вешать придётся. Можно, конечно, вынести создание массива в отдельную функцию, но это уже много лишних действий. Да и есть опция array_horizontal_layout_threshold
, но пока только в "ночном" формате.
как обстоят дела со статическими анализаторами для Rust?
мне первым дело в голову приходит https://github.com/Manishearth/rust-clippy/
В Расте довольно сложно написать херню.
Очень легко, как минимум в unsafe.
На то он и unsafe.
Но по этому повод есть мысль: в большом проекте на все файлы должно распространяться #![deny(unsafe_code)]
, а на пару файлов с необходимыми unsafe-абстракциями CI-робот должен требовать r+ от пары старших разработчиков проекта.
А вообще, как вы выразились, «херня» понятие растяжимое.
А так — да, проще всего вспомнить про ту же возможность утечки памяти в безопасном коде.
если ли для него что-то подобное инструментам Frama-C для языка C и SPARK для языка Ada?
про формальную верификацию вот тут — https://brson.github.io/2017/07/10/how-rust-is-tested#s-form — есть актуальные сылки. В частности на rustbelt.
Но, насколько я знаю, это пока все очень сырое.
А, еще из обновок за этот месяц: выкатили альфа версию официального расширения для vscode — rls-vscode. Работает через RLS, само собой, пилится его же авторами. Пользуюсь пока полторы недели: не без шероховатостей (в них обычно виноваты недоработки RLS), но в целом опыт более положительный чем с vscode-rust и выглядит как-то перспективней.
Прямо сейчас может и не имеет особо смысла прыгать. Из мгновенных последствий перехода — с ним RLS чуть реже падает. Но вот в будущем мне верится что rls-vscode станет доминирущим просто из-за официальной поддержки — его пилят те же чуваки что и RLS, так что это расширение с самого начала полностью полагается на RLS, очень тесно с ним интегрировано и фактически является просто тонким клиентом к нему, почти без своей логики на typescript.
В оригинале статьи, если я все правильно понимаю, неточность:
union MyUnion {
f1: u32,
f2: f32,
}
fn main() {
let mut u = MyUnion { f1: 1 };
u.f1 = 5;
let value = unsafe { u.f1 };
println!("value = {}", value);
}
https://play.rust-lang.org/?gist=fd55cfbbcfca58df996eae30fa6446f6
^ запись Copy-полей работает без unsafe, а только такие поля сейчас и разрешены (реддит).
Да, конечно, в этом и есть суть unsafe
. Если небезопасный код присутствует у вас в программе — вы должны четко понимать, зачем он вам.
Хотя само чтение уже всё же привлекает внимание что нужно быть осторожным.
Но запись никак не может повредить программе. А вот чтение — очень даже может.
В языке уже в любом случае с самого начала есть сырые указатели — у их очень похожая ситуация: взятие и передача любого сырого указателя безопасна, а разыменование — опасно. Так что такое поведение вполне в рамках философии языка.
Кроме того, есть мелкие ништяки: например стрикт алиасинг в си идет для единиц трансляции, а в раст — каждом месте использования. Указатели на виртуальную таблицу в раст хранятся вместе с указателем, а не с данными (свои плюсы и минусы).
То, что BSP написаны на С — тоже не технический момент, а «организационный», и исторически сложившаяся в текущий момент времени данность. Раст, кстати, сопрягается с другими языками. В первую очередь с си. Так что вобщем «в железо» это тоже можно шить, теоретически. Но там скорей всего придется шпарить без растовской stdlib.
Думаю, си и плюсы — устарели, и их преимущество лишь в том, что к ним много написано кода и много есть специалистов.
let the_answer_to_everything: i8 = loop{ if false {break 42;}};
То есть мы записываем значение 42 в the_answer_to_everything, но только никогда.
я надеюсь что clippy скоро подтянется и будет ругаться на такое. как раз для него задача
Так-то этот код особо не отличается от старого
let the_answer_to_everything: i8;
loop {
if false {
the_answer_to_everything = 42;
break;
}
}
Экзестенциальная проблема есть конечно, но она же и раньше была уже. Я не вижу принципиальных отличий с точки зрения "экзестенциальной проблемности" от
fn f(should_stop: bool, n: i64) -> i64 {
if !should_stop {
f(should_stop, n + 1)
} else {
0
}
}
fn main() {
let n = f(false, 0);
println!("n = {}", n);
}
Тоже вот ожидается что функция вернет значение, а она стек лопнет и грохнет все. Был бы стек бесконечный или сработала бы хвостовая оптимизация (edit: в release сборке срабатывает, кстати) — был бы полный аналог кода с loop
.
^ Без should_stop
булки, кстати, будет предупреждение warning: function cannot return without recurring
— приятная мелочь.
А вот к обратному не привыкли: с точки зрения системы типов у меня написано, что бесконечный цикл возвращает значение. Это что-то из матанализа — после того, как мы n устремили к бесконечности, мы получаем результат и добавляем его к значению другой величины.
Выпуск Rust 1.19