{
  "$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"
}