Assigning a derived type variable to itself

In the case of gfortran-12, an intrinsic assignment seems to preserve bounds of allocatable array components (even with (...)), although copy of arrays loses bounds if parens are used directly on arrays… So maybe for scalar objects, no need to worry about the bounds of component arrays? (But I haven’t tried other compilers, so the result may vary…)

program main
    implicit none

    type Foo_t
        integer, allocatable :: n(:)
    endtype
    type DeepFoo_t
        type(Foo_t) :: foo
    endtype

    type(DeepFoo_t) :: x, y, z, xx(0:1)
    type(DeepFoo_t), allocatable :: yy(:), zz(:)

    allocate( x% foo% n( -1 : 1 ), source= [-10, 0, 10] )

    print *, "x: bounds = ", lbound( x% foo% n ), ubound( x% foo% n ), " val = ", x% foo% n

    y = x   !! copy of scalars (intrinsic assignment)

    print *, "y: bounds = ", lbound( y% foo% n ), ubound( y% foo% n ), " val = ", y% foo% n

    z = ( x )   !! copy of scalars (with parens)
    print *, "z: bounds = ", lbound( z% foo% n ), ubound( z% foo% n ), " val = ", z% foo% n

    xx(0) = x
    xx(1) = x

    yy = xx   !! copy of arrays
    print *, "yy: bounds = ", lbound( yy ), ubound( yy )
    print *, "yy(1): bounds = ", lbound( yy(1)% foo% n ), ubound( yy(1)% foo% n ), " val = ", yy(1)% foo% n

    zz = ( xx )   !! copy of arrays (with parens)
    print *, "zz: bounds = ", lbound( zz ), ubound( zz )
    print *, "zz(1): bounds = ", lbound( zz(1)% foo% n ), ubound( zz(1)% foo% n ), " val = ", zz(1)% foo% n

end
$ gfortran-12 test.f90  && ./a.out
 x:     bounds =      -1       1  val =      -10       0      10
 y:     bounds =      -1       1  val =      -10       0      10
 z:     bounds =      -1       1  val =      -10       0      10
 yy:    bounds =       0       1
 yy(1): bounds =      -1       1  val =      -10       0      10
 zz:    bounds =       1       2
 zz(1): bounds =      -1       1  val =      -10       0      10
1 Like

Arf, you’re right, I forgot that the bound transfer rules were different for the allocatable components

1 Like

I have found that most times, I prefer the syntax of the component assignment over the syntax of the array assignment itself. In order to get the yy=xx assignment that the programmer usually wants, with the bounds preserved, the programmer must do something like

if( allocated(yy) ) deallocate(yy)
allocate( yy(lbound(xx):), source=xx )

And to be honest, that doesn’t really do what I would want either. I would really want conditional allocation only if the sizes are different, with some simple and cheap method to change the bounds to the correct values without the actual (expensive) memory allocation process. As far as I know, there is currently no cheap way to permanently change the bounds of a given allocatable array. There is a workaround using ASSOCIATE that does it temporarily, but not a permanent way.