Type-bound procedure gives error about non-polymorphic passed-object dummy argument
Asked Answered
N

2

12

I'm trying to compile the Fortran module below (using gfortran 7.2.0). The point is to define a derived type that in turn contains two instances of the derived type bspline_3d from the bspline-fortran library (https://github.com/jacobwilliams/bspline-fortran). I then want to define a type-bound procedure that will in turn call the type-bound evaluate procedure of both of those types, and return the result as an array with two elements.

When I try to compile the module below, I get an error message saying

     procedure  :: evaluate => evaluate_2d
             1
Error: Non-polymorphic passed-object dummy argument of 'evaluate_2d' at (1)

I understand absolutely nothing of the error message.

I managed to compile the simple example program found here: http://fortranwiki.org/fortran/show/Object-oriented+programming and as far as I can tell, the only difference is that in my case, the "passed-object" (this) does itself have derived-type member variables (type(bspline_3d) :: fvx, fvy), which in turn probably contain all sorts of stuff.

module interpolator_module

use bspline_module
use parameters, only: WP

implicit none

private
public :: interpolator

type :: interpolator
    type(bspline_3d) :: fvx, fvy
    contains
        private
        procedure  :: evaluate => evaluate_2d
end type interpolator

contains
    function evaluate_2d(this, X, t) result(V)
        implicit none
        ! inputs
        type(interpolator),     intent(inout) :: this
        real(WP), dimension(2), intent(in)    :: X
        real(WP),               intent(in)    :: t
        ! output
        real(WP), dimension(2)                :: V
        ! local variables
        integer                               :: iflag
        integer, parameter                    :: d = 0

        call this%fvx%evaluate(X(1), X(2), t, d, d, d, V(1), iflag)
        call this%fvy%evaluate(X(1), X(2), t, d, d, d, V(2), iflag)
    end function
end module interpolator_module
Nemertean answered 21/1, 2018 at 16:48 Comment(0)
P
14

For a type-bound procedure defined like

type my_type
 contains
  procedure :: proc
end type

the type-bound procedure has a passed argument. That is, when

type(my_type) my_obj
call my_obj%proc

is used, the object my_obj is in the argument list. With proc defined as

subroutine proc(me)
  type(my_type) me   ! Not correct
end subroutine

then call my_obj%proc is like call proc%(my_obj).1 That's the "passed-object dummy argument" part of the error message.

In the definition of proc above, the passed-object dummy argument type(my_type) me is non-polymorphic. You can read about polymorphism elsewhere, but to answer the question: a passed-object dummy argument may not be non-polymorphic. It must be polymorphic, declared using class(my_type) me:

subroutine proc(me)
  class(my_type) me   ! Polymorphic, declared type my_type
end subroutine

This means that an object of type my_type or of a type extending my_type may be passed. This is a requirement of the Fortran language.

In short: change your

type(interpolator),     intent(inout) :: this

to

class(interpolator),     intent(inout) :: this

To complicate matters, older versions of gfortran, for example, understood type-bound procedures before understanding polymorphism. This means that there are some examples of erroneous use of non-polymorphic passed-objects around.


1 I've deliberately left the binding name as proc the same as the procedure's name. In the context of the question it would be call my_obj%evaluate(...) like call evaluate_2d(my_obj, ...).

Palaeozoic answered 21/1, 2018 at 17:41 Comment(0)
R
8

The passed dummy argument this must always be polymorphic. That means it must be

 class(interpolator),     intent(inout) :: this

and not

 type(interpolator),     intent(inout) :: this

That is a fundamental requirement for type-bound procedures. Otherwise you could not usse the procedure for extended types (children).

Rudder answered 21/1, 2018 at 17:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.