Chapel: Passing a function with an array argument results in internal error

Created on 6 Jan 2019  路  3Comments  路  Source: chapel-lang/chapel

Summary of Problem


I am trying to pass a function mult10 to another function and ask some calculation. Here,mult10 is a test function that receives a one-dimensional array and multiplies their elements by 10. But the compilation fails with an internal error. I also tried attaching one of ref, in, out, inout (disregarding their meaning anyway), but all of them result in the same internal error.

My motivation for this code is to pass a function with an array argument to a different routine and set the calculated result to the array in-place (rather than getting the result as a function return value).

Steps to Reproduce

Source Code:

// test1.chpl
proc mult10( arr : [] int ) {
    arr *= 10;
}

proc test( f ) {
    var A : [1..5] int = 5;
    f( A );
    writeln( A );
}

// This part works
var B : [1..7] int = 7;
mult10( B );
writeln( B );  // -> 70 70 70 70 70 70 70

// This line results in internal error
test( mult10 );

Because the mult10() above may be still "generic" (by being able to receive an arbitrary dimensional array), I also tried making it a specific function somehow. First, this "test2.chpl"

// test2.chpl
proc mult10( arr : [domain(1,int(64),false)] int(64) ) {
    arr *= 10;
}
// (the remaining part is the same)

fails with a compilation error (probably because my specification of array type is wrong...), while "test3.chpl" below works somehow (although I am not sure whether the use of [1..1] for array1Dint is reasonable or not).

// test3.chpl
var array1Dint: [1..1] int;

proc mult10( arr : array1Dint.type ) {
    arr *= 10;
}
// (the remaining part is the same)

Compile command:
chpl test.chpl

Error message:

test1.chpl:2: In function 'mult10':
test1.chpl:2: internal error: CAL0124 chpl version 1.18.0

Internal errors indicate a bug in the Chapel compiler ("It's us, not you"),
and we're sorry for the hassle.  We would appreciate your reporting this bug -- 
please see https://chapel-lang.org/bugs.html for instructions.  In the meantime,
the filename + line number above may be useful in working around the issue.

Configuration Information

  • Output of chpl --version:
    chpl version 1.18.0

  • Output of $CHPL_HOME/util/printchplenv --anonymize:
    CHPL_TARGET_PLATFORM: darwin
    CHPL_TARGET_COMPILER: clang
    CHPL_TARGET_ARCH: native
    CHPL_LOCALE_MODEL: flat
    CHPL_COMM: none
    CHPL_TASKS: qthreads
    CHPL_LAUNCHER: none
    CHPL_TIMERS: generic
    CHPL_UNWIND: none
    CHPL_MEM: jemalloc
    CHPL_ATOMICS: intrinsics
    CHPL_GMP: none
    CHPL_HWLOC: hwloc
    CHPL_REGEXP: none
    CHPL_AUX_FILESYS: none

  • Output of clang --version
    Apple LLVM version 8.0.0 (clang-800.0.42.1)
    Target: x86_64-apple-darwin15.6.0
    Thread model: posix
    InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Compiler user issue

All 3 comments

@ty1027 - first class functions are missing a lot of functionality and design right now. This is a known issue and will take some time to solve. It's described in #8351 but and for now we are prioritizing other things above improving the situation.

Something that works much better in the current compiler is to use a "function object". This term is borrowed from C++. The idea is to create a record or a class that implements the this method which means that it can be syntactically called like a function. But in fact this just translates into calling the this method.

For example, here is a working version of your program using this approach:

record Mult10 {
  proc this( arr : [] int ) {
    arr *= 10;
  }
}

proc test( f ) {
    var A : [1..5] int = 5;
    f( A );
    writeln( A );
}

// This part works
var B : [1..7] int = 7;
var mult10 = new Mult10();
mult10(B);
writeln( B );  // -> 70 70 70 70 70 70 70

// This line results in internal error
test( mult10 );

When using this function object approach, the expectation is that you'd explicitly store any state the function needs (state that with first class functions you could encode by referring to outer variables). This state needs to be stored as fields in the record or class defining the function object.

@mppf Thanks very much for suggesting a workaround approach (= function object). I have just tried it on my machine, and it seems to work very nicely. In my actual code, I need to pass various functions that calculate energy and gradient vector in-place, which should be straightforward if the above Mult10 case works. Thanks much!

@ty1027 - glad your immediate problem is solved. Let's leave this and the other issue open for whenever we fix up first class functions. I'd still like those to work one day as they're simpler to write.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ben-albrecht picture ben-albrecht  路  3Comments

bradcray picture bradcray  路  4Comments

ben-albrecht picture ben-albrecht  路  3Comments

BryantLam picture BryantLam  路  3Comments

BryantLam picture BryantLam  路  3Comments