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

Call overridden type bound procedure of abstract type

adamswetnam
Beginner
1,663 Views
This might seem like a strange thing to do, but what I am trying to achieve is to extend (instead of just overriding) a type bound procedure. The attached code does this but if the parent type is made abstract then I get:

ifort call_overridden.f90
call_overridden.f90(28): error #8314: If the rightmost part-name is of abstract type, data-ref shall be polymorphic [PARENT]
call self%parent%proc
----------------^
call_overridden.f90(28): error #8422: If the component immediately preceding the type-bound procedure is abstract, the entire data reference before the procedure name must be polymorphic. [PARENT]
call self%parent%proc
----------------^
compilation aborted for call_overridden.f90 (code 1)

This article about error #8307 gives two possible solutions. The first is to make the procedure "nonoverridden" which is obviously contrary to what I'm trying to achieve and I can't make sense of the second. Is there a way to do what I'm try to do or should I go about this in a different way?
0 Kudos
4 Replies
mecej4
Honored Contributor III
1,663 Views
I do not understand your stipulations.

In the first sentence you say you wish to extend instead of override. In the penultimate sentence you reject a solution that does not allow overriding.

And, since type child in your code has a component proc identical in name to that of the parent type parent that it extends, overriding must occur. What gives?

Rather than parsing the error messages from the compiler, it would be helpful if we could make the requirements clear.
0 Kudos
John4
Valued Contributor I
1,663 Views

I guess the OP is referring to the behavior of "complements" instead of "overrides", in regards to abstract types. As the OP's example shows, if the parent type is non-abstract, its implementation of proc can still be accessed through the %parent% component (which is analogous to Java's "super" keyword), and therefore the procedure defined in the extended type complements that of the parent type. As an example, consider the following code:

[fortran]module mod1

    implicit none

    type :: t1
        integer :: a, b
    contains
        procedure :: square => square_t1
    end type

    type, extends(t1) :: t2
        integer :: c
    contains
        procedure :: square => square_t2
    end type

contains

    integer function square_t1(this) result(sq)
        class(t1), intent(IN) :: this
        sq = this%a ** 2 + this%b ** 2
    end function

    integer function square_t2(this) result(sq)
        class(t2), intent(IN) :: this
        sq = this%t1%square() + this%c ** 2
    end function

end module mod1

program test
    use mod1

    implicit none

    type(t1) :: x = t1(2, 3)
    type(t2) :: y = t2(2, 3, 4)

    print '("t1%square() = ", I0)', x%square()
    print '("t2%square() = ", I0)', y%square()

end program test[/fortran]

The new "square" procedure doesn't need to be a re-implementation, but simply a complement to the "square" procedure in the parent type.

It seems that in Fortran, such thing is not possible if the parent type is abstract ---I'm not sure either if other programming languages allow it.

0 Kudos
mecej4
Honored Contributor III
1,663 Views
I see. Thanks. Perhaps the O.P. can expand on his intentions a little more clearly.

Here is another version of your example, but using an abstract type.

[fortran]module test_mod
implicit none

type, abstract :: atype
integer :: x, y
end type atype


type, extends(atype) :: btype
contains
procedure :: proc => sqp
end type btype

type, extends(btype) :: ctype
integer :: z
contains
procedure :: proc => sqc
end type ctype

contains

integer function sqp(self)
implicit none
class(btype) :: self
sqp = self%x**2 + self%y**2

end function sqp

integer function sqc(self)
implicit none
class(ctype) :: self

sqc = self%btype%proc() + self%z**2 !leaving out () cause ICE

end function sqc

end module test_mod

program test
use test_mod
implicit none
type(ctype) :: c

c%x = 2; c%y = 3; c%z = 4;

write(*,*)' x^2 + y^2 + z^2 = ',c%proc()

end program test[/fortran]
The Intel compiler compiles this fine, and the answer is as expected; however, with the parentheses left out on line-33, the Intel compiler w_cprof_p_11.1.065 dies with an ICE.

If, in the main program tst, the variable c is initialized using the declaration
[fortran]  type(ctype) :: c = ctype(2, 3, 4)
[/fortran]
the compiler gives the confusing error message
[bash]error #8212: Omitted field is not initialized. Field initialization missing:  [/bash]
0 Kudos
adamswetnam
Beginner
1,663 Views
Apologies if my post was not clear and thank you for your clarification John. Yes the point is that, if the parent type is abstract, it is not possible to get the desired behaviour, however this post indicates that it is not clear whether or not this should be the case under the standard.

Mecej4, I get the ICE you do with the latest beta of the compiler. A similar bug was reported here but, as you point out, it has been fixed. It seems that the difference in this case is that the procedure is not external.
0 Kudos
Reply