Pure procedure and intent(out) polymorphic pointer argument

Can you give an example of how a type would be lost? I absolutely do not understand that reasoning. How a type would be “lost” (it would not be) and invalidate other variables (it would not?)

The more we discuss the more I think I am right.

Funnily enough, gfortran 13 does not say a word about explicit deallocation, which should be forbidden (the finalizer can be invoked).

module bugmod

   implicit none

   type value_t
   end type

contains

   pure subroutine reset_ptr(ptr)
      class(value_t), intent(inout), pointer :: ptr

      nullify(ptr)
   end subroutine

   pure subroutine dealloc_ptr(ptr)
      class(value_t), intent(inout), pointer :: ptr
      ! hey, here we might call an impure finalizer
      ! but no word from gfortran
      deallocate(ptr)
   end subroutine

end module

I was speaking of the dynamic type.

class(animal_t), pointer :: john, clone
allocate(spider_t :: john)
clone => john

call fetch_ptr(john) ! john becomes undefined on entry
                     ! the target and hence the dynamic type are lost
                     ! clone changes too

If these were integers, everything would be fine (although it can potentially cause a memory leak, break associations, and is discouraged stylistically).

I’m just trying to play devil’s advocate here. Correct me if I’m wrong, but you are suggesting an amendment (in bold):

C1587 An INTENT (OUT) dummy argument of a pure procedure that is not a pointer, shall not be polymorphic or have a polymorphic allocatable ultimate component.

This code is invalid, but gfortran doesn’t catch it (yet). This is a quality of implementation issue. As written in the reply by @themos,

C15106 A statement that might result in the deallocation of a polymorphic entity is not permitted in a pure procedure.

Other compilers catch it.

ifx 2024.0:

/app/example.f90(14): error #5585: A statement that might result in the deallocation of a polymorphic entity is not permitted in a pure procedure.
      deallocate(ptr)
------^

flang:

error: Semantic errors in /app/example.f90
/app/example.f90:14:18: error: Object in DEALLOCATE statement is not deallocatable
        deallocate(ptr)
                   ^^^
/app/example.f90:14:18: because: 'ptr' is polymorphic in a pure subprogram
        deallocate(ptr)

I suggest reading F08/0033 in the N2121 document, keeping in mind the POINTER attribute added, and noting the exact point made there that you disagree with.

That document says:

Note that finalization can also occur via DEALLOCATE of an ALLOCATABLE
or POINTER dummy argument that is not INTENT(IN).

Is this because a processor could choose to use garbage collection?

When the pointer became undefined, if the reference count were to drop to zero, the garbage collector would trigger a finalization (but this finalization can be impure and is undecidable at compile-time).

Somewhere along reading the Interp discussion, I thought that garbage collection (or some unspecified finite resource management) was being considered, yes, but I can’t go back and replay everything right now.

I think there is some misunderstanding of what intent(out) of a pointer can do.

Yes,

Yes, the target and dynamic type of john

No, not at all. clone is completely unaffected. It still points at an anonymous target with dynamic type spider_t.

I was struggling to think of the reason that the pointer case could invoke a final subroutine, but I think you hit on it.

I got confused here. The association is not between pointers, but between pointers and targets. Thanks for the correction.

Is there possibility of garbage collection in Fortran? Now that would be quite shocking! But something feels not right there: I do not recollect any rules for possible lifetime of a garbage-collected object given in the standard. And there is no possible way to indicate which objects are managed by Fortran runtime: after all, we might share memory with C code, and having pointers (possibly) garbage corrected would be very C non-interoperable.

NAG has it: NAG Fortran Compiler Release 7.1

Maybe Silverfrost Fortran has it too, because it targets the .NET platform (.NET garbage collection - .NET | Microsoft Learn).

There exist several garbage collectors for C,

C++ also had garbage collector support, but it has been kicked out in C++23.

That is something that I completely did not expect! :exploding_head: In this case yes, the “hole” seems to be purposedly left to allow garbage collection. It would not even cross my mind!

Thank you, definetely learned something new today!

1 Like

I just checked J3/24-007, 7.5.6.3,

7.5.6.3 When finalization occurs

[…]

When a pointer is deallocated its target is finalized. When an allocatable entity is deallocated, it is finalizedunless it is the variable in an intrinsic assignment statement. If an error condition occurs during deallocation, it is processor dependent whether finalization occurs

[…]

When a procedure is invoked, a nonpointer, nonallocatable, INTENT (OUT) dummy argument of that procedure is finalized before it becomes undefined. The finalization caused by INTENT (OUT) is considered to occur within the invoked procedure; so for elemental procedures, an INTENT (OUT) argument will be finalized only if a scalar or elemental final subroutine is available, regardless of the rank of the actual argument.

If an object is allocated via pointer allocation and later becomes unreachable due to all pointers associated with that object having their pointer association status changed, it is processor dependent whether it is finalized. If it is finalized, it is processor dependent as to when the final subroutines are called.

According to the last paragraph, the pointer intent(out) case can potentially trigger finalization of a derived type.

1 Like

With that in mind everything changes. Thank you!

@ivanpribec Fortran allows compilers to do reference counting or garbage collection for pointers? I didn’t know that!

I guess I know what next feature will be coming to LFortran :slight_smile:

1 Like

Should be possible to do with WASM: A new way to bring garbage collected programming languages efficiently to WebAssembly · V8

1 Like

We already have this in our TODO list after beta, but I just created a dedicated issue: Reference counted pointers · Issue #5382 · lfortran/lfortran · GitHub.

Here are past relevant discussions and proposals:

But I haven’t seen mentioned there that possibly the existing pointers in Fortran could be implemented like that. Definitely worth investigating!

1 Like

The Standard does not even mention “memory” in normative text (“Interoperability with C” Clause exempted), not even in the part about the SYNC MEMORY statement.

“Garbage” is a by-product of a certain implementation of Fortran semantics, so of course “garbage collection” is not specified by Fortran, in the same way that it does not specify operating temperature range of the hardware.

1 Like