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

Custom constructor initializing constant - error #6259 with IFORT 18.2

Wolf_W_
New Contributor I
1,233 Views

Hello,

since IFORT 18 Update 2 i get an error when i try to use custom constructors on derived type constants. In the following example it throws two errors in Line 14:
error #6259: This array or function or substring is invalid in constant expressions.   [CONSTRUCTOR3X1]
error #7715: Replacing invalid structure constructor by integer 1.   [<NULL_STRING>]

Code:

module M_MODULE
  use, intrinsic :: iso_fortran_env, only: DP => real64


  type, public :: T_VEC
    real(DP), public :: vec(1:3) = [0.0_DP,0.0_DP,0.0_DP]
  end type T_VEC

  interface T_VEC
    module procedure constructor3x1
    module procedure constructorXYZ
  end interface T_VEC

  type(T_VEC), parameter, public :: E_X = T_VEC([1.0_DP,0.0_DP,0.0_DP])
  type(T_VEC), parameter, public :: E_0 = T_VEC()

contains

  pure function constructor3x1(array) result(new_vec)
    real(DP), intent(in) :: array(3)
    type(T_VEC) :: new_vec

    new_vec%vec = array

  end function constructor3x1

  elemental function constructorXYZ(x, y, z) result(new_vec)
    real(DP), intent(in) :: x,y,z
    type(T_VEC) :: new_vec

    new_vec%vec(1) = x
    new_vec%vec(2) = y
    new_vec%vec(3) = z

  end function constructorXYZ

end module M_MODULE

This worked as intendet since Version 16 i think. I was not able to find a workaround so far, as an initialization of a variable with this constructor does not work, too.

I tried to replace line 14 with

type(T_VEC), parameter, public :: E_X = transfer([1.0_DP,0.0_DP,0.0_DP], T_VEC())

This compiles in the example, but fails in my project with an ICE. And i did not try, if it works as intendet.

Is this a compiler bug or is this usage of an user defined constructor not allowed?

 

Greetings

Wolf

0 Kudos
5 Replies
andrew_4619
Honored Contributor II
1,233 Views
0 Kudos
FortranFan
Honored Contributor II
1,233 Views

Based on a quick glance, I think this is a problem with the Fortran standard itself i.e., from OP's need point of view.  The code in the original post is non-conforming; the standard only allows certain intrinsic procedures in a constant expression that is required in a named constant declaration.

Given what OP shows though, defined constructor is not needed, the following should work fine:

module M_MODULE

   use, intrinsic :: iso_fortran_env, only: DP => real64


   type, public :: T_VEC
      real(DP), public :: vec(1:3) = [0.0_DP,0.0_DP,0.0_DP]
   end type T_VEC

   type(T_VEC), parameter, public :: E_X = T_VEC([1.0_DP,0.0_DP,0.0_DP])
   type(T_VEC), parameter, public :: E_0 = T_VEC()

end module M_MODULE

 

The case mentioned by Andrew is different; the named constant in there uses the default constructor which is ok; the defined constructor interface with one dummy argument is different from what is used in the named constant, so it doesn't come into play other than perhaps 'confuse' the compiler.

0 Kudos
Steve_Lionel
Honored Contributor III
1,234 Views

I agree with FortranFan here - user generic constructors are not allowed in constant expressions.

However, that your substitution using TRANSFER got an ICE is definitely a compiler bug, and you should report it to Intel.

0 Kudos
Wolf_W_
New Contributor I
1,234 Views

Thanks Steve and FortranFan for the clarification on the standard conformity.

I didn't realize that i can leave out the "standard" constructor from the interface. It works now with just the special constructors in the interface.

  interface T_VEC
!    module procedure constructor3x1
    module procedure constructorXYZ
  end interface T_VEC

I will try to post an example for ICE, as soon as i can pin it down.
 

0 Kudos
Steve_Lionel
Honored Contributor III
1,234 Views

Better to submit the ICE at https://supporttickets.intel.com/?lang=en-US , since you'll be asked to do so anyway.

0 Kudos
Reply