Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

type signature error -- why?

niels_veldhuijzen
1,137 Views
Dear friends,
May I invoke your help for a baffling error which I can't get rid of?
I'm trying to overload the intrinsic MOD function with three extra functions (see the small source at the end of this message). Whenever I try to compile the source, I end up with the following message:
C:TMP est.f90(42) : Error: The type/rank/keyword signature for this specific procedure matches another specific procedure that shares the same generic-name. [MOD_INT_BIG]
In my opinion, the source complies to the following rules, excerpted from the help file:
"When a generic procedure reference is made, a specific procedure is invoked. If the following rules are used, the generic reference will be unambiguous:
Within a scoping unit, two procedures that have the same generic name must both be subroutines (or both be functions). One of the procedures must have a nonoptional dummy argument that is one of the following:
- Not present by position or argument keyword in the other argument list
- Is present, but has different type and kind parameters, or rank
Within a scoping unit, two procedures that have the same generic operator must both have the same number of arguments or both define assignment. One of the procedures must have a dummy argument that corresponds by position in the argument list to a dummy argument of the other procedure that has a different type and kind parameters, or rank."
I think the "Not present by position or argument keyword in the other argument list" is relevant here. My first specific function has its arguments in the order "big_integer, integer", and the second one in the order "integer, big_integer". So, there is no integer argument in second position in the second function argument list, but only in the first funcion argument list. What is happening here?
Yours sincerely,
Niels H. Veldhuijzen
Cito, Research Department
Arnhem, The Netherlands
niels.veldhuijzen@cito.nl
! Don't spend time in trying to understand the declarations; they are not the problem here!
module test
implicit none
private :: mod_big_int,mod_int_big,mod_big_big
integer(kind=4), parameter, public :: nr_of_decimal_digits = 100
logical(kind=1), parameter, private :: t=.true.,f=.false.
real, parameter, private :: log_base_10_of_radix = 0.30103
integer(kind=4), parameter, private :: &
d = digits(0)-1 , &
r = radix(0), &
base = r ** d, &
half_base = base/2
integer(kind=4), parame ter, public :: &
nr_of_digits = nr_of_decimal_digits / (log_base_10_of_radix * d) + 1
integer(kind=4),parameter,private, dimension(9):: tien=((/10,100,1000,10000,100000,1000000,10000000,100000000,1000000000/))
type, public :: big_integer
integer (kind=4), dimension(0 : nr_of_digits) :: digit
logical (kind=1) :: neg !** true means negative
logical (kind=1) :: zero !** true means number is zero
logical (kind=1) :: inf !** true means abs. value larger than huge
logical (kind=1) :: nan !** true means not a number (e.g. by illegal input)
end type big_integer
integer (kind=4), private :: n
type(big_integer), public, parameter :: &
Big_Zero = big_integer((/ (0, n = 0, nr_of_digits) /),f,t,f,f )
interface mod
module procedure mod_big_int, mod_int_big, mod_big_big
end interface
contains
pure function mod_big_int(b,i) result ! take care: r is an integer
type(big_integer),intent(in)::b
type(big_integer):: q,br
integer(kind=4),intent(in)::i
integer(kind=4)::r
r=0
end function mod_big_int
pure function mod_int_big(i,b) result
type(big_integer), intent(in)::b
integer(kind=4), intent(in)::i
type(big_integer)::q,r
r=big_zero
end function mod_int_big
pure function mod_big_big(x,y) result
type(big_integer), intent(in)::x,y
type(big_integer)::q,r
r=big_zero
end function mod_big_big
end module test
0 Kudos
11 Replies
Jugoslav_Dujic
Valued Contributor II
1,137 Views
It's a bug, and it looks like an ancient one -- I can reproduce it in both CVF6.6C (!) and IVF 9.0.025, with even simpler code:
module test
implicit none
interface mood
module procedure mod_big_int
module procedure mod_int_big
end interface
contains

subroutine mod_big_int(b,i)
real,intent(in)::b
integer(kind=4),intent(in)::i
end subroutine mod_big_int

subroutine mod_int_big(i,b)
integer(kind=4), intent(in)::i
real, intent(in)::b
end subroutine mod_int_big

end module test
I'll submit a Premier support issue (If I still recall my password :-D ).

Jugoslav
0 Kudos
Steven_L_Intel1
Employee
1,137 Views
It's not a bug. Tell me which specific routine gets called in the following case:

program main
use test
real b
integer i
call mood (b=b, i=i)
end
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,137 Views
Uh-oh; it is allowed to use keyword arguments even if they're not optional? Didn't know that, but you seem right a simple renaming of arguments helps fix this "bug". Guess I'll withdraw my bug report.

Jugoslav
0 Kudos
Steven_L_Intel1
Employee
1,137 Views
Yes, you can use keywords for any arguments you like, optional or otherwise. The only rule is that once you have started using keywords, you can't use a positional argument later in the list.
0 Kudos
niels_veldhuijzen
1,137 Views

Dear Steve,

I apologize for being away and replying late, but we had a bereavement in the family.

I am a bit confused about the discussion that followed the problem I presented. My problem is, that the module cannot be compiled. So trying your test program is of no avail. Perhaps I missed an essential point in your and Jugoslav's replies.

Yours sincerely,

Niels H. Veldhuijzen

Cito, Arnhem, The Netherlands

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,137 Views
Hi Niels,

First, sorry for your loss.

The bottom line is: your code is potentially ambiguous indeed, because both dummy arguments are named b and i in both routines. However, you can resolve the ambiguity by simply renaming at least one of them.

Regards,
Jugoslav
0 Kudos
niels_veldhuijzen
1,137 Views

Dear Jugoslav,

Thank you for your advice: my module can be compiled now.

I still think the problem is a (bit of a) bug. One of the great things in Fortran is that program units are independent of each other. So why should the compiler muse about argument names in different program units? The help file is not very helpful in this respect, I think.

Best wishes, Niels

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,137 Views
But the situation is not so simple as of F90 -- a module is a "supra-program-unit".

Note that the compiler does not actually complain about the routines themselves it complains about correctness of the INTERFACE block, and if you'd take it out you'd get a compilable code. MODULE PROCEDURE keyword "imports" the declarations of routines, including argument names. This is somewhat akin to using same names for entities of different scoping units -- you may define a subrotine Foo in module M1 and module M2, but you can't use symbol Foo if you USE both M1 and M2 in the same unit. In this case, argument names and types (and I initially forgot about the former) are considered a part of routine signature, which must be unique within same generic interface block.

Jugoslav
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,137 Views
P.S. See Steve's first reply in this thread.
0 Kudos
niels_veldhuijzen
1,137 Views

Dear Jugoslav (and Steve),

OK, I rest my case. It IS a subtle matter, isn't it?

Thanks, and best wishes, Niels

0 Kudos
Steven_L_Intel1
Employee
1,137 Views
To be more specific, it is an issue only with generic interfaces where you're asking the compiler to decide which of several "specific procedures" is to be called to satisfy a generic call. The language has detailed rules on how the compiler is to make this determination and how you are to ensure that there is no ambiguity.
0 Kudos
Reply