Implicit typing and backwards compatibility

Note 7/13/2022: I split this thread from Which five features should Fortran 202Y implement?. Unfortunately the first comment that started the discussion was deleted, but here is the rest of the discussion starting from the second comment:


@kargl you are correct that these behaviors are well documented (including in the standard) and well-known to experienced practitioners of Fortran, but when I teach Fortran to people who don’t know it, these are the very first issues that every single beginner encounters, and if there is a way to not having to deal with these things for beginners, or at least not right away, I think it would be a good thing.

1 Like

Yeah, I thought that “lack of documentation” comment was weird too, particularly regarding typed constants and default implicit mapping.

I mostly agree with the sentiment regarding implicit SAVE. That was a mistake to add to the language, many people realized it was a mistake at the time, yet it got added to the language anyway. Now that it is added however, it would probably do more harm than good to fix it. However, one thing that would be good is to encourage compilers to detect when implicit save is triggered, and print a warning to the programmer so that he can fix it immediately (either by adding the SAVE statement to eliminate the warning, or by moving the initialization to an executable statement). That way we would have the practical benefits of removing it from the language without actually breaking the 15+ years of backward compatibility.

Regarding the kind-constant issue, has anyone proposed a “fix” for this problem that doesn’t break backward compatibility with 60+ years of code? I personally don’t think this needs to be fixed, I like things the way they are (with the programmer having complete control over the kinds in an expression), so this is a nonproblem for me.

The same question holds also for the implicit mapping issue. Has anyone proposed a “fix” for this nonproblem that doesn’t break backward compatibility with 60+ years of code? Would those who advocate for a change be satisfied with a compiler warning if any default implicitly typed entity occurs? Another thing that might help this process is if there were standard tools that would automatically insert the appropriate declarations for any such implicitly typed entities.

1 Like

To be fair, the standard is a compiler developer’s doc, not a user’s doc. Indeed, there are books that are user-oriented and cover this. :slight_smile:

3 Likes

I agree we should not fix a few Fortran’s warts while breaking compatibility. I think there is a way to improve things without breaking compatibility.

3 Likes

There is no convincing evidence to back up such an assertion that it will “do more harm than good” to remove implicit save. On the other hand, there is a lot to indication the implicit save semantics is a nasty surprise for many a coder who did not seek such behavior at all.

An overwhelming majority of coders, arguably >99.99%, have sought to overcome the implicit mapping scheme in the standard at least since the FORTRAN MIL-STD 1753 document was put out way back in 1978 ; most commonly it has been via implicit none.

Under the circumstances, it is high time the entirely nonsensical argument of backward compatibility is put to rest and the language moves forward on this count. Particularly when one considers the long time window before any change can come to fruition: it will be the end of this decade before the revised standard toward this can even be published.

The standard loses its meaning if fails to standardize what is de facto a standard practice.

4 Likes

The original argument in favor of implicit save was that there were many lazy programmers who expected save semantics without specifying the previously required SAVE attribute. So implicit save made those previously nonconforming codes conformant to the new semantics. That was a poor argument to support something as profound as implicit save semantics, and it complicated the process of writing parallel and recursive subprograms, but that argument won the day and here we are.

This is basically the same argument that is being used now to try to make INTEGER*n and REAL*n standard. There are lazy programmers with nonconforming code, and they want the warning statements to disappear. It isn’t clear if it should be equivalent to REAL(KIND=n) or to DOUBLE PRECISION, just so it compiles without giving warnings, that is all that they want. It doesn’t matter that it will make it more difficult for compiler writers, or more confusing to both old and new fortran programmers, or arguably that it is contrary to the fortran KIND system that everyone should be moving toward now, they just want their warnings to go away without investing any of their own effort to fix their code. Prior to f90, I wrote a lot of code with REAL*n declarations, so I’m as guilty as anyone, but for the last 30 years there has been a better way.

I have no idea where that 99.99% number comes from. Possibly it is the same place that the “99.99% of all statistics are made up on the spot” statement comes from. In any case, some programmers don’t like to write declarations of their variables, so they like implicit declarations. That’s just a fact. Many popular languages don’t even have variable declarations. There is a 60+ year convention that has supported that programming style. I’m not in that set, I prefer explicit declarations, but I’m just stating the fact.

I looked at the arguments in the previous discussion about this that you linked previously. Many of those posts suggest eliminating the IMPLICIT statement altogether and forcing every programmer to explicitly declare all variables. I don’t think that position will sway many people, but if it did, then I’m pretty sure that it would be the death of the language. People would continue doing what they have been doing with old compilers, until eventually when new compilers stop allowing them to do that, and then they will just quit using fortran.

As for the MIL-STD standard, not all compilers supported that, so I think that appeal to authority falls a little short. Although IMPLICIT NONE was common, I’m not even sure that a majority of compilers supported the rest of the standard. If my memory is right, g77 did not support the bit operators, it supported the f2c operators instead. I never used the labeled ENDDO statements at all. I’m guessing that only a small minority of programmers used those statements.

I think backward compatibility is important in the language. It is frustrating when you have a working program that suddenly stops working due to some software update. That has happened to me with both perl and python scripts. I’m not fluent in those languages, so it is always a hassle to figure out exactly what broke. That seldom happens with conforming fortran codes. If it did happen often, then I think the fortran language would just die off. Your opinion is different, and that is alright, but I think you are simply wrong on this point.

As far as “standardize what is de facto a standard practice,” the standard practice is to either use implicit mappings or to use implicit none. Only a small fraction of fortran programmers use compiler flags to change the fortran convention and to force implicit none behavior without the declaration. I don’t know the actual statistics, but I’m sure it is somewhere in the 99.99% range.

Here is an odd thing about IMPLCIT NONE. If you have a code that works correctly with the declaration, or with the compiler option for that matter, then you can remove the statement and the code will continue to work exactly as it did before. The declaration is more for the program development stage, to aid the programmer, than it is to, for example, affect the semantics of the compilation step. Its purpose, as a practical matter, is to help the programmer to identify any undeclared variables. Once those variables have been declared, then the IMPLCIT NONE statement is redundant, or unnecessary, or superfluous. This is unlike the use of implicit mappings with undeclared variables. In this latter case, the implicit statement, or the default implicit mapping, is an essential part of the semantics that is required in order to compile the code correctly.

I don’t agree on removing implicit save.
It is different thing compared to removing the implicit typing that I fully sustain. Removing implicit typing means that old codes stop compiling and one have to explicitly add declarations. But it didn’t make old code behave wrongly without any issue in compilation.

Removing implicit save means that perfectly behaving codes will start not to work correctly, even though they will compile as before and be conformant as before.

2 Likes

For all of those who argue for keeping implicit typing and implicit save argueing it will break code and force people to modify existing code, I need to remind you that no compiler vendor is going to do that. You might be forced to set some compiler flags/options to get the old behavior but I doubt you will be forced to rewrite code. Basically, all some of us are asking is a change in policy that favors newer programming practices and constructs over things that have been obsolete for 20 or 30 years.

Just my 2 cents

5 Likes

As mentioned by others before, compiler vendors could provide specific flags for legacy code to maintain “implicit save”.

A counter-argument to give higher priority to the removal of “implicit save” over the default “implicit none” is that “here and now” we can already use compiler flags to turn on “implicit none” with (all?) compilers whereas I am not aware of any compiler flag to remove “implicit save”. Thus, the standard committee might help provide such feature.

2 Likes

Would compiler vendors even change the default, or would you have to add a flag like -std=f202Y to get the new behaviour? Some compilers (maybe all?) don’t currently have strict Fortran 2018 semantics enabled by default.

1 Like

That all depends on which way the implicit typing is removed. If IMPLICIT statements are removed from the language, then most legacy codes will no longer compile. Explicit declarations for every varible will need to be added, and all existing IMPLICIT statements will need to be removed. Presumably, there will be tools developed to automate that task, but it will require some effort. I think the backward compatibility argument wins out here, that would be too much of a change for little to no gain in functionality.

Removing implicit save means that perfectly behaving codes will start not to work correctly, even though they will compile as before and be conformant as before.

This again depends on the details of how it is changed. If it is made illegal to initialize an entity without the SAVE attribute, then the compiler will tell the programmer what needs to be changed. There would be no possibility to compile the code incorrectly and silently continue. If it is simply a warning, or if there are compiler options that override the new standard behavior (which I think would be likely), then yes, there could be code compiled incorrectly.

This idea of requiring the SAVE attribute is, in my opinion, what should have been done in the first place. The previously nonconforming code needed to be changed, and that would have accomplished it. Instead, the language was changed to make that code conformant, bringing with it the overall confusion over this issue and the problems with parallel and recursive situations.

1 Like

As others said, I think we all agree that old codes must keep compiling (one way or the other), without requiring manual modifications to the code. So let’s not use the argument of “old codebase must be changed to continue working”, since none of the people in this thread above have proposed anything like that.

2 Likes

This is exactly the kind of nonconforming f77 code that resulted in the implicit SAVE being added to the language 15 years ago. Instead of requiring the programmers to change these codes, which is what I think should have happened, the standard was changed to make these codes conformant. This is why we are in this confusing and frustrating situation now.

As for the removal of implicit typing, there has so far been no proposals that will change the default in future codes while being backward compatible with legacy codes. Certainly if the IMPLICIT statement is removed, then legacy codes will need to be modified, extensively I would say. Some people participating in these discussions on this issue do advocate that, so it is not something that is just made up for the sake of argument.

The other more moderate proposal is to change the past (60+ years) and current default from

IMPLICIT REAL(A-H,O-Z), INTEGER(I-N)

to

IMPLICIT NONE

We can anticipate that even that modest compromise will cause problems. Experienced programmers will know how to add that first line to the legacy codes, and I would say that that is even not a high barrier for these programmers. But the problem will be the inexperienced programmers who apparently do not understand data types and kinds. When they download some legacy fortran code from netlib, or from their professor in a class, or wherever, and they get errors due to the change in default implicit types, how are they supposed to know how to insert that line and to make that change? And if they do understand data types, then isn’t it better for them to make the change in the code once than it is to add compiler options (or whatever other alternative is available) from now to eternity?

This is why I think this IMPLICIT issue is a nonproblem. It is probably better for programmers, old and new alike, to work with the current default than it is to change things and then confront a whole new level of confusion due to the lack of backward compatibility.

4 Likes

I see: I think your main argument is that if the standard makes implicit none the default, then older codes that were standard conforming (that were using implicit typing) will now not be standard conforming; consequently the standard is breaking compatibility.

Isn’t that the same as with any deleted and obsolescent feature? See the “Annex B” in the F2018 (“Deleted and obsolescent features”), there are tons of features that used to be standard conforming, but now are not. Say the “Fixed form source”, which is “obsolescent” (=“A future revision of this document might delete an obsolescent feature if its use has become insignificant.”). But literally right now I am implementing a proper dedicated fixed-form parser in LFortran, because old codes must compile without modification (but possibly with extra command line flags). In the same way, implicit typing is on our TODO list, no matter whether it gets removed from the standard or not.

So in my mind you can indeed have it both ways. I still have to implement it in LFortran no matter what (so that you do not have to modify old codes). But I think the standard should make it obsolescent and eventually remove.

5 Likes

@certik,

Please note again it would be good to understand and clarify making implicit none the default need not and should not mean deletion of implicit typing.

Implicit typing that is achieved by explicit IMPLICIT statements need not be and should not be affected with the proposal to make implicit none the default.

It will be good if the scope here is converged is to remove the implicit mapping semantics only. The implicit mapping is what declares undeclared variables whose names with letters begin with I, J, K, L, M, N to be default integer type and any other undeclared variables as of the default real type. Removing this implicit mapping scheme is the route, I believe, to make implicit none the default. My request is to coalesce around such a limited scope.

I personally think it is rather confusing to a certain set of readers and also detrimental to the discourse to bring in the phrase delete/eliminate “implicit typing”.

2 Likes

On evidence, one can concede the evolution of the Fortran language has erred more on the side of pragmatic progress rather than intransigence on the basis of an extreme ideological position on backward compatibility. And that is a good thing.

I would like to appeal to the same sentiment moving forward and once and for all gift the future generation of programmers of Fortran with an evolved and truly modern Fortran language feature that has implicit none as the default in all program units and interface bodies.

Consider the following conformant code per current standard:

   character(len=:), allocatable :: s
   allocate( character(len=10) :: s )
   write( s, fmt="(a)" ) "x"
   print *, "len(s) = ", len(s)
end

and the program behavior according to a couple of compilers:

C:\temp>gfortran p.f90 -o p.exe

C:\temp>p.exe
 len(s) =           10
C:\temp>ifort /standard-semantics p.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.6.0 Build 20220226_000000
Copyright (C) 1985-2022 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.30.30706.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:p.exe
-subsystem:console
p.obj

C:\temp>p.exe
 len(s) =  10

Now note starting Fortran 202X, the program behavior according to conforming compiler will change, the program output shall be len(s) = 1.

This is a breaking change, I know at least one program in production use by the team I work with that will break as a result of Fortran 202X. The change comes into play with the use of deferred-length allocatable objects of character type in certain instructions, internal IO being one of them but there are other situations also.

This was pointed out to the Fortran committee, but it made no difference to the decision making: the feeling was any programs that might break can go pound sand - they can fix themselves if they are to remain in Fortran, but they shall not stand in the way of the collective decision-making by the committee.

Let the same sentiment and line of thinking come to apply with implicit none, let it be the default starting Fortran 202Y.

I think this is what the Fortran community should clamor and call for.

The community should realize the drop-by-drop waste of time and resources by being forced to include implicit none in every module, program, interface body, etc. and say enough is enough.

1 Like

No, it isn’t the same for all deleted features. I have codes with alternate returns, computed goto, and assigned goto. Those are all (I think) deleted features. Yet they still compile correctly because they do not conflict with any of the new features, and compilers have continued to support them as extensions. There are new features that replace these older ones, or straightforward work-arounds to replace them, and when compilers stop working with them, I will take the time to replace those code sections.

But changing the default implicit typing does conflict with old code. Examples have been given in this thread of valid legacy code that will become invalid.

1 Like

I agree with your comments, this does seem like a mess. Is there any way to stop the 202X reallocation from occurring? Will

write( s(1:10), fmt="(a)" ) "x"

stop it? What if s is a TARGET of a pointer? What happens to the pointer after the write statement?

I also would like to extend the language regarding allocatable strings and arrays. But my suggestion is to allocate the entity during the read statement only if it was initially unallocated. If it was previously allocated, then it should behave the same as always. Thus my suggestion is backward compatible, unlike the above situation which breaks backward compatibility.

1 Like

Good point that even if some features are deleted, newer features do not conflict with them, although as pointed out by @FortranFan, there are exceptions.

I think this is the key. Compilers, including new compilers under development, will support these older (deleted) features, as long as they are in use.

@RonShepard do you see an issue with using a compiler option to enable these older features, if a newer feature is conflicting with them? For example in GFortran, I can use an option like -fimplicit-none for modern code. Why not turn it around, and make -fimplicit-none the default, so no option is required for modern code, and one has to use -fno-implicit-none for old code?

1 Like