{"action":"created","issue":{"url":"https://api.github.com/repos/crystal-lang/crystal/issues/3266","repository_url":"https://api.github.com/repos/crystal-lang/crystal","labels_url":"https://api.github.com/repos/crystal-lang/crystal/issues/3266/labels{/name}","comments_url":"https://api.github.com/repos/crystal-lang/crystal/issues/3266/comments","events_url":"https://api.github.com/repos/crystal-lang/crystal/issues/3266/events","html_url":"https://github.com/crystal-lang/crystal/issues/3266","id":175180733,"number":3266,"title":"Type inference: strange behavior with the || operator","user":{"login":"olbat","id":96066,"avatar_url":"https://avatars.githubusercontent.com/u/96066?v=3","gravatar_id":"","url":"https://api.github.com/users/olbat","html_url":"https://github.com/olbat","followers_url":"https://api.github.com/users/olbat/followers","following_url":"https://api.github.com/users/olbat/following{/other_user}","gists_url":"https://api.github.com/users/olbat/gists{/gist_id}","starred_url":"https://api.github.com/users/olbat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/olbat/subscriptions","organizations_url":"https://api.github.com/users/olbat/orgs","repos_url":"https://api.github.com/users/olbat/repos","events_url":"https://api.github.com/users/olbat/events{/privacy}","received_events_url":"https://api.github.com/users/olbat/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/crystal-lang/crystal/labels/compiler","name":"compiler","color":"fef2c0"},{"url":"https://api.github.com/repos/crystal-lang/crystal/labels/enhancement","name":"enhancement","color":"84b6eb"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2016-09-06T07:43:59Z","updated_at":"2016-09-06T11:48:13Z","closed_at":null,"body":"The type inference algorithm does not infer the same type when using two equivalent `||` and `&&` expressions:\r\n```crystal\r\na = b = nil\r\nif rand() >= 0\r\n  a = b = 1\r\nend\r\n\r\npp typeof(a), typeof(b)\r\n# typeof(a) # => (Int32 | Nil)\r\n# typeof(b) # => (Int32 | Nil)\r\n\r\nif a && b\r\n  pp typeof(a), typeof(b)\r\n  # typeof(a) # => Int32\r\n  # typeof(b) # => Int32\r\nend\r\n\r\nunless !a || !b\r\n  pp typeof(a), typeof(b)\r\n  # typeof(a) # => (Int32 | Nil)\r\n  # typeof(b) # => (Int32 | Nil)\r\nend\r\n```\r\nI think that in this case `a` and `b` should have the type `Int32` in the `unless` block or at least the type inference for equivalent `||` and `&&` expressions should behave the same way ...\r\n\r\n```bash\r\n$ crystal --version\r\nCrystal 0.18.7 [68783f1] (2016-07-03)\r\n```"},"comment":{"url":"https://api.github.com/repos/crystal-lang/crystal/issues/comments/244926555","html_url":"https://github.com/crystal-lang/crystal/issues/3266#issuecomment-244926555","issue_url":"https://api.github.com/repos/crystal-lang/crystal/issues/3266","id":244926555,"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},"created_at":"2016-09-06T11:48:13Z","updated_at":"2016-09-06T11:48:13Z","body":"True, though it seems a bit hard to implement. The problem is that in this:\r\n\r\n```cr\r\nif a.nil? || b.nil?\r\n  # We can't conclude anything about a or b\r\nelse\r\nend\r\n```\r\n\r\nThe compiler works by first trying to conclude something about the `if` condition, and then negating that conclusion for the `else` branch. But in the case of an `||` over distinct variables there's nothing to conclude about `a` and `b` at the same time, so there's nothing to negate.\r\n\r\nI'll leave it as an enhancement, maybe we can find a way to make it work."}}
{"actor":{"display_login":"asterite"}}