Open Ixrec opened 6 years ago
I realize I should've added this to this Issue instead of a comment here:
One possibility for "solving" this diesel-chrono type of issue is the notion of "friend" crates.
// Crate t containing Trait T
// (nothing new/special required)
// Crate u containing trait U
// (nothing new/special required)
// Crate s providing structs that need impls for u::U and t::T
// main.rs/lib.rs
// (nothing new/special required)
// Make the 'baz' module's private (no visibility spec) (not pub(self), pub(nofriend), pub(super), pub(in ...mod)) items publicized to friends
pub(friend) mod baz;
...
// foo.rs (module foo)
// if nothing is designated as pub(friend) then the "friend" visible items are the same as the "pub" visible items
// no changes to this module in that case
// foo/bar.rs (module foo::bar)
// even though this module isn't pub(friend) items within it (including structs, enums, Trait impls, fns, Inheren Methods, and sub-modules) can be pub(friend)
pub(friend) struct FooBarYep {
// struct private elements are made "friend" accessible too
}
pub(friend) impl for FooBarYep {
...
}
pub(friend) fn FooBarYepProcessor( p : FooBarYep ) {
}
// not accessible to friends
struct FooBarNope {
}
// ...etc...
// baz.rs (module baz)
// nothing special needed here as the entire 'baz' module has been publicized to friends, so, if anything needs special access by a friend, it has it
// this is accessible to friends
struct Bazup {
// all private/pub members of this accessible to friends
}
// however, if something should be "true private" (even hidden from friends, it can be declared as "pub(self)" or "pub(nofriend)"
// not accessible to friends
pub(self) struct Bazzit {
}
pub(nofriend) struct Bazout {
}
// accessible to friends
struct Bazme {
x : i32; // accessible to friends (because the mod has been "friended")
pub(self) y: i32; // not accessible to friends, only accessible within the Baz mod
pub(nofriend) z: i32; // not accessible to friends, true private even though the module was friended
pub t : i32; // also accessible to friends
pub(super) u : i32; // not accessible to friends
pub(friend) v : i32; // accessible to friends (lint warning for unneeded pub(friend)
pub(self,friend) v : 32; // only accessible to self and friends
}
// accessible to friends, but, has a lint warning for unneeded pub(friend)
pub(friend) Bazyou {
...
}
// main-friends.rs/lib-friends.rs (declare friend crates)
friend friend-t-impl-s-Sy impl (::t::T) for ::crate::{Baz,Foo::Bar} // provide impls of Trait T of crate t by friend crate friend-t-impl-s-Sy
friend friend-t-impl-s-Sy impl (::t::T2) for ::crate::{Baz,Foo::Bar} // provide impls of Trait T2 of crate t by friend crate friend-t-impl-s-Sy
//// friend friend-t-impl-s-Sy impl (::t::T,::t::T2) for ::crate::{Baz,Foo::Bar}
friend friend-u-impl-s-Sy impl (::u::U) for ::crate::{Baz,Foo::Bar} // provide impls of Trait U of crate u by friend crate friend-u-impl-s-Sy
// Crate friend-t-impl-s-Sy containing impls for Trait T from t for types Sy subset(a) of Sx of crate s
use ::t::T;
use ::u::U;
use ::s::friend::Baz;
use ::s::friend::Foo::Bar;
pub timpl {
impl T for Baz::Bazup {
...
}
impl T for Bar::FooBarYep {
...
}
// Not permitted
//impl T for Bar::FooBarNope {
// ...
//}
}
// Crate friend-u-impl-s-Sz containing impls for Trait U from u for types Sz subset(b) of Sx of crate s
// similar for u::U as for t::T above
// Crate u that uses Sy from s and wants to use the impls of T for Sy from s provided by friend-t-impl-s-Sy and for Sz from s provided by frient-t-impl-s-Sz
use ::t::T;
use ::u::U;
use ::s::Bar::FooBarYep;
use ::friend-t-impl-s-Sy::timpl;
// have impl of T for FooBarYep provided by friend-t-imp-s-Sy crate here
In other words, solve the the
diesel-chrono
problem by making bothdiesel
andchrono
add something likeallowed-orphan-implers = ["diesel-chrono"]
to their Cargo.tomls (the precise mechanism isn't important), and then adiesel-chrono
crate that impls diesel traits for chrono types will no longer fail to compile.To me, this seems like the only viable solution for "official orphans" use cases aside from giving up and embracing incoherence (because I don't think https://github.com/Ixrec/rust-orphan-rules/issues/16 or https://github.com/Ixrec/rust-orphan-rules/issues/12 are viable/actually solve the problem).
Specific "blessing mechanisms" that have been proposed include:
forward impl
blocks, from this internals thread by Manishearthtrait-delegate
Cargo.toml key, from this RFC issue comment by blusspub(friend)
/pub(nofriend)
visibility modifiers, from gbutler69's comment below