{"action":"created","issue":{"url":"https://api.github.com/repos/rust-lang/rfcs/issues/1154","repository_url":"https://api.github.com/repos/rust-lang/rfcs","labels_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1154/labels{/name}","comments_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1154/comments","events_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1154/events","html_url":"https://github.com/rust-lang/rfcs/pull/1154","id":85998122,"number":1154,"title":"Disjoins (anonymous enums)","user":{"login":"canndrew","id":5555066,"avatar_url":"https://avatars.githubusercontent.com/u/5555066?v=3","gravatar_id":"","url":"https://api.github.com/users/canndrew","html_url":"https://github.com/canndrew","followers_url":"https://api.github.com/users/canndrew/followers","following_url":"https://api.github.com/users/canndrew/following{/other_user}","gists_url":"https://api.github.com/users/canndrew/gists{/gist_id}","starred_url":"https://api.github.com/users/canndrew/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/canndrew/subscriptions","organizations_url":"https://api.github.com/users/canndrew/orgs","repos_url":"https://api.github.com/users/canndrew/repos","events_url":"https://api.github.com/users/canndrew/events{/privacy}","received_events_url":"https://api.github.com/users/canndrew/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":"closed","locked":false,"assignee":null,"milestone":null,"comments":66,"created_at":"2015-06-08T02:44:09Z","updated_at":"2016-05-03T04:27:19Z","closed_at":"2015-07-31T18:43:19Z","pull_request":{"url":"https://api.github.com/repos/rust-lang/rfcs/pulls/1154","html_url":"https://github.com/rust-lang/rfcs/pull/1154","diff_url":"https://github.com/rust-lang/rfcs/pull/1154.diff","patch_url":"https://github.com/rust-lang/rfcs/pull/1154.patch"},"body":"[Rendered view](https://github.com/canndrew/rfcs/blob/master/text/0000-disjoins.md)\r\n\r\n**Edit 2:** I have split off a separate RFC for the `!` type [here](https://github.com/rust-lang/rfcs/pull/1216). This RFC now assumes that RFC as a prerequisite.\r\n\r\n**Edit:** A lot of people are getting stuck on this point so it bears further clarification. `()` and `!` are not the same type. They are related, but different. `()` is the type with **one** value, `!` is the type with ***zero*** values. What this means:\r\n  * A function with return type `()` can only return `()`. This why you don't need a return statement in such a function, because there's only one thing it can possibly return. A function with return type `!` can *never return at all* - because there's nothing that it could return.\r\n  * A variable of type `()` can only be assigned one value (ie. the value `()`). A variable of type `!` can *never be assigned a value at all*. This doesn't mean you can't use them, for example it's totally okay to write `let x: ! = panic!()` because `panic!()` never returns. You could also write a function that takes a `!` argument - but that function could never be called.\r\n  * Likewise, an enum variant of type `!` can never exist. For example, a value of type `Result<T, !>` is guaranteed to be `Ok` because there's nothing the `Err` variant could hold. Contrast this with `Result<T, ()>` which has a value `Err(())`.\r\n  * Code that handles a variable of type `!` never executes. This is enforced at compile time by the type-checker. Rust doesn't allow uninitialized variables and it's impossible to write (safe) code that initializes a `!`.\r\n  * `!` can be mapped to any other type. To see why this is so consider the definition of a (pure) function: A function assigns to every value in it's domain a value in it's codomain. For example, to specify a function `fn foo(x: bool) -> i32` we need to specify the values of `foo(true)` and `foo(false)`. For this we can use something like `match x { true => 23, false => 34}`. Likewise, to specify a function `fn bar(x: !) -> i32` we need to specify a value for each possible `x` - of which there are none. We could write the function body as `match x {}`. This works because there is one match branch for each possible `x` and every branch returns an `i32`. If you find yourself asking \"but what value does that return?\", ask yourself \"for what x?\" and then look at the match statement again. Also, remember that that match statement can never execute.\r\n  * `!` can be thought of as a subtype of every other type. Every `!` is also a `String`, and an `i32`, and a `char` etc. This is true for the same reason that `Iterator::all` returns `true` on an empty iterator - there are no counterexamples. By contrast, the same is not true of `()`. The value `()` is not a `String`, or an `i32`, or a `char` etc. This RFC proposed to allow `!` to unify with any other type (as it already does) meaning that a variable of type `!` can be treated as any type.\r\n  * `()` can be thought of as being an empty *value* (the value `()` has no bits of information). `!` is an empty *type* (the type `!` has not inhabitants). They both mean \"nothing\", but it's a different \"nothing\".\r\n\r\nNote that `!` is not new or in any way special. We already have all these behaviours with empty enums. Given `enum Empty {}` and `e: Empty` we know:\r\n  * A function that returns `Empty` diverges.\r\n  * A function that takes an `Empty` can never be called\r\n  * `e` can never be assigned a value\r\n  * The code that handles `e` will never execute.\r\n  * a `Result<T, Empty>` can only be `Ok`, never `Err`\r\n  * `e` can be mapped into any type with `match e {}`\r\n"},"comment":{"url":"https://api.github.com/repos/rust-lang/rfcs/issues/comments/216432597","html_url":"https://github.com/rust-lang/rfcs/pull/1154#issuecomment-216432597","issue_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1154","id":216432597,"user":{"login":"eternaleye","id":99404,"avatar_url":"https://avatars.githubusercontent.com/u/99404?v=3","gravatar_id":"","url":"https://api.github.com/users/eternaleye","html_url":"https://github.com/eternaleye","followers_url":"https://api.github.com/users/eternaleye/followers","following_url":"https://api.github.com/users/eternaleye/following{/other_user}","gists_url":"https://api.github.com/users/eternaleye/gists{/gist_id}","starred_url":"https://api.github.com/users/eternaleye/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eternaleye/subscriptions","organizations_url":"https://api.github.com/users/eternaleye/orgs","repos_url":"https://api.github.com/users/eternaleye/repos","events_url":"https://api.github.com/users/eternaleye/events{/privacy}","received_events_url":"https://api.github.com/users/eternaleye/received_events","type":"User","site_admin":false},"created_at":"2016-05-03T04:27:18Z","updated_at":"2016-05-03T04:27:18Z","body":"I can see a few potentially-sensible approaches. Firstly, in your example, the caller constructed a `u32 | u32`, so I can simply say \"`bar::<u32>()` is not callable\".\r\n\r\nMore interesting, perhaps, might be this:\r\n\r\n```Rust\r\nfn bar<T>(x: T) -> Foo<T> {\r\n  X\r\n}\r\n```\r\n\r\nHere, the disjoin construction occurs in a context where unification is unknown. I see two-and-a-half approaches here:\r\n\r\n1. If no `Foo<T>` ever escapes to a context where `T` is a specific type, the compiler can still distinguish, thus `T` and `u32` do not unify _in any `Foo<T>`_\r\n2. Fail at monomorphization time\r\n3. (1/2) Unify the variants (likely nonviable)\r\n\r\nPersonally, I prefer (1) - it maintains the idea I used for your example that it's the responsibility of the code specifying the type parameter to avoid creating invalid disjoins."}}