To: J3                                                     J3/25-153
From: Malcolm Cohen
Subject: US08 Polymorphic PURE function results, edits
Date: 2025-June-23
Reference: 23-186, 25-116r1


1. Introduction

This paper contains the edits for Fortran 2028 proposal US08,
allowing pure functions to have polymorphic results.

Requirements, Specifications, and Syntax are all in 25-116r1.


2. Edits to 25-007

[xv] Introduction, Data declaration bullet, insert sentence:

   "A derived type can be given the PURE or SIMPLE attribute; such a type
    has restrictions that ensure it is usable in pure or simple
    procedures, respectively."

{NOTE to J3: This "enforced usability" effect applies equally to non-
             polymorphic entities, so is slightly different from the main
             effect of the feature. That said, it is pretty minor, so we
             could omit this edit without great loss.}

[xv] Introduction, Program units and procedures bullet, insert sentence:

   "A polymorphic entity whose declared type has the PURE or SIMPLE
    attribute can be used within, or as the function result of, a pure or
    simple procedure, respectively."

{NOTE to J3: Explain the main feature.}

[79:22+] 7.5.2.1 Syntax of a derived-type definition, R728 type-attr-spec,
         append two new productions:

    "or PURE
     or SIMPLE"

Index both these keywords as attribute definitions, but not as hyperlink
targets - existing hyperlinks for PURE and SIMPLE should continue to be
the ones in Clause 15 Procedures.

If no other paper adds a new type-attr-spec, that makes the whole rule:

type-attr-spec is ABSTRACT
               or access-spec
               or BIND (C)
               or EXTENDS ( parent-type-name )
               or PURE
               or SIMPLE

[79:25+] Same subclause, after C735 "The same type-attr-spec...",
         insert new constraints:

    "C735a If the \si{type-attr-spec} PURE or SIMPLE appears in a
           \si{derived-type-stmt}, BIND(C) shall not appear in the
           statement. If PURE appears, SIMPLE shall not appear."

{NOTE to J3: I might just do "PURE or SIMPLE attribute" instead of using
             the BNF term. That would probably be easier to read.}

Edit continues:

    "C735b If EXTENDS appears in a \si{derived-type-stmt} and the parent
           type is a \ref*{pure type}, the PURE or SIMPLE
           \si{type-attr-spec} shall appear in the statement."

{NOTE to J3: The wording "has the PURE attribute"
             might be better than "is a pure type"?}

Edit continues:

    "C735c If EXTENDS appears in a \si{derived-type-stmt} and the parent
           type is a \ref*{simple type}, the SIMPLE \si{type-attr-spec}
           shall appear in the statement.

     C735d If the \si{type-attr-spec} PURE or SIMPLE appears in a
           \si{derived-type-stmt}, the SEQUENCE statement shall not appear
           in that type definition."

[82:1-] Just before 7.5.3 Derived-type parameters, insert new subclause

   "7.5.2.5 Pure and simple types

    The PURE \si{type-attr-spec} specifies that the type is a
    \defn*{pure type}. The SIMPLE \si{type-attr-spec} specifies that the
    type is a \defn*{simple type}; a simple type is also a pure type.

    C745a A final subroutine of a \ref*{pure type} shall be pure. A final
          subroutine of a potential subobject component of a pure type
          shall be pure.

    C745b The declared type of a polymorphic potential subobject component
          of a pure type shall be pure.

    C745c A potential subobject component of a pure type shall not be a
          coarray.

    C745d A type-bound defined assignment procedure of a pure type shall be
          pure. A type-bound defined assignment procedure of a nonpointer
          component of a pure type shall be pure."

{NOTE to J3: The second sentence of C745d did not appear in the syntax
             paper, but seems necessary for this to work.}

Edit continues:

   "C745e An ancestor type of a simple type that is not itself simple shall
          satisfy constraints C745a-C745d as if it were simple."

    C745f A final subroutine of a \ref*{simple type} shall be simple. A
          final subroutine of a potential subobject component of a simple
          type shall be simple.

    C745g The declared type of a polymorphic potential subobject component
          of a simple type shall be simple.

    C745h A potential subobject component of a simple type shall not be a
          coarray.

    C745i A type-bound defined assignment procedure of a simple type shall
          be simple. A type-bound defined assignment procedure of a
          nonpointer component of a simple type shall be simple.

    C745j An ancestor type of a simple type that is not itself simple shall
          satisfy constraints C745f-C745i as if it were simple."

{Note to the editor: the usages in these constraints of pure and simple
    referring to a procedure being pure or simple should be hyperlinked
    to our usual pure/simple terms.}

Edit continues:

"NOTE 1

    A nonpolymorphic component of a pure or simple type can be of a type
    that is not pure or simple, as long as that type does not have impure
    (or nonsimple when the containing type is simple) type-bound defined
    assignment.

    An intrinsic type is not considered to be pure or simple, even though
    it satisfies the requirements re final and assignment. That is because
    cannot be the declared type of a polymorphic entity, so calling an
    intrinsic type pure or simple would have no effect.

NOTE 2

    Here is an example of a pure type definition.
    A useful definition would have a lot more type-bound operators.

    TYPE, PURE :: rational
        INTEGER numerator, denominator
    CONTAINS
        PROCEDURE :: rat_asgn_i
        GENERIC :: ASSIGNMENT(=) => rat_asgn_i
    END TYPE
    ...
    PURE SUBROUTINE rat_asgn_i(a, b)
        CLASS(rational), INTENT(OUT) :: a
        INTEGER, INTENT(IN) :: b
        a%numerator = b
        a%denominator = 1
    END SUBROUTINE

    Given this example, the following pure function can be defined.

    PURE FUNCTION new_rational(num, dem, mold) RESULT(new)
        CLASS(rational), ALLOCATABLE :: new
        INTEGER, INTENT(IN) :: num, dem
        CLASS(rational), OPTIONAL :: mold

        IF (PRESENT(mold)) THEN
            new = mold
        ELSE
            ALLOCATE(new)
        END IF
        new%numerator = num
        new%denominator = dem
    END FUNCTION
"

{NOTES to J3:
    - The macro \defn* creates a new definition, indexed in bold.
    - The macro \ref* indexes it (not bold) and hyperlinks to the
      definition.
    - Both of them put the argument into the standard as is.
    - If anyone has a better (not any longer, please) example, please
      suggest it.
    - If someone has a long example which they think is useful, we
      could put that in Annex C, with a sentence in NOTE 2 linking to it.}

[370:19-20] 15.7 Pure procedures, constraint C1594 which begins
                "The function result... polymorphic..."
    Replace whole constraint with

       "C1594 If the function result of a pure function is both polymorphic
              and allocatable, it shall have a declared type that is pure.
              If it has a polymorphic potential subobject component, the
              component shall have a declared type that is pure."

{NOTE: "declared type with the PURE or SIMPLE attribute" also works, and
       would avoid using "pure type" outside of 7.2.5.2.
 NOTE: The existing constraint used "polymorphic allocatable ultimate",
       and this is *WRONG*, as an intervening allocatable component would
       deactivate the constraint while still permitting side-effects.}

[370:25-26] Same subclause, constraint C1597 which begins
                "An INTENT (OUT) dummy argument... polymorphic..."
            Replace whole constraint with two constraints:

       "C1594 If an INTENT (OUT) dummy argument of a pure procedure is
              polymorphic, it shall have a declared type that is pure.

        C1594a If an INTENT (OUT) dummy argument of a pure procedure has a
               polymorphic potential subobject component, the component
               shall have a declared type that is pure."

{NOTE: Separating into two because C1594a operates when the argument is not
       polymorphic, i.e. the situations are mutually exclusive. That's
       because when it is polymorphic, C1594 already requires polymorphic
       subobjects to be have a pure declared type.
 NOTE: The original constraint also suffered from the polymorphic
       allocatable ultimate defect.
 NOTE: Could use "type with the PURE or SIMPLE attribute" here too.
       I won't say this again for the following edits.}

[371:20-21] Same subclause, constraint C15106 "A statement that might...",
            Replace whole constraint with

   "C15106 If a statement that might result in the deallocation of a
           polymorphic entity appears in a pure procedure, the entity shall
           have a declared type that is pure."

[373:5+] 15.8 Simple procedures, after C15117 "A simple... ENTRY...",
         insert new constraints:

   "C15117a If the function result of a simple function is both polymorphic
            and allocatable, it shall have a declared type that is simple.

    C15117b If the function result of a simple function has a polymorphic
            potential subobject component, the component shall have a
            declared type that is pure.

    C15117c If an INTENT (OUT) dummy argument of a simple procedure is
            polymorphic, it shall have a declared type that is simple.

    C15117d If an INTENT (OUT) dummy argument of a simple procedure has a
            polymorphic potential subobject component, the component shall
            have a declared type that is simple.

    C15117e If a statement that might result in the deallocation of a
            polymorphic entity appears in a simple procedure, the entity
            shall have a declared type that is simple."

===END===