Search code examples
interfacefortranambiguous

Problem with Ambiguous interfaces with gfortan


I have a situation similar to the following code snipped (saved in test.f90):

module interfaces_mod

    private
    
    public :: interf

    interface interf
        module procedure interf1
        module procedure interf2
    end interface

    contains
        subroutine interf1(&
                        numbers,&
                        num_numbers,&
                        dense_ranks&
                        )
            Implicit None
            integer, dimension(:), intent(in) :: numbers
            integer, intent(in) :: num_numbers
            integer, dimension(:), intent(out), optional :: dense_ranks
        end subroutine interf1

        subroutine interf2(&
                        degeneracies,&
                        numbers,&
                        num_numbers,&
                        dense_ranks&
                        )
            Implicit None
            Integer, dimension(:), intent(inout) :: degeneracies
            integer, dimension(:), intent(in) :: numbers
            integer, intent(in) :: num_numbers
            Integer, dimension(:), intent(out), optional :: dense_ranks
        end subroutine interf2
end module interfaces_mod

The module therefore defines a generic interfaces with two possible realizations.

This snipped can be compiled using ifort with

ifort -c -o "test.o" "test.f90"

to create a module. However trying to compile the same code with gfortran:

gfortran -c -o "test.o" "test.f90"

leads to the error:


   15 |         subroutine interf1(&
      |                          1
......
   32 |         subroutine interf2(&
      |                          2
Error: Ambiguous interfaces in generic interface 'interf' for ‘interf1’ at (1) and ‘interf2’ at (2)

Now looking at the dummy parameters of the realizations, interf1 is called with an Integer array followed by an Integer and an optional Integer array. interf2 instead is called with two Integer arrays followed by an Integer and an optional Integer array. So I dont understand where the ambiguity is coming from, and why ifort can compile this snipped and gfortran is not able to compile it.

gfortran version is 9.3.0, ifort version is 19.0.5.281


Solution

  • Your procedures do not meet the rules for having the same generic identifier, and gfortran is entitled to reject the generic.

    The constraint to consider is C1514 of Fortran 2018. Let's take a detailed look. There are no dummy procedures or passed-object dummy arguments, so we're down to (1) and (4) of that constraint. One of these conditions must pass.

    For (1):

    • We have one scalar argument in each procedure, called num_numbers in each. The scalar argument cannot be used to disambiguate.

    • In interf1 we have a (1a) score of 1 for the two array dummy arguments, whereas the (1b) score for each is 3. For interf2 the (1a) scores are 2 for the three array dummy, whereas the (1b) score for each is also 2.

    (1) is not met.

    For (4):

    • No dummy argument in one procedure is distinguishable from that with the same name in the other.
    • interf1 does not have a dummy argument with name not appearing in interf2.
    • interf2 has name-disambiguating argument degeneracies at position 1 while its first position-disambiguating argument is at position 2.

    (4) is not met.

    Although (4) is not met, it is easy to modify the procedure definitions such that it is: move degeneracies later in the argument list.

    There's an important note in the Fortran standard itself, before you try to work out exactly how to create an ambiguous reference:

    These rules are sufficient to ensure that references to procedures that meet them are unambiguous, but there remain examples that fail to meet these rules but which can be shown to be unambiguous [...] The rules to cover all cases are too complicated to be useful.