- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I've recently updated ifort from version 2021.8.0 to version 2021.9.0.
Some code which was previously compiling file now gives the following error:
error #5585: A statement that might result in the deallocation of a polymorphic entity is not permitted in a pure procedure.
Here is a small reproducer.
Module MyModule
implicit none
Type :: MyType
class(*) ,allocatable :: p
contains
procedure :: Free
End Type
contains
Pure Subroutine Free( This )
class(MyType) ,intent(inout) :: This
deallocate( This%p ) ! <====== Using ifort 2021.9.0: error #5585: A statement that might result in the deallocation of a polymorphic entity is not permitted in a pure procedure.
End Subroutine
End Module
Program Main
use MyModule
implicit none
type(MyType) :: var
allocate( var%p , source = 9 )
write(*,*) "allocated(var%p) = ", allocated(var%p)
write(*,*) "call var%Free"
call var%Free
write(*,*) "allocated(var%p) = ", allocated(var%p)
End Program
The following built instructions (I'm using the intel modulefiles)
echo "##########"
module purge --silent
module load compiler/2023.0.0 --silent
ifort -v
ifort main.f90
./a.out
echo "##########"
module purge --silent
module load compiler/2023.1.0 --silent
ifort -v
ifort main.f90
./a.out
give
##########
ifort version 2021.8.0
allocated(var%p) = T
call var%Free
allocated(var%p) = F
##########
ifort version 2021.9.0
main.f90(15): error #5585: A statement that might result in the deallocation of a polymorphic entity is not permitted in a pure procedure.
deallocate( This%p ) ! <====== Using ifort 2021.9.0: error #5585: A statement that might result in the deallocation of a polymorphic entity is not permitted in a pure procedure.
--^
compilation aborted for main.f90 (code 1)
Now, my fear is that this error is actually valid and it was simply not caught in ifort version 2021.8.0.
However, it puts a lot of restriction on the use of the pure attribute, which nearly becomes useless when polymorphic variables are involved.
Is this restriction really necessary ?
Is there any workaround apart from removing the pure attribute ?
Thank you.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear FlyingHermes,
Are you tried with gfortran?, e.g.
$ gfortran --version
GNU Fortran (GCC) 13.0.1 20230124 (experimental)
$ gfortran -march=native -mtune=native -fall-intrinsics -fcheck=all -fimplicit-none -fmax-errors=4 -std=f2018 -Wall -Waliasing -Warray-temporaries -Wcharacter-truncation -Werror -Wextra -Wimplicit-interface -Wimplicit-procedure -Wintrinsic-shadow -Wline-truncation -Wrealloc-lhs-all -Wsurprising -Wtabs -Wunused-parameter -O2 -c test180.f90
test180.f90:29:22:
29 | pure subroutine free (this)
| 1
Error: ‘free’ declared at (1) may shadow the intrinsic of the same name. In order to call the intrinsic, explicit INTRINSIC declarations may be required. [-Werror=intrinsic-shadow]
Then, if the pure subroutine free is renamed, say, to pure subroutine free_b, then,
$ test180.exe
allocated(var%p) = T
call var%free
allocated(var%p) = F
However, it persists the restriction already shown, i.e.
$ ifort --version
/opt/intel/oneapi/compiler/2023.1.0/linux/bin/intel64/ifort
$ ifort -o test180-i.exe test180.f90
test180.f90(30): error #5585: A statement that might result in the deallocation of a polymorphic entity is not permitted in a pure procedure.
deallocate (this%p) ! <= using ifort 2021.9.0: error #5585:
----^
compilation aborted for test180.f90 (code 1)
Regards,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It is a restriction arising from a required correction to F2008 as published. There is no work around with the current language (that may change in future).
The Fortran concept of PURE imposes a set of checkable constraints on a procedure, that collectively guarantee that calls to the procedure will have reasonably deterministic semantics when it is invoked from code that has no ordering requirements (like DO CONCURRENT, specification parts, FORALL...).
(Calls from code with no ordering requirement may permit a suitably capable Fortran processor to arrange the calls such that they happen at the same time, so people get excited about PURE and parallel code, but that's actually secondary to its language purpose.)
Final procedures for a derived type do not have to be PURE. There is no practical way that a compiler can check whether final procedures for a derived type that is an extension of the type of a polymorphic argument are pure. This inability to check breaks the Fortran language concept of PURE - hence the correction to the language.
In future revisions of the language (not sure where this is at with current language proposals) types could be augmented with an attribute that says "extensions must not have impure FINAL procedures", which would then be checkable, and those sorts of types would be permitted to be deallocated inside PURE procedures. But today is not the future.
Meanwhile it is just certain contexts that are prohibited for polymorphic variables - "nearly useless" is a bit of an exaggeration.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you.
What you say makes sense. In particular, that the language needs to introduce a set of constraints that guarantee that pure procedures can be called within loops without any ordering requirements. Since non-polymorphic procedure arguments can be deallocated inside pure procedures, I was wrongly assuming that it was also the true for polymorphic procedure arguments.
However, I still don't understand why there is a particular constraint for the deallocation of polymorphic arguments and not for non-polymorphic arguments. If someone out there has the answer I would be happy to know.
I hope this restriction will be relaxed in a future revision of the standards, if possible.
And regarding:
@IanH wrote:Meanwhile it is just certain contexts that are prohibited for polymorphic variables - "nearly useless" is a bit of an exaggeration.
You are right, it was not such a big deal after all. I always try to make all my procedures pure whenever possible, and, because of the transitive requirement of pure procedures, I was afraid that this restriction will force me to make many procedure impure. It was not the case.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Consider your original module in combination (take out the Pure keyword if you want this all to compile) with this additonal module and alternative main program:
Module MyOtherModule
Implicit None
Type :: HasAFinalizer
Contains
Final ::f
End Type HasAFinalizer
Integer :: global
Contains
Subroutine f( arg )
Type(HasAFinalizer) :: arg
! Not pure things!
global = 123
Print "('I am not pure!!')"
End Subroutine f
End Module MyOtherModule
Program Main
use MyModule
Use MyOtherModule
implicit none
type(MyType) :: var
allocate( var%p , source = HasAFinalizer() )
write(*,*) "allocated(var%p) = ", allocated(var%p)
write(*,*) "call var%Free"
call var%Free
write(*,*) "allocated(var%p) = ", allocated(var%p)
End Program
When compiling the subroutine that was supposed to be pure, the compiler has no idea what the type of This%p is. It has no idea whether This%p has a finalizer, if it did have a finalizer, it has no idea whether it is pure or not. Without knowing, this the compiler cannot check whether the subroutine is pure.
For non-polymorphic arguments the compiler knows everything about the type and its bindings - so it can check purity.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page