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

Calling a parent type-bound procedure from a extended type when the parent is abstract

FlyingHermes
New Contributor I
1,153 Views

Hi,

I define a derived-type (denoted "child") which extends from another derived-type (denoted "parent").

The parent derived-type has a type-bound procedure that is overloaded by the child derived-type.

I know I can call still call the parent derived-type from a variable declared with the child derived-type since each type extension contains an implicit parent object of the same name and type as the parent.

This works fine unless this parent derived-type is abstract.

In such a case ifort version 14.0.1 gives me the following compile-time error:

[bash]$ ifort main.f90
main.f90(93): error #8314: If the rightmost part-name is of abstract type, data-ref shall be polymorphic   [ABS_PARENT_TYPE]
  call Var_Abs%Abs_Parent_Type%Do_Something( Out )              ! ===>  main.f90(93): error #8314: If the rightmost part-name is of abstract type, data-ref shall be polymorphic   [ABS_PARENT_TYPE]
---------------^
main.f90(93): error #8422: If the component immediately preceding the type-bound procedure is abstract, the entire data reference before the procedure name must be polymorphic.   [ABS_PARENT_TYPE]
  call Var_Abs%Abs_Parent_Type%Do_Something( Out )              ! ===>  main.f90(93): error #8314: If the rightmost part-name is of abstract type, data-ref shall be polymorphic   [ABS_PARENT_TYPE]
---------------^
compilation aborted for main.f90 (code 1)[/bash]

The fortran program to reproduce this error is:

[fortran]Module Abstract_Module

  implicit none
  private  
  public        ::      Abs_Parent_Type, NoA_Parent_Type
 
  Type  ,abstract               ::      Abs_Parent_Type
  contains
    procedure   ,public         ::      Do_Something => Do_Something_Abs
  End Type
 
  Type                          ::      NoA_Parent_Type
  contains
    procedure   ,public         ::      Do_Something => Do_Something_NoA
  End Type

  contains
 
  Subroutine Do_Something_Abs( This, Out )
    class(Abs_Parent_Type)      ,intent(in)     ::      This
    integer                     ,intent(out)    ::      Out
    Out   =       0
  End Subroutine
 
  Subroutine Do_Something_NoA( This, Out )
    class(NoA_Parent_Type)      ,intent(in)     ::      This
    integer                     ,intent(out)    ::      Out
    Out   =       0
  End Subroutine
 
End Module


Module Child_Module

  use Abstract_Module   ,only:  Abs_Parent_Type, NoA_Parent_Type
  implicit none
  private  
  public        ::      Abs_Child_Type, NoA_Child_Type
 
  Type  ,extends(Abs_Parent_Type)       ::     Abs_Child_Type
  contains
    procedure   ,public                 ::      Do_Something => Do_Something_Abs
  End Type
 
  Type  ,extends(NoA_Parent_Type)       ::     NoA_Child_Type
  contains
    procedure   ,public                 ::      Do_Something => Do_Something_NoA
  End Type

  contains
 
  Subroutine Do_Something_Abs( This, Out )
    class(Abs_Child_Type)       ,intent(in)     ::      This
    integer                     ,intent(out)    ::      Out
    Out   =       1
  End Subroutine
 
  Subroutine Do_Something_NoA( This, Out )
    class(NoA_Child_Type)       ,intent(in)     ::      This
    integer                     ,intent(out)    ::      Out
    Out   =       1
  End Subroutine
 
End Module

Program Main

  use Child_Module   ,only:  Abs_Child_Type, NoA_Child_Type
 
  implicit none
 
  type(NoA_Child_Type)                          ::      Var_NoA
  type(Abs_Child_Type)                          ::      Var_Abs
  integer                                       ::      Out        
 
  write(*,"('Calling Var_NoA%Do_Something')")
  call Var_NoA%Do_Something( Out )                              ! ===> ok
  write(*,"('Out = ',g0)") Out
 
  write(*,"('Calling Var_NoA%NoA_Parent_Type%Do_Something')")
  call Var_NoA%NoA_Parent_Type%Do_Something( Out )              ! ===> ok
  write(*,"('Out = ',g0)") Out
 
  write(*,"('Calling Var_Abs%Do_Something')")
  call Var_Abs%Do_Something( Out )                              ! ===> ok
  write(*,"('Out = ',g0)") Out
 
  write(*,"('Calling Var_Abs%Abs_Parent_Type%Do_Something')")
  call Var_Abs%Abs_Parent_Type%Do_Something( Out )              ! ===>  main.f90(93): error #8314: If the rightmost part-name is of abstract type, data-ref shall be polymorphic   [ABS_PARENT_TYPE]
  write(*,"('Out = ',g0)") Out                                  !       main.f90(93): error #8422: If the component immediately preceding the type-bound procedure is abstract, the entire data reference before the procedure name must be polymorphic.   [ABS_PARENT_TYPE]
 
End Program[/fortran]

So, I'm wondering:

  • if this is a compiler bug or
  • if what I'm trying to do is not legal.

Thanks.

1 Reply
IanH
Honored Contributor II
1,153 Views

Programmer bug.  Workarounds include:

- Call the procedure directly (i.e. CALL Do_something_abs(var_abs).  I rationalise this by considering that the object%binding thing is really about type lookup - if you have object% parent %binding you are specifying the type, so therefore not doing type lookup, so don't use the syntax for type lookup.

- Create another "top" level in your extension hierarchy that hold the non-deferred bindings and acts as a parent type to the abstract type.  (Your abstract type doesn't need to be abstract, presumably in your real code you have deferred bindings in that type).

0 Kudos
Reply