Should we avoid assignment of derived types in robust programs?

I absolutely agree, but I don’t see, how I can ensure (with the help of type bound procedures), that both, assignment to a static variable and assignment to an allocatable variable works in combination with user defined assignment. You can see my trial below, which demonstrates the problem:

  • If I overload both, assignment to allocatable variable and assignment to static variable, the interface is claimed to be ambiguous.
  • If I only overload the assignment to a static variable, assignment to an allocatable on the consumer side segfaults.
  • If I only overload the assignment to a dynamic variable, the assignment to a static variable does not compile on the consumer side.

@sblionel Can you show me a way to resolve this conflict (without using an embedding type as discussed above)? Is it possible at all according to the current standard?

Unsuccesful attempt to overload assignment to static and allocatable variables
module testmod
  implicit none

  type :: dirty
    integer :: value = 0
  contains
    procedure :: assign_static_static
    procedure, pass(this) :: assign_alloc_static
    ! if both generic assignments are active, interface is claimed to be ambigous
    ! if only assign_static_static is active, "alloc = static1" below segfaults
    ! if only assign_alloc_static is active, "static2 = static1" below fails to compile
    generic :: assignment(=) => assign_static_static
    generic :: assignment(=) => assign_alloc_static
  end type dirty

contains

  subroutine assign_static_static(this, other)
    class(dirty), intent(out) :: this
    type(dirty), intent(in) :: other

    this%value = other%value + 1
    print "(a,i0,a,i0,a)", "static = static (", other%value, "->", this%value, ")"

  end subroutine assign_static_static

  subroutine assign_alloc_static(lhs, this)
    type(dirty), allocatable, intent(out) :: lhs
    class(dirty), intent(in) :: this

    allocate(lhs)
    lhs%value = this%value + 1
    print "(a,i0,a,i0,a)", "alloc = static (", this%value, "->", lhs%value, ")"

  end subroutine assign_alloc_static

end module testmod

program testprog
  use testmod
  implicit none

  type(dirty) :: static1, static2
  type(dirty), allocatable :: alloc

  print "(a)", "static2 = static1"
  static2 = static1
  print "(a)", "alloc1 = static1"
  alloc = static1

end program testprog
1 Like