- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The following code sample with generic assignment(=) interfaces compiles fine under Version 15.0.5.280. I just installed Version 16 and it produces an error.
module test implicit none private type, public :: ref_t private integer :: idum = 0 contains generic :: assignment(=) => get_new generic :: assignment(=) => acquire procedure, private :: get_new procedure, private :: acquire end type contains subroutine get_new(my,ptr) class(ref_t), intent(out) :: my class(*), pointer, intent(in) :: ptr print *, "get_new" my%idum = 1 end subroutine subroutine acquire(my,ref) class(ref_t), intent(out) :: my class(ref_t), intent(in) :: ref print *, "acquire" my%idum = ref%idum+1 end subroutine end module program main call run contains subroutine run use test type(ref_t) a,b class(*), pointer :: p a = p b = a end subroutine end program
With Version 15, I can compile and get the following output:
$ ./GenericAmbiguity.exe
get_new
acquire
But with Version 16, I get the following error message:
$ ifort GenericAmbiguity.f90
Intel(R) Visual Fortran Compiler for applications running on IA-32, Version 16.0 Build 20151021
Copyright (C) 1985-2015 Intel Corporation. All rights reserved.GenericAmbiguity.f90(24): error #8437: The type/rank signature for the arguments of this specific subroutine matches another specific subroutine that shares the same ASSIGNMENT generic binding. [ACQUIRE]
subroutine acquire(my,ref)
-------------------^
compilation aborted for GenericAmbiguity.f90 (code 1)
Since `acquire` has a more specific interface than `get_new`, it seems that there should be no ambiguity (unless, of course, the actual argument is of type `class(ref_t),pointer`).
So why the change from V15 to V16?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
since class(*) matches anything, it is ambiguous when the second argument is compatible with class(ref_t). The older compiler did not catch the error. Note that one argument being a pointer and the other not is not a distinguishing characteristic, since one can pass a non-pointer to the pointer and the compiler will "fake" a pointer, as the language specifies.
I'll note that a future version of the compiler gives a somewhat more helpful message:
U607413.f90(24): error #5286: Ambiguous generic interface ASSIGNMENT(=): previously declared specific procedure GET_NEW is not distinguishable from this declaration. [ACQUIRE]
subroutine acquire(my,ref)
---------------^
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think I understand the problem. But by analogy, I would expect the code below to have the same problem, but it doesn't. Since a_sub can always match the arguments to b_sub, there should be an ambiguity, but there isn't. Is "class(*)" so super-special that a routine with a more specific argument can't be distinguished?
To turn the question around, how would one define a generic interface so that one routine could respond for one type (i.e. class(ref_t)), but a different routine would be called for all other types (i.e. class(*))?
Thanks much!
module m type :: a end type type, extends(a) :: b end type contains subroutine a_sub(a1,a2) class(a) :: a1 class(a) :: a2 end subroutine subroutine b_sub(b1,b2) class(b) :: b1 class(b) :: b2 end subroutine end module
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You haven't declared a generic in this example. If you add one, like this:
interface mygen module procedure a_sub module procedure b_sub end interface
You get:
t.f90(23): warning #6738: The type/rank/keyword signature for this specific procedure matches another specific procedure that shares the same generic-name. [B_SUB]
subroutine b_sub(b1,b2)
-------------------^
class(*) matches any type. For generic resolution, some other argument must also be distinguishable. So to answer your question, no, that's not possible. The way to do what you want is a single routine that accepts a class(*) argument and then does a SELECT TYPE to determine what it's going to do with it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You haven't declared a generic in this example
Oops. Sorry 'bout that. I've just installed V16 and am getting a boatload of ICEs as well as this error. So far this is the only one I've been able to narrow down to a simple example and I missed that part. I thought about using SELECT TYPE, but that doesn't enforce the pointer requirement that I'd like to have, but I have some other ideas that I can pursue.
Thanks for the clarification.
Regarding the ICEs, I'll make a formal submission if I can narrow it down a bit.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page