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

Regression of Fortran's polymorphic assignment in oneAPI 2023.0.0

GreenScreen
Beginner
234 Views

The following code demonstrates a regression of Fortran 2008's polymorphic assignment, in both ifx and ifort, that wasn't present in Version 2021.4.0 of both compilers.

module interface

   private
   
   type, public, abstract :: IGrid
   contains
      procedure(dimens), deferred :: dimens
   end type IGrid
   
   abstract interface
      function dimens(self) result(dims)
         import; implicit none
         class(IGrid), intent(in)  :: self
         integer,      allocatable :: dims(:)
      end function dimens
   end interface

end module interface


module implementation

   use interface, only: IGrid

   implicit none
   private
   
   type, public, extends(IGrid) :: Grid
   contains
      procedure :: dimens
   end type Grid
   
contains
   
   function dimens(self) result(dims)
      class(Grid), intent(in)  :: self
      integer,     allocatable :: dims(:)
      dims = [400,200]
   end function dimens

end module implementation


module test

   use interface,      only: IGrid
   use implementation, only: Grid

   implicit none
   
contains
   
   subroutine grid_array_builder(grids)
      !
      ! Demonstrates polymorphic assignment regression.
      !
      class(IGrid), allocatable, intent(out) :: grids(:)
      
      integer :: i
      integer, parameter :: ngrids = 5
      
      allocate( Grid :: grids(ngrids) )
      
      do i = 1, ngrids
         grids(i) = Grid()
      end do

   end subroutine grid_array_builder
   
end module test

Here's the output after trying to compile this code with ifx Version 2023.0.0:

ifx -c test.f90


test.f90(65): error #8304: In an intrinsic assignment statement, variable shall not be a non-allocatable polymorphic. [GRIDS]
grids(i) = Grid()
---------^
compilation aborted for test.f90 (code 1)

 

Ifort Version 2021.8.0 Build 20221119_000000 (that is included in oneAPI 2023.0.0) gives exactly the same "error". This is clearly a compiler bug, because variable "grids" is explicitly declared to be "allocatable" in the above code, and both compilers simply ignore the "allocatable" attribute.

 

The above code compiled fine with both ifx and ifort Version 2021.4.0.

0 Kudos
1 Solution
FortranFan
Honored Contributor II
201 Views

Yes.  The assignment instruction can have a whole object that is an allocatable, polymorphic and the semantics of intrinsic assignment in the standard informs the processor on the suitable steps it needs to take.  Or the assignment can have an element (like your grids(i)) which is nonpolymorphic such as with a SELECT TYPE construct.  Working with whole objects, in situations like this I advise, is better in the long-term as processors get better.

View solution in original post

4 Replies
FortranFan
Honored Contributor II
225 Views

@GreenScreen ,

Rather than a regression, this is a case where the latest versions of IFX and IFORT now conform to the Fortran standard whereas the earlier versions failed to do so.  Per the standard, a reference to an element (or an array section) is not supported in an assignment with a polymorphic variable on the left-hand side and an extended type as the result of the expression on the right.   You will need to refactor your code to conform, a possible option you can consider with 2023.0.0 version (I have not tried it myself, thus untested):

 

      ..
      allocate( Grid :: grids(ngrids) )
      
      select type ( grids )
         type is ( Grid )
            do i = 1, ngrids
               grids(i) = Grid()
            end do
         class default 
      end select
      ..

 

A better option will be to consider the functional programming support in the language and make use of much of the built-in elemental facility and simply go with:

 

      ..
      allocate( Grid :: grids(ngrids) )
      
      grids = Grid()
      ..

 

 

 

 

GreenScreen
Beginner
216 Views

Thanks for your reply.

 

So what you're basically saying is that, in order to conform to the standard, one has to use an array (or elemental) expression to initialize the "grids" array as a whole (if one wishes to avoid the use of a "select type" statement).

 

FortranFan
Honored Contributor II
202 Views

Yes.  The assignment instruction can have a whole object that is an allocatable, polymorphic and the semantics of intrinsic assignment in the standard informs the processor on the suitable steps it needs to take.  Or the assignment can have an element (like your grids(i)) which is nonpolymorphic such as with a SELECT TYPE construct.  Working with whole objects, in situations like this I advise, is better in the long-term as processors get better.

Ron_Green
Moderator
118 Views

Gfortran 12.0.1, a superb Fortran compiler, also catches this Standard violation.  It is helpful to have a copy of a recent gfortran handy for cross checking code against the Standard.  Also, the NAG compiler is amazing at diagnostics for Standards violations.


gfortran qnew2.f90
qnew2.f90:65:9:

   65 |          grids(i) = Grid()
      |         1
Error: Nonallocatable variable must not be polymorphic in intrinsic assignment at (1) - check that there is a matching specific subroutine for '=' operator
rwgreen@orcsle153:~/quad$ gfortran --version
GNU Fortran (GCC) 12.0.1 20220413 (Red Hat 12.0.1-0)
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Reply