LINUX.ORG.RU

Rust 1.34

 ,


2

11
  • cargo теперь умеет в сторонние репозитории

  • оператор ? теперь может использоваться в доктестах

  • стабилизированы трейты TryFrom и TryInto

  • стабилизированы типы AtomicU8AtomicU64 и AtomicI8AtomicI64 в дополнение к имевшимся ранее Atomic{Bool,Ptr,USize,ISize}

  • стабилизированы типы NonZeroI8NonZeroI128 и NonZeroISize в дополнение к имевшимся ранее беззнаковым аналогам

https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html

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

Время жизни такое же как и в C++, только тут компилятор его проверяет.

Вы писали что-нибудь на rust?

И почему меня это должно волновать.

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

Нельзя дважды использовать мутабельную ссылку? Код не запускал.

Не угадали. Какие еще варианты?=)

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

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

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

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

Вы писали что-нибудь на rust?

Ссылка на гитхаб в профиле.

Потому что нужно будет разбираться, почему не собирается

УМВР

Не угадали. Какие еще варианты?=)

Запустил - работает. Это собеседование?

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

Нет. В C++ все в порядке с move-семантикой.

По вашему, вызов деструктора для объекта, данные которого перемещены — это удачное решение?

На практике это выливается в постоянные проверки в деструкторе на предмет того, был ли объект перемещён или нет.

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

А такое вам как(смог сделать маленький пример для демонстрации проблемы, с которым столкнулся в реальном коде).

Написали мы структурку:

struct A<'a> {
    x: &'a i32
}

И impl:

impl<'a> A<'a> {
    fn get(&self) -> &i32 {
        self.x
    }
}

Вроде бы все ок, компилятор говорит, что все хорошо.

Дальше пишем вроде бы простую функцию:

fn foo(a: A) -> &i32 {
    a.get()
}

Как вы думаете, что скажет компилятор?

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

Зачем ты передаёшь A в foo() по значению?

А почему нет? Поле же ссылка и ее время жизни будет больше, чем функция foo.

Пример иначе фиксить нужно. Но компилятор тут не помощник.

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

давай еще

Погоди :)

Объясни для местных, почему так. А то трудновато заходит.

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

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

потому что вот это:

impl<'a> A<'a> {
    fn get(&self) -> &i32 {
        self.x
    }
}

это на самом деле вот это:

impl<'a> A<'a> {
    fn get<'b>(&'b self) -> &'b i32 {
        self.x
    }
}

а можно сделать, чтобы возвращался &'a i32 ссылки на int, а не более узкий лайфтайм ссылки на структуру

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

потому что...

Ага.

А почему при описание impl лайфтайм 'a не соответствует 'b? И как так получается, что в foo у нас на 'a мапится нужный лайфтайм? Тут наверное нужно еще поговорить про lifetime elision для foo, иначе сложновато...

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

Тут наверное нужно еще поговорить про lifetime elision для foo, иначе сложновато…

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

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

как раз не нужно

Мне кажется без этого тяжело понять твой фикс. Тем более, что ругаться компилятор в исходном примере будет в foo. У меня потому и время ушло много тогда - не сразу понял, куда смотреть.

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

я просто в определениях функций лайфтаймы проименовал, и сообщение компилятора внезапно стало раз в 8 читабельней

error[E0515]: cannot return value referencing function parameter `a`
  --> src/lib.rs:12:5
   |
12 |     a.get()
   |     -^^^^^^
   |     |
   |     returns a value referencing data owned by the current function
   |     `a` is borrowed here

vs

error[E0312]: lifetime of reference outlives lifetime of borrowed content...
 --> src/lib.rs:7:9
  |
7 |         self.x
  |         ^^^^^^
  |
note: ...the reference is valid for the lifetime 'b as defined on the method body at 6:12...
 --> src/lib.rs:6:12
  |
6 |     fn get<'b>(&self) -> &'b i32 {
  |            ^^
note: ...but the borrowed content is only valid for the lifetime 'a as defined on the impl at 5:6
 --> src/lib.rs:5:6
  |
5 | impl<'a> A<'a> {
  |      ^^

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

Вот у меня большой опыт проведения собеседований на плюсах, но думаю для раста это веселее.

Спрашивать «как поведет себя вот этот код» на собеседованиях? Ну лол же.

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

Компилятор тебе скажет, что ты тупой (и будет прав). У тебя ссылка на A берется из скопированного значения внутри функции.

Ну тупым тут оказался вовсе не я. Ты второй с тем же неправильным ответом. Правильный - в постах MyTrooName.

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

Только на собеседованиях задают подобные, оторванные от жизни, вопросы.

Это был пример из жизни(сокращенный), который выпил крови и пару часов жизни.

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

Ну тупым тут оказался вовсе не я. Ты второй с тем же неправильным ответом. Правильный - в постах MyTrooName.

Чо, правда, да? Смотри:

$ cat src/main.rs
struct A<'a> {
    x: &'a i32
}

impl<'a> A<'a> {
    fn get(&self) -> &i32 {
        self.x
    }
}

fn foo(a: A) -> &i32 {
    a.get()
}

fn main() {
    let x = 0;
    let s = A { x: &x };

    println!("{}", foo(s));
}
$ cargo build
   Compiling t v0.1.0 (/tmp/t)
error[E0515]: cannot return value referencing function parameter `a`
  --> src/main.rs:12:5
   |
12 |     a.get()
   |     -^^^^^^
   |     |
   |     returns a value referencing data owned by the current function
   |     `a` is borrowed here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0515`.
error: Could not compile `t`.

To learn more, run the command again with --verbose.

Только не отмазывайся, что не знаешь английского, ок?

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

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

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

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

ЕМНИП abi у плюсов не стандартизировано, поэтому в отличии от сишечки с подключением плюсов возникают проблемы.

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

На практике это выливается в постоянные проверки в деструкторе на предмет того, был ли объект перемещён или нет.

Нет, не выливается.

template<typename T>
class Foo {
public:
    Foo(T&& bar) : m_ptr(new T(bar)) {}

    Foo(Foo&& foo) : m_ptr(nullptr) {
        std::swap(this->m_ptr, foo.m_ptr);
    }

    ~Foo() {
        if (this->m_ptr != nullptr) {
            delete this->m_ptr;
        }
    }
private:
    T* m_ptr;
};

Как в подобных ситуациях избавляться от проверки?

P.S. Я знаю, что delete проверяет на nullptr. Будем считать, что он этого не делает. Речь идёт об абстрактном ресурсе. Управление памятью здесь как пример.

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

Кстати, деструктор unique_ptr не избавлен от проверки на nullptr.

/// Destructor, invokes the deleter if the stored pointer is not null.
~unique_ptr() noexcept
{
    auto& __ptr = _M_t._M_ptr();
    if (__ptr != nullptr)
    get_deleter()(__ptr);
    __ptr = pointer();
}
anonymous ()
Ответ на: комментарий от anonymous

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

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

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

Абстрактный ресурс у тебя это что?

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

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

Да, именно это.

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

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

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