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

Type bound generic assignment not being inherited

Izaak_Beekman
New Contributor II
1,102 Views

Consider the following skeletal code:

[fortran] module abstract_m

private

public:: abs_t

type ,abstract :: abs_t

contains

!other bindings

procedure(sub_abs_t_abs_t) ,deferred :: assign

generic :: assignment(=) => assign

end type

abstract interface

elemental subroutine assign(lhs,rhs)

import :: abs_t

class(abs_t) ,intent(inout) :: lhs

class(abs_t) ,intent(in) :: rhs

end subroutine

end interface

end module

module concrete_m

use abstract_m ,only:abs_t

implicit none

private

public :: cncrt_t

type ,extends(abs_t) :: cncrt_t

private

!State/data variables

contains

procedure :: assign => copy

procedure :: some_op

end type

contains

elemental subroutine copy(lhs,rhs)

class(cncrt_t) ,intent(inout) :: lhs

class(abs_t) ,intent(in) :: rhs

select type(rhs)

class is(cncrt_t) lhs%.... = rhs%.... etc.

:

end select type

end subroutine

elemental function some_op(lhs,rhs) result(res)

class(cncrt_t) ,intent(in) :: lhs

class(abs_t) ,intent(in) :: rhs

class(abs_t) ,allocatable :: res

allocate(res,source=lhs)

select type(rhs)

class is (cncrt_t)

!Shouldn't this call the generic assignment bound to Assign in the abstract class, implemented as copy?

res = lhs .other_op. rhs

:

end select type

end function

end module [/fortran]

When I run the syntax checker on a similar code I get the following error message:

[bash] $ ifort -warn -stand f03 -syntax-only -fpp statN.F90 statN.F90(97):

error #8304: In an intrinsic assignment statement, variable shall not be polymorphic. [LOCAL_RES]

local_res = rhs !I think this will call copy...nope.jpg

-------------^ [/bash]

I believe that the generic assignment specified in the abstract type should be inherited by the implementation. Therefore, a polymorphic object of class(abs_t) or one of it's children should try to call assign() when it encounters an assignment statement like local_res = .... Please correct me if my understanding is flawed or I missed some subtlety surrounding polymorphism, inheritance and generic type bound procedures.

I'm super swamped at the moment, and don't really have time to go through the original code and make a simplified reproducer. For the time being I can work around this by calling the copy subroutine directly rather than through the generic type bound assignment. I will try to work up a reproducer soon.

0 Kudos
8 Replies
Izaak_Beekman
New Contributor II
1,102 Views

In my haste I forgot to mention that this is with: ifort (IFORT) 13.0.2 20130314 on a 64 bit Intel Mac OS X (Mavericks). I don't know if the issue was corrected in ifort 14.x as I haven't had a chance to upgrade my home machine (and work/school hasn't upgraded yet either)

0 Kudos
Izaak_Beekman
New Contributor II
1,102 Views

OK, no one is responding, but it seems that this code is affected by another issue, and is not standards conforming. I'm going to fix the problems surrounding deallocation of polymorphic entities in pure subroutines and then I'll test this again. Hopefully that fix will resolve this issue. I'll report back later today or tomorrow--lots to do today!

0 Kudos
Ferdinand_T_
New Contributor II
1,102 Views

Hello Zaak,

since I had similar issues (on ifort 14.0.1), maybe I should bring up those problems here too. The problem occurs only with assignment but not with other binary operators in my code; and only for abstract types, as you already mentioned.

I think the core of the problem is that having an abstract parent is the only setup where ifort must do dynamic generic resolution on type-bound assignment operators depending on the dynamic type; and only calling directly from the lhs via %copy or from an abstract lhs explicitly enforces that. Instead, I have a feeling that ifort is trying to resovle the generic assignment staticall (which fails).

Here's a sample which is essentially your initial sample-code, but shows the same issue on ifort 14.0.1:

[fortran]

module m
    implicit none
 
    ! extendable abstract type
 
    type, abstract :: parent_type
    contains
        ! some generic type-bound operator
        procedure(copy_interf), deferred :: copy
        generic :: assignment(=) => copy
    end type
 
    abstract interface
        subroutine copy_interf(lhs,rhs)
            import parent_type
            class(parent_type), intent(inout) :: lhs
            class(parent_type), intent(in) :: rhs
        end subroutine
    end interface
 
    type, extends(parent_type) :: child_type
    contains
        procedure :: copy => copy_child
    end type
contains
    subroutine copy_child(lhs,rhs)
        class(child_type), intent(inout) :: lhs
        class(parent_type), intent(in) :: rhs
    end subroutine
end module
 
program p
    use m
    implicit none
 
    type(child_type) :: static_child
    class(child_type),  allocatable :: child_declared_child
    class(parent_type), allocatable :: child_declared_parent
 
    allocate(child_type :: child_declared_child)
    allocate(child_type :: child_declared_parent)
 
    static_child         = static_child
    child_declared_child     = static_child
    child_declared_parent     = static_child ! ERROR
 
    static_child         = child_declared_child
    child_declared_child     = child_declared_child
    child_declared_parent     = child_declared_child ! ERROR
 
    static_child         = child_declared_parent
    child_declared_child     = child_declared_parent
    child_declared_parent     = child_declared_parent
end program

[/fortran]

Each line with '! ERROR' comment triggers the following error messages:

error #6197: An assignment of different structure types is invalid.   [STATIC_CHILD]
    child_declared_parent     = static_child ! ERROR
----------------------------------^
error #8304: In an intrinsic assignment statement, variable shall not be polymorphic.   [CHILD_DECLARED_PARENT]
    child_declared_parent     = static_child ! ERROR
--------^

With regards
Ferdinand

0 Kudos
Ferdinand_T_
New Contributor II
1,102 Views

...and while we are already at this, here's an ifort 14.0.1 internal compiler error if one makes the assignment from above non-virtual:

[fortran]
module m
    implicit none
 
    ! extendable derived type

    type :: parent_type
    end type
 
    type, extends(parent_type) :: child_type
    contains
        procedure :: copy
        generic :: assignment(=) => copy
    end type
contains
    subroutine copy(lhs,rhs)
        class(child_type), intent(inout) :: lhs
        class(parent_type), intent(in) :: rhs
    end subroutine
end module
 
program p
    use m
    implicit none
 
    type(child_type) :: static_child
    class(parent_type), allocatable :: child_declared_parent
 
    allocate(child_type :: child_declared_parent)
 
    ! try type-bound assignment
    call static_child%copy(child_declared_parent)    ! OK
    static_child = child_declared_parent       ! ICE (catastrophic error)
end program

[/fortran]

Regards
Ferdinand

0 Kudos
Kevin_D_Intel
Employee
1,102 Views

Thank you for the convenient reproducers. I reported both issues to Development and will update this forum thread as I hear back from them.

(Internal tracking id: DPD200249796 - Type bound generic assignment not inherited for abstract types)
(Internal tracking id: DPD200249798 - Internal compiler error related to non-virtual type-bound assignment)

(Resolution Update on 02/14/2014): The defect DPD200249798 is fixed in the Intel® Fortran Composer XE 2013 SP1 Update 2 release (Version 14.0.2.144 Build 20140120 - Linux)

0 Kudos
Kevin_D_Intel
Employee
1,102 Views

Development has a fix for the internal error (DPD200249798) that I expect to be targeted to the next Composer XE 2013 SP1 update early next year. The error occurs when using a type-bound assignment when either there are no fields in the type of interest or the variable is class(*).

In addition to the work around you noted, Development noted another is to add a dummy field to the type declaration for parent_type.

I will update the posting again when the fix is available.

0 Kudos
Izaak_Beekman
New Contributor II
1,102 Views

Kevin,

Thanks for the work around. That is a much more attractive alternative.

0 Kudos
Kevin_D_Intel
Employee
1,102 Views

I confirmed the fix to the internal error (DPD200249798) in the latest Composer XE 2013 SP1 Update 2 release now available from the Intel Registration Center.

There is no new update on the type bound generic assignment (DPD200249796) issue. I will update once I hear anything.

0 Kudos
Reply