ponylang / ponyc

Pony is an open-source, actor-model, capabilities-secure, high performance programming language
http://www.ponylang.io
BSD 2-Clause "Simplified" License
5.7k stars 415 forks source link

compiler segfaults when calling function with private default parameter that is not visible to caller #2930

Open aturley opened 5 years ago

aturley commented 5 years ago

Environment

OS: MacOS 10.13.6

Ponyc: 0.25.0-232a0abe1 [release] compiled with: llvm 3.9.1 -- Apple LLVM version 9.1.0 (clang-902.0.39.2) Defaults: pic=false ssl=openssl_0.9.0

Description

The compiler segfaults if there is a function call to a function with a default parameter that is private and not visible to the caller.

Steps to Reproduce

I've created a class called DoIt with an apply method that takes an Fn object as an argument, but the parameter has a default value of _DefaultFn. DoIt() is then called from main.pony, which is in another module and therefore cannot see _DefaultFn.

Create a directory that looks like this:

|- fn.pony
|- subdir
  |- main.pony

where fn.pony looks like this:

interface val Fn
  fun apply(): String =>
    "fn"

primitive _DefaultFn
  fun apply(): String =>
    "default fn"

primitive DoIt
  fun apply(fn: Fn = _DefaultFn): String =>
    fn()

and subdir/main.pony looks like this:

use ".."

actor Main
  new create(env: Env) =>
    env.out.print(DoIt())

From the subdir directory, run the Pony compiler like this:

ponyc

Expected Behavior

My expectation was that this would compile. If there's a reason it shouldn't compile then the compiler should generate an error.

Actual Behavior

The compiler segfaults. Here's the lldb backtrace:

➜  subdir lldb ~/development/ponyc.aturley/build/debug/ponyc
(lldb) target create "/Users/aturley/development/ponyc.aturley/build/debug/ponyc"
Current executable set to '/Users/aturley/development/ponyc.aturley/build/debug/ponyc' (x86_64).
(lldb) run
Process 11851 launched: '/Users/aturley/development/ponyc.aturley/build/debug/ponyc' (x86_64)
Building builtin -> /Users/aturley/development/ponyc.aturley/packages/builtin
Building . -> /private/tmp/issue/subdir
Building .. -> /private/tmp/issue
Process 11851 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    frame #0: 0x0000000100004bdf ponyc`method_check_type_params(opt=0x0000000000000000, astp=0x00007ffeefbfed08) at call.c:69
   66     typeparams = ast_childidx(type, 1);
   67     ast_replace(&typeparams, ast_from(typeparams, TK_NONE));
   68  
-> 69     REPLACE(astp, NODE(ast_id(lhs), TREE(lhs) TREE(typeargs)));
   70     ast_settype(*astp, type);
   71  
   72     return true;
Target 0: (ponyc) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
  * frame #0: 0x0000000100004bdf ponyc`method_check_type_params(opt=0x0000000000000000, astp=0x00007ffeefbfed08) at call.c:69
    frame #1: 0x0000000100004961 ponyc`method_check_type_params(opt=0x00007ffeefbff878, astp=0x000000010aed8280) at call.c:0
    frame #2: 0x00000001000162cd ponyc`pass_verify(astp=0x00007ffeefbfeee0, options=0x00007ffeefbff878) at verify.c:122
    frame #3: 0x00000001000145d9 ponyc`ast_visit(ast=0x00007ffeefbfeee0, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:457
    frame #4: 0x0000000100014510 ponyc`ast_visit(ast=0x00007ffeefbfef70, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:428
    frame #5: 0x0000000100014510 ponyc`ast_visit(ast=0x00007ffeefbff000, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:428
    frame #6: 0x0000000100014510 ponyc`ast_visit(ast=0x00007ffeefbff090, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:428
    frame #7: 0x0000000100014510 ponyc`ast_visit(ast=0x00007ffeefbff120, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:428
    frame #8: 0x0000000100014510 ponyc`ast_visit(ast=0x00007ffeefbff1b0, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:428
    frame #9: 0x0000000100014510 ponyc`ast_visit(ast=0x00007ffeefbff240, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:428
    frame #10: 0x0000000100014510 ponyc`ast_visit(ast=0x00007ffeefbff2d0, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:428
    frame #11: 0x0000000100014510 ponyc`ast_visit(ast=0x00007ffeefbff360, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:428
    frame #12: 0x0000000100014510 ponyc`ast_visit(ast=0x00007ffeefbff3f0, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:428
    frame #13: 0x0000000100014510 ponyc`ast_visit(ast=0x00007ffeefbff480, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:428
    frame #14: 0x0000000100014510 ponyc`ast_visit(ast=0x00007ffeefbff510, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:428
    frame #15: 0x0000000100014510 ponyc`ast_visit(ast=0x00007ffeefbff5a0, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:428
    frame #16: 0x0000000100014510 ponyc`ast_visit(ast=0x00007ffeefbff630, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:428
    frame #17: 0x0000000100014510 ponyc`ast_visit(ast=0x00007ffeefbff768, pre=0x0000000000000000, post=(ponyc`pass_verify at verify.c:109), options=0x00007ffeefbff878, pass=PASS_VERIFY) at pass.c:428
    frame #18: 0x00000001000150ec ponyc`visit_pass(astp=0x00007ffeefbff768, options=0x00007ffeefbff878, last_pass=PASS_ALL, out_r=0x00007ffeefbff733, pass=PASS_VERIFY, pre_fn=0x0000000000000000, post_fn=(ponyc`pass_verify at verify.c:109)) at pass.c:176
    frame #19: 0x0000000100014b29 ponyc`ast_passes(astp=0x00007ffeefbff768, options=0x00007ffeefbff878, last=PASS_ALL) at pass.c:275
    frame #20: 0x00000001000146d5 ponyc`ast_passes_program(ast=0x000000010bfbfd00, options=0x00007ffeefbff878) at pass.c:318
    frame #21: 0x00000001000f51ee ponyc`program_load(path=".", opt=0x00007ffeefbff878) at package.c:907
    frame #22: 0x000000010000242f ponyc`compile_package(path=".", opt=0x00007ffeefbff878, print_program_ast=false, print_package_ast=false) at main.c:56
    frame #23: 0x00000001000022da ponyc`main(argc=1, argv=0x00007ffeefbff978) at main.c:109
    frame #24: 0x00007fff5c35a015 libdyld.dylib`start + 1
    frame #25: 0x00007fff5c35a015 libdyld.dylib`start + 1
jemc commented 5 years ago

This is probably related to the "accidental" "fixing" of https://github.com/ponylang/ponyc/issues/539.

That is, that issue got magically resolved without anyone actually trying to do so, but that resolution probably has bugs, as evidenced by this segfault.