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

Конфликты разрешения методов

Что происходит, когда возникает конфликт имён между собственным методом и методом-расширением?

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

mod ext {
    pub trait CountOnesExt {
        fn count_ones(&self) -> u32;
    }

    impl CountOnesExt for i32 {
        fn count_ones(&self) -> u32 {
            let value = *self;
            (0..32).filter(|i| ((value >> i) & 1i32) == 1).count() as u32
        }
    }
}
fn main() {
    pub use ext::CountOnesExt;
    // Какой метод `count_ones` будет вызван?
    // Тот, что из `CountOnesExt`? Или собственный метод `i32`?
    assert_eq!((-1i32).count_ones(), 32);
}
  • Внешний тип в новой версии может добавить новый собственный метод с тем же именем, что и наш метод-расширение.

    Спросите: что произойдёт в примере выше? Будет ли ошибка компиляции? Получит ли один из двух методов более высокий приоритет? Какой именно?

    Добавьте panic!("Extension trait"); в тело CountOnesExt::count_ones, чтобы понять, какой метод вызывается.

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

    Продемонстрируйте: измените вызов на (&-1i32).count_ones() и покажите, что теперь вызывается метод трейта. Затем измените метод трейта так, чтобы он принимал self (вместо &self), и покажите, что снова вызывается собственный метод.

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

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

  • Взаимодействие приоритетного поиска, который использует алгоритм разрешения методов Rust, и автоматического Deref можно применить для эмуляции специализации на стабильном тулчейне, в первую очередь в контексте кода, сгенерированного макросами. Подробности см. в статье «Autoref Specialization».