{"action":"opened","issue":{"url":"https://api.github.com/repos/crystal-lang/crystal/issues/2661","repository_url":"https://api.github.com/repos/crystal-lang/crystal","labels_url":"https://api.github.com/repos/crystal-lang/crystal/issues/2661/labels{/name}","comments_url":"https://api.github.com/repos/crystal-lang/crystal/issues/2661/comments","events_url":"https://api.github.com/repos/crystal-lang/crystal/issues/2661/events","html_url":"https://github.com/crystal-lang/crystal/issues/2661","id":157228386,"number":2661,"title":"[RFC] Don't unify types under the same hierarchy as a base virtual type","user":{"login":"asterite","id":209371,"avatar_url":"https://avatars.githubusercontent.com/u/209371?v=3","gravatar_id":"","url":"https://api.github.com/users/asterite","html_url":"https://github.com/asterite","followers_url":"https://api.github.com/users/asterite/followers","following_url":"https://api.github.com/users/asterite/following{/other_user}","gists_url":"https://api.github.com/users/asterite/gists{/gist_id}","starred_url":"https://api.github.com/users/asterite/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/asterite/subscriptions","organizations_url":"https://api.github.com/users/asterite/orgs","repos_url":"https://api.github.com/users/asterite/repos","events_url":"https://api.github.com/users/asterite/events{/privacy}","received_events_url":"https://api.github.com/users/asterite/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2016-05-27T15:11:33Z","updated_at":"2016-05-27T15:11:33Z","closed_at":null,"body":"Given:\r\n\r\n```crystal\r\nclass Foo\r\nend\r\n\r\nclass Bar < Foo\r\nend\r\n\r\nclass Baz < Foo\r\nend\r\n```\r\n\r\nWe have:\r\n\r\n```crystal\r\nvar = rand < 0.5 ? Bar.new : Baz\r\ntypeof(var) #=> Foo\r\n```\r\n\r\nThat is, the type of the variable becomes `Foo`. Internally the compiler sees this as `Foo+`, which means \"`Foo` or any of its subtypes\".\r\n\r\nMaybe the compiler shouldn't do this. Before 0.16.0 this was kind of needed because otherwise instance variables would end up with huge unions. Now one has to specify their type, and so one could choose to do either of these, depending on the use case:\r\n\r\n```crystal\r\n# Foo or any of its subclasses\r\n@foo : Foo\r\n\r\n# I know foo can only be Bar or Baz (or any of its subclasses), but not other subclasses of Foo\r\n@foo : Bar | Baz\r\n```\r\n\r\nThis needs to be tested in the compiler to see if there's nothing obvious that would break, so this RFC is actually more a \"needs to try this and see what happens\" and then take a decision. Big union types could still appear for local variables, and there's also the thing that `[Bar.new, Baz.new]` would be typed as `Array(Bar | Baz)` instead of `Array(Foo)`, where one might expect that to be typed as the later.\r\n"}}
{"actor":{"display_login":"asterite"}}