[J3] Still a problem for elemental type-bound functions

Van Snyder van.snyder at sbcglobal.net
Mon Mar 29 21:32:33 UTC 2021


Thanks to Tom and Bill for pointing out that TYPEOF and CLASSOF, which
were rejected in 2004, are finally arriving. I missed this. You might
have observed that after the thought police took over, my participation
has not been as enthusiastic and extensive as it once was.

But...

C708 An entity declared with the CLASS or CLASSOF keyword shall be a
dummy argument or have the ALLOCATABLE or POINTER attribute.

means that the result variable of an elemental function still cannot be
of the same dynamic type as its passed-object dummy argument, if the
dummy argument's dynamic type is an extension of its declared type,
unless the result is ALLOCATABLE or a POINTER, which it cannot be
because the function is elemental.

A generic operator binding can be invoked by way of an operation whose
operands' dynamic types are extensions of the result type. Because the
result is not polymorphic, its dynamic type cannot be the same as its
operands' dynamic type. The processor is not required to provide any
notice of this potentially serious error.

So this implementation of CLASSOF doesn't solve the problem.

There are many ways to proceed, none that are complete solutions, but
all are better than doing nothing.


One way is to allow CLASSOF for a function result, provided the <data-
ref> is a polymorphic dummy argument, with a specification that the
dynamic type of the result is the same as the dynamic type of the data-
ref.

Would this work?

"C708 An entity declared with the CLASS keyword shall be a dummy
argument or have the ALLOCATABLE or POINTER attribute.

"C708a An entity declared with the CLASSOF keyword shall be a dummy
argument or function result, or have the ALLOCATABLE or POINTER
attribute. If the entity is a function result, the <data-ref> shall be
a polymorphic dummy argument of that function."


Somewhere else, not in C708a:

"If the function result is declared using the CLASSOF keyword, and does
not have the ALLOCATABLE or POINTER attribute, the dynamic type of the
result is the same as the dynamic type of the <data-ref> in the
declaration."

This works for elemental functions because the dynamic types of the
elements of the arguments are homogeneous. It should also be required
that if the function is type-bound that the result gets its dynamic
type from the passed-object dummy argument. This would be detected in
the binding, not in the function definition.

"C789a If NOPASS does not appear and the procedure is a function for
which the result is declared using CLASSOF, the <data-ref> in the
CLASSOF declaration shall refer to the passed-object dummy argument."
Thereby, if one writes "A = B + C" (with A polymorphic and allocatable)
the result will be of the dynamic type of B or C, depending upon which
one is associated with the dummy argument from whose declaration the
result gets its dynamic type of the passed-object dummy argument. This
doesn't guarantee that B and C have the same dynamic type, but it's an
improvement over the result dynamic type not being the same as either
argument's dynamic type.

Another way is to allow the passed-object dummy argument not to be
polymorphic, and to require that type-bound procedures whose passed-
object dummy argument is not polymorphic be overridded in every
extension. There are still problems with this. For example, if B and C
do not have the same declared type in "A = B + C", for example if the
declared type of the one associated with the passed-object dummy
argument is an extension of the type of the other, the operation cannot
be invoked (with our present argument association rules, which ought
not to be relaxed).

This still doesn't completely work because, without a polymorphic
passed-object dummy argument, dynamic dispatch does not take place.
Dispatching could be inferred if the actual argument associated with
the passed-object dummy argument is polymorphic.  A passed-object dummy
argument is required if there is a generic operator binding.

The problem is actually a bit deeper because there is no requirement
when invoking a type-bound function by way of an OPERATOR(...) generic
binding that the operands have the same dynamic type. In some cases,
this is important; in others, the program's author can "do the right
thing" if the dynamic types are different.

Tom briefly advocated NON_OVERRIDABLE, and then retracted that, because
it doesn't do the right thing.

A third way is to allow a SHALL_OVERRIDE attribute for a type-bound
procedure. This might actually be the best solution, but it doesn't
mean that allowing CLASSOF for function results that are neither
ALLOCATABLE nor POINTER would not be useful.


One thing that would be helpful is an exception system, so that a
function can raise an exception if the dynamic types of its arguments
are not the same (if the function doesn't have some other way to cope
with that situation). At least the invoking procedure could catch the
exception and "do something" more meaningful than the function simply
stopping the program. If the exception isn't caught, a "good" processor
would provide a back trace to the exception. This is better than a STOP
statement (STOP with traceback was proposed for Fortran 90, but was not
accepted). Compile-time protection is, however, always preferable to
run-time error messages.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.j3-fortran.org/pipermail/j3/attachments/20210329/028cab98/attachment.htm>


More information about the J3 mailing list