If I'm reading the standard correctly, then section 12.5.2.5 §2 puts restrictions on actual arguments where the dummy argument is allocatable and polymorphic:
The actual argument shall be polymorphic if and only if the associated dummy argument is polymorphic, and either both the actual and dummy arguments shall be unlimited polymorphic, or the declared type of the actual argument shall be the same as the declared type of the dummy argument.
and the following Note 12.27:
The dynamic type of a polymorphic allocatable or pointer dummy argument may change as a result of execution of an ALLOCATE statement or pointer assignment in the subprogram. Because of this the corresponding actual argument needs to be polymorphic and have a declared type that is the same as the declared type of the dummy argument or an extension of that type. However, type compatibility requires that the declared type of the dummy argument be the same as, or an extension of, the type of the actual argument. Therefore, the dummy and actual arguments need to have the same declared type.
I believe this is too restrictive for arguments with intent(in) and intent(out):
When the intent is in then it is sufficient that the actual argument is type compatible with the dummy argument as no allocate or redefinition can take place (though an allocated check can). This will also make the use of a dummy allocatable consistent with a dummy optional.
When the intent is out then it is sufficient that the actual argument is type compatible with the dummy argument because the dummy argument can (should) not be used before it has been allocated inside the subprogram.
Here is a simple example that illustrates how the latter could be useful:
module some_mod
implicit none
type, abstract :: base_t
end type
type, abstract, extends(base_t) :: sub_t
integer :: i
end type
type, extends(sub_t) :: my_t
integer :: j
end type
contains
subroutine sub1(val)
class(sub_t), allocatable, intent(out) :: val
val = my_t(3, 4)
end subroutine
end module
program main
use some_mod
class(base_t), allocatable :: base
! This works, but is very verbose
block
class(sub_t), allocatable :: sub
call sub1(sub)
call move_alloc(sub, base)
end block
! However this porduces a compile error
call sub1(base)
select type(base)
type is (my_t)
print *, base%i, base%j
end select
end program
If I'm reading the standard correctly, then section 12.5.2.5 §2 puts restrictions on actual arguments where the dummy argument is allocatable and polymorphic:
and the following Note 12.27:
I believe this is too restrictive for arguments with
intent(in)
andintent(out)
:When the intent is
in
then it is sufficient that the actual argument is type compatible with the dummy argument as noallocate
or redefinition can take place (though anallocated
check can). This will also make the use of a dummyallocatable
consistent with a dummyoptional
.When the intent is
out
then it is sufficient that the actual argument is type compatible with the dummy argument because the dummy argument can (should) not be used before it has been allocated inside the subprogram.Here is a simple example that illustrates how the latter could be useful: