2

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

francescalus
  • 30,576
  • 16
  • 61
  • 96
ntausend
  • 43
  • 2

1 Answers1

1

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.

francescalus
  • 30,576
  • 16
  • 61
  • 96
  • Ok thank you for this clarification.. You suggestion to move `degeneracies` late in the list was solving the problem. I think I need to study those constrains, since I was not completely aware of them. However, I do not understand your counting for (1), may you explain how you achieved these scores? – ntausend Feb 18 '21 at 16:50
  • I can try to explain the counting, but for clarity of that, can you work through and say which bit of the counting you don't get? – francescalus Feb 18 '21 at 17:25
  • Ok I think I just understand the meaning of C1514 1).. So to make it clear: One has to count for each Dummy Data Argument the number of all TKR compatible non optional dummy data arguments in the argument list (which would give me for the interf1 for the only array 1) and have to compare this to the number of all dummy data arguments form all other parameter lists which have the same type ( which would give 3 for interf2). Am I correct? – ntausend Feb 19 '21 at 10:00
  • That's correct (although more generally for `interf2` you'd have to consider _not distinguishable_ rather than the same type - in your case they are the same thing). – francescalus Feb 20 '21 at 16:05
  • Ok thank you, I think I have understood the problem and how to solve it! – ntausend Feb 22 '21 at 07:54