j3-fortran / fortran_proposals

Proposals for the Fortran Standard Committee
173 stars 14 forks source link

Feature proposal: open to derive an inextensible derived type #37

Open FortranFan opened 4 years ago

FortranFan commented 4 years ago

I submitted this paper 19-186 for the joint WG5/J3 meeting in Tokyo (August 5 - 9, 2019) but the paper was ignored on account of the worklist for Fortran 202X being closed. I don't know how to get it considered now for Fortran 202Y, perhaps various "thumbs up" by readers here might help push its case?

Introduction

18-007r1 states in section 7.5.7.1 Extensible, extended, and abstract types, "A derived type, other than the type C_PTR or C_FUNPTR from the intrinsic module ISO_C_BINDING, that 7 does not have the BIND attribute or the SEQUENCE attribute is an extensible type." An extension type can thus be derived from any other user derived type which does not have the BIND or the SEQUENCE attributes.

Consider a user derived type in Fortran that does not have the BIND or the SEQUENCE attributes and which is employed toward calculational needs involving data structures of some complexity in scientific and technical computing, particulary in industry: the allowance per current standard to extend said type is a matter of great concern in terms of security and predictability of computer operations and results, especially to senior software design architects, computational technology leaders, and budget and business managers.

The facility in current Fortran standard to be able to extend all derived types except as stated above makes it feasible, at least conceptually, to manipulate the data and states of objects of such types and to corrupt or otherwise misuse them via type extension, either intentionally or unknowingly. It then becomes difficult, if not impossible, to develop technical software involving specialized derived types because it leaves open the possibility of violation of a technical/business understanding across or within teams not to override some type behavior or functionality via type inheritance.

This situation hinders the adoption of Fortran in new engineering and/or scientific software projects where the design paradigm of object-orientation is important but where the needs of the projects also include the requirement to encapsulate the business/technical logic using data structures which are 'sealed' so that objects of such structures can then be consumed across the program or libraries without concern of easy alteration.

In addition to the above-stated use case of added security and reliability of a 'sealed' derived type, it is also expected that a few or all of the processor implementations will be able to provide some performance benefit with the use of bound procedures with such 'sealed' types. This is on account of some or all processors succeeding in providing more efficient code via nonpolymorphic descriptors of the passed-object dummy argument utilized in procedure calls.

certik commented 4 years ago

I don't feel strongly about this particular proposal. But I feel strongly about the fact that the committee essentially ignored your proposal on procedural grounds, instead of providing feedback. They did the same to me with the 19-246 proposal that I submitted as part of #1 at the last meeting. It effectively got ignored. All I wanted is some general feedback "yes, submit a full proposal" or "no, not worth it".

As a solution, I think we need the committee to consider all proposals not just for 202x, but for 202y also, all the time, so that we can push all proposals forward (or not if they get rejected), but what we do not want is to wait the next several years until to even consider 202y proposals. So I created #36 to address this exact issue.

FortranFan commented 4 years ago

I don't feel strongly about this particular proposal. ..

To hope to make readers care about this, please note

So why can't the Fortran standard extend the same courtesy to user derived types that it allows itself when it comes to intrinsic derived types? It's a basic need in object-oriented (OO) inheritance scheme after all that so many OO languages offer such support. Avoidance of "deep inheritance hierarchies" is increasingly a compelling design consideration and involves a strong business need when it comes to encapsulation, development, and utilization of knowledge frameworks in any domain. Many now seek to design 'classes' and use them but without the travails of inheritance.

It'll really help those among my acquaintance develop code with better 'insurance' toward program vulnerabilities if such a low-cost facility were added to Fortran - the idea of an inextensible type already exists in the standard, the wiring is mostly there, and the feature mainly requires only EDITS. In addition, such a facility can really free up compiler implementations to optimize instructions on data components of derived types operated via type-bound procedures (TBPs) by no longer having to be mindful of possible polymorphic nature of the passed dummy object. One just has to look at some commercial implementations out there (clue: xxxxx inside) to see how guarded and conservative they are at the moment with TBPs when it comes to optimization.

There are other aspects as well which become cleaner with inextensible derived types e.g., finalization because Fortran, similar to C++, does not allow 'virtual destructirs' (the dummy argument is TYPE(..) with INTENT(INOUT)( that then doesn't provide any kind of a 'guard rail' when it comes to enforcing any finalizer discipline by extension types.

A question is how much of a benefits case does one have to make for a reasonable group of 'modern' Fortranners to extend (pun intended!) support for this proposal!?

certik commented 4 years ago

@FortranFan My apologies if my sentence sounded dismissive. When I said to not feel strongly, I meant that in my list of priorities, there are other issues that are higher priority that I want to concentrate on personally, such as #1, #36, #26, #4 and the general success of this repository and figuring out a way for the committee to consider our proposals. But that's why we have a community, and hopefully other people have different priorities and so we can improve Fortran as a language together.

Regarding your proposal, thanks for posting the links to other languages. I think that significantly strengthened your argument. Python seems to have it proposed. C++ has it (https://en.cppreference.com/w/cpp/language/final). So I think your proposal should be improved with these links. Also, what alternative syntax keywords can be used? I don't know if sealed is the best. What are some other options?

cmacmackin commented 4 years ago

A keyword in line with Fortran's general verbosity would be nonextensible.

On Wed, 23 Oct 2019, 08:31 Ondřej Čertík, notifications@github.com wrote:

@FortranFan https://github.com/FortranFan My apologies if my sentence sounded dismissive. When I said to not feel strongly, I meant that in my list of priorities, there are other issues that are higher priority that I want to concentrate on personally, such as #1 https://github.com/j3-fortran/fortran_proposals/issues/1, #36 https://github.com/j3-fortran/fortran_proposals/issues/36, #26 https://github.com/j3-fortran/fortran_proposals/issues/26, #4 https://github.com/j3-fortran/fortran_proposals/issues/4 and the general success of this repository and figuring out a way for the committee to consider our proposals. But that's why we have a community, and hopefully other people have different priorities and so we can improve Fortran as a language together.

Regarding your proposal, thanks for posting the links to other languages. I think that significantly strengthened your argument. Python seems to have it proposed. C++ has it (https://en.cppreference.com/w/cpp/language/final). So I think your proposal should be improved with these links. Also, what alternative syntax keywords can be used? I don't know if sealed is the best. What are some other options?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/j3-fortran/fortran_proposals/issues/37?email_source=notifications&email_token=AB6ESPMKEDMOGDUQ5QKCYRDQP74VTA5CNFSM4JDUHGY2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECAMMDY#issuecomment-545310223, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB6ESPMS4RJ5CYKDS3G2SGDQP74VTANCNFSM4JDUHGYQ .

FortranFan commented 4 years ago

A keyword in line with Fortran's general verbosity would be nonextensible.

The proposal does try to leave the keyword up to the committee!

Now, with favor to English dictionary, INEXTENSIBLE makes more sense to me.

Or per the ugliness of many of the terms in the Fortran standard, NON_OVERRIDABLE can be reapplied here!!? c.f. ISO IEC standard for C++ standard with 'final' for both classes (derived types in Fortran parlance) as well as functions (TBPs in Fortran).

Or to add to confusion with further terminology in the language but in a consistent manner in terms of hyphenation, NON_EXTENSIBLE??!

certik commented 4 years ago

@cmacmackin, @FortranFan let's discuss the options here, that's what github is for.

Can final be used?

cmacmackin commented 4 years ago

That keyword already has a meaning in Fortran (destructor). I feel like it would be confusing if it were given two meanings.

On 23/10/2019 19:43, Ondřej Čertík wrote:

@cmacmackin https://github.com/cmacmackin, @FortranFan https://github.com/FortranFan let's discuss the options here, that's what github is for.

Can |final| be used?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/j3-fortran/fortran_proposals/issues/37?email_source=notifications&email_token=AB6ESPOA6H3EYCZ3CMLCNV3QQCLOBA5CNFSM4JDUHGY2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECCO25Y#issuecomment-545582455, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB6ESPITW2CDOP2JL4IPBWTQQCLOBANCNFSM4JDUHGYQ.

-- Chris MacMackin cmacmackin.github.io http://cmacmackin.github.io

certik commented 4 years ago

That keyword already has a meaning in Fortran (destructor). I feel like it would be confusing if it were given two meanings.

I see, I forgot about that. (It gave away that I actually never use destructors...)

plevold commented 1 year ago

I like this proposal a lot and I think sealed is a good keyword. I think it's also worth considering allowing types inside the same module to extend a sealed type. This would also be similar to sealed classes in Kotlin and somewhat comparable to sealed classes in Java. Note that Java has both sealed and final classes though, but I believe that is mainly due to historical reasons, Kotlin's version is way less complicated and I believe it should be sufficient in Fortran.

For example, I think this should be legal:

module sealed_mod
    implicit none

    type, abstract, sealed :: base_t
    end type

    type, extends(base_t) :: a_t
    end type

    type, extends(base_t) :: b_t
    end type
end module

but this should be illegal:

module other_mod
    use sealed_mod, only: base_t, a_t
    implicit none

    type, extends(base_t) :: c_t
    end type

    type, extends(a_t) :: d_t
    end type
end module

If the proposal is expanded with this capability then it would finally be possible to implement proper sum types in Fortran instead of the highly limited enum and enumerator functionalities. It would also make it possible to add a select type statement which the compiler could check for exhaustiveness. For example:

use sealed_mod, only: base_t, a_t

class(base_t), allocatable :: b
select type(b)
    type is (a_t)
         ! ...
end select

could be required to give an error "select statement must be exhaustive, missing b_t", while

use sealed_mod, only: base_t, a_t, b_t

class(base_t), allocatable :: b
select type(b)
    type is (a_t)
         ! ...
    type is (b_t)
         ! ...
end select

should be accepted.

perazz commented 2 months ago

Fortran doesn't have very flexible object-oriented patterns. In that, I believe introducing non-extensible classes would probably pose a quite significant burden on the initiative and many edits to the standard.

On the other hand, if we look at what advantage is being sought for by this facility, I believe it is the fact that non-polymorphic type-bound procedures can be resolved at compile time instead of at run time. This is very important as speed and optimization are Fortran's major selling point. In my experience, this can have a quite huge impact (in one of my codes, I could speed up the overall runtime of an OO interpolation library by ~25% just by replacing TBPs with direct non-polymorphic function calls).

One very easy and straightforward extension to the language, would be to allow the non_overridable keyword to be applied at the top of the TBP block, defining a default behavior for all TBPs. For example:

type :: my_fast_type
   public ! applies to all data members
   integer :: i          ! -> default: public
   integer, private :: j ! -> non-default: private
   contains
   non_overridable ! applies to all TBPs
   procedure :: proc1              ! default -> non_overridable
   procedure, overridable :: proc2 ! non-default -> overridable
end type my_fast_type

As the example shows, a new overridable keyword should then be defined to achieve the opposite behavior.

Advantages:

klausler commented 2 months ago

One related thing that you should be able to do today is to define your TBPs as being private to their module. This prevents their usage within the module from being overridden by bindings in extended derived types outside the module, and allows the same compile-time resolution. Obviously the NON_OVERRIDABLE attribute is more appropriate for derived types intended for use by module clients, but a private binding might be useful for others.

(Reference: F'2023 7.5.5 paragraph 9; example: https://github.com/klausler/fortran-wringer-tests/blob/main/override.f90; caveat, 3 out of 7 compilers tested mishandle this case.)

FortranFan commented 2 months ago

I believe introducing non-extensible classes would probably pose a quite significant burden on the initiative and many edits to the standard.

This is an insufficiently informed and an inaccurate presumption.

FortranFan commented 2 months ago

I think it's also worth considering allowing types inside the same module to extend a sealed type.

Now this is a needless complication, if there were one. Once made inextensible, a derived type has no business to be extended.

Anyways, the original proposal died on the vine thanks to a few highly influential ones on the committee who like to cut Fortran's nose to spite its face. Now at least until the 2030s, the proposal is of no relevance because the "office is closed" on any requests.

Needless complications like this though will ensure no resurrection, sadly.