{"action":"created","issue":{"url":"https://api.github.com/repos/rust-lang/rust/issues/18764","labels_url":"https://api.github.com/repos/rust-lang/rust/issues/18764/labels{/name}","comments_url":"https://api.github.com/repos/rust-lang/rust/issues/18764/comments","events_url":"https://api.github.com/repos/rust-lang/rust/issues/18764/events","html_url":"https://github.com/rust-lang/rust/issues/18764","id":48159467,"number":18764,"title":"Permit unqualified references to associated types of the trait within the trait definition","user":{"login":"cmr","id":704250,"avatar_url":"https://avatars.githubusercontent.com/u/704250?v=3","gravatar_id":"","url":"https://api.github.com/users/cmr","html_url":"https://github.com/cmr","followers_url":"https://api.github.com/users/cmr/followers","following_url":"https://api.github.com/users/cmr/following{/other_user}","gists_url":"https://api.github.com/users/cmr/gists{/gist_id}","starred_url":"https://api.github.com/users/cmr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cmr/subscriptions","organizations_url":"https://api.github.com/users/cmr/orgs","repos_url":"https://api.github.com/users/cmr/repos","events_url":"https://api.github.com/users/cmr/events{/privacy}","received_events_url":"https://api.github.com/users/cmr/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/rust-lang/rust/labels/A-associated-items","name":"A-associated-items","color":"d7e102"},{"url":"https://api.github.com/repos/rust-lang/rust/labels/I-wrong","name":"I-wrong","color":"e10c02"},{"url":"https://api.github.com/repos/rust-lang/rust/labels/P-backcompat-lang","name":"P-backcompat-lang","color":"eb6420"}],"state":"open","locked":false,"assignee":{"login":"nrc","id":762626,"avatar_url":"https://avatars.githubusercontent.com/u/762626?v=3","gravatar_id":"","url":"https://api.github.com/users/nrc","html_url":"https://github.com/nrc","followers_url":"https://api.github.com/users/nrc/followers","following_url":"https://api.github.com/users/nrc/following{/other_user}","gists_url":"https://api.github.com/users/nrc/gists{/gist_id}","starred_url":"https://api.github.com/users/nrc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nrc/subscriptions","organizations_url":"https://api.github.com/users/nrc/orgs","repos_url":"https://api.github.com/users/nrc/repos","events_url":"https://api.github.com/users/nrc/events{/privacy}","received_events_url":"https://api.github.com/users/nrc/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/rust-lang/rust/milestones/22","html_url":"https://github.com/rust-lang/rust/milestones/1.0%20beta","labels_url":"https://api.github.com/repos/rust-lang/rust/milestones/22/labels","id":924511,"number":22,"title":"1.0 beta","description":"","creator":{"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},"open_issues":15,"closed_issues":63,"state":"open","created_at":"2015-01-06T21:40:55Z","updated_at":"2015-03-28T01:53:38Z","due_on":null,"closed_at":null},"comments":16,"created_at":"2014-11-08T08:00:06Z","updated_at":"2015-03-29T02:05:01Z","closed_at":null,"body":"```rust\r\n#![feature(associated_types)]\r\npub trait Transfer {\r\n    type Result;\r\n    fn transfer(&mut self) -> Result;\r\n}\r\n\r\nfn main(){}\r\n```\r\n\r\nGives the error:\r\n\r\n```\r\nfoo.rs:4:31: 4:37 error: wrong number of type arguments: expected 2, found 0\r\nfoo.rs:4     fn transfer(&mut self) -> Result;\r\n                                       ^~~~~~\r\n```\r\n\r\nAccording to [the RFC](https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md#namespacingshadowing-for-associated-types) the `Result` ought to refer to the associated type."},"comment":{"url":"https://api.github.com/repos/rust-lang/rust/issues/comments/87341631","html_url":"https://github.com/rust-lang/rust/issues/18764#issuecomment-87341631","issue_url":"https://api.github.com/repos/rust-lang/rust/issues/18764","id":87341631,"user":{"login":"nrc","id":762626,"avatar_url":"https://avatars.githubusercontent.com/u/762626?v=3","gravatar_id":"","url":"https://api.github.com/users/nrc","html_url":"https://github.com/nrc","followers_url":"https://api.github.com/users/nrc/followers","following_url":"https://api.github.com/users/nrc/following{/other_user}","gists_url":"https://api.github.com/users/nrc/gists{/gist_id}","starred_url":"https://api.github.com/users/nrc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nrc/subscriptions","organizations_url":"https://api.github.com/users/nrc/orgs","repos_url":"https://api.github.com/users/nrc/repos","events_url":"https://api.github.com/users/nrc/events{/privacy}","received_events_url":"https://api.github.com/users/nrc/received_events","type":"User","site_admin":false},"created_at":"2015-03-29T02:05:01Z","updated_at":"2015-03-29T02:05:01Z","body":"A key question here is what to do where an associated item could shadow an outer item, e.g.,\r\n\r\n```\r\ntype Foo = ...\r\ntrait Bar {\r\n    type Foo;\r\n    fn foo() -> Foo;   // <- which Foo does this refer to?\r\n}\r\n```\r\nThere are two options: we prefer the non-shorthand type of the module-level `Foo` or we imagine that the associated type `Foo` shadows the outer `Foo`. The latter seems the most expected behaviour, however, it is far more complex to implement. (There are a couple of other strategies too - we could consider this ambiguous and error out, but that has the same drawbacks, implementation-wise as preferring `Self::Foo`. We could prefer `Self::Foo` if the associated type is declared in the current trait, but not a super-trait (by using a more naive implementation strategy), but that is kind of awful). We also need to think about the expected behaviour for associated (static) methods.\r\n\r\nThe general implementation strategy here is that when resolving a path, we take note of whether `Self` is in scope (i.e., we're in a trait or impl) and if so we record two (well, n, really) possible resolutions - a partial resolution which assumes the `Self::` shorthand and a regular resolution (in the example these are the two `Foo`s). The former resolution is fully resolved during type checking, we then decided which resolution to use (this is something of a simplification, we arrange things in resolve such that if the partial resolution fully resolves, then it must be the correct resolution, otherwise we use the 'local' resolution). Note that the 'local' resolution may be no resolution at all, i.e., there is a resolve error if there is no `Self::` resolution.\r\n\r\nIf this all worked, then the shadowing behaviour would fall out nicely. However, there are situations where even testing for `Self::` shorthands causes an error, in particular, because of cycle detection (other cases can just defer the errors and fallback to the 'local' name resolution). For example, `num::Int` has a super-trait with a type parameter which has a bound of `num::Int`, and this is Ok because we don't need to fully resolve all the bounds to this depth in type checking as it currently stands. However, trying to resolve `Self::` causes us to do so and detect this cycle. The only way I see to solve this is to defer this error too - so if we try to resolve the `Self::Foo` shorthand and hit an error, then we fallback to 'local' resolution. If that fails, then hopefully we can give the cycle error rather than just a bland name resolution error.\r\n\r\nHowever, this seems kind of bad - by changing a parameter on a bound of super-trait (or something equally remote) we can cause name resolution errors in fairly unconnected places. Furthermore, whether you can use a `Self::` shorthand or not in a given trait becomes essentially unpredictable (you need knowledge of all parameters and bounds on all super-traits, etc.). It also seems really unsatisfactory some how.\r\n\r\nThe alternative is a slightly weird scoping rule that non-associative items in an outer scope shadow unqualified, associated items from an inner scope. This breaks local reasoning somewhat, i.e., you need to know the entire context of an item to know whether you can use the shorthand or not. And adding an item in an arbitrary place can break the use of a shorthand (imagine a glob import in an outer module). OTOH, at least you don't need to know about bounds and super-traits.\r\n\r\nThe implementation is also much simpler - you only need to worry about the `Self::` shorthand if name resolution fails otherwise. Furthermore, when finalising name resolution in type checking, you never need to fallback to another possible resolution, if finalisation fails, then you have an actual error (well, there might be more than one `Self` in scope, in which case you have to try multiple resolutions still, but we could simplify further and only take into account the innermost `Self`, which seems sensible since this is a shorthand and this is a kind of partial solution in any case because of the shadowing issue).\r\n\r\nNote that relative to current Rust, the first solution is backwards incompatible and the second is backwards compatible. If we adopt the second solution, changing to the first is a backwards incompatible change."}}