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

Ambiguous generic interface

Noel_B_
Novice
898 Views

interface register_plot_keys

 

module subroutine register_plot_keys_fm_scalar(self, fm, id, pk_id, name)

  use field_manager_m

  class(plot_manager_t), intent(inout) :: self

  class(field_manager_t), intent(inout) :: fm

  integer(int_kind), intent(in) :: id, pk_id

  character(*), intent(in) :: name

end subroutine

 

module subroutine register_plot_keys_fm_array(self, pk_id, fm, id, name)

  use field_manager_m

  class(plot_manager_t), intent(inout) :: self

  class(field_manager_t), intent(inout) :: fm

  integer(int_kind), intent(in) :: id, pk_id

  character(*), intent(in) :: name

end subroutine

 

end interface

 

These interfaces should be unique (argument order alone is sufficient).  Intel OneAPI Fortran compiler complains:

 

error #5286: Ambiguous generic interface REGISTER_PLOT_KEYS: previously declared specific procedure REGISTER_PLOT_KEYS_FM_SCALAR is not distinguishable from this declaration. [REGISTER_PLOT_KEYS_FM_ARRAY]

 

This is with:

 

s1076943:cmake-build-debug kbelco$ ifort --version

ifort (IFORT) 2021.10.0 20230609

Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.

 

On MacOS Venture 13.6.1.

 

0 Kudos
5 Replies
Xiaoping_D_Intel
Employee
870 Views

At <https://www.intel.com/content/www/us/en/docs/fortran-compiler/developer-guide-reference/2023-2/unambiguous-generic-procedure-references.html#GUID-E66FDAD7-CDF5-4555-958E-FE5C0AB24D4E> it is written:


  • 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 is distinguishable from the dummy argument in the other argument list


The dummy arguments of one of those two procedures are all present by argument keyword in the other one's argument list and none of them is distinguishable according to:


  • Two dummy arguments are said to be distinguishable if any of the following are true:
    • One is a procedure and the other is a data object.
    • One has the ALLOCATABLE attribute and the other has the POINTER attribute without INTENT (IN).
    • They are both data objects or both known to be functions, and they have different type and kind parameters, or different rank.
    • One is a function with nonzero rank and the other is not known to be a function.


So these two procedures are ambiguous for a generic interface reference.





0 Kudos
andrew_4619
Honored Contributor III
853 Views

Hi,

I was reading this thread and a read the quotes from the developer guide two or three times and I don't get what the specific problem with the OPs code is. It seemed to me me that the two interfaces did not meet the ambiguity criteria. I expect I am missing something but would be grateful if someone could explain a bit further,  is there for example some reason that the two classes can be distinguished by the compiler?

0 Kudos
Xiaoping_D_Intel
Employee
799 Views

Besides positional association Fortran procedure argument association can also be done through argument key word which allows the change of argument sequence. For example, if the generic procedure "register_plot_keys" in OP's code is called as:


 type(plot_manager_t) :: self_v

 type(field_manager_t) :: fm_v


call register_plot_keys(self_v, id=1, fm=fm_v, pk_id=11, name="hello")


Compiler will not be able to decide which one of the specific procedure to be called because the argument with the same name always has the same data type in both specific procedure's argument list. A possible solution is to change the name of one of the dummy arguments at different position in one procedure so that it doesn't present in the other one's argument list. For example:


module subroutine register_plot_keys_fm_scalar(self, fm1, id, pk_id, name)


Then the call to the generic procedure "register_plot_keys" will no longer be ambiguous because if want to change the position by argument keyword there will be a difference between the dummy argument names of those two specific procedure.


andrew_4619
Honored Contributor III
780 Views

Thanks I hadn't considered keyword which is a good point using keywords allows order changes so long as all the subsequent args have a keyword. The KW thing is mentioned in your earlier reply I just hadn't picked up on it.

 

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
758 Views

@Noel_B_ 

From the names of your subroutine interfaces, wouldn't this be appropriate:

 

interface register_plot_keys
module subroutine register_plot_keys_fm_scalar(self, fm, id, pk_id, name)
  use field_manager_m
  class(plot_manager_t), intent(inout) :: self
  class(field_manager_t), intent(inout) :: fm
  integer(int_kind), intent(in) :: id, pk_id
  character(*), intent(in) :: name
end subroutine

module subroutine register_plot_keys_fm_array(self, pk_id, fm, id, name)
  use field_manager_m
  class(plot_manager_t), intent(inout) :: self(:) ! array of plot_manager_t
  class(field_manager_t), intent(inout) :: fm(:)  ! and/or array of field_manager_t
  integer(int_kind), intent(in) :: id, pk_id
  character(*), intent(in) :: name
end subroutine
end interface

 

Should the class itself disambiguate scalar vs array, then place the disambiguation inside the single subroutine register_plot_keys.

 

Jim Dempsey

0 Kudos
Reply