{"action":"created","issue":{"url":"https://api.github.com/repos/CausalityLtd/ponyc/issues/441","labels_url":"https://api.github.com/repos/CausalityLtd/ponyc/issues/441/labels{/name}","comments_url":"https://api.github.com/repos/CausalityLtd/ponyc/issues/441/comments","events_url":"https://api.github.com/repos/CausalityLtd/ponyc/issues/441/events","html_url":"https://github.com/CausalityLtd/ponyc/issues/441","id":121761155,"number":441,"title":"Map.keys() causes \"Illegal instruction (core dump)\"","user":{"login":"phrom","id":1063233,"avatar_url":"https://avatars.githubusercontent.com/u/1063233?v=3","gravatar_id":"","url":"https://api.github.com/users/phrom","html_url":"https://github.com/phrom","followers_url":"https://api.github.com/users/phrom/followers","following_url":"https://api.github.com/users/phrom/following{/other_user}","gists_url":"https://api.github.com/users/phrom/gists{/gist_id}","starred_url":"https://api.github.com/users/phrom/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/phrom/subscriptions","organizations_url":"https://api.github.com/users/phrom/orgs","repos_url":"https://api.github.com/users/phrom/repos","events_url":"https://api.github.com/users/phrom/events{/privacy}","received_events_url":"https://api.github.com/users/phrom/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2015-12-11T18:02:38Z","updated_at":"2015-12-11T23:42:14Z","closed_at":null,"body":"Hello,\r\n\r\nI'm almost finished going through the tutorial and started trying out some of the stdlib. I've run into trouble when using the map collection, with the following code:\r\n\r\n```pony\r\nuse \"collections\"\r\n\r\nactor Main\r\n  new create(env: Env) =>\r\n    let map = Map[I32, String]\r\n    try\r\n      map.insert(42, \"The answer\") \r\n      env.out.print(map(42))\r\n    end\r\n    for i in map.keys() do\r\n      env.out.print(i.string())\r\n    end\r\n    for s in map.values() do\r\n      env.out.print(s)\r\n    end\r\n```\r\n\r\nIt compiled without errors, but when I run it, I get the first print of \"The answer\", followed by a crash:\r\n\r\n```\r\n[phr@q10 hello]$ ponyc\r\nBuilding . -> /home/phr/hd/pony/hello\r\nBuilding builtin -> /usr/lib/pony/0.2.1.20151028/packages/builtin\r\nBuilding collections -> /usr/lib/pony/0.2.1.20151028/packages/collections\r\nBuilding ponytest -> /usr/lib/pony/0.2.1.20151028/packages/ponytest\r\nGenerating\r\nOptimising\r\nWriting ./hello.o\r\nLinking ./hello\r\n[phr@q10 hello]$ ./hello\r\nThe answer\r\nIllegal instruction (core dumped)\r\n```\r\n\r\nI got curious whether gdb would be of any use debugging Pony code, so I tried it out. Here's what it says:\r\n\r\n```\r\nProgram received signal SIGILL, Illegal instruction.\r\n[Switching to Thread 0x7fffee0ff700 (LWP 4043)]\r\n0x000000000040414e in collections_MapKeys_I32_String_collections_HashEq_I32_collections_HashMap_I32_String_collections_HashEq_I32_create (map=0x7ffff70d8080) at /usr/lib/pony/0.2.1.20151028/packages/collections/map.pony:289\r\n289\t  var _i: U64 = -1\r\n(gdb) bt\r\n#0  0x000000000040414e in collections_MapKeys_I32_String_collections_HashEq_I32_collections_HashMap_I32_String_collections_HashEq_I32_create (map=0x7ffff70d8080) at /usr/lib/pony/0.2.1.20151028/packages/collections/map.pony:289\r\n#1  collections_HashMap_I32_String_collections_HashEq_I32_keys (this=0x7ffff70d8080) at /usr/lib/pony/0.2.1.20151028/packages/collections/map.pony:269\r\n#2  Main_create (this=<optimized out>, env=0x7ffff7100400) at main.pony:10\r\n#3  0x0000000000409f3e in handle_message.lto_priv ()\r\n#4  0x0000000000412097 in run.lto_priv ()\r\n#5  0x0000000000412682 in run_thread.lto_priv ()\r\n#6  0x00007ffff7bc54a4 in start_thread () from /usr/lib/libpthread.so.0\r\n#7  0x00007ffff71eb13d in clone () from /usr/lib/libc.so.6\r\n```\r\n\r\nSo, it seems to crash when trying to initialize an unsigned variable with -1. I'm a bit surprised the type system would allow that, but fair enough... I tried to change the MapKeys code to initialize _i with 0, just to see what would happen. It didn't go much further:\r\n\r\n```\r\nProgram received signal SIGILL, Illegal instruction.\r\n[Switching to Thread 0x7fffee900700 (LWP 3958)]\r\n0x0000000000404157 in Main_create (this=<optimized out>, env=0x7ffff7100400) at main.pony:10\r\n10\t    for i in map.keys() do\r\n(gdb) bt\r\n#0  0x0000000000404157 in Main_create (this=<optimized out>, env=0x7ffff7100400) at main.pony:10\r\n#1  0x0000000000409f3e in handle_message.lto_priv ()\r\n#2  0x0000000000412097 in run.lto_priv ()\r\n#3  0x0000000000412682 in run_thread.lto_priv ()\r\n#4  0x00007ffff7bc54a4 in start_thread () from /usr/lib/libpthread.so.0\r\n#5  0x00007ffff71eb13d in clone () from /usr/lib/libc.so.6\r\n```\r\n\r\nThe same problems happens if I call map.values() instead of map.keys().\r\n\r\n`ponyc --version` gives me `0.2.1-96-g57461c4`. It's the current version packaged on ArchLinux. I tried building from the git latest, but got a compilation error:\r\n\r\n```\r\nsrc/libponyc/codegen/gencontrol.c:508:26: error: too many arguments to function ‘LLVMBuildLandingPad’\r\n   LLVMValueRef landing = LLVMBuildLandingPad(c->builder, lp_type,\r\n```\r\n\r\nThis could be because I have LLVM 3.7, while the README.md instructions for Linux builds is asking for 3.6. But I don't have time to try looking for LLVM 3.6 now."},"comment":{"url":"https://api.github.com/repos/CausalityLtd/ponyc/issues/comments/164080978","html_url":"https://github.com/CausalityLtd/ponyc/issues/441#issuecomment-164080978","issue_url":"https://api.github.com/repos/CausalityLtd/ponyc/issues/441","id":164080978,"user":{"login":"andymcn","id":7050628,"avatar_url":"https://avatars.githubusercontent.com/u/7050628?v=3","gravatar_id":"","url":"https://api.github.com/users/andymcn","html_url":"https://github.com/andymcn","followers_url":"https://api.github.com/users/andymcn/followers","following_url":"https://api.github.com/users/andymcn/following{/other_user}","gists_url":"https://api.github.com/users/andymcn/gists{/gist_id}","starred_url":"https://api.github.com/users/andymcn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/andymcn/subscriptions","organizations_url":"https://api.github.com/users/andymcn/orgs","repos_url":"https://api.github.com/users/andymcn/repos","events_url":"https://api.github.com/users/andymcn/events{/privacy}","received_events_url":"https://api.github.com/users/andymcn/received_events","type":"User","site_admin":false},"created_at":"2015-12-11T23:42:13Z","updated_at":"2015-12-11T23:42:13Z","body":"I can't reproduce this, so I'd guess it is a problem with your VM. Let us know if you fix it or decide it is a Pony problem.\r\n\r\nThe reason for requiring explicit integer size conversions is bug reduction. There are many bugs in languages like C caused by people assuming integer sizes are different from what the compiler thinks they are. In Pony we don't like things where you have to guess / know exactly how the compiler handles things, so we try to make everything explicit.\r\n\r\nHere's an example bug if explicit conversion wasn't needed. I'm using small sizes to make it more obvious what's going on, but exactly the same principle applies to all sizes.\r\n```pony\r\nlet x: U8 = 0x12\r\nlet y: U16 = x << 8\r\n```\r\nWhat is the value of `y`? Well it's either `0x1200` or `0`, depending on when the size change occurs. Basically it's the difference between\r\n```pony\r\nlet y: U16 = x.u16() << 8  // 0x1200\r\n```\r\nand\r\n```pony\r\nlet y: U16 = (x << 8).u16()  // 0\r\n```\r\n\r\nMost languages have **very** complex rules to determine what the size of each operation result is, which catches out so many people. By being explicit about **all** conversions Pony avoids this.\r\n\r\nFor more information on the problem look up the \"usual arithmetic conversions\" in C and other languages. If you've never looked at this stuff before I guarantee C does not do what you think it does in many cases when using integers of different sizes, especially anything smaller than `int`."}}