Fortran Wiki
Polymorphism for procedure pointers inside derived types

Proposal: When type1 is extended to type2, procedure pointers with (type1) passed-object dummy argument in type1, will be able to point to both procedures with type1 and procedures with type2 dummy arguments in type2. *1 in the example.

Also, procedure pointers with an extended argument should be able to point to procedures with a parent argument. *2 in the example.

This is already in the standard for type-bound procedures, the request is to do it also for procedure pointers.

module mod_type1
  implicit none

  type :: type1
    procedure(type1interface), pointer :: point1
  end type

  interface
    subroutine type1interface(a)
      import type1
      implicit none
      class(type1) :: a

    end subroutine
  end interface

  type, extends(type1) :: type2
    procedure(type2interface), pointer :: point2 
  end type

  interface
    subroutine type2interface(a)
      import type2
      implicit none
      class(type2) :: a

    end subroutine
  end interface

  contains
    
    subroutine type1subroutine(a)
      implicit none
      class(type1) :: a

      write(*,*) 'hello world'

    end subroutine

    subroutine type2subroutine(a)
      implicit none
      class(type2) :: a

      write(*,*) 'hello world 2'

    end subroutine

end module

program Main
  use mod_type1 
  implicit none

  type(type2) :: mytype2
  procedure(type2subroutine), pointer :: mypointer2
  procedure(type1subroutine), pointer :: mypointer1

  mytype2%point1 => type1subroutine
  mytype2%point2 => type2subroutine

  mytype2%point1 => type2subroutine  !*1 !THIS IS NOT CONFORMING TO THE STANDARD (PROPOSAL)
  
  mytype2%point2 => type1subroutine  !*2 !THIS IS NOT CONFORMING TO THE STANDARD (PROPOSAL)
  mypointer2 => type1subroutine      !*2 !THIS IS NOT CONFORMING TO THE STANDARD (PROPOSAL)
  mypointer2 => mypointer1           !*2 !THIS IS NOT CONFORMING TO THE STANDARD (PROPOSAL)


  call mytype2%point1

end program

Responses

The first part of the proposal breaks type safety.

Consider what happens with the code above if the call statement was replaced with:

call mytype2%type1%point1

which is legal F2003+. The passed object dummy argument will be of type type1 (that’s what the syntax object%parent means), which is not what the procedure expects.

(The example type2subroutine doesn’t actually reference the dummy argument, and hence doesn’t reference anything about the dummy argument that is specific to the type2 extension. In real code such a reference to components of the extended (declared) type is certainly possible, perhaps expected.)

Or, given the statements in the example program, consider:

type(type1) :: other
other%point1 => mytype2%point1
! or other = mytype2%type1
CALL other%point1

Same problem.

(Posted on behalf of Ian Harvey by Jason Blevins. The original code block above was not closed, triggering a bug where this new post was not being rendered properly.)