This issue is mainly constructive feedback on and mysterious compiler message from chpl. the message does not state what is happening during compilation. output message also encurage bug reports. So here it is.
Please compile the program below. My best guess is that the untyped variable openSet can not be initialized with value noinit. However the message is somewhat unclear on what the issue is.
mac-c02nk5cng3qd:AStar andreas.hysing$ mason build
Skipping registry update since no dependency found in manifest file.
Compiling [debug] target: AStar
/Users/andreas.hysing/Documents/code/AStar/src/AStar.chpl:52: In initializer:
/Users/andreas.hysing/Documents/code/AStar/src/AStar.chpl:57: internal error: RES-FUN-ION-6655 chpl version 1.23.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.
/Users/andreas.hysing/Documents/code/AStar/src/AStar.chpl:207: called as borrowed Searcher.init(type eltType = real(64), impl: ConnectFour, N: int(64), M: int(64))
Build Failed
Compile the program below
Source Code:
/* Documentation for AStar */
module AStar {
private use List;
private use BlockDist;
private use Heap;
private use Map;
pragma "no doc"
iter backtrace(cameFrom, end) {
var at = end;
while cameFrom.contains(at) {
const next = cameFrom.getValue(at);
at = next;
yield next;
}
}
pragma "no doc"
proc reconstructPath(cameFrom, current)
{
var fullPath = List.init(cameFrom.type);
for current in backtrace(cameFrom, current) do
fullPath.prepend(current);
return fullPath;
}
enum Visit {
Unexplored,
Open,
Closed
}
public class Searcher {
/* The type of the states contained in this EStar space. */
type eltType;
/* The distance, heuristic and findNeighbors functions */
var impl;
forwarding impl only distance, heuristic, findNeighbors;
/* The size of the AStar state space. */
var N : int;
var M : int;
type BlockDom = domain(2) dmapped Block({0..16, 0..16});
var openSet;
var fScore : [BlockDom] real = noinit;
var gScore : [BlockDom] real = noinit;
var cameFrom : map;
/*
Initializes an empty Searcher.
:arg eltType: The type of the states
:arg N: the size of the search space
*/
proc init(type eltType, impl, N : int, M : int) {
this.eltType = eltType;
this.impl = impl;
this.N = N;
this.M = M;
this.openSet = noinit;
this.fScore = {0..N, 0..M};
this.gScore = {0..N, 0..M};
this.cameFrom = Map.init(eltType, eltType);
this.complete();
_checkType(eltType);
}
pragma "no doc"
proc _checkType(type eltType) {
if isGenericType(eltType) {
compilerWarning("creating a AStar with element type " +
eltType:string);
if isClassType(eltType) && !isGenericType(borrowed eltType) {
compilerWarning("which now means class type with generic management");
}
compilerError("AStar element type cannot currently be generic");
}
}
pragma "no doc"
proc initializeOpenSet(start) {
forall i in openSet.indices do
openSet[i] = Visit.Unexplored;
openSet[start] = Visit.Open;
}
pragma "no doc"
proc initializeFScore(start) {
forall i in 0..fScore.indices do
fScore[i] = 0.0;
fScore[start] = heuristic(start);
}
pragma "no doc"
proc initializeGScore(start) {
forall i in gScore.indices do
gScore[i] = max(real);
gScore[start] = 0.0;
}
iter iterateSet(openSet) {
for i in openSet.indices {
yield openSet[i];
}
}
pragma "no doc"
proc isEmpty(openSet) {
var empty = true;
forall state in iterateSet(openSet) with (&& reduce empty) {
empty &&= (state == Visit.Closed);
}
return empty;
}
/*
A* search function.
*/
proc search(start : eltType, f : real, g : real, goal : eltType) {
// The set of discovered nodes that may need to be (re-)expanded.
// Initially, only the start node is known.
initializeOpenSet(start);
// For node n, cameFrom[n] is the node immediately preceding it on the cheapest path from start
// to n currently known.
cameFrom.clear();
// For node n, gScore[n] is the cost of the cheapest path from start to n currently known.
initializeFScore(start);
// For node n, fScore[n] = gScore[n] + h(n). fScore[n] represents our current best guess as to
// how short a path from start to finish can be if it goes through n.
initializeGScore(start);
var result : real;
for loc in Locales do
on loc do
while ! isEmpty(openSet) do {
// This operation can occur in O(1) time if openSet is a min-heap or a priority queue
const current = openSet.top();
if current == goal then
result = reconstructPath(cameFrom, current);
else {
const state = openSet.pop();
// d(current,neighbor) is the weight of the edge from current to neighbor
// tentative_gScore is the distance from start to the neighbor through current
forall neighbor in findNeighbors(this, current) do {
const tentative_gScore = score[current] + distance(current, neighbor);
if tentative_gScore < gScore[neighbor] {
// This path to neighbor is better than any previous one. Record it!
cameFrom[neighbor] = current;
gScore[neighbor] = tentative_gScore;
fScore[neighbor] = gScore[neighbor] + heuristic(neighbor);
}
var neighborNotInOpenSet = true;
forall n in openSet.these() do
if n == neighbor then neighborNotInOpenSet = false;
if neighborNotInOpenSet then
openSet.add(neighbor);
}
}
}
// Open set is empty but goal was never reached
return result;
}
}
pragma "no doc"
record Comparator { }
pragma "no doc"
proc Comparator.compare(a, b) {
return abs(a) - abs(b);
}
record ConnectFour {
var depth : int(32);
proc _minimax() {
return 1.0;
}
proc heuristic(searcher : borrowed Searcher) {
return _minimax();
}
proc distance(a, b) {
return 1:real;
}
proc findNeighbors(searcher : borrowed Searcher, state) {
var l = List.init(real);
return l;
}
}
proc main() {
writeln("Started");
writeln("This program is running on ", numLocales, " locales");
var D = {0..16, 0..16};
var values: [D] Visit;
const connectFour = new ConnectFour(5);
const numRows : int = 6;
const numColumns : int = 7;
var searcher = new Searcher(real, connectFour, numRows, numColumns);
writeln("Finished");
}
}
Compile command:
mason build
Execution command:
N/A
Associated Future Test(s):
N/A
Output of chpl --version:
chpl version 1.23.0
Copyright 2020 Hewlett Packard Enterprise Development LP
Copyright 2004-2019 Cray Inc.
(See LICENSE file for more details)
Output of $CHPL_HOME/util/printchplenv --anonymize:
CHPL_TARGET_PLATFORM: darwin
CHPL_TARGET_COMPILER: clang
CHPL_TARGET_ARCH: x86_64
CHPL_TARGET_CPU: 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: cstdlib
CHPL_GMP: gmp
CHPL_HWLOC: hwloc
CHPL_REGEXP: re2
CHPL_LLVM: none
CHPL_AUX_FILESYS: none
Back-end compiler and version, e.g. gcc --version or clang --version:
gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 12.0.0 (clang-1200.0.32.27)
Target: x86_64-apple-darwin20.1.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
clang --version
Apple clang version 12.0.0 (clang-1200.0.32.27)
Target: x86_64-apple-darwin20.1.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
module list:@ahysing: Thanks very much for reporting this. With a quick look, I believe that you are correct that this is due to applying noinit to an untyped variable. Specifically, here's a shorter program that reproduces the same behavior:
class C {
var x;
proc init() {
x = noinit;
}
}
var myC = new C();
While this isn't a pattern that we intended to support, at least at present, it shouldn't be generating an internal error either, but should generate a user-facing one.
Something that may be of use to you as you go on (if you're interested) is that Chapel's internal errors can be viewed in more of a developer mode by throwing the --devel flag upon hitting them (though I wouldn't recommend using the flag in general for most users). For example, for my program, using this flag gives:
testit1a.chpl:3: In initializer:
testit1a.chpl:4: internal error: bad no init call [resolution/functionResolution.cpp:6655]
(where even the internal error could be improved by using 'noinit' rather than 'no init' :) ).
Thanks again for bringing this to our attention.
Tagging @mppf on this, who has worked in this area most recently.
PR #16796 should resolve the issue with the error message.
Most helpful comment
PR #16796 should resolve the issue with the error message.