Open
Description
Currently, if you do:
integer :: x = 5
Fortran implicitly adds a save
attribute:
integer, save :: x = 5
This is a common gotcha (https://www.fortran90.org/src/gotchas.html#variable-initialization-using-initialization-expression). I would like this behavior to get deprecated somehow, then removed, and instead use the syntax integer :: x = 5
to mean that the variable gets initialized to 5
. Because this implicit save
behavior is used extremely rarely in modern Fortran codes.
One approach would be that when you declare a module, you do something like:
implicit save(.false.)
Right next to implicit none
(we should find a better syntax), and then this behavior is disabled. There are other approaches.
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
FortranFan commentedon Oct 23, 2019
Bravo!
See a recent thread with lots of debate at comp.lang.fortran!
Note Fortran 2018 standard introduced
WG5 document N2161 by J. Reid states, "The appearance of external requires that the names of external and dummy procedures with implicit interfaces in the scoping unit and any contained scoping units be explicitly declared to have the external attribute. The appearance of type requires the types of all data entities in the scoping unit and any contained scoping units to be explicitly declared"
The standard could extend the above abomination with
Or why not short-circuit all this once and for all with a new
Or better yet, make one BIG BRAVE LEAP forward by changing the default in all scopes to the equivalent of
implicit none (type, external, save)
so most coders do not have to worry about IMPLICIT semantics any longer!Off-topic: can anyone point to a link/reference to any current OPEN codebase in FORTRAN or modern Fortran that employs implicit typing and save (i.e., no 'implicit none' but the implied use of 'implicit integer(i-n), real(a-h,o-z)', etc.) per code design i.e., not as an outstanding bug, or a legacy carry-over that is simply awaiting code refactoring.
certik commentedon Oct 23, 2019
I think there should be a mechanism to fine grain these things (such as
implicit none (type, external, save)
). But then I would actually suggest that if you do not have anyimplicit none
present, then by default it would be yourexplicit all
. And have a compiler option that can do the old behavior, so that you can enable it for legacy code. This idea might be an uphill battle, and I might be convinced otherwise, as I do not want to break backwards compatibility. But let's at least consider it. It would be great if things "just worked" by default.aradi commentedon Oct 23, 2019
I absolutely agree! However, while deprecating
integer :: x = 5
may be done at some point, I don't think it is reasonable to allow this syntax later again, but with a different meaning as it had before (simple initialization instead of implicit save).@FortranFan
EXPLICIT ALL
is a great idea! It would not break backwards compatibility, and with one simple line you could enforce good programming practice. Whether it ever becomes default, I doubt.certik commentedon Oct 23, 2019
@aradi are you against allowing
integer :: x = 5
to mean initialization only ifimplicit none (save)
is added? That would not break backwards compatibility.aradi commentedon Oct 23, 2019
If you introduce
implicit none (save)
orexplicit all
then that would be OK! But, then, it would be not a "deprecation" of implicit save (which maybe the committee won't support anyway), but just adding a new feature to change the behaviour ofinteger :: x = 5
if explicitly asked for. (And we could hope, that compiler vendors will offer appropriate switches to enforceexplicit all
during compilation, even if it had not been specified.)certik commentedon Oct 23, 2019
@aradi I see. I am fine almost either way, as long as the natural syntax
integer :: x = 5
can eventually mean initialization, one way or another.gronki commentedon Oct 28, 2019
Well, I think the "no implicit save" behavior should be the default. It was introduced 30 years ago, which is not long for the industry standards (most codes until 2000s were still written in F77), therefore I don't believe changing the default behavior and then compiler vendors providing switches to satisfy their government customers would hurt anyone. Some people argue that "it's again Fortran spirit" but that the dark side of Fortran spirit I'd rather have nothing to do with. Dominik
jacobwilliams commentedon Nov 12, 2019
I've seen implicit save cause so many problems over the years. I've literally never seen it used on purpose, only by mistake. It's just a weird and terrible feature and needs to go.
gronki commentedon Nov 13, 2019
I will argue that the solution of using a switch to not break old code is inherently dangerous. Either the default behavior should be changed or a new syntax should be used. Here is my argumentation. (Note: this is a cross-post from another thread.)
First, let me prefice that with what I consider the absolutely basic design feature I expect Fortran to have: prevent silent errors. So ugly syntax or not, what I personally get paid for is to get good numeric results.
Consider the very root of such solutions, which probably is the familiar line
implicit none
The implicit typing feature was deemed to be unsafe and thus new, stricter rules for typing can be enabled with this switch. Please notice:
implicit none
, the functionality of the code will not change-fimplicit-none
(or equivalent) switch, the functionality of the code will not changeReading the code mid-file, you don't need to check the top of the file to see the
implicit none
. You just use the implicit typing and whether this mode is enabled or not, you will be good. Now if you start using implicit typing andimplicit none
was in effect, you will get a compiler error. All good.Now consider the proposed switch (let's stick to my favorite implicit save). For example:
If you do that, the behavior of the code will change violently in a completely non-distinguishable way. Whenever you see:
you have no idea whether
i
will be zero on each call or not. And worst of all, if you make a mistake, you will not be warned.Now when you work with different files, some of them written in 1980s, other in 2010s, you cannot just write right Fortran: you have to keep in mind which typing/saving/... rules are in place. Which is exactly the reason why implicit typing was deemed unsafe!
As much as I hate and despise this feature, I think we cannot provoke such situations. It must be clear looking at the code whether the variable is
save
or not. A couple of solutions have been proposed:integer, nosave :: i = 0
-- IMO pain to typeinteger, init :: i = 0
-- nicer to type on QWERTY keyboardinteger :: i := 0
-- or some other operator, such as=>
. The good side is that there are no keywords that clutter the code.Any solution must be nice to type. This keyword/syntax will be used a lot. So I personally would prefer some operator-based syntax because having
nosave
every 3 lines would cause a lot of clutter, especially in editors with syntax highlighting. But the worst caseinit
would be not that much pain.certik commentedon Nov 13, 2019
@gronki I agree with your overall sentiment here and many of your points. Here is the best proposal that I have so far. All of these will be allowed:
integer, init :: i = 0
integer, save :: i = 0
integer :: i = 0
The 1. will initialize the variable, the 2. will do the
save
attribute, and finally 3. will emit a compiler warning that you are using "implicit save" feature which is deprecated, and you should convert 3. to 2.aradi commentedon Nov 13, 2019
That's a reasonable proposal. However, one should keep in mind, that if combined with the possibility of variable declarations at arbitrary positions (#81), one would probably see a lot of
kind of lines, which when occuring too often I find still more verbose then it should be. (But on the other hand, I agree, it is explicit and does not break backwards compatibility.)
An other question: What would those assigments do within a
block
statement?Would any of these be allowed, and if yes, with which behavior?
66 remaining items
jme52 commentedon Jan 17, 2020
@klausler
Sorry, you are right - I don't know what I was thinking. Let me rephrase: At the moment,
Both are cases where the SAVE attribute is implicit. If an
implicit none(save)
statement option is introduced, I think it will be confusing if it only affects variables that obtain their implicit SAVE via explicit initialisation.jme52 commentedon Jan 17, 2020
I think we agree on
implicit none(save)
,init
andsave
within a subprogram - please do check:(modulus the existance of the bare
init
statement, but I think the real problems are others, see my next post).jme52 commentedon Jan 17, 2020
What we may not agree on yet is:
implicit none(save)
on variables (initialised or not) declared in a main program, module or submodule. Do we want them to have the same rules subprograms will have, or different ones?implicit none(save)
: currently otherimplicit none
s affect contained subprograms or BLOCK constructs. Do we want the same for this thirdimplicit none
spec or not?save
andinit
statements: currently asave
statement only affects its scoping unit (see definition in 3.123: "BLOCK construct, derived-type definition, interface body, program unit, or subprogram, excluding all nested scoping units in it"), i.e., is not inherited. Do we want to keep this, and extend this rule to theinit
statement?jme52 commentedon Jan 17, 2020
My current views on them:
-> 2) Yes, same inheritance rules for all spec's of
implicit none
, for simplicity of the rules and of the code.-> 3) Yes,
save
andinit
statements should only affect the current scoping unit, there is no need to inherit them - they should be tuned in every contained subprogram or block.-> 1) Yes, I want the same rules for program units and subprograms. When using
implicit none(save)
in the program unit, we can recover the old program unit-wide implied save by adding a spec-lesssave
there. Sincesave
is not inherited by contained subprograms, this won't affect them.Example:
aradi commentedon Jan 17, 2020
@jme52 I agree on your view for 2).
As for 1): What meaning do you suggest then for a module variable in presence of
implicit none(save)
but in absence of aninit
attribute:Would this behave like a global (saved) variable (as it is now)? Or would it when a module goes out of scope (whatever that means) loose its value? I think, from your argumentation latter would follow, but I definitely would prefer the former.
As on 3): I would argue against having an
init
keyword at all, I'd propose to have it only in the attribute form. If we allow for its keyword version, we again come back to the original problem: A line somewhere in the code changes the meaning of other lines somewhere else, as in:I think, such a scenario would degrade code readability a lot! Furthermore it would be basically equivalent the original proposal to let
implicit none(save)
turn all assignments at a declaration into a non-saved assignment, but doing it more complicated (with two keywords instead of one). There was no consensus on that (although I still favor it...), this is why theinit
attribute was suggested as a compromise.certik commentedon Jan 17, 2020
What does
save
mean for module level (or program level) global variables? The Fortran module never goes "out of scope". If we equatesave
for Fortran withstatic
for C, then C allows to have global variables that are non-static. But in Fortran's semantic, that would make no sense. The standard talks aboutsave
in section 8.5.16, and the definition ofsave
is thatIf this is the definition, then it makes no sense for module variables or the main program because there is no
end
orreturn
.What exactly does this mean:
because they didn't define what
save
means in this case...Unless somebody can clarify that, I will continue assuming that module level and program variables do not have
save
attribute, because it makes no sense. Soimplicit none(save)
(obviously) does not apply to them either.certik commentedon Jan 17, 2020
What does it mean for a variable in a module to have a
save
attribute? I know you can write code like this:where
x
has explicitsave
andy
has impliedsave
attributes. But I do not understand what that (implied)save
means in this case. I quoted the definition above, and that definition does not seem to apply for this case.certik commentedon Jan 17, 2020
@klausler thanks a lot for the explanation. I didn't realize that the module variable could have been destroyed between subroutine calls if it didn't have the implied
save
attribute. You are right that it make sense that common blocks could override each other to save memory in the early days of computing. I thinkEQUIVALENCE
was used for the same reason.milancurcic commentedon Jan 17, 2020
This is not true. All variables declared in a module (initialized or not) have the
save
attribute automatically and implicitly and I think that's what is meant by this:For example, if you declare this in a module:
and use it from other modules, procedures, or a main program, it's value is preserved between uses. It's a true global.
But this is also why the implicit save rule doesn't matter for modules and programs:
This is why the caveat of implicit save is irrelevant for modules and programs.
certik commentedon Jan 17, 2020
@milancurcic we are in agreement (you might have misunderstood my comment). @klausler was explaining the history behind this, that in a common block, if you didn't have the
save
attribute, the contents could get destroyed. And a module is successor of a common block, and from the beginning they made all variables implicitlysave
d, so that their contents cannot get destroyed. So the reason they have an implicitsave
is so that they do not behave like variables in a common block. That's what I meant by:milancurcic commentedon Jan 17, 2020
Ah, okay, I missed that piece, great!