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

class(*) intrinsic assignment

Carl_S_1
Beginner
774 Views

When trying to compile a module to assign class(*) to an integer I get the following error:

stl.f90(10): error #6762: The type for the arguments of this specific subroutine for a defined ASSIGNMENT redefines intrinsic assignment operations.   [ASSIGN_CLASS_STAR_TO_INT]

 

module stl
implicit none

interface assignment(=)
    module procedure assign_class_star_to_int
end interface

contains

subroutine assign_class_star_to_int(a, b)
implicit none
integer, intent(out) :: a
class(*), intent(in) :: b

select type(b)
    type is (integer)
        a = b
end select

end subroutine assign_class_star_to_int

end module stl

This would suggest that I can use a built-in intrinsic to assign a class(*) to an integer. If I try to compile the following program, I get the error:

test.f90(22): error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands.

module foo_m

contains

function foo() result(f)
implicit none
integer :: i
class(*), allocatable :: f

i=10
allocate(f, source=i)

end function foo

end module foo_m

program main
use foo_m
implicit none
integer :: i

i = foo()

end program main

 

 

What am I missing here?

Thanks for your help.

0 Kudos
5 Replies
IanH
Honored Contributor II
774 Views

With your first example, your subroutine would be matched by an assignment such as:

integer :: i
i = 3

This could present various quandries for the Fortran language, Fortran programmers and Fortran compilers (the defined assignment could specify that the resulting value of i is 2!) - so it is not permitted to keep everybody sane.

For your second example, the dynamic type of the right hand side may be something that is not an integer (or not convertible to an integer by the rules of intrinsic assignment) - so that is also not permitted.

As of Fortran 2008 (and soon-to-be-current ifort) you can assign to a left hand side variable that is an allocatable unlimited polymorphic object.

program p
  implicit none
  class(*), allocatable :: lhs
  lhs = 1
  
  select type (lhs)
  type is (integer)
    print *, lhs
  class default
    print "('what??')"
  end select
end program p

If you want to convert an unlimited polymorphic object to an integer, then you can write a function that does so:

module m
  implicit none
  private
  public :: operator(.GetAsInteger.)
  interface operator(.GetAsInteger.)
    procedure :: GetAsInteger
  end interface operator(.GetAsInteger.)
contains
  function GetAsInteger(rhs)
    class(*), intent(in) :: rhs
    integer :: GetAsInteger
    
    select type (rhs)
    type is (integer)
      GetAsInteger = rhs
    class default
      GetAsInteger = -1
    end select
  end function GetAsInteger
end module m

program p
  use m
  implicit none
  
  class(*), allocatable :: thing
  integer :: i
  allocate(thing, source = 99)   ! or with F2008: thing = 99
  
  i = .GetAsInteger. thing
  
  print *, i
end program p
0 Kudos
Ragossnig__Florian
774 Views

Hi!

If I understood right, then this is absolutely ridiculous! What is the point of overriding an assignment if then it is not permitted by the compiler? I ran into the same problem just recently and I think I will simply stop using the intel fortran compiler! The first example above works fine with gnu fortran.

0 Kudos
Juergen_R_R
Valued Contributor I
774 Views

stl.f90(10): error #6762: The type for the arguments of this specific subroutine for a defined ASSIGNMENT redefines intrinsic assignment operations.   [ASSIGN_CLASS_STAR_TO_INT]

Can someone point to the corresponding part of the Fortran standard where this is actually forbidden? I am asking because PGI v18.7, nagfor v6.2 and gfortran v5.4 or 9.0 do compile this code without any complaints. So the question is: is ifort correctly complaining about a violation of the standard, or are the other compilers correctly accepting this code. 

0 Kudos
FortranFan
Honored Contributor II
774 Views

Juergen R. wrote:

.. Can someone point to the corresponding part of the Fortran standard where this is actually forbidden? I am asking because PGI v18.7, nagfor v6.2 and gfortran v5.4 or 9.0 do compile this code without any complaints. So the question is: is ifort correctly complaining about a violation of the standard, or are the other compilers correctly accepting this code. 

Refer to section 12.4.3.4.3 on Defined Assignments in document 10-007r1 toward Fortran 2008; also look at the subsection 12.4.3.4.4 Restrictions on generic declarations and the constrains therein.

I believe Intel Fortran is standard-conforming with respect to first example in the original post:

  1. The rules on disambiguation of generic interfaces in the standard effectively disallow coders from overriding assignment and operations on intrinsic types.  Thus one cannot implement one's own interface for integer a = integer b assignment, to cite a scenario.
  2. Now it's NOT possible to distinguish a dummy argument of an unlimited polymorphic type (CLASS(*)) in an interface with another interface involving a dummy argument of any another type, intrinsic type or otherwise.  This essentially brings the restriction in point 1 above to the defined assignment implementation attempt by OP in the first example.

Those other compilers need bug reports.

0 Kudos
FortranFan
Honored Contributor II
774 Views

Ragossnig, Florian wrote:

Hi!

If I understood right, then this is absolutely ridiculous! What is the point of overriding an assignment if then it is not permitted by the compiler? I ran into the same problem just recently and I think I will simply stop using the intel fortran compiler! The first example above works fine with gnu fortran.

@Ragossnig, Florian,

See Quote #2 and Quote #5.  Which processor you want to use is your (team/leader/management) decision, but this case is entirely positive for Intel Fortran.

 

0 Kudos
Reply