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

"Procedure(intf) :: proc" where intf is another procedure is recursive?

IanH
Honored Contributor III
600 Views
An OOP sort of question. Consider the following snippet, where out of laziness I used the name of an existing procedure as the interface in a procedure statement in the contains bit of a abstract type definition. With 12.0.1.127 I get an error 6437 about a recursive call.

[fortran]MODULE UsingAProcedureAsAnInterface
  IMPLICIT NONE  
  PRIVATE
  
  TYPE, PUBLIC, ABSTRACT :: Parent
    INTEGER :: comp
  CONTAINS
    PROCEDURE(one_proc_intf), DEFERRED :: OneProc
  END TYPE Parent
  
  TYPE, PUBLIC, EXTENDS(Parent), ABSTRACT :: Relay      
  CONTAINS
    PROCEDURE, NON_OVERRIDABLE :: OneProc => relay_proc    
    PROCEDURE(relay_proc), DEFERRED :: TwoProc        ! #A
    !PROCEDURE(two_proc_intf), DEFERRED :: TwoProc    ! #B    
  END TYPE Relay
  
  TYPE, PUBLIC, EXTENDS(Relay) :: EndPoint    
  CONTAINS
    PROCEDURE :: TwoProc => end_proc
  END TYPE EndPoint

  ABSTRACT INTERFACE
    SUBROUTINE one_proc_intf(obj)
      IMPORT :: Parent
      IMPLICIT NONE
      CLASS(Parent), INTENT(IN) :: obj
    END SUBROUTINE one_proc_intf

   ! (for use when #B is substituted for #A)
   SUBROUTINE two_proc_intf(obj)
      IMPORT :: Relay
      IMPLICIT NONE
      CLASS(Relay), INTENT(IN) :: obj
    END SUBROUTINE two_proc_intf
  END INTERFACE  
CONTAINS
  SUBROUTINE relay_proc(obj)
    CLASS(Relay), INTENT(IN) :: obj
    !****
    ! Some behaviour that we want common to all extensions of Relay.
    PRINT "('Relay::OneProc')"
    CALL obj%TwoProc
  END SUBROUTINE relay_proc
  
  SUBROUTINE end_proc(obj)
    CLASS(EndPoint), INTENT(IN) :: obj
    !****
    PRINT "('EndPoint::TwoProc')"
  END SUBROUTINE end_proc
END MODULE UsingAProcedureAsAnInterface

[/fortran]
But my understanding (which might be wrong - note that recent gfortran 4.6 also complains about the same thing) is that this isn't a recursive call. "CALL obj%TwoProc" doesn't call relay_proc, it is a call to something that has to look like relay_proc which will be implemented by a extension of Relay.

Maybe? The work-around is simple (switch #A and #B), but I am lazy...
0 Kudos
1 Reply
Steven_L_Intel1
Employee
600 Views
A very interesting question. If the binding wasn't deferred, then it could be recursive as the compiler could not guarantee that the binding was overridden. I was also thinking that one might declare another type extending Relay and overriding TwoProc with relay_proc, but that runs into other issues.

I don't see wording in the standard that excuses this case. You can also add RECURSIVE to the declaration of relay_proc and it will compile - that seems the simplest course to me.
0 Kudos
Reply