17649, "glitch", "Overridden method Named Arg defaults not being honored.", "2021-05-06T14:35:28Z"
Summary of Problem
This is an issue involving inheritance, overriding methods and named argument defaults values; a more complete description of the problem is below. In short the default values in the overridden method are not being honored, the parent class's are still being used. I'm not sure if this is expected behavior or a bug; if it's expected maybe the Named Arguments and Default Values documentation could be clarified (Procedures — Chapel Documentation 1.24)
What behavior did you observe when encountering this issue?
I declared a base class Foo with a proc hello
and an inheriting class Bar which overrides hello
. In proc hello
I have named arguments with default values. Foo has one set of defaults and Bar has another. When I declare and create a Foo and test out the defaults I get Foo's defaults; when i declare Bar and construct a Bar and repeat the test I get Bar's defaults; so far so good, everything works as expected. The issue I run into is when I declare a Foo but provide Bar as the concrete implementation. When I invoke the hello
proc, it runs the overridden Bar.hello()
but it gets Foo's defaults.
What behavior did you expect to observe?
When declaring a Foo and providing Bar as the concrete impl. I expected to get Bar's default values for the named arguments since Bar's hello
proc was the one that got invoked.
This may be working as the Chapel team intended but it was unexpected and the documentation on Named Arguments and Default Values (Procedures — Chapel Documentation 1.24) didn't really mention anything about what happens in the case of inheritance.
Is this a blocking issue with no known work-arounds?
This is not a blocking issue, it's really easy to work around, it's more that it was unexpected behavior, see previous note about possibly intended behavior.
Steps to Reproduce
Source Code:
Note, I also made a gist of it here: Chapel code example to illustrate issue with inheritance, overriding methods and named vars. · GitHub
/*
Chapel code example to illustrate issue with inheritance, overriding methods and named vars.
Declare a base class Foo with a hello proc. It has 3 named args with defaults.
Next Declare Bar which inherits from Foo and overrides Foo's hello proc with its own
default values for the named args.
When we declare a Foo with a concrete implementation of Bar we see that the Bar hello proc
gets invoked as expected, but the default args do not; they are still Foo's defaults.
Since the overridden proc of Bar's gets invoked, I would have expected Bar's defaults to go
along with it, but that's not the case based on the output.
*/
class Foo {
proc hello(greeting:string="foo default greeting", prefix:string="FOO_default_prefix", suffix:string="FOO_default_suffix"): string throws {
return "FOO.hello(...)=> greeting:`" + greeting + "`, prefix:`" + prefix + "`, suffix:`" + suffix + "`";
}
}
class Bar : Foo {
override proc hello(greeting:string="bar default greeting", prefix:string = "default_bar[", suffix:string = "]bar_default"): string throws {
return "I'm in BAR.hello(...)=> greeting:`" + greeting + "`, prefix:`" + prefix + "`, suffix:`" + suffix + "`";
}
}
// Create Foo with concrete Foo impl
// 1. Prove we get the defaults
// 2. Pass in greeting and get defaults on prefix & suffix
// 3. Pass in greeting & prefix, get default on suffix
var f:Foo = new Foo();
writeln("----Foo----");
writeln(f.hello());
writeln(f.hello(greeting="hello"));
writeln(f.hello(greeting="hello", prefix="<<<"));
// Create Bar with concrete Bar impl
// 1. Prove we get Bar's defaults
// 2. Pass in greeting and get Bar's defaults on prefix & suffix
// 3. Pass in greeting & prefix, get Bar's default on suffix
var b:Bar = new Bar();
writeln("----Bar----");
writeln(b.hello());
writeln(b.hello(greeting="I'm Bar"));
writeln(b.hello(greeting="I'm Bar", prefix="<<<"));
// Create Foo with conreate Bar impl.
// This uses Bar's overridden proc hello, but doesn't get the Bar default named args, why?
// 1. We see it inokes Bar's hello method in the output, but we get Foo's named defaults
// 2. Pass in greeting, we see Bar's method invoked, but still get Foo defaults on prefix & suffix
// 3. Pass in greetin & suffix, same thing, We see Bar's output message, but still Foo default suffix.
var fb:Foo = new Bar();
writeln("----Foo with Bar as impl----");
writeln(fb.hello());
writeln(fb.hello(greeting="expect Bar defaults"));
writeln(fb.hello(greeting="expect Bar defaults minus passed in prefix", prefix="<<<"));
Compile command:
chpl default-args-example.chpl
Execution command:
./default-args-example -nl 1
Configuration Information
-
Output of
chpl --version
: chpl version 1.24.1 -
Output of
$CHPL_HOME/util/printchplenv --anonymize
:
CHPL_TARGET_PLATFORM: linux64
CHPL_TARGET_COMPILER: gnu
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: none
CHPL_HWLOC: bundled
CHPL_REGEXP: re2
CHPL_LLVM: none
CHPL_AUX_FILESYS: none -
Back-end compiler and version, e.g.
gcc --version
orclang --version
: gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Thanks Chapel Team!