Summary

Allow

許可する、可能にする
inherent implementations
実装
on types outside of the module they are defined
定義する
in, effectively reverting RFC PR 155.

Motivation

The main motivation for disallowing

許可しない
such impl bodies was the implementation
実装
detail of fake modules being created to allow
許可する、可能にする
resolving Type::method, which only worked correctly for impl Type {...} if a struct Type or enum Type were defined
定義する
in the same module. The old mechanism
仕組み、機構
was obsoleted by UFCS, which desugars Type::method to <Type>::method and performs a type-based method lookup instead, with path resolution having no knowledge of inherent impls - and all of that was implemented
実装する
by rust-lang/rust#22172.

Aside from invalidating the previous

前の
RFC's motivation, there is something to be said about dealing with restricted inherent impls: it leads to non-DRY single
単一の
use extension traits, the worst offender being AstBuilder in libsyntax, with almost 300 lines of redundant method definitions.
定義

Detailed design
設計(する)

Remove the existing limitation, and only require that the Self type of the impl is defined

定義する
in the same crate. This allows
許可する、可能にする
moving methods to other modules:

#![allow(unused)] fn main() { struct Player; mod achievements { struct Achievement; impl Player { fn achieve(&mut self, _: Achievement) {} } } }

Drawbacks

Consistency and ease of finding method definitions

定義
by looking at the module the type is defined
定義する
in, has been mentioned as an advantage of this limitation. However, trait impls already have that problem and single
単一の
use extension traits could arguably be worse.

Alternatives
代わりのもの、選択肢

  • Leave it as it is. Seems unsatisfactory given

    与えられた
    that we're no longer limited by implementation
    実装
    details.

  • We could go further

    さらなる、それ以上
    and allow
    許可する、可能にする
    adding
    たす
    inherent methods to any type that could implement
    実装する
    a trait outside the crate:

    #![allow(unused)] fn main() { struct Point<T> { x: T, y: T } impl<T: Float> (Vec<Point<T>>, T) { fn foo(&mut self) -> T { ... } } }

    The implementation

    実装
    would reuse the same coherence rules as for trait impls, and, for looking up methods, the "type definition
    定義
    to impl" map would be replaced with a map from method name to a set
    セットする、集合
    of impls containing
    含む
    that method.

    Technically, I am not aware of any formulation that limits inherent methods to user-defined types in the same crate, and this extra support could turn out to have a straight-forward implementation

    実装
    with no complications, but I'm trying to present
    ある
    the whole situation to avoid
    避ける、回避する
    issues in the future - even though I'm not aware of backwards compatibility
    互換性
    ones or any related to compiler internals.

Unresolved questions

None.