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

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

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:

$ 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)

The fortran program to reproduce this error is:

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

So, I'm wondering:

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

Thanks.

2 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

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

Leave a Comment

Please sign in to add a comment. Not a member? Join today