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
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):
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.