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

Parameterised derived types seam incapable of functioning as a function return

Andrew_Smith
New Contributor III
232 Views

Consider a function returning a parameterised derived type that depends on inputs to set its parameter length. Such a use seams the most logical way to use this feature. This example is part of some AD code I suspect many will attempt:

module Bar
   implicit none

   integer, parameter :: DP = 8
   
   type Foo(n)
      integer, len :: n
      real(DP) :: v
      real(DP) :: d(n)
   end type
   
contains
      
   function divide(a, b) result(c)
      type(Foo(*)), intent(in) :: a
      type(Foo(*)), intent(in) :: b
      type(Foo(a%n)) c
      c%v = a%v/b%v
      c%d = (a%d - a%v*b%d/b%v)/b%v
   end function
   
   subroutine divideSub(a, b, c)
      type(Foo(*)), intent(in) :: a
      type(Foo(*)), intent(in) :: b
      type(Foo(a%n)), intent(out) :: c
      c%v = a%v/b%v
      c%d = (a%d - a%v*b%d/b%v)/b%v
   end subroutine
   
end module
   
program test
   use Bar
   implicit none

   type (Foo(n=100)) :: x, y, z
   
   x%v = 1.0d0
   x%v = 1.0d0
   y%v = 2.0d0
   y%d = 0.0d0
   z = divide(x, y)
   call divideSub(x, y, z)
end program

If gives:

1>------ Build started: Project: TestDerivedTypeCompilerCrash, Configuration: Debug Win32 ------
1>Compiling with Intel(R) Visual Fortran Compiler 16.0 [IA-32]...
1>Source1.f90
1>Bla\Bla\Source1.f90(42): error #6197: An assignment of different structure types is invalid.
1>Bla\Bla\Source1.f90(43): error #6633: The type of the actual argument differs from the type of the dummy argument.  
1>compilation aborted for Bal\Bla\Source1.f90 (code 1)
1>
1>Build log written to  "file://Bla\Bla\BuildLog.htm"
1>TestDerivedTypeCompilerCrash - 3 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

The problem appears to arise because the return type of the function is not explicit and so can not be assumed to match the type of the local variable we assign it to. The same problem arises for a subroutine version with an intent(out) result.

The compiler must be intelligent enough to work through the function call to determine the implied result type but has not done so. With these severe limitations of the 16.0 compiler we have very little we can usefully do with parameterised derived types apart from declare a few just for fun. Will Intel attempt to fix this issue soon ?

0 Kudos
4 Replies
jimdempseyatthecove
Honored Contributor III
232 Views

You may need a copy operator (principally to handle cases of different n values).

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor II
232 Views

Andrew Smith wrote:

.. The compiler must be intelligent enough to work through the function call to determine the implied result type but has not done so. With these severe limitations of the 16.0 compiler we have very little we can usefully do with parameterised derived types apart from declare a few just for fun. Will Intel attempt to fix this issue soon ? ..

Welcome to the club in which you're a long-time member!  I believe your case is similar to one or more of many issues involving PDTs that have already been reported to Intel for resolution.  Hopefully Intel can fix all those issues soon to provide us with a most robust implementation of PDTs, for it is indeed a very valuable feature of the language. 

In the meantime, a temporary workaround I suggest you try is assumed type dummy argument for c in the subroutine procedure; forget about the function procedure until the compiler becomes "intelligent enough":

   subroutine divideSub(a, b, c)
      type(Foo(n=*)), intent(in) :: a
      type(Foo(n=*)), intent(in) :: b
      type(Foo(n=*)), intent(inout) :: c
      c%v = a%v/b%v
      c%d = (a%d - a%v*b%d/b%v)/b%v
   end subroutine

 

0 Kudos
FortranFan
Honored Contributor II
232 Views

jimdempseyatthecove wrote:

You may need a copy operator (principally to handle cases of different n values).

Jim Dempsey

I've not found it to help due to limitations in the current implementation of PDTs in Intel Fortran:

module Bar
   implicit none

   integer, parameter :: DP = 8

   type Foo(n)
      integer, len :: n
      real(DP) :: v
      real(DP) :: d(n)
   end type

   interface assignment(=)
      module procedure assign_foo
   end interface

contains

   function divide(a, b) result(c)
      type(Foo(*)), intent(in) :: a
      type(Foo(*)), intent(in) :: b
      type(Foo(n=a%n)) c
      
      c%v = a%v/b%v
      c%d = (a%d - a%v*b%d/b%v)/b%v
      
   end function

   subroutine divideSub(a, b, c)
      type(Foo(*)), intent(in) :: a
      type(Foo(*)), intent(in) :: b
      type(Foo(*)), intent(out) :: c
      
      !.. corrective action elided if length parameter of c is different
      
      c%v = a%v/b%v
      c%d = (a%d - a%v*b%d/b%v)/b%v
   end subroutine

   subroutine assign_foo( lhs, rhs )

      type(Foo(*)), intent(out) :: lhs
      type(Foo(*)), intent(in)  :: rhs

      !.. corrective action elided if length parameter of lhs is different
      
      lhs%v = rhs%v
      lhs%d = rhs%d

   end subroutine assign_foo

end module
program test
   use Bar
   implicit none

   type (Foo(n=100)) :: x, y, z

   x%v = 1.0d0
   x%v = 1.0d0
   y%v = 2.0d0
   y%d = 0.0d0
   z = divide(x, y)
   call divideSub(x, y, z)
end program
Compiling with Intel(R) Visual Fortran Compiler 16.0 [Intel(R) 64]...
p.f90
p.f90(11): error #6197: An assignment of different structure types is invalid.
compilation aborted for p.f90 (code 1)

 

0 Kudos
Kevin_D_Intel
Employee
232 Views

I will report this case to Development shortly and inquire about a general status/update on PDT related defects.

0 Kudos
Reply