17679, "cassella", "spec coverage of virtual dispatch and default values", "2021-05-12T12:45:32Z"
I think we need to update the spec with our decision here - identical signatures needs to include intent, type and existence of default value - but not the default value itself.
The spec does now mention intent and type, in classes.rst, but doesn't mention default valueness;
In order to have identical signatures, two methods must have the same
names, and their formal arguments must have the same names, intents, types,
and order.
As a language user though, one of the ways of a method and its
overload differing wrt default valueness make intuitive sense. And
that case does work as I'd expect on master today, when the parent
class method has no default but the child class method does:
var five = 5;
var six = 6;
class C {
proc foo(x: int) { writeln("C.foo: ", x); }
}
class D : C {
override proc foo(x: int = six) { writeln("D.foo: ", x); }
}
var c = new C();
c.foo(1);
var d = new D();
d.foo();
d.foo(2);
var d2: C = new D();
d2.foo(3);
C.foo: 1
D.foo: 6
D.foo: 2
D.foo: 3
The other way around compiles and runs, but isn't as intuitive to me:
var five = 5;
var six = 6;
class C {
proc foo(x: int = five) { writeln("C.foo: ", x); }
}
class D : C {
override proc foo(x: int) { writeln("D.foo: ", x); }
}
var c = new C();
c.foo();
c.foo(1);
var d = new D();
d.foo();
d.foo(2);
var d2: C = new D();
d2.foo();
d2.foo(3);
As a language user, I'm especially surprised that the call to d.foo() compiles. Through #7880 et. al. I think I've picked up that
the method call's default values are computed at the call site via
virtual dispatch to something like c.foo_default_x_method(). The
behavior makes sense in light of that.
But I don't think that's an understanding that's granted by the
documentation. Though I can guess now that D has inherited C's foo_default_x_method(), and the compiler seeing that existing
inserts a call to it for d.foo()?
In procedures.rst, where the spec covers default values, it doesn't
suggest that default values are provided by compiler-generated
functions/methods:
If the actual argument is omitted from the function call, the default expression is evaluated when the function call is made and the evaluated result is passed to the formal argument as if it were passed from the call site.
If both of these cases should work this way, then the spec section on
signatures doesn't need an update for this issue. But I think it
should say somewhere that an overriding function inherits default
values, if not spelling out the existence and semantics of default
value methods.
If one or both of these cases shouldn't compile, the spec section on
signatures and the compiler both need updating.