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

Extensible type restriction in same_type_as

Martin1
New Contributor I
323 Views

Consider the code below, which has nested derived-types with default initialisation in it.

module mod

implicit none
private

type, public :: a
   integer :: i = 5
end type a

type, public :: b
   type(a) :: n
end type b

interface b
   module procedure create_b
end interface b

contains

   function create_b() result(x)
      type(b) :: x
      x%n = a()
   end function create_b

end module mod


program definit

use mod
implicit none

type(b) :: u

print *, same_type_as(u, b())

end program definit

 

I have several issues with the code and ifort (beta release):

(1) Without the constructor create_b and "interface b", ifort complains that

definit.f90(25): error #8212: Omitted field is not initialized. Field initialization missing:  
print *, same_type_as(u, b())
^

I have reported this as a bug, but was told that this is not legal fortran. But I think default initialisation in nested derived-types is pretty clear (at least if I read Metcalf "7.5.4 Default initialisation of components", edition from 2011, correctly). Please correct me if I am wrong.

(2) As a work-around I tried to add explicit default initialisation

type, public :: b
   type(a) :: n = a()
end type b

which works fine. And I also tried adding create_b (where I explicitly need to initialise component n with x%n = a(), probably the same problem mentioned in (1)). But now I get

definit.f90(36): error #8250: The argument to the SAME_TYPE_AS intrinsic function must be an object of extensible type.
print *, same_type_as(u, b())

Why are u and b() (without the create_b interface) accepted, but not type(b) as a function result of create_b? In general type(b) is an extensible type and all three arguments should be accepted by same_type_as, right?

 

0 Kudos
4 Replies
Juergen_R_R
Valued Contributor I
323 Views

Interesting piece of code: It is clear that your code doesn't work without the interface and the create_b procedure, because the proper structure constructor would be b(a()) instead of b(). The type a has to be created first, before you are using a structure constructor for b.

The modified code with the interface compiles with NAG, PGI and gfortran, and is rejected by ifort. The F2018 standard in 16.9.165.3 states that same_type_as as an inquiry function has two arguments which shall be objects of extensible type or [unlimited polymorphic, doesn't apply]. An extensible type is one that may be extended using the EXTENDS clause (definition 3.147.6), which applies to both your types a and b. It explicitly applies to u which is of type b, and accepted by ifort, but also to the function result of the procedure create_b. I consider this second thing (not the first one that you sent in) a compiler bug from ifort which you might check with the Ifort support.

0 Kudos
Martin1
New Contributor I
323 Views

Juergen R. wrote:

Interesting piece of code: It is clear that your code doesn't work without the interface and the create_b procedure, because the proper structure constructor would be b(a()) instead of b(). The type a has to be created first, before you are using a structure constructor for b.

I do not quite understand this. According to Metcalf, all components are initialised (there is an example which is similar to mine).

A declaration

type(b) :: x

should initialise all components, no need to write x%n = a() (as requested by the compiler for the create_b function, this is actually a third issue I have). So why should I give a default value by b(a()) if component n already has default initialisation? Moreover, if I replace component "type(a) :: n", with "integer :: k =3" or something, then I can just write b() instead of b(3). I find this inconsistent and confusing. Is this really fortran standard? I am not able to find anything, except that all should be default initialised.

 

0 Kudos
Juergen_R_R
Valued Contributor I
323 Views

The F2008 standard says in 7.5.4.6.7 on default initialization for components:

A subcomponent (9.4.2) is default-initialized if the type of the object of which it is a component specifies default initialization for that component, and the subcomponent is not a subobject of an object that is default-initialized or explicitly initialized.

Your subcomponent n of type a is the subcomponent of type b which is default initialized because you are using a structure constructor.

0 Kudos
Martin1
New Contributor I
323 Views

Juergen R. wrote:

The F2008 standard says in 7.5.4.6.7 on default initialization for components:

A subcomponent (9.4.2) is default-initialized if the type of the object of which it is a component specifies default initialization for that component, and the subcomponent is not a subobject of an object that is default-initialized or explicitly initialized.

Your subcomponent n of type a is the subcomponent of type b which is default initialized because you are using a structure constructor.

I already found this section in the standard, and I understand that for b() everything should be initialised. I feel pretty dumb, but I just do not understand this?

0 Kudos
Reply