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

// Крейт `postgresql-bindings`

pub struct PostgresqlConn(/* подробности */);

// Крейт `database-traits`, зависит от `postgresql-bindings`

pub trait DbConnection {
    /* методы */
}

impl DbConnection for PostgresqlConn {} // ✅, `DbConnection` локальный.

// Крейт `mycoolnewdb` зависит от `database-traits`

pub struct MyCoolNewDbConn(/* подробности */);

impl DbConnection for MyCoolNewDbConn {} // ✅, `MyCoolNewDbConn` локальный.

// Ни `PostgresqlConn`, ни `DbConnection` не являются локальными для `mycoolnewdb`.
// Это привело бы к двум реализациям `DbConnection` для `PostgresqlConn`!
impl DbConnection for PostgresqlConn {} // ❌🔨
  • Трейт в экосистеме Rust никогда не должен реализовываться дважды. Две реализации одного трейта для одного типа — это конфликт, который не имеет решения.

  • Внутри крейта это можно предотвратить, обнаруживая множественные определения и запрещая их, но что насчёт разных крейтов во всей экосистеме Rust?

  • Типы либо локальны для крейта (определены в нём), либо нет.

    В примере «крейтов» PostgresqlConn локален для postgresql-bindings, а MyCoolNewDbConn локален для mycoolnewdb.

  • Трейты тоже либо локальны для крейта, либо нет.

    И снова в примере трейт DbConnection локален для database-traits.

  • Если что-то локально, для него можно писать реализации трейтов.

    Если трейт локален, его реализации можно писать для любого типа.

    Если тип локален, для него можно писать реализации любых трейтов.

  • За пределами этих границ реализации трейтов написать нельзя.

    Это сохраняет реализации «согласованными»: на весь набор крейтов может существовать только одна реализация трейта для типа.

Справка:

  • https://doc.rust-lang.org/stable/reference/items/implementations.html#r-items.impl.trait.orphan-rule