# Linked list with PDT

**URL:** <https://fortran-lang.discourse.group/t/linked-list-with-pdt/5729>\
**Category:** Help\
**Created:** [May 3, 2023, 12:11am UTC](https://fortran-lang.discourse.group/t/linked-list-with-pdt/5729 "2023-05-03T00:11:20Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![han190](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/han190/32/7158_2.png) [@han190](https://fortran-lang.discourse.group/u/han190)\
**Post date:** [May 3, 2023, 12:11am UTC](https://fortran-lang.discourse.group/t/linked-list-with-pdt/5729/1 "2023-05-03T00:11:20Z")

</div>

I am trying to create a linked list with parameterized derived type, and here is a minimal example that triggers the error:

```fortran
module module_utility
implicit none

type :: array_type(kind, len)
  integer, kind :: kind
  integer, len :: len
  real(kind=kind) :: values(len)
end type array_type

type :: node_type(kind, len)
  integer, kind :: kind
  integer, len :: len
  type(array_type(kind, len)) :: array
  type(node_type(kind, len)), pointer :: next => null()
end type node_type

end module module_utility

program main

  use iso_fortran_env, only: real32
  use module_utility
  implicit none

  ! type(node_type(kind=real32, len=10)) :: list 
  ! It works

  type(node_type(kind=real32, len=:)), allocatable :: list
  ! error #6147: The structure definition stack has been exceeded.

end program main

```

Both `ifx` and `ifort` throw me

> error #6147: The structure definition stack has been exceeded.

Since it is not an ICE, I must be doing something wrong. What is the proper method for constructing a linked list type using PDT?

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [May 3, 2023, 2:39am UTC](https://fortran-lang.discourse.group/t/linked-list-with-pdt/5729/2 "2023-05-03T02:39:29Z")

</div>

> [@han190](#):
>
> .. What is the proper method for constructing a linked list type using PDT?

@han190, your pointer component of `node_type` needs to have deferred-length. Then with default initialization of type parameters you should get a **not implemented** error. You can follow-up on the Intel’s plans to implement support for this, you may be out of luck at the moment like with many other aspects of PDTs.

```fortran
module module_utility
   use, intrinsic :: iso_fortran_env, only : real32
   type :: array_type(kind, len)
     integer, kind :: kind = real32
     integer, len :: len = 1
     real(kind=kind) :: values(len)
   end type array_type

   type :: node_type(kind, len)
     integer, kind :: kind = real32
     integer, len :: len = 1
     type(array_type(kind, len)) :: array
     type(node_type(kind, len=:)), pointer :: next => null()
   end type node_type

end module

  use, intrinsic :: iso_fortran_env, only : real32
  use module_utility

  type(node_type(kind=real32, len=:)), allocatable :: list
end

```

```auto
C:\temp>ifort /c /free /standard-semantics p.f
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.9.0 Build 20230302_000000
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

p.f(15): error #7555: Not yet implemented: Type containing ALLOCATABLE/POINTER component of same type with different type parameters. [KIND]
  type(node_type(kind, len=:)), pointer :: next => null()
-----------------^
p.f(23): error #7013: This module file was not generated by any release of this compiler. [MODULE_UTILITY]
  use module_utility
------^
p.f(29): error #6457: This derived type name has not been declared. [NODE_TYPE]
  type(node_type(kind=real32, len=:)), allocatable :: list
-------^
p.f(22): error #6580: Name in only-list does not exist or is not accessible. [REAL32]
  use, intrinsic :: iso_fortran_env, only : real32
--------------------------------------------^
compilation aborted for p.f (code 1)

```

A strange error #6580 to boot.

---

<div class="post-metadata">

**Author:** ![RonShepard](https://avatars.discourse-cdn.com/v4/letter/r/a3d4f5/32.png) [@RonShepard](https://fortran-lang.discourse.group/u/RonShepard)\
**Post date:** [May 3, 2023, 6:17am UTC](https://fortran-lang.discourse.group/t/linked-list-with-pdt/5729/3 "2023-05-03T06:17:50Z")

</div>

> [@FortranFan](#):
>
> ```auto
> type :: node_type(kind, len)
> integer, kind :: kind = real32
> integer, len :: len = 1
> type(array_type(kind, len)) :: array
> type(node_type(kind, len=:)), pointer :: next => null()
> end type node_type
> 
> ```

I understand that no compiler can compile this yet, but if they could, then what exactly does it do. Can each member in the linked list have an array with a different `kind` and a different `len`, or must all the arrays have the same `kind` and `len`, or is it the same `kind` but different `len`?

Over the last 15 years or so, I have tried several times to use PDTs, and there has always been at least one compiler that I need to target that can’t compile the code. On paper, they look like a really nice feature, but in practice, I guess they were just too difficult to implement.

---

<div class="post-metadata">

**Author:** ![han190](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/han190/32/7158_2.png) [@han190](https://fortran-lang.discourse.group/u/han190)\
**Post date:** [May 3, 2023, 4:56pm UTC](https://fortran-lang.discourse.group/t/linked-list-with-pdt/5729/4 "2023-05-03T16:56:16Z")

</div>

Thanks @FortranFan and @RonShepard . But by making the length of the pointer deferred kind of disobeys my original idea that I wanted a `node_type` with fixed `len` and `kind` when I allocate the type. I can always make `values` an allocatable array and achieve this by

```fortran
type :: array_type(kind)
  integer, kind :: kind
  real(kind=kind), allocatable :: values(:)
end type array_type

type :: node_type(kind)
  integer, kind :: kind
  type(array_type(kind)) :: array
  type(node_type(kind)), pointer :: next => null()
end type node_type

```

Then I must create a suitable constructor and destructor, given that the particular type I am working with consists of several such components. At the moment, I don’t seem to have any alternative options.

---

<div class="post-metadata">

**Author:** ![AniruddhaDas](https://avatars.discourse-cdn.com/v4/letter/a/8491ac/32.png) [@AniruddhaDas](https://fortran-lang.discourse.group/u/AniruddhaDas)\
**Post date:** [May 3, 2023, 5:09pm UTC](https://fortran-lang.discourse.group/t/linked-list-with-pdt/5729/5 "2023-05-03T17:09:13Z")

</div>

Just out of curiosity I tried to compile the code by @FortranFan in godbolt with gfortran 12.2 and it compiled without any issue as can be seen [here](https://godbolt.org/).

---

<div class="post-metadata">

**Author:** ![rwmsu](https://avatars.discourse-cdn.com/v4/letter/r/48db29/32.png) [@rwmsu](https://fortran-lang.discourse.group/u/rwmsu)\
**Post date:** [May 3, 2023, 7:34pm UTC](https://fortran-lang.discourse.group/t/linked-list-with-pdt/5729/6 "2023-05-03T19:34:49Z")

</div>

A question for the compiler developers and those who have more experience with PDTs than I do. Are most of the problems compilers have with PDTs due to the len parameter (either fixed, assumed or deferred). I recently went through an exercise trying to use PDTs to develop an automatic differentiation package based on operator overloading. I was using the len parameter to set the size of the differential/derivative array. In a test problem that tried to return the derived type containing the function evaluation and its derivatives as a function result, I kept getting all sorts of weird memory allocation type errors even though I wasn’t using any kind of allocatable array. So far only the most recent version of ifx works as I expect it to. Ifort, gfortran, and nvfortran all gag with errors that appear to be related to trying to set the size of the derivative arrray with a len parameter.

Edit: the gfortran version was 11.2, ifort and nvfortran are the latest versions as of today

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [May 4, 2023, 1:52am UTC](https://fortran-lang.discourse.group/t/linked-list-with-pdt/5729/7 "2023-05-04T01:52:42Z")

</div>

> [@AniruddhaDas](#):
>
> Just out of curiosity I tried to compile the code by @FortranFan in godbolt with gfortran 12.2 and it compiled without any issue as can be seen [here](https://godbolt.org/).

+1

That’s superb news, outstanding progress by `gfortran` team, they leapfrog over everyone else.

> [@han190](#):
>
> .. But by making the length of the pointer deferred kind of disobeys my original idea that I wanted a `node_type` with fixed `len` and `kind` when I allocate the type ..

Not sure I understand your concern here. The standard semantics with deferred-length component gives you the flexibility to work with rectangular lists or jagged ones. You can review the simple word list case to see how it can work for you.

```fortran
module wordlist_m
   use, intrinsic :: iso_c_binding, only : CK => c_char
   type :: wordlist_t(k,n)
      integer, kind :: k = CK
      integer, len :: n = 1
      character(kind=k,len=n) :: s
      type(wordlist_t(k=k,n=:)), pointer :: next => null()
   end type
contains
   subroutine add_to_list( list, s )
      ! Argument list
      type(wordlist_t(k=CK,n=:)), pointer, intent(inout) :: list
      character(len=*), intent(in) :: s
      ! Local variables
      type(wordlist_t(k=CK,n=:)), pointer :: item
      ! Elided are checks, etc.
      allocate( wordlist_t(k=CK,n=len(s)) :: item )
      item%s = s
      item%next => list
      list => item
      item => null()
   end subroutine 
   subroutine print_list( list )
      ! Argument list
      type(wordlist_t(k=CK,n=:)), pointer, intent(in) :: list
      ! Local variables
      type(wordlist_t(k=CK,n=:)), pointer :: item
      integer :: i
      character(len=*), parameter :: fmtg = "(g0,t10,g0,t20,g0)"
      i = 0
      item => list
      loop_items: do
         if ( .not. associated(item) ) exit loop_items
         i = i + 1 
         if ( i == 1 ) print fmtg, "i", "Length", "item"
         print fmtg, i, len(item%s), trim( item%s )
         item => item%next 
      end do loop_items
      item => null()
   end subroutine 
end module
   use wordlist_m
   type(wordlist_t(k=CK,n=:)), pointer :: words
   words => null()
   call add_to_list( words, ck_"Hello" ) 
   call add_to_list( words, ck_"Fortran" ) 
   call add_to_list( words, ck_"Lang" )
   call add_to_list( words, ck_"Discourse" )
   call print_list( words )
   ! Elided is clean up
end

```

```auto
C:\temp>gfortran -ffree-form p.f -o p.exe

C:\temp>p.exe
i Length item
1 9 Discourse
2 4 Lang
3 7 Fortran
4 5 Hello

```

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [May 4, 2023, 2:08pm UTC](https://fortran-lang.discourse.group/t/linked-list-with-pdt/5729/8 "2023-05-04T14:08:45Z")

</div>

> [@RonShepard](#):
>
> I understand that no compiler can compile this yet, but if they could, then what exactly does it do. Can each member in the linked list have an array with a different `kind` and a different `len`, or must all the arrays have the same `kind` and `len`, or is it the same `kind` but different `len`?
> 
> Over the last 15 years or so, I have tried several times to use PDTs, and there has always been at least one compiler that I need to target that can’t compile the code. On paper, they look like a really nice feature, but in practice, I guess they were just too difficult to implement …

@RonShepard , see this [**trivial example**](https://fortran-lang.discourse.group/t/linked-list-with-pdt/5729/7) re: your question, “but if they could, then what exactly does it do.” The example works with `gfortran` but not `IFORT` or `IFX`, the latter two issue, “error #7555: Not yet implemented.”

Given the brilliant enhancements in `gfortran` of late, perhaps you will give `PDT`s another look. I agree entirely, “ **they look like a really nice feature** ”

---

<div class="post-metadata">

**Author:** ![han190](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/han190/32/7158_2.png) [@han190](https://fortran-lang.discourse.group/u/han190)\
**Post date:** [May 6, 2023, 2:22am UTC](https://fortran-lang.discourse.group/t/linked-list-with-pdt/5729/9 "2023-05-06T02:22:11Z")

</div>

Apologize for the late reply. Yes, this is exactly what I want and the example you present looks neat! But as you mentioned the intel compiler throws “Not yet implemented” errors. I am actually surprised that gfortran compiles and runs the sample code with no problems.

---

<div class="post-metadata">

**Author:** ![VladimirF](https://avatars.discourse-cdn.com/v4/letter/v/e9a140/32.png) [@VladimirF](https://fortran-lang.discourse.group/u/VladimirF)\
**Post date:** [May 10, 2023, 7:21am UTC](https://fortran-lang.discourse.group/t/linked-list-with-pdt/5729/10 "2023-05-10T07:21:30Z")

</div>

Not yet implemented? I thought ifort claimed full F2003 conformance a long time.ago.
