New Issue: FCF fields and the nothing type

20175, "lydia-duncan", "FCF fields and the nothing type", "2022-07-07T22:22:19Z"

Summary of Problem

I tried making a field that stores a first class function use the nothing type and the compiler was unhappy. It outputs the following:

saveInField-nothing.chpl:10: In initializer:
saveInField-nothing.chpl:11: error: could not find a copy initializer ('init=') for type 'shared chpl__fcf_type_int64_t_chpl_bool' from type 'nothing'
$CHPL_HOME/modules/internal/SharedObject.chpl:255: note: this candidate did not match: _shared.init=(pragma"nil from arg"in take: owned)
saveInField-nothing.chpl:11: note: because actual argument #1 with type 'nothing'
$CHPL_HOME/modules/internal/SharedObject.chpl:255: note: is passed to formal 'in take: owned'
saveInField-nothing.chpl:11: note: other candidates are:
$CHPL_HOME/modules/internal/SharedObject.chpl:281: note:   _shared.init=(pragma"nil from arg"const ref src: _shared)
$CHPL_HOME/modules/internal/SharedObject.chpl:303: note:   _shared.init=(src: borrowed)
note: and 2 other candidates, use --print-all-candidates to see them

The details block has the actual scenario that motivated me to find this, for the curious:

I was playing around with storing a hasher function in my attempt at the DistributedMap implementation (so that users can have control over which locale the key hashes to). Because the key and value type fields make any hashing of them generic, I can't write a default function to use that lives outside of the DistributedMap type, and I can't make a field that stores a fcf of a method, because the field initialization doesn't know about the methods on the type yet. So what I was hoping to do was have the hasher field be set to `none` when it is relying on the default hasher function and just call a method I've defined instead. That ran into this problem, which I've boiled down into a simpler test case.

Steps to Reproduce

Source Code:

record Foo {
  var funcStored = false;
  var funcField: func(int, bool) = none;

  proc init(x: func(int, bool)) {
    funcStored = true;
    funcField = x;
  }

  proc init() {
    this.complete();
  }

  proc callTheField(arg: int) {
    if (funcStored) {
      if (funcField(arg)) {
        writeln("fcf with arg ", arg, " successful");
      } else {
        writeln("fcf with arg ", arg, " unsuccessful");
      }
    } else {
      writeln("no fcf stored");
    }
  }
}

proc bar(x: int): bool {
  if (x * 3 > 15) {
    return true;
  } else {
    return false;
  }
}

var f1 = new Foo(bar); // field is a fcf
f1.callTheField(2);
f1.callTheField(6);
var f2 = new Foo();  // field is none
f2.callTheField(17);

Compile command:
chpl foo.chpl

Execution command:
N/A

Associated Future Test(s):
test/functions/firstClassFns/saveInField-nothing.chpl #TBD

Configuration Information

  • Output of chpl --version: 1.28.0 (pre-release)