Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add revised protected components & types proposal #182

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

zjibben
Copy link
Member

@zjibben zjibben commented Sep 21, 2020

Here is a revised version of the protected components proposal (#156). The next committee meeting is 3 weeks away (Oct 12) so I wanted to make sure we had time to discuss beforehand.

To recap, last time it became clear there were competing interests. I and others here and at LANL wanted an access specifier roughly in between private and public. Other committee members want something far more restrictive, something really unlike an access specifier and more analogous to the existing protected attribute for module data. This would act to really protect the data from virtually any modifications outside the module where the type was defined, and was far too restrictive to be useful for those of us who wanted an access specifier.

The best way forward seemed to be to tease apart these separate needs and provide tools to manage both. That way we all get what we want. This paper has specifications & syntax for protected components and protected types based on our withdrawn 20-121. If we're happy with it, I can either submit it as a paper or as a work item for the DATA subgroup.

@zjibben
Copy link
Member Author

zjibben commented Sep 21, 2020

@aradi

@zjibben zjibben mentioned this pull request Sep 21, 2020

G. A protected component or a subobject of a protected component can only
be argument associated with INTENT(IN) dummy, even if the referenced
procedure is in the module in which the type is defined.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is implied by B, but nothing wrong with being explicit.

the target in a pointer assignment outside the module, as that would
lose the protection.
- Here I think it would be valuable to somehow expose an immutable
reference, which could tie into the const-pointer proposals.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good eye, forward thinking. I had a similar thought, but didn't see a reason to bring it up and complicate matters. Worth keeping in mind though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. We'll see what comes of this, but given there's already work on the other feature it would be cool to get both of these working together.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I absolutely agree, a read-only reference would be very handy here.

N. Structure constructor outside the module in which the type is allowed if
and only if no value is supplied for any protected component (otherwise
this would subvert the module's control over what values are acceptable
in the protected component).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we actually don't want this. The motivation behind the feature is more about keeping objects internally consistent, and a structure constructor would potentially (probably?) produce an internally inconsistent object.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I think) structure constructors are not modifiable. Of course a type-bound procedure called init or something like that can do anything, but this would be for the language-defined structure constructor. e.g.:

type :: foo
  integer :: a, b, c
  integer, private :: d
  integer, protected :: e
end type foo

type(foo) :: x

x = foo(a=1, b=2, c=3)

In this case, we can't specify values for d or e via the structure constructor. I'm sure some discussion will come up on this point, though, because a private variable d cannot be specified here because its name isn't accessible in the scoping unit. The name e is accessible, so some extra rules will need to be added to the standard to handle this.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I see it. a, b, and c aren't being protected anyways, so getting rid of the structure constructor doesn't buy you any extra protection. Got it.

- The function result shall not be a pointer.
- The function result will (hopefully) be finalised after its use.

N2. Structure constructor outside the module in which the type is allowed.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this just be a copy of N?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I'm thinking about it, we might actually want the opposite: "A structure constructor outside the module in which the type is defined is not allowed".

The original version was concerned with assigning to a protected component, so prohibited intrinsic assignment but basically allowed an exception for structure constructors which did not name those protected components (though this could effectively overwrite existing data in a protected component, if I'm not mistaken). Now that we've separated out the protected components, I'm thinking we don't need the exception and would just forbid structure constructors on protected types (when outside the module where the type is defined).

I think I'll change it to that for now, but I'll defer to the interested parties in the committee for behavior of type protection.

Copy link
Member

@certik certik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The paper looks good.

My major suggestion for improvement would be to add test/example cases of how the feature is used. The only examples are how it is declared, but it would be nice to add examples showing:

  • how it can be used
  • what usage is allowed
  • what usage is not allowed
  • how exactly it differs from the previous proposals

Copy link
Contributor

@aradi aradi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx. for setting this up! This is all fine, see a few minor comments. My only concern is, that we are now putting two different categories of protected-nes into one proposal:

  • The protected component, which is probably not too difficult to implement in compilers and seem to have not too many implications/side effects.
  • The protected type, which seems to be a monster with many-many implications and side-effects.
    I fear, that it would put the first one on hold due to numerous discussions on and problems with the second one.

Also, I'd recommend to use a different name for the two features as to me, their puprose is completely different. To me protected just means 'read-only', in the sense that you need routines of the defining modules to manipulate that value. Note, that also in case of protected module variables, the same meaning still holds. The only reason, why such variables are also behaving kind of 'persistent', is that modules do not go out of scope. If they would, protected module variables would "vanish" exactly the same way as all other (private and public) module variables, so they were not persistent. So it is not they protected-nes which makes they persistent... Therefore, I'd suggest to keep the term protected for expressing read-only behaviour (of the derived type components), and use something else for defining persistent/undestroyable types (e.g. persistent).

the target in a pointer assignment outside the module, as that would
lose the protection.
- Here I think it would be valuable to somehow expose an immutable
reference, which could tie into the const-pointer proposals.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I absolutely agree, a read-only reference would be very handy here.

Comment on lines +80 to +85
L1. No intrinsic assignment to a protected component or subobject thereof,
outside the module in which the protected component is defined. (cf.
19-135r1)
- This does not prohibit intrinsic assignment to a type containing a
protected component. It is only meant to prevent the protected
component from being modified by name.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this already covered by B anyway?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it is covered by B. The original paper I built off had both (19-214r1), and I can't say I know why. I'm taking a "change as little as possible" approach compared to what they had.

Comment on lines 156 to 160
- This presents a loophole which may allow a programmer to write to a
protected component outside the module in which it is defined.
However, subgroup did not like the alternative of disallowing
protected components in extensions of parent types without any
protected component.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens, if the parent type is deallocated? It would basically allow to deallocate protected types.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question, I'll clarify in here. This was something concluded by Malcolm & Van, and I believe the intention is that the protected component would become deallocated & finalized. This is basically a loophole to avoid the other restrictions on deallocation & finalization, but the alternative they had in mind (prohibiting protected components in type extensions) was too strong.

But I'm noticing some holdovers from the old protected component terminology, which here is a protected type. That needs to be fixed.

@zjibben
Copy link
Member Author

zjibben commented Sep 24, 2020

Thanks @aradi!

The protected type, which seems to be a monster with many-many implications and side-effects.
I fear, that it would put the first one on hold due to numerous discussions on and problems with the second one.

This is definitely a valid concern. For our part, I wouldn't be proposing that monster feature at all (I don't see it as extremely useful personally). But when presented with protected components, the committee really wanted something extremely strong, and had lots of work towards that already. These specs derive from the work on those very restrictive protected components. It looks like if we want our more lightweight protected components, we need something strict to go with it. But we'll see as discussions develop, maybe seeing both alongside each other the committee will be willing to drop the heavy one. Hopefully the committee doesn't decide they don't see the value in our lighter protected components, deciding to go ahead with heavy-only, or decide the whole combination is more than they wanted and kill the whole concept.

I'd suggest to keep the term protected for expressing read-only behaviour (of the derived type components), and use something else for defining persistent/undestroyable types (e.g. persistent).

I like this, and have struggled to come up with an alternative name for "protected type". persistent is a good option, as it really just disables intrinsic assignment, allocation, deallocation, and automatic finalization. I'll include that along with the other name alternatives I now have at the end. I think naming will be a big point of discussion.

@zjibben
Copy link
Member Author

zjibben commented Sep 24, 2020

@certik thanks for the suggestion. I added a section on use-cases, which naturally was very detailed on what we want to see in protected components, but lighter for protected types. I tried to faithfully relay the motivation described to me by Van, and I think it ended up being similar to described by Malcolm in 19-135r1.

@zjibben
Copy link
Member Author

zjibben commented Jun 15, 2021

Tagging a few others who might be interested: @FortranFan @milancurcic @gklimowicz @tclune @vansnyder

I think we got this into pretty good shape during our discussion in September, but I've added a bit more clarifying discussion. I'm planning to show this to the committee for our meeting next week. I think this approach offers enough flexibility to satisfy everyone, but we'll see how it goes.

@vansnyder
Copy link

vansnyder commented Jun 15, 2021 via email

@zjibben
Copy link
Member Author

zjibben commented Jun 16, 2021

Hi Van, thanks for looking at this!

I assume this disabling does not apply in the scoping unit where the type is defined.

This is correct, specification L3 allows for intrinsic assignment inside the module which defines the protected type.

@FortranFan
Copy link
Member

@zjibben wrote 15 June 2021, 6:19 PM EDT:

I've added a bit more clarifying discussion. I'm planning to show this to the committee for our meeting next week. I think this approach offers enough flexibility to satisfy everyone, but we'll see how it goes.

Great paper, Zach. I read your revised version closely just now and you've covered everything that I can think of, especially with formal specifications toward the protected components feature that is of particular importance in many codes in my experience.

My only change will be on line 113: 'inadvertently'.

I feel strongly this will be an excellent addition to Fortran 202X. The discussion at the plenary on this paper will be of great interest, hope no technical surprises arise then.

@aradi
Copy link
Contributor

aradi commented Jun 16, 2021

Good luck! Let's hope, this time the proposal gets further as last time.

Copy link
Contributor

@jvdp1 jvdp1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @zjibben. This feature would be a useful addition. Good luck!

proposals/protected-components.txt Outdated Show resolved Hide resolved
Comment on lines +175 to +176
P1. Protected components are inherited through type extension.
- In this regard, PROTECTED is like PUBLIC, not PRIVATE.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In all other rules, PROTECTED behaves as PRIVATE, except for its readable behavior. Should it not be the case for this rule too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My reasoning here is PROTECTED components are part of an API, something a client can see and read. PRIVATE components are completely invisible outside the type, hence it's safe not to inherit them. But if a client has a class(parent) with a protected component, the dynamic type type(child) ought to share the parent's API.

Copy link
Member

@milancurcic milancurcic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great proposal and useful potential addition, thank you for pushing it.

proposals/protected-components.txt Outdated Show resolved Hide resolved
Comment on lines 358 to 361
A: I believe the answer here is yes. Specification K allows modification of
the components of a protected type; i.e. the protection of a type really
only restricts what can be done to the type as a whole. This is up for
discussion, though, and could be changed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems reasonable to me.

combination of more than one of these attributes.


3.2 Protected Types
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can a protected type be extended? If yes, would the extending type also be protected? It seems to me that it would have to be, otherwise it would be easy to "unprotect" a protected type. This should be spelled out in the spec.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I see P2.

@zjibben
Copy link
Member Author

zjibben commented Jun 18, 2021

Thank you everyone! The paper has been submitted: https://j3-fortran.org/doc/year/21/21-148.txt

@certik certik added the Clause 9 Standard Clause 9: Use of data objects label Apr 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Clause 9 Standard Clause 9: Use of data objects
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants