Fortran generic interface procedure with optional arguments

Fortran 2018 added syntax useful for polymorphism including select rank, which allows rank polymorphism and select type, which allows class polymorphism. For reference, GCC ≥ 7 has select type and GCC ≥ 10 has select rank. Intel oneAPI supports both.

To be compatible with older compilers as well as handle cases where it’s simply more concise to use Fortran 2003 generic procedure interfaces, each procedure must be unambiguously distinguishable. Several criteria make a procedure distinguishable. Here we focus on having at least one non-optional argument that is TKR-distinct (Type, Kind, Rank).

Notice that this example has the first variable non-optional to make the procedures TKR-distinct.

module mod1

implicit none (type, external)

interface manyranks
  procedure m0,m1
end interface manyranks

public :: manyranks


subroutine m0(val1, val2)
real, intent(in) :: val1
real, intent(in), optional :: val2
!! omitted code
end subroutine m0

subroutine m1(val1, val2)
real, intent(in) :: val1(:)
real, intent(in), optional :: val2(:)
!! omitted code
end subroutine m1

end module mod1

The code will compile as above. If you add optional to both “val1”, the compilation will fail like:

  • GCC: Error: Ambiguous interfaces in generic interface 'manyranks' for 'm0' at (1) and 'm1' at (2)
  • Intel: error #5286: Ambiguous generic interface MANYRANKS: previously declared specific procedure M0 is not distinguishable from this declaration. [M1]

Although this example used rank polymorphism, the same issue arises when using any of type, kind or rank (TKR) generic procedures–there must be an unambiguous resolution with at least one non-optional argument. This polymorphism is implemented at runtime, and so there is no guarantee of non-ambiguity when all arguments are optional.