- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
...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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Kevin,
Thanks for the work around. That is a much more attractive alternative.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page