Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Заимствование одного

В этом примере find_nearest принимает несколько заимствований, но возвращает только одно из них. Аннотации времён жизни явно связывают возвращаемое заимствование с соответствующим заимствованием аргумента.

// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0

#[derive(Debug)]
struct Point(i32, i32);

/// Ищет в `points` точку, ближайшую к `query`.
/// Предполагается, что в `points` есть хотя бы одна точка.
fn find_nearest<'a>(points: &'a [Point], query: &Point) -> &'a Point {
    fn cab_distance(p1: &Point, p2: &Point) -> i32 {
        (p1.0 - p2.0).abs() + (p1.1 - p2.1).abs()
    }

    let mut nearest = None;
    for p in points {
        if let Some((_, nearest_dist)) = nearest {
            let dist = cab_distance(p, query);
            if dist < nearest_dist {
                nearest = Some((p, dist));
            }
        } else {
            nearest = Some((p, cab_distance(p, query)));
        };
    }

    nearest.expect("at least one point expected").0
    // query // Что будет, если сделать вот так?
}

fn main() {
    let points = &[Point(1, 0), Point(1, 0), Point(-1, 0), Point(0, -1)];
    let query = Point(0, 2);
    let nearest = find_nearest(points, &query);

    // `query` в этот момент не заимствуется.
    drop(query);

    dbg!(nearest);
}
This slide should take about 5 minutes.
  • Может помочь свернуть определение find_nearest, чтобы сделать акцент на сигнатуре функции. Реальная логика функции довольно сложна и для анализа заимствований не важна.

  • Когда мы вызываем find_nearest, возвращённая ссылка не заимствует query, поэтому мы свободны освободить его, пока nearest ещё активна.

  • Но что будет, если вернуть неправильное заимствование? Измените последнюю строку find_nearest, чтобы она возвращала query. Покажите студентам ошибку компилятора.

  • Первое, что нужно сделать, — добавить аннотацию времени жизни к query. Покажите студентам, что мы можем добавить второе время жизни 'b к find_nearest.

  • Покажите новую ошибку студентам. Анализатор заимствований проверяет, что логика тела функции действительно возвращает ссылку с правильным временем жизни, обеспечивая соответствие функции контракту, заданному её сигнатурой.

Для дальнейшего изучения

  • В сообщении «help» сказано, что мы можем добавить ограничение времени жизни 'b: 'a, чтобы указать, что 'b будет жить не меньше, чем 'a, что позволит вернуть query. Это пример подтипизации времён жизни (lifetime subtyping), которая позволяет вернуть более долгое время жизни там, где ожидается более короткое.

  • Похожее можно сделать, вернув время жизни 'static, например ссылку на переменную static. Время жизни 'static гарантированно длиннее любого другого, поэтому его всегда безопасно возвращать вместо более короткого.