Каков порядок вычисления аргументов функции и структуры инициализации в Rust?

Определен ли порядок вычисления аргумента функции в Rust?

fn f(a: u64, b: u64, c: u64) {}
fn g() -> u64 { 0 }
fn h() -> u64 { 1 }
fn i() -> u64 { 2 }

fn main() {
    f(g(), h(), i());
}

Также меня беспокоит порядок инициализации структур:

fn f() {}
fn g() {}

A {
    a: f(),
    b: g(),
}

Гарантирован ли заказ a, а затем b?

Для моего конкретного случая использования я собираюсь инициализировать структуру в транзакции diesel следующим образом:

db_connection.transaction(||
    Ok(CompanyAndUser {
        company: companies::register_company(...)?, // performs diesel insert
        user: users::register_user(...)?, // performs diesel insert
    })
);

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

Ответы

Ответ 1

Официально

Порядок оценки пока не указан в ссылке на данный момент:

Заявления и выражения:

[...] правила оценки выражений включают в себя указание как значения, создаваемого выражением, так и порядка, в котором его подвыражения сами оцениваются.

Давайте посмотрим на эти подвыражения:

  • На дополнительной странице о выражениях вызова ничего не указано о приоритете в вызове функции.

  • Однако в отношении инициализации структуры в ссылке, похоже, говорится, что порядок оценки соответствует порядку объявления:

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

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

Неофициально


Чтобы ответить на ваш конкретный вопрос, очевидное решение состоит в том, чтобы превратить ваши операции в операторы:

db_connection.transaction(|| {
    let company = companies::register_company(...)?; // performs diesel insert
    let user = users::register_user(...)?; // performs diesel insert

    Ok(CompanyAndUser { company, user })
});