{"action":"created","issue":{"url":"https://api.github.com/repos/rust-lang/rfcs/issues/1210","labels_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1210/labels{/name}","comments_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1210/comments","events_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1210/events","html_url":"https://github.com/rust-lang/rfcs/pull/1210","id":94822300,"number":1210,"title":"RFC: impl specialization","user":{"login":"aturon","id":709807,"avatar_url":"https://avatars.githubusercontent.com/u/709807?v=3","gravatar_id":"","url":"https://api.github.com/users/aturon","html_url":"https://github.com/aturon","followers_url":"https://api.github.com/users/aturon/followers","following_url":"https://api.github.com/users/aturon/following{/other_user}","gists_url":"https://api.github.com/users/aturon/gists{/gist_id}","starred_url":"https://api.github.com/users/aturon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aturon/subscriptions","organizations_url":"https://api.github.com/users/aturon/orgs","repos_url":"https://api.github.com/users/aturon/repos","events_url":"https://api.github.com/users/aturon/events{/privacy}","received_events_url":"https://api.github.com/users/aturon/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/rust-lang/rfcs/labels/T-lang","name":"T-lang","color":"bfd4f2"}],"state":"open","locked":false,"assignee":{"login":"aturon","id":709807,"avatar_url":"https://avatars.githubusercontent.com/u/709807?v=3","gravatar_id":"","url":"https://api.github.com/users/aturon","html_url":"https://github.com/aturon","followers_url":"https://api.github.com/users/aturon/followers","following_url":"https://api.github.com/users/aturon/following{/other_user}","gists_url":"https://api.github.com/users/aturon/gists{/gist_id}","starred_url":"https://api.github.com/users/aturon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aturon/subscriptions","organizations_url":"https://api.github.com/users/aturon/orgs","repos_url":"https://api.github.com/users/aturon/repos","events_url":"https://api.github.com/users/aturon/events{/privacy}","received_events_url":"https://api.github.com/users/aturon/received_events","type":"User","site_admin":false},"milestone":null,"comments":197,"created_at":"2015-07-13T22:00:51Z","updated_at":"2016-01-13T20:11:48Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/rust-lang/rfcs/pulls/1210","html_url":"https://github.com/rust-lang/rfcs/pull/1210","diff_url":"https://github.com/rust-lang/rfcs/pull/1210.diff","patch_url":"https://github.com/rust-lang/rfcs/pull/1210.patch"},"body":"This RFC proposes a design for *specialization*, which permits multiple `impl`\r\nblocks to apply to the same type/trait, so long as one of the blocks is clearly\r\n\"more specific\" than the other. The more specific `impl` block is used in a case\r\nof overlap. The design proposed here also supports refining default trait\r\nimplementations based on specifics about the types involved.\r\n\r\nAltogether, this relatively small extension to the trait system yields benefits\r\nfor performance and code reuse, and it lays the groundwork for an \"efficient\r\ninheritance\" scheme that is largely based on the trait system (described in a\r\nforthcoming companion RFC).\r\n\r\n[Rendered](https://github.com/aturon/rfcs/blob/impl-specialization/text/0000-impl-specialization.md)"},"comment":{"url":"https://api.github.com/repos/rust-lang/rfcs/issues/comments/171419188","html_url":"https://github.com/rust-lang/rfcs/pull/1210#issuecomment-171419188","issue_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1210","id":171419188,"user":{"login":"nikomatsakis","id":155238,"avatar_url":"https://avatars.githubusercontent.com/u/155238?v=3","gravatar_id":"","url":"https://api.github.com/users/nikomatsakis","html_url":"https://github.com/nikomatsakis","followers_url":"https://api.github.com/users/nikomatsakis/followers","following_url":"https://api.github.com/users/nikomatsakis/following{/other_user}","gists_url":"https://api.github.com/users/nikomatsakis/gists{/gist_id}","starred_url":"https://api.github.com/users/nikomatsakis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nikomatsakis/subscriptions","organizations_url":"https://api.github.com/users/nikomatsakis/orgs","repos_url":"https://api.github.com/users/nikomatsakis/repos","events_url":"https://api.github.com/users/nikomatsakis/events{/privacy}","received_events_url":"https://api.github.com/users/nikomatsakis/received_events","type":"User","site_admin":false},"created_at":"2016-01-13T20:11:48Z","updated_at":"2016-01-13T20:11:48Z","body":"@aturon \r\n\r\n> I don't think that would fly, at least not that simply. For example, you could have two impls, one specializing the other, and both mentioning non-dispatchable bounds (where the specialization was based on some other factor).\r\n\r\nI think what you're saying is that just ignoring dispatchable impls might mean we have no impls at all to pick. This makes sense. I think there may be a way to make it work, but let's leave it aside, because I don't like the idea of trans picking impls anyay. But also, I think there are some deeper complications: It seems like it could easily lead to inconsistent results between the type-checker and trans. \r\n\r\nIn particular, the type-checker *does* know something about lifetimes. So it may pick a more specialized impl. If we have defaultable associated types, this could affect the results of associated type projections, but even absent that it could affect the types of associated fns (once we implement that correctly). Let me illustrate what I mean with an example that uses defaultable associated types (but I think the problem runs deeper):\r\n\r\n```rust\r\nimpl Send for Foo<'static> { }\r\n\r\ntrait SomeTrait {\r\n    type Output;\r\n    fn get() -> Self::Output;\r\n}\r\n\r\nimpl<T> SomeTrait for T {\r\n    default type Output = ();\r\n    fn get() -> Self::Output;\r\n}\r\n\r\nimpl<T:Send> SomeTrait for T {\r\n    type Output = i32;\r\n    fn get() -> Self::Output;\r\n}\r\n\r\nfn foo(f: Foo<'static>) {\r\n    let x: i32 = f.get();\r\n}\r\n```\r\n\r\nThis would, presumably, type-check, but it only works because we know that `Foo<'static>: Send`. Something that trans is not allowed to consider -- so if trans just started picking other impls, it would produce a value of type `()`, which would cause the types to be all wrong.\r\n\r\n"}}