I don’t think that this program depends on any standard feature more recent that Fortran 2003, yet I can’t find any Fortran compiler implementation that can compile it without failing with internal errors or bogus error messages. (I tried recent versions of gfortran, ifort, nvfortran, nagfor, and xlf). Is this indeed a conforming program?

module m
interface
pure recursive function ifact(j)
integer, intent(in) :: j
end function
end interface
type :: t(len)
integer, len :: len
integer :: a(ifact(len))
end type
contains
subroutine subr(n)
integer, intent(in) :: n
type(t(n)) :: x
do j = 1, size(x%a)
x%a(j) = j
end do
print *, x
end subroutine
end module
pure recursive function ifact(j) result(i)
integer, intent(in) :: j
if (j <= 0) then
i = 1
else
i = j * ifact(j - 1)
end if
end function
use m
call subr(4)
end

The way I see it, you are not allowed to declare an explicit shaped array with nonconstant bounds, as in:

integer :: a(ifact(len))

I suppose you could try and use an allocatable array instead, but atleast with gfortran-9, the support is kind of buggy. Here is what I mean precisely:

module m
implicit none
private
public :: t2, init_t2
type :: t2(len)
integer, len :: len
integer, allocatable :: a(:)
end type
contains
subroutine init_t2(this)
type(t2(*)), intent(inout) :: this
if (allocated(this%a)) deallocate(this%a)
allocate(this%a(ifact(this%len)))
end subroutine
pure recursive function ifact(j) result(i)
integer, intent(in) :: j
integer :: i
if (j <= 0) then
i = 1
else
i = j * ifact(j - 1)
end if
end function
end module
program test_m
use m ! works
! use m, only: t2, init_t2 ! does not work
implicit none
integer, parameter :: n = 4
type(t2(:)), allocatable :: obj1
type(t2(3)) :: obj2
allocate(t2(n) :: obj1)
print *, obj1%len, allocated(obj1%a)
print *, obj2%len, allocated(obj2%a)
call init_t2(obj1)
print *, obj1%len, size(obj1%a)
call init_t2(obj2)
print *, obj2%len, size(obj2%a)
end program

The output I get is:

$ gfortran-9 fortran_prog.f90
$ ./a.out
4 F
3 F
4 24
3 6

For whatever it’s worth, I think the program conforms.

My hunch is all the processors are falling over the specification expression in the derived type component definition of integer :: a(ifact(len)), something which I know Intel Fortran supports to some extent but still has gaps; and for which gfortran effectively has no support.

Based on what I see, the program adheres to what is stated in the standard in Section 10.1.11 on Specification Expression: the paragraphs relevant to the example code in the original post (per my understanding) being shown below

39 10.1.11 Specification expression
40 1 A specification expression is an expression with limitations that make it suitable for use in specifications such as
41 length type parameters (C704) and array bounds (R817, R818). A specification-expr shall be a constant expression
42 unless it is in an interface body (15.4.3.2), the specification part of a subprogram or BLOCK construct, a derived
43 type definition, or the declaration-type-spec of a FUNCTION statement (15.6.2.2).
44 R1028 specification-expr is scalar-int-expr
45 C1010 (R1028) The scalar-int-expr shall be a restricted expression.

2 A restricted expression is an expression in which each operation is intrinsic or defined by a specification function
2 and each primary is
…
4 (2) an object designator with a base object that is a dummy argument that has neither the OPTIONAL
5 nor the INTENT (OUT) attribute,
…
23 (12) a reference to a specification function where each argument is a restricted expression,
24 (13) a type parameter of the derived type being defined,
…
38 4 A function is a specification function if it is a pure function, is not a standard intrinsic function, is not an internal
39 function, is not a statement function, and does not have a dummy procedure argument.

Here’s a simplified variant of the code in the original post where a specification expression which reduces to a constant expression is supported in the specification part of a subprogram by some compilers I tried. However even this simple example is processed to varying levels of accuracy by Intel Fortran (looks ok) and gfortran (not so):

module m
interface
pure recursive function ifact(j)
integer, intent(in) :: j
end function
end interface
type :: t(len)
integer, len :: len
integer :: a(len)
end type
contains
subroutine subr()
!integer, intent(in) :: n
type(t(len=ifact(4))) :: x
do j = 1, size(x%a)
x%a(j) = j
end do
print *, x
end subroutine
end module
pure recursive function ifact(j) result(i)
integer, intent(in) :: j
if (j <= 0) then
i = 1
else
i = j * ifact(j - 1)
end if
end function
use m
call subr()
end

These processors thus struggle with the use of a pure function in a derived type component definition and also when an object designator that is a dummy argument is used.

I agree that the code is conforming. Allowing pure user functions to be referenced in a restricted expression is relatively new, and some compilers (apparently a lot) have not caught up to the change yet. An ICE is always a bug, independent of whether a compiler us up to date with new features.

Interesting. I had not delved this deep. It seems like a very powerful feature (if it worked correctly).

With some (pure) intrinsic functions it appears to work:

program test
implicit none
character(len=5), parameter :: c = "123"
integer :: b(len_trim(c))
type :: t
integer :: b(len_trim(c))
end type
type(t) :: mt
print *, size(b), size(mt%b)
end program

On the other hand for the case of

type :: t
character(len=5) :: d
integer :: b(len(d))
end type

with a references to a type parameter I get error messages.

Now, this code snippet does not conform: other than type parameters and restricted expressions involving them (as per section 10.1.11), the standard does not permit the component of a type being defined to be an object designator in another component of the same type.