Recursively defined derived types - bug in gfortran?

I am experimenting with a recursively defined derived type, where the recursion is via an allocatable component instead of a pointer. This way I hope to avoid having to program a deep copy of the structure. I used this little program:

! chkrecursive.f90 --
!     Check a feature: recursively defined derived type with allocatable components
!     Does assignment do a "deep" allocation?
!
program chkrecursive
    implicit none

    type recursive
        integer :: chk
        type(recursive), allocatable :: next
    end type recursive

    type(recursive) :: chain1, chain2

    chain1%chk  = 1
    chain2      = chain1
    chain1%chk  = 2
    chain2%next = chain1
    chain1%chk  = 3

    write(*,*) 'chain1: ', chain1%chk     , ' - expected: 3'
    write(*,*) 'chain2: ', chain2%chk     , ' - expected: 1'
    write(*,*) 'chain2: ', chain2%next%chk, ' - expected: 2'

    chain2%next = chain2
    write(*,*) 'chain2: ', chain2%chk          , ' - expected: 1'
    write(*,*) 'chain2: ', chain2%next%chk     , ' - expected: 1'
    write(*,*) 'chain2: ', chain2%next%next%chk, ' - expected: 2'
end program chkrecursive      

With Intel Fortran oneAPI I get what I expect, but gfortran (version 10.2.0 from Equation Solution on Windows) gives 1 for the last line instead of 2.

I checked my expectations rather carefully, but of course a mistake is still possible. Have I run into a bug in either compiler or is my understanding of such data structures wrong?

I obtain the same error with gfortran 11.1.0 on a mac.

I have been using this recursive type pattern with ifort for several years and find it very useful and have not encountered any problems, but, sorry, I have not tried it with gfortran (yet?)

Well, in the program I intend this for I run into a mysterious problem with Intel Fortran: I overload the // operation, but Intel Fortran does not accept that, at least in that full source code, small reproducers were accepted gracefully, which makes me add the epitaph “mysterious” :slight_smile:.

Two alternatives come to mind, but both involve descending the derived type and allocating and assigning explicitly (pointer or allocatable components). An allocatable component is attractive as it avoids memory leaks automatically (or should).

As far as I can judge, it is a bug in gfortran, nagfor agrees with ifort and the expected solution.

Thanks, that means that my understanding is indeed correct. It does not solve the immediate problem, alas, but still :slight_smile:

As it was said in a few topics already (one of them) support for newer features of derived types in gfortran is not complete yet. Surely PDTs, apparently also recursive DTs.

Just curious: any use case for such a construct? At first glance it looks a bit awkward to me.

I suppose it’s easier to simply complain in some on-line forum.

Normally, bugs are reported to the vendor.

gfortran is an open-source project. It does not spontaneously
manifest newer features of the Fortran standard without someone’s
intervention.

We use it for a multi-dimensional population balance, outer array time, then cancer type, then size of primary tumour then secondary spread if appropriate to tumour type etc, but is incredibly flexible especially used as an extension of an abstract data type, where each new layer has procedure pointers to relevant calculation for that layer

I will report it as a bug, now that I know my expectations for this particular program are correct.

The context of my program is the Mathematics of Arrays project (see the thread in this forum). My current implementation is flawed as it can cause self-references (ending in an endless loop :slight_smile:) and I need to be more careful about the references. My first thought was that with allocatable recursive types this would be solved automatically, so I wrote this program to check that.

My comment is not directly specifically at you. Yep, PDTs are broken
in gfortran. No amount of discussion/complaining in FD is going to
miraculously fix the problems.

1 Like