{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreibf3dmyerkzie2bquc7dhviat2dmefuoc4omr25ns3ijbe3i4omze",
"uri": "at://did:plc:ivbknywyskln22er3nkssdhl/app.bsky.feed.post/3ml5qf44nzpd2"
},
"path": "/t/too-strict-orphan-rules-e0117/24221#post_5",
"publishedAt": "2026-05-06T02:51:11.000Z",
"site": "https://internals.rust-lang.org",
"tags": [
"Adding blanket implementations is a breaking change.",
"[1]",
"↩︎"
],
"textContent": "robofinch:\n\n> AFAIK the sole extra power for non-fundamental stuff — setting aside whatever reasoning goes into `unsafe` code — is the ability to add new blanket impls of existing non-`#[fundamental]` traits for existing non-`#[fundamental]` types in a nonbreaking change\n\nAdding blanket implementations is a breaking change.\n\nBlanket implementations are defined in terms of uncovered generic parameters. A type constructor `TyCons<T>` covers `T` if it is non-fundamental, and does not if it is fundamental.\n\nChanging a non-fundamental type constructor to a fundamental one is a breaking change, as mentioned below. (And vice-versa, too.)\n\nPC-Killer:\n\n>\n> impl<T> From<VecDeque<Box<Node<T>>>> for Option<Box<Node<T>>> {\n>\n\nUnder the current orphan rules, `alloc` (`VecDeque`'s crate) has the \"right\" to add this implementation in a non-SemVer-breaking fashion:\n\n\n impl<T> From<VecDeque<T>> for Option<T> { ... }\n\n\nAnd that overlaps with your example.\n\nSimilarly, crates today can have their own implementations following the pattern:\n\n\n // These can exist in the current ecosystem.\n impl<T> From<MyTypeConstructor<T>> for Option<T> { ... }\n impl<T> From<MyTypeConstructor<T>> for VecDeque<T> { ... }\n\n\nChanging the orphan rules to take away the \"right\" generally would break those crates.\n\nMaking `Option<T>` or `VecDeque<T>` fundamental would make an implementing type in the example uncovered, which is not allowed on foreign traits -- and thus would also break those crates.\n\n* * *\n\nIt's harder to construct conundrums for your other specific examples that don't involve `Option` making breaking changes of its own, but not impossible. If `Vec` somehow moved to `core`,[1] the following implementation would be allowed with todays orphan rules, so long as `Vec<T>` didn't meet the `SomeHypotheticalTrait` bound.\n\n\n trait SomeHypotheticalTrait {}\n impl<T> SomeHypotheticalTrait for T where /* ... */;\n\n impl<T, U> From<Option<Vec<T>>> for Option<U>\n where\n U: SomeHypotheticalTrait,\n { ... }\n\n\nIf `MyVec<_>` could meet the hypothetical bound, the above implementation would conflict with your first two examples.\n\nEven if we discard such a possibility, you would need to formally define what set of circumstances allows downstream to use negative reasoning about `Option`'s implementations. Like some argument that it's impossible for `Option` to write such an implementation that isn't itself a breaking change or otherwise not allowed.\n\n(If the argument relies on coherence assuming types never change crates (like a type moving to a dependency and becoming an alias in the original crate), I doubt that would fly either.)\n\n* * *\n\n 1. like some attempts to move `io::Error` to `core` ↩︎\n\n\n",
"title": "Too strict orphan rules E0117"
}