Subject: 16.2.3 Edits J3/02-252 From: Kurt W. Hirchert (Meeting 162) 29 Jul 2002 This document contains a number of proposed changes to 16.2.3. All are intended to be strictly editorial, with no technical effect. They include the following: A. The largest single proposed change is the addition of a note including the explanatory text promised in 02-185r2. Some related changes are made to other explanatory text. B. The edits on 02-185r2 introduced the term "TKR compatible" and used it in the rules that were revised. For consistency, the rules that did not require revision are now changed to use the same terminology. Additionally, one of 02-185r2 edits introducing this term was apparently inadvertently omitted. It is repeated here so the editor will have one less place to look for edits to apply to this section. C. A minor reordering of the rules is suggested. Text enclosed in (* *) is intended as explanation or rationale for the proposed edits and should _not_ be inserted into the draft standard. ===== Edits ===== 395:18 Delete "They ensure ... unambiguous." (* A: Something similar will be said in the note. *) 395:25-26 Replace "has a different ... rank" with "is TKR incompatible". (* B *) 395:27-28 Replace "type incompatible ... parameters" with "TKR incompatible". (* B *) 395:31-396:4 Move to 396:17+ with appropriate renumbering and changes in connecting punctuation and conjunctions. (* C: The rule currently numbered (2) is very similar to the rules for operators, assignment, and dtio immediately preceding, so it really ought to appear first in this list. The rule currently numbered (1) is sufficiently ugly that I suspect one will want to attempt to apply it only when (2) and (3) have already failed, so I think it would be better to present it last. *) (* The extra sentence in rule (3) makes it slightly awkward for it not to be the last rule. If this bothers people, it can be addressed either by rewording this bit so it is not a separate sentence or by making 396:6+ the target of the (1) move and keeping (3) last. *) 396:10-11,14-15 Replace "type incompatible ... different rank" with "TKR incompatible". (* B: This is the edit from 02-185r2 that was apparently inadvertently omitted. *) 396:24+1-14 Delete NOTE 16.6. (* A: This note seems unnecessary in light of the examples in the note being added below. If we do choose to retain it, the rule numbers within it should be made to agree with the actual rule numbers. What it calls (2)(a) and (2)(b) are currently (3)(a) and (3)(b). *) 397:1- Insert new note: (* A: The new explanatory text is of limited value if people don't know to read it. *) //////// NOTE 16.7+1 An extensive explanation of the application of these rules may be found in C.11.1+1. \\\\\\\\ 472:33+ Insert new subsection in section notes: (* A: This is the promised explanatory note. *) (* Rule numbers in this text reflect the way they are currently ordered. If one of the above proposed reorderings is performed, these numbers should be changed accordingly. *) //////// C.11.1+1 Rules ensuring unambiguous generics (16.2.3) The rules in 16.2.3 are intended to ensure o that it is possible to reference each specific procedure in the generic collection, o that for any valid reference to the generic, the determination of the specific procedure referenced is unambiguous, and o that the determination of the specific procedure referenced can be made before execution of the program begins (during compilation). Specific procedures are distinguished by fixed properties of their arguments, specifically type, kind type parameters, and rank. A valid reference to one procedure in a generic collection will differ from another because it has an argument that the other cannot accept, because it is missing an argument that the other requires, or because one of these fixed properties is different. Although the declared type of a data entity is a fixed property, extensible types allow for a limited degree of type mismatch between dummy arguments and actual arguments, so the requirement for distinguishing two dummy arguments is type incompatibility, not merely different types. (This is illustrated in the *bad6* example later in this note.) (* Is *word* the right way to indicate that word should be set in the code font? *) That same limited type mismatch means that two dummy arguments that are not type incompatible can be distinguished on the basis of the values of the kind type parameters they have in common; if one of them has a kind type parameter that the other does not, that is irrelevant in distinguishing them. Rank is a fixed property, but some forms of array dummy arguments allow rank mismatches when a procedure is referenced by its specific name. In order to allow rank to always be usable in distinguishing generics, such rank mismatches are disallowed for those arguments when the procedure is referenced as part of a generic. Additionally, the fact that elemental procedures can accept nonscalar arguments is not taken into account when applying these rules, so apparent ambiguity between elemental and non- elemental procedures is possible; in such cases, the reference is interpreted as being to the nonelemental procedure. The concept of TKR incompatibility encapsulates the rules for distinguishing dummy arguments on the basis of any of these properties. For procedures referenced as operators or defined-assignment, syntactically distinguished arguments are mapped to specific positions in the argument list, so the rule for distinguishing such procedures is that it be possible to distinguish the arguments at one of the argument positions. For user-defined derived-type input/output procedures, only the *dtv* argument corresponds to something explicitly written in the program, so it is the *dtv* that is required to be distinguished. Since *dtv* arguments are required to scalar, they cannot differ in rank. Thus, in this rule, TKR incompatibility effectively involves only type and kind type parameters. For generic procedures identified by names, the rules are more complicated because optional arguments may be omitted and because arguments may be specified either positionally or by name. In the special case of type-bound procedures with passed-object dummy arguments, the passed-object argument is syntactically distinguished in the reference, so rule (2) can be applied. The type of passed-object arguments is constrained in ways that prevent passed-object arguments in the same scoping unit from being type incompatible. Thus, in this rule, TKR incompatibility effectively involves only kind type parameters and rank. The primary means of distinguishing named generics is rule (3). The most common application of that rule is a single argument satisfying both (3)(a) and (3)(b): INTERFACE good1 FUNCTION f1a(x) REAL :: f1a,x END FUNCTION f1a FUNCTION f1b(x) INTEGER :: f1b,x END FUNCTION f1b END INTERFACE good1 Whether one writes *good1(1.0)* or *good1(x=1.0)*, the reference is to f1a because f1b would require an integer argument where these references provide the real constant 1.0. [This example and those that follow are expressed using interface bodies, with type as the distinguishing property. This was done to make it easier to write and describe the examples. The principles being illustrated are equally applicable when the procedures get their explicit interfaces in some other way or when kind type parameters or rank are the distinguishing property.] (* The above paragraph is, in effect, a note about the note. We leave it to the editor's discretion how that should be presented. *) Another common variant is the argument that satisfies (3)(a) and (3)(b) by being required in one specific and completely missing in the other: INTERFACE good2 FUNCTION f2a(x) REAL :: f2a,x END FUNCTION f2a FUNCTION f2b(x,y) COMPLEX :: f2b REAL :: x,y END FUNCTION f2b END INTERFACE good2 Whether one writes *good2(0.0,1.0)*, *good2(0.0,y=1.0)*, or *good2(y=1.0,x=0.0)*, the reference is to f2b, because f2a has no argument in the second position or with the name *y*. This approach is used as an alternative to optional arguments when one wants a function to have different result TKR depending on whether the argument is present. In many of the intrinsic functions, the DIM argument works this way. It is possible to construct cases where different arguments are used to distinguish positionally and by name: INTERFACE good3 SUBROUTINE s3a(w,x,y,z) REAL :: w,y INTEGER :: x,z END SUBROUTINE s3a SUBROUTINE s3b(x,w,z,y) REAL :: w,z INTEGER :: x,y END SUBROUTINE s3b END INTERFACE good3 If one writes *good3(1.0,2,3.0,4)* to reference s3a, then the third and fourth arguments are consistent with a reference to s3b, but the first and second are not. If one switches to writing the first two arguments as keyword arguments in order for them to be consistent with a reference to s3b, the latter two arguments must also be written as keyword arguments, *good3(x=2,w=1.0,z=4,y=3.0)*, and the named arguments *y* and *z* are distinguished. The ordering requirement in rule (3) is critical: INTERFACE bad4 ! this interface is invalid ! SUBROUTINE s4a(w,x,y,z) REAL :: w,y INTEGER :: x,z END SUBROUTINE s4a SUBROUTINE s4b(x,w,z,y) REAL :: x,y INTEGER :: w,z END SUBROUTINE s4b END INTERFACE bad4 In this example, the positionally distinguished arguments are *y* and *z*, and it is *w* and *x* that are distinguished by name. In this order it is possible to write *bad4(1.0,2,y=3.0,z=4)*, which is a valid reference for both s4a and s4b. Rule (1) can be used to distinguish some cases that are not covered by rule (3): INTERFACE good5 SUBROUTINE s5a(x) REAL :: x END SUBROUTINE s5a SUBROUTINE s5b(y,x) REAL :: y,x END SUBROUTINE s5b END INTERFACE good5 In attempting to apply rule (3), position 2 and name *y* are distinguished, but they are in the wrong order, just like the *bad4* example. However, when we try to construct a similarly ambiguous reference, we get *good5(1.0,x=2.0)*, which can't be a reference to s5a because it would be attempting to associate two different actual arguments with the dummy argument *x*. Rule (3) catches this case by recognizing that s5b requires two real arguments, and s1b cannot possibly accept more than one. The application of rule (1) becomes more complicated when extensible types are involved. If *fruit* is an extensible type, *pear* and *apple* are extensions of *fruit*, and *bosc* is an extension of *pear*, then INTERFACE bad6 ! this interface is invalid ! SUBROUTINE s6a(x,y) TYPE(pear) :: x,y END SUBROUTINE s6a SUBROUTINE s6b(x,y) TYPE(fruit) :: x TYPE(bosc) :: y END SBUROUTINE s2b END INTERFACE bad6 might, at first glance, seem distinguishable this way, but because of the limited type mismatching allowed, *bad6(a_pear,a_bosc)* is a valid reference to both s6a and s6b. It is important to try rule (1) for each type present: INTERFACE good7 SUBROUTINE s7a(x,y,z) TYPE(pear) :: x,y,z END SBUROUTINE s7a SUBROUTINE s7b(x,z,w) TYPE(fruit) :: x TYPE(bosc) :: z TYPE(apple),OPTIONAL :: w END SUBROUTINE s7b END INTERFACE good7 Looking at the most general type, s7a has a minimum and maximum of 3 fruit arguments, while s7b has a minimum of 2 and a maximum of three. Looking at the most specific, s7a has a minimum of 0 and a maximum of 3 bosc arguments, while s7b has a minimum of 1 and a maximum of 2. However, when we look at the intermediate, s7a has a minimum and maximum of 3 pear arguments, while s7b has a minimum of 1 and a maximum of 2. Because s7a's minimum exceeds s7b's maximum, they can be distinguished. In identifying the minimum number of arguments with a particular set of TKR properties, we exclude optional arguments and test TKR compatibility, so the corresponding actual arguments are required to have those properties. In identifying the maximum number of arguments with those properties, we include the optional arguments and test not TKR incompatible (i.e., TKR compatible in either direction), so we include actual arguments which could have those properties but are not required to have them. These rules are sufficient to ensure that procedures that meet them are distinguishable, but there remain examples that fail to meet these rules but which can be shown to be unambiguous: INTERFACE bad8 ! this interface is invalid ! ! despite the fact that it is unambiguous ! SUBROUTINE s8a(x,y,z) REAL,OPTIONAL :: x INTEGER :: y REAL :: z END SUBROUTINE s8a SUBROUTINE s8b(x,z,y) INTEGER,OPTIONAL :: x INTEGER :: z REAL :: y END SUBROUTINE s8b END INTERFACE bad8 This interface fails rule (3) because there are no required arguments that can be distinguished from the positionally corresponding argument, but in order for the mismatch of the optional arguments not to be relevant, the later arguments must be specified as keyword arguments, so distinguishing by name does the trick. This interface is nevertheless considered invalid so a standard-conforming Fortran processor is not required to do such reasoning. In addition to not recognizing distinguishable patterns like the one in *bad8*, the rules do not distinguish on the basis of any properties other than type, kind type parameters, and rank: INTERFACE bad9 ! this interface is invalid ! ! despite the fact that it is unambiguous ! SUBROUTINE s9a(x) REAL :: x END SUBROUTINE s9a SUBROUTINE s9b(x) INTERFACE FUNCTION x(a) REAL :: x,a END FUNCTION x END INTERFACE END SUBROUTINE s9b SUBROUTINE s9c(x) INTERFACE FUNCTION x(a) REAL :: x INTEGER :: a END FUNCTION x END INTERFACE END SUBROUTINE s9c END INTERFACE bad9 The real data objects that would be valid arguments for s9a are entirely disjoint from procedures that are valid arguments to s9b and s9c, and the procedures that valid arguments for s9b are disjoint from the procedures that are valid arguments to s9c because the former are required to accept real arguments and the latter integer arguments. Again, this interface is considered invalid, so a standard-conforming Fortran processor need not examine such properties when deciding whether a generic collection is valid. (* Should we be saying anything here about whether subroutines should be considered distinguished from functions and variables that have type, kind type parameters, and rank? *) \\\\\\\\ 472:34-473:15 Move to 467:43+. (* Although this is a subsection of "C.11 Section 16 notes", it contains no references to section 16. It belongs in C.9. *) - end - -- Kurt W Hirchert hirchert@atmos.uiuc.edu UIUC Department of Atmospheric Sciences +1-217-265-0327