The following constraints are added to Rule R1215 in Section 188.8.131.52 of the Fortran 90 standard (defining function-subprogram):
The above constraints are designed to guarantee that a pure function is free from side effects (i.e., modifications of data visible outside the function), which means that it is safe to reference concurrently, as explained earlier.
The first constraint (requiring explicit INTENT(IN)) declares behavior that is ensured by the following rules. It is not technically necessary, but is included for consistency with the explicit declaration rules for defined operators. Note that POINTER arguments may not have the INTENT attribute; the restrictions below ensure that POINTER arguments also behave as if they had INTENT(IN), for both the argument itself and the object pointed to.
The second constraint (disallowing SAVE variables) ensures that a pure function does not retain an internal state between calls, which would allow side-effects between calls to the same procedure.
The third constraint (the restrictions on use of global variables and dummy arguments) ensures that dummy arguments and global variables are not modified by the function. In the case of a dummy or global pointer, this applies to both its pointer association and its target value, so it cannot be subject to a pointer assignment or to an ALLOCATE, DEALLOCATE, or NULLIFY statement. Incidentally, these constraints imply that only local variables and the dummy result variable can be subject to assignment or pointer assignment.
In addition, a dummy or global data object cannot be the target of a pointer assignment (i.e., it cannot be used as the right hand side of a pointer assignment to a local pointer or to the result variable), for then its value could be modified via the pointer. (An alternative approach would be to allow such objects to be pointer targets, but disallow assignments to those pointers; syntactic constraints to allow this would be even more draconian than these.)
In connection with the last point, it should be noted that an ordinary (as opposed to pointer) assignment to a variable of derived type that has a pointer component at any level of component selection may result in a pointer assignment to the pointer component of the variable. That is certainly the case for an intrinsic assignment. In that case, the expression on the right hand side of the assignment has the same type as the assignment variable, and the assignment results in a pointer assignment of the pointer components of the expression result to the corresponding components of the variable (see section 184.108.40.206 of the Fortran 90 standard). However, it may also be the case for a defined assignment to such a variable, even if the data type of the expression has no pointer components; the defined assignment may still involve pointer assignment of part or all of the expression result to the pointer components of the assignment variable. Therefore, a dummy or global object cannot be used as the right hand side of any assignment to a variable of derived type with pointer components, for then it, or part of it, might be the target of a pointer assignment, in violation of the restriction mentioned above.
(Incidentally, the last two paragraphs only prevent the reference of a dummy or global object as the only object on the right hand side of a pointer assignment or an assignment to a variable with pointer components. There are no constraints on its reference as an operand, actual argument, subscript expression, etc. in these circumstances.)
Finally, a dummy or global data object cannot be used in a procedure reference as an actual argument associated with a dummy argument of INTENT(OUT) or INTENT(INOUT) or with a dummy pointer, for then it may be modified by the procedure reference. This constraint, like the others, can be statically checked, since any procedure referenced within a pure function must be either a pure function, which does not modify its arguments, or a pure subroutine, whose interface must specify the INTENT or POINTER attributes of its arguments (see below). Incidentally, notice that in this context it is assumed that an actual argument associated with a dummy pointer is modified, since Fortran 90 does not allow its intent to be specified.
The fourth constraint (only pure procedures may be called) ensures that all procedures called from a pure function are themselves side-effect free, except, in the case of subroutines, for modifying actual arguments associated with dummy pointers or dummy arguments with INTENT(OUT) or INTENT(INOUT). As we have just explained, it can be checked that global or dummy objects are not used in such arguments, which would violate the required side-effect freedom.
Constraints 5 and 6 restrict the explicit declaration of the mapping of local variables and the dummy arguments and dummy results. This is because the function may be invoked concurrently, with each invocation active on a subset of processors specific to that invocation, and operating on data that are mapped to that processor subset. Indeed, in an optimising implementation, the caller may well automatically arrange the mapping of the actual arguments and result according to the context, e.g. to maximise concurrency in a FORALL, and/or to reduce communication, taking into account the mappings of other arguments, other terms in the expression, the assignment variable, etc. Thus, a dummy argument or result may not appear in a mapping directive that fixes its location with respect to the processor array (e.g. it may not be aligned with a global variable or template, or be explicitly distributed, or given the inherit attribute, all of which would remove the caller's freedom to determine the actual's mapping as described above). The only type of mapping information that may be specified for the dummy arguments and result is their alignment with each other; this will provide useful information to the caller about their required relative mappings. For similar reasons, local variables may be aligned with the dummy arguments or result (either directly or through other local variables), but may not have arbitrary mappings.
Constraints 7 and 8 prevent any realignment and redistribution of data within a pure function (another type of side effect).
The penultimate constraint prevents external I/O and file operations, whose order would be non-deterministic in the context of concurrent execution. Note that internal I/O is allowed, provided that it does not modify global variables or dummy arguments.
Finally, the last constraint disallows PAUSE and STOP statements. A PAUSE statement requires input and so is disallowed for the same reason as I/O. A STOP brings execution to a halt, which is a rather drastic side effect.
(End of rationale.)