Version 1.7 of ai12s/ai12-0191-1.txt

Unformatted version of ai12s/ai12-0191-1.txt version 1.7
Other versions for file ai12s/ai12-0191-1.txt

!standard 3.9.1(4.1/2)          19-02-20 AI12-0191-1/04
!standard 7.3.2(10.1/4)
!standard 7.3.2(15/5)
!class binding interpretation 16-06-06
!status work item 16-06-06
!status received 16-05-31
!priority Low
!difficulty Medium
!qualifier Omission
!subject Clarify "part" for type invariants
!summary
Screened components are not checked even if a type invariant check would apply to them.
!question
The term "part" is used several times in the section on Type Invariants. Does this usage of "part" include the "parent part"? (No.)
!recommendation
(See Summary.)
!wording
Add after AARM 3.1(7.d/3): [continuing the AARM note]
For example, a reference to the components of an object in a rule that is interpreted at compile-time would not apply to components that are not visible. On the other hand, a reference to the components of an object in a dynamic semantics rule would apply to all components of the object, visible or not, including (for tagged objects) components which are not components of the the view of the object (this can occur when the tag of the object does not match the tag of the type of the view of the object). Other terms, such as "subcomponent" and "part", are interpreted analogously.
Add after 3.9.1(4.1/2):
In the case where the (compile time) view of an object X is of a tagged type T1 or T1'Class and the (runtime) tag of X is T2'Tag, the components (if any) of X which are not components of T1 (and which are not discriminants which correspond to a discriminant of T1) are said to not be "components of the view of the object". For example, if T2 is an undiscriminated extension of T1 which declares a component named Comp, then X.Comp would not be a component of the view of X. Similarly, a part of an object might or might not be a part of the view of the object. [Redundant: A component of an untagged object, or of a tagged object whose tag matches that of the type of the view of the object, is always a component of the view of the object, even if (for example) the view of the type of the object is a partial view.]
AARM note: For example, there is a dynamic semantics rule that finalization of an object includes finalization of its components (see 7.6.1). In the following case
type T1 is tagged null record; type T2 is new T1 with record Comp : Some_Controlled_Type; end record; function Func return T1'Class is (T2'(others => <>)); X : T1'Class := Func;
the rule that "every component of the object is finalized" (as opposed to something like "every component of the view of the object is finalized") means that the finalization of X will include finalization of X.Comp. For another example, see the rule about accessibility checking of access discriminants of parts of function results in 6.5. In contrast, the rules in 7.3.2 explicitly state that type invariant checks are only performed for parts which are of the type-invariant bearing type and which are parts of the view of the object (as opposed to for all parts, whether part of the view of the object or not, which are of that type). Similarly, the rule in 13.13.2 governing which components of a composite value are read and written by the default implementations of Read and Write for a composite type states that only the components of the view of the object are read or written.
Modify 7.3.2(10.1/4):
After successful explicit initialization of the completion of a deferred constant with a part of type T {that is a part of the view of the object}, if the completion is inside the immediate scope of the full view of T, and the deferred constant is visible outside the immediate scope of T, the check is performed on the part(s) of type T{ that are parts of the view of the object};
Modify 7.3.2(15/5):
Upon a successful return from a call on any subprogram or entry which is type-invariant preserving for T, an invariant check is performed on each part of type T{ that is a part of the view of the object} which is subject to an invariant check for T. In the case of a call to a protected operation, the check is performed before the end of the protected action. In the case of a call to a task entry, the check is performed before the end of the rendezvous;
Replace AARM 7.3.2(20.a.1/5):
To be honest: {AI12-0167-1} In all of the above, for a class-wide object, we are only referring to the parts of the specific root type of the class. We don't want the overhead of checking every class-wide object in case some future extension component might have type T (contrast this to finalization, where we do intend that overhead).
with:
Reason: The various rules requiring type invariant checks only for parts of type T which are parts of the view of the object, as opposed to all parts of type T (whether part of the view of the object or not), are motivated by a desire to avoid overhead associated with the possibility that there might exist an extension of the tagged type in question that has a part of type T.
Modify in 13.13.2(9/3):
... the Write or Read attribute for each component of the view of the object is called ...
!discussion
If the programmer wants the invariant to be enforced on all descendants, she can use Type_Invariant'Class on the original type. Therefore, we want Type_Invariant to work differently.
Also note that it is unusual to have a type extension in the same package as its parent. If, at a later point, the type extension is given its own package, we'd prefer that the invariant enforcement change as little as possible.
The wording does not guarantee that every use of "component", "subcomponent", and "part" in the RM has the correct meaning with respect to "hidden" components of tagged types, but it fixes the problematic cases that we know about and provides a framework so that fixing any further problems that are discovered should be straightforward.
Note that we don't use the word "hidden" in the proposed wording because that seems too tied to visibility, which is not what we are talking about. We are talking about components whose existence is likely to be unknown at compile-time even if the compiler looks through all private types and expands all generic instances (specs and bodies). The implementation of any dynamic semantics rule requiring that some action needs to be performed for such components (e.g., finalization) will typically require dispatching.
!example
with Derived; use Derived; procedure Testinv is X : D; begin Create (X); end Testinv; --- package Derived is
type T is tagged private; type D is tagged private;
procedure Create (X : out T); procedure Create (X : out D);
private
type T is tagged record C : Integer; end record with Type_Invariant => T.C /= 0;
type D is new T with null record;
end Derived; --- package body Derived is
procedure Create (X : out T) is begin X.C := 1; end Create;
procedure Create (X : out D) is begin X.C := 0; -- Parent part type-invariant failure on return? (No.) end Create;
end Derived;
!ASIS
No ASIS effect.
!ACATS test
!appendix

From: Tucker Taft
Sent: Tuesday, May 31, 2016  2:13 PM

The term "part" is used several times in the section on Type Invariants.  The 
question is whether this always is meant to apply to the "parent part" (and
for that matter, every ancestor part) of the object.  My view is that when the
RM says "any part", we usually want it to mean precisely "any subcomponent, or
the object as a whole."  The definition of "part" also talks about sets of
subcomponents, and mentions it use in terms like the "parent part" and the
"extension part."  But I think those usages only make sense when we are
talking about untyped sets of things.  For a type invariant, clearly we are
only talking about "typed" parts, and I don't believe the parent part has a
type in the normal sense.  You can create a "typed view" of the parent part
by a view conversion, but until you do that, the parent part is not an object,
but rather just a collection of components.

Below is an example that shows the issue.  The question is whether the call on
Create for type D should fail on return, because the parent part doesn't
satisfy its invariant:
----

with Derived; use Derived;
procedure Testinv is
    X : D;
begin
    Create (X);
end Testinv;
---
package Derived is

    type T is tagged private;
    type D is tagged private;

    procedure Create (X : out T);
    procedure Create (X : out D);

private

    type T is tagged record
       C : Integer;
    end record
      with Type_Invariant => T.C /= 0;

    type D is new T with null record;

end Derived;
---
package body Derived is

    procedure Create (X : out T) is
    begin
       X.C := 1;
    end Create;

    procedure Create (X : out D) is
    begin
       X.C := 0; --  Parent part type-invariant failure on return?
    end Create;

end Derived;

****************************************************************

From: Randy Brukardt
Sent: Tuesday, May 31, 2016  6:48 PM

> The term "part" is used several times in the section on Type 
> Invariants.  The question is whether this always is meant to apply to 
> the "parent part" (and for that matter, every ancestor part) of the 
> object.  My view is that when the RM says "any part", we usually want 
> it to mean precisely "any subcomponent, or the object as a whole."  
> The definition of "part" also talks about sets of subcomponents, and 
> mentions it use in terms like the "parent part" and the "extension 
> part."  But I think those usages only make sense when we are talking 
> about untyped sets of things.  For a type invariant, clearly we are 
> only talking about "typed" parts, and I don't believe the parent part 
> has a type in the normal sense.  You can create a "typed view" of the 
> parent part by a view conversion, but until you do that, the parent 
> part is not an object, but rather just a collection of components.

As usual, it's probably better to figure out what we want and then decide
whether the words say that, rather than try to figure out what the words
actually say. We already know (at least those of us that have tried to write
ACATS tests and objectives) that the wording of 7.3.2 is pretty fast-and-loose
about what is and is not included. (Steve's notes about "parts" known
dynamically vs. "parts" known statically are a big deal to this check being
efficient, but the wording is interpreted 100% differently than the very
similar wording for finalization.)

And I think that it doesn't make much sense for the parent extension to get
enforced separately for a type extension. If a programmer wants to ensure
that an invariant is enforced on extensions, they can use a
Type_Invariant'Class. Otherwise, as with all derived types, nothing gets
inherited.

> Below is an example that shows the issue.  The question is whether the 
> call on Create for type D should fail on return, because the parent 
> part doesn't satisfy its invariant:
> ----
> 
> with Derived; use Derived;
> procedure Testinv is
>     X : D;
> begin
>     Create (X);
> end Testinv;
> ---
> package Derived is
> 
>     type T is tagged private;
>     type D is tagged private;
> 
>     procedure Create (X : out T);
>     procedure Create (X : out D);
> 
> private
> 
>     type T is tagged record
>        C : Integer;
>     end record
>       with Type_Invariant => T.C /= 0;
> 
>     type D is new T with null record;
> 
> end Derived;
> ---
> package body Derived is
> 
>     procedure Create (X : out T) is
>     begin
>        X.C := 1;
>     end Create;
> 
>     procedure Create (X : out D) is
>     begin
>        X.C := 0; --  Parent part type-invariant failure on return?
>     end Create;
> 
> end Derived;

It's of course unusual to put a type and its extension into the same package,
so the answer here isn't terrible critical. But it's probably best for the
behavior to change as little as possible when these two types are inevitably
split into separate packages.

****************************************************************

From: Steve Baird
Sent: Friday, August 19, 2016  2:24 PM

Pisa minutes say:

   Steve volunteers to help find out what GNAT does on cases of “parts”
   that are only dynamically known for type invariant checks.

No checks for these guys. For the following example (with all assertions
enabled) compiled with the GNAT compiler,

  procedure Type_Invariant_Breaker is

   type Root is tagged null record;

    package Pkg is
       type Has_Invariant is private;

       procedure Oops (X : in out Root'Class);
       procedure Rely_On_Incoming_Invariant (Y : Has_Invariant);
    private
       type Has_Invariant is record Lo, Hi : Integer := 0; end record
	with Type_Invariant => (Has_Invariant.Lo <= Has_Invariant.Hi);
    end Pkg;

    type Ext is new Root with
      record Field : Pkg.Has_Invariant; end record;

    package body Pkg is
       procedure Break_It (Xx : out Has_Invariant) is
       begin
	 Xx := (Lo => 1, Hi => 0);
       end;

       procedure Oops (X : in out Root'Class) is
       begin
	 if X in Ext'Class then
	    Break_It (Ext (X).Field);
	 end if;
       end;

       procedure Rely_On_Incoming_Invariant (Y : Has_Invariant) is
       begin
	 pragma Assert (Y.Lo <= Y.Hi);
       end;
    end Pkg;

    Ext_Var : Ext;
  begin
    Pkg.Oops (Ext_Var);
    Pkg.Rely_On_Incoming_Invariant (Ext_Var.Field);
  end;

we fail the assertion in Rely_On_Incoming_Invariant, which means that the
preceding call to Oops didn't fail any checks. I believe this implementation
is correct and should not be changed. The problem here is that the RM wording
doesn't make this clear (which is the topic of this AI).

The other interpretation (i.e., the one where the call to Oops would be
required to fail an invariant check) would be better in some sense but I don't
know how to implement it without introducing distributed overhead and a lot
more implementation complexity than than this feature would be worth.

****************************************************************

From: Jeff Cousins
Sent: Tuesday, August 23, 2016  9:34 AM

Thanks for looking into that Steve.  I think we have accepted that invariant
checking can't check everything all of the time, and is just providing a
limited number of check points.

****************************************************************

From: Steve Baird
Sent: Wednesday, February  6, 2019  7:18 PM

Here is some proposed wording for this AI, although I still have not gone 
through the RM with a fine-toothed comb reviewing each use of the terms 
"component", "subcomponent", and "part" with these issues in mind.

Many thanks to Randy for much helpful review, although (as usual) don't 
blame him for anything here that you don't like.

[This is version /02 of the AI - Editor.]

****************************************************************

From: Randy Brukardt
Sent: Wednesday, February  6, 2019  10:06 PM

> Here is some proposed wording for this AI, ...

>!discussion (in addition to existing !discussion section)
>
>The following wording ...

Ahem. !wording *precedes* any !discussion. I dropped the word "following".

Also:

> ... The current write-up of the AI uses "screened", ...

Ahem, the reader is currently reading the AI, so this is mostly noise. I 
replaced this with "We used "screened", ..."

>append after 3.1(7.d/3), continuing the AARM note

As I noted before (and in the formatting rules I posted to the list), this 
should read something like:

Add after AARM 3.1(7.d/3): [continuing the AARM note]

Similar comments apply to the rest of this wording section.

Otherwise, looks good.

****************************************************************

From: Steve Baird
Sent: Tuesday, February 12, 2019  7:32 PM

Here is another version of this AI, reflecting feedback received since the
previous version was distributed on Feb 6 2019, notably at the last phone 
meeting.

Two changes:
    1) The term "screened" has been replaced with "supplementary"
       throughout the AI as per the guidance of the group.

    2) The rules about which components are streamed in and out in
       the default implementations of 'Read and 'Write for a
       a tagged type are clarified.

[This is version /03 of the AI - Editor.]

****************************************************************

From: Tucker Taft
Sent: Tuesday, February 12, 2019  8:01 PM

The term "supplementary" is growing on me.  The !discussion should still 
come afterward.

I am somewhat worried we are combining the rules for class-wide objects
with the rules for "shortened" specific views of objects.  By "shortened" I 
mean a specific view of a type extension like T2 through a T1 "lens," where T1
is an ancestor of T2.  A class-wide view and a "shortened" view generally seem
to behave pretty differently.  For example on assignment, clearly you finalize 
the whole left-hand side in the case of a class-wide assignment, but for a 
"shortened" specific view, I would think the "supplementary" components are 
completely untouched as far as finalization and adjustment.  Is there really 
*any* case where for a shortened view, we touch the supplementary components?

For type invariants, we have an elaborate set of rules on type conversions, 
so that we start looking at the masked components (hmm -- "masked" vs. 
"supplementary"?) as we unwind the conversions.  But when you have the 
shortened view, you don't do anything with those supplementary/masked 
components.

****************************************************************

From: Tucker Taft
Sent: Tuesday, February 12, 2019  9:03 PM

How about "masked" vs. "unmasked" components?
Not sure if it is better...

****************************************************************

From: Steve Baird
Sent: Tuesday, February 12, 2019  9:12 PM

I prefer "masked" to "supplementary".

****************************************************************

From: Randy Brukardt
Sent: Tuesday, February 12, 2019  9:22 PM

Of course, if the concern is about implying something about visibility,
"screened" or "masked" certainly have that flavor, while "supplementary"
does not.

The correct flavor would be more like "unknown components", since they are 
completely unknown to the implementation at the interesting point. "Unknown"
doesn't appear in my thesaurus, someone else will have to look for 
alternatives to that...

****************************************************************

From: Randy Brukardt
Sent: Tuesday, February 12, 2019  9:29 PM

> I am somewhat worried we are combining the rules for class-wide 
> objects with the rules for "shortened" specific views of objects.  By 
> "shortened" I mean a specific view of a type extension like T2 through 
> a T1 "lens," where T1 is an ancestor of T2.  A class-wide view and a 
> "shortened" view generally seem to behave pretty differently.  For 
> example on assignment, clearly you finalize the whole left-hand side 
> in the case of a class-wide assignment, but for a "shortened"
> specific view, I would think the "supplementary" components are 
> completely untouched as far as finalization and adjustment.  Is there 
> really *any* case where for a shortened view, we touch the 
> supplementary components?

Dunno. I didn't know/remember that assignment isn't supposed to finalize such
components. I doubt that there is any ACATS test like that (assignments to 
[entire] tagged objects are rare in real code) -- I wonder if anyone gets that 
right?

> For type invariants, we have an elaborate set of rules on type 
> conversions, so that we start looking at the masked components (hmm -- 
> "masked" vs. "supplementary"?) as we unwind the conversions.  But when 
> you have the shortened view, you don't do anything with those 
> supplementary/masked components.

But specifically for type conversions, if you have a class-wide view (that 
is, T'Class) in the spec of an invariant-preserving , then you want to check 
the T components (only). That is what is different here, I think.

If that's not the case, then there's an argument that there never was a bug 
in the first place. That is, the (dynamic) components are *always* those of 
the view of the object (where the runtime view ignores any privacy). When 
one finalizes a stand-alone object or component of such an object, you always 
have the original view of that object/component, so of course you can see all 
of the subcomponents. And if you always see all of the components of a 
class-wide object, then QED (since that would cover any "interesting"
deallocations).

****************************************************************

From: Tucker Taft
Sent: Wednesday, February 13, 2019  11:02 AM

> But specifically for type conversions, if you have a class-wide view 
> (that is, T'Class) in the spec of an invariant-preserving , then you 
> want to check the T components (only). That is what is different here, I 
> think.

I am not convinced we have this right.  In my understanding of the intent, 
any class-wide object is presumed to satisfy all of its invariants.  Another 
way of thinking about it is when you create a class-wide object, you are 
effectively passing outside of the package barrier, and you must be sure the 
object satisfies all invariants that apply to it.

> If that's not the case, then there's an argument that there never was 
> a bug in the first place. That is, the (dynamic) components are 
> *always* those of the view of the object (where the runtime view 
> ignores any privacy). When one finalizes a stand-alone object or 
> component of such an object, you always have the original view of that 
> object/component, so of course you can see all of the subcomponents. 
> And if you always see all of the components of a class-wide object, then 
> QED (since that would cover any "interesting" deallocations).

Class-wide objects generally worry about all of their components.  The weird 
case is an object of a specific type, that was produced by doing a view 
conversion on an object with more components.  These are the real oddball 
guys, and we need to decide how these are to be handled.

****************************************************************

From: Steve Baird
Sent: Wednesday, February 13, 2019  12:29 PM

> For example on assignment, clearly you finalize the whole left-hand 
> side in the case of a class-wide assignment, but for a "shortened" 
> specific view, I would think the "supplementary" components are completely
> untouched as far as finalization and adjustment.

That's certainly true, but maybe this ought to be stated more clearly (perhaps 
in an AARM note) in the section on assignment statements. If we want to do 
that, that should probably be included in this AI.

> Is there really *any* case where for a shortened view, we touch the 
> supplementary components?
I can't think of any. The two cases that came to mind are finalization and 
the accessibility checks for access discriminants of a function result. But 
if the function result type is specific then there are no supplementary 
components of the function result object. And the cases where we get 
"shortened" views of longer objects (e.g., via parameter passing or 
View_Conversion'Access) are not cases where exiting a scope causes 
finalization of that shortened object.

****************************************************************

From: Tucker Taft
Sent: Wednesday, February 13, 2019  1:23 PM

>I am not convinced we have this right.  In my understanding of the intent, 
>any class-wide object is presumed to satisfy all of its invariants.  Another 
>way of thinking about it is when you create a class-wide object, you are 
>effectively passing outside of the package barrier, and you must be sure the 
>object satisfies all invariants that apply to it.

See AARM 7.3.2(20.a/4) for this "intent":

Reason: Class-wide objects are treated as though they exist outside the scope 
of every type, and may be passed across package "boundaries" freely without 
further invariant checks.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, February 13, 2019  3:50 PM

>See AARM 7.3.2(20.a/4) for this "intent":
>
>Reason: Class-wide objects are treated as though they exist outside the
>scope of every type, and may be passed across package "boundaries" freely 
>without further invariant checks.

This note is on class-wide types that are in the tree-of-T. These are 
invariants that the package reasonably could know about. 

But Steve has pointed out this also happens in the case of extensions of 
otherwise unrelated types that contain objects of T. This intent is not 
covered by any current invariant checks, since nothing class-wide related to T 
is involved.

In the somewhat pathological case that the body has sufficient visibility to 
such an extension to pass/assign it an unchecked T, preventing that requires 
a dispatching check. Or some other substantial change to the model.

Since this case requires contortions, we don't want to require implementations 
to check it, but would rather would describe it as a hole.
At least that has been my understanding.

Steve shows the case in interest in the e-mail:

  procedure Type_Invariant_Breaker is

   type Root is tagged null record;

    package Pkg is
       type Has_Invariant is private;

       procedure Oops (X : in out Root'Class);
       procedure Rely_On_Incoming_Invariant (Y : Has_Invariant);
    private
       type Has_Invariant is record Lo, Hi : Integer := 0; end record
	with Type_Invariant => (Has_Invariant.Lo <= Has_Invariant.Hi);
    end Pkg;

    type Ext is new Root with
      record Field : Pkg.Has_Invariant; end record;

    package body Pkg is
       procedure Break_It (Xx : out Has_Invariant) is
       begin
	    Xx := (Lo => 1, Hi => 0);
       end;

       procedure Oops (X : in out Root'Class) is
       begin
	 if X in Ext'Class then
	    Break_It (Ext (X).Field);
	 end if;
       end;

       procedure Rely_On_Incoming_Invariant (Y : Has_Invariant) is
       begin
	 pragma Assert (Y.Lo <= Y.Hi);
       end;
    end Pkg;

    Ext_Var : Ext;
  begin
    Pkg.Oops (Ext_Var);
    Pkg.Rely_On_Incoming_Invariant (Ext_Var.Field);
  end;

I was thinking a case with an interface:

    package Pkg2 is
       type Has_Invariant is private;

       procedure Rely_On_Incoming_Invariant (Y : Has_Invariant);

       type Some_Interface is interface;
       procedure Munge (I : in out Some_Interface; Z : Has_Invariant) is abstract;

       procedure Oops (X : in out Some_Interface'Class);

    private
       type Has_Invariant is record Lo, Hi : Integer := 0; end record
	with Type_Invariant => (Has_Invariant.Lo <= Has_Invariant.Hi);
    end Pkg2;

    package body Pkg2 is
       procedure Break_It (Xx : out Has_Invariant) is
       begin
  	    Xx := (Lo => 1, Hi => 0);
       end;

       procedure Oops (X : in out Some_Interface'Class) is
          Bad : Has_Invariant;
       begin
          Break_It (Bad);
          X.Munge (Bad);
       end;
    end Pkg2;

Here, the implementation of Munge (which is not related at all to the package, 
and thus will not be checking any invariants) can save Bad into an extension 
of X. Oops in theory should be checking that part when it exits, but there is 
no way for that to happen short of there being a dispatching routine that 
knows about all of the components of each extension of Some_Interface. (Again, 
Some_Interface itself is not related to T in any way.)

---

I also note that the original question was about "parent part", and was posed 
by one Tucker Taft. I'm not sure why this matters (the "parent part" is not a
"part" in the technical sense of "object or its components"), but I can see 
why it would confuse.
 
****************************************************************

From: Randy Brukardt
Sent: Wednesday, February 13, 2019  6:25 PM

> Here, the implementation of Munge (which is not related at all to the 
> package, and thus will not be checking any
> invariants) can save Bad into an extension of X. Oops in theory should 
> be checking that part when it exits, but there is no way for that to 
> happen short of there being a dispatching routine that knows about all 
> of the components of each extension of Some_Interface. (Again, 
> Some_Interface itself is not related to T in any
> way.)

You might want to claim that Munge should check the invariant (inbound) because 
the dispatching is to an abstract routine that is itself "invariant-preserving".
I think that's arguable, but in any case, if we change Munge to a function, it 
becomes irrelevant (invariants of inbound "in" parameters of functions are 
never checked). (And even if the invariant is checked in the procedure case, 
the object X is modified before the failure, meaning that the "leak" has 
already happened.)

One could also create this case by using two interfaces, I1 and I2, with I2 a 
descendant of I1, I2 being in a separate package C1 and containing the Munge 
operation (which is therefore not invariant-preserving itself). If the body 
of the invariant-containing package Pkg2 withs C1, it can dispatch to the 
Munge operation, and again we can have a leak.

As with all permitted holes in invariant protection, this sort of issue 
requires active participation of the package containing the invariant, so 
there is no reason to pay the steep cost to fix it. But we also want to ensure 
that (A) no one thinks that they have to implement such a check; and
(B) that we include it in the list of holes. Both of these require a 
reasonable definition of what is *not* checked.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, February 13, 2019   6:47 PM

...
> Of course, if the concern is about implying something about 
> visibility, "screened" or "masked" certainly have that flavor, while 
> "supplementary"
> does not.
> 
> The correct flavor would be more like "unknown components", since they 
> are completely unknown to the implementation at the interesting point. 
> "Unknown"
> doesn't appear in my thesaurus, someone else will have to look for 
> alternatives to that...

I just ran across a thesaurus in LibreOffice (never thought to look there),
and it is happy to give alternatives to "unknown":

"unmapped"
"unbeknownst"
"unheard-of"
"unacknowledged"
"unfamiliar"
"dishonorable" :-)
"unidentified"
"anonynous" (um, no.)
"unsuspected"
"obscure"
"unsung"
"terra incognita" :-) :-)
"stranger"
"alien"
"variable" (um, really no.)

I have some favorites here, both serious and not so serious. Not sure how the 
rest of us feel.

****************************************************************

From: Tullio Vardanega
Sent: Thursday, February 14, 2019  2:17 AM

Seems like "obscure", to me.

****************************************************************

From: Tucker Taft
Sent: Thursday, February 14, 2019  7:39 AM

Here are two other pairs:

   *Overt* components, and *latent* components, of the current view.

   Components *included* in the current view, components *excluded* from the 
   current view.

I think it is worth using the term "view" when talking about this distinction, 
because it really is all about the view, not about the underlying object.

****************************************************************

From: Edmond Schonberg
Sent: Thursday, February 14, 2019  9:43 AM

“Overt” seems perfect. Maybe “implicit” instead of latent?

****************************************************************

From: Jean-Pierre Rosen
Sent: Thursday, February 14, 2019  9:54 AM

> I think it is worth using the term "view" when talking about this 
> distinction, because it really is all about the view, not about the 
> underlying object.

Agreed, but if a full phrase is acceptable, then "components that are/are not
part of the current view" would exactly describe what we mean.

****************************************************************

From: Tucker Taft
Sent: Thursday, February 14, 2019  11:16 AM

>“Overt” seems perfect. Maybe “implicit” instead of latent?

Alas, Ada already refers to the "implicit" components of a task or protected 
object, to represent entry queues.  And implicit is already pretty heavily 
used for "implicit declarations" of inherited operations.  I like "latent" in 
the sense of a "latent talent."  It is there, but it just hasn't yet been 
brought forward.

****************************************************************

From: Steve Baird
Sent: Thursday, February 14, 2019  11:54 AM

I agree.

I don't think an antonym of "active" would be confusing even though we already 
have active priorities, active partitions, active locales, and active tasks.

Interestingly, a variant part does not have an active variant; other 
terminology was used for that.

****************************************************************

From: Tucker Taft
Sent: Thursday, February 14, 2019  12:52 PM

Yes.  Let's leave "active" for something relating to tasks.

****************************************************************

From: Gary Dismukes
Sent: Thursday, February 14, 2019  12:49 PM

> Alas, Ada already refers to the "implicit" components of a task or protected 
> object, to represent entry queues.  And implicit is already pretty heavily 
> used for "implicit declarations" of inherited operations.  I like "latent" 
> in the sense of a "latent talent."  It is there, but it just hasn't yet been
> brought forward.

I had thought of mentioning "latent" at the meeting (as well as "concealed"), 
but didn't because it seemed to have too much of the sense of hidden, which 
was objected to.  I would be OK with that choice, but J-P's suggestion along 
the lines of "components that are part of the current view" seems reasonable, 
and would avoid the need to introduce another new term.

****************************************************************

From: Tucker Taft
Sent: Thursday, February 14, 2019  1:24 PM

> I had thought of mentioning "latent" at the meeting (as well as 
> "concealed"), but didn't because it seemed to have too much of the 
> sense of hidden, which was objected to.

"Latent" doesn't imply any sort of hiding in my view.  It just means it hasn't
been recognized yet.

> I would be OK with that choice, but J-P's suggestion along the lines 
> of "components that are part of the current view" seems reasonable, 
> and would avoid the need to introduce another new term.

I agree, it may be that if we use the term "current view" explicitly, that 
everything will be quite clear -- "part of the current view," "a component of 
the current view," etc. all seem pretty clear.

****************************************************************

From: Steve Baird
Sent: Thursday, February 14, 2019  3:22 PM

> I agree, it may be that if we use the term "current view" explicitly, that 
> everything will be quite clear -- "part of the current view," "a component 
> of the current view," etc. all seem pretty clear.

I'll take another look at the AI with this approach in mind.

****************************************************************

From: Steve Baird
Sent: Thursday, February 21, 2019  9:56 PM

I have attached two versions of this AI using the approach suggested by 
Jean-Pierre that Tuck referred to above.

I like the idea of using a phrase instead of a single word to capture the 
property in question, but I don't like the suggested phrase.

Nonetheless, in the attached v3 version (which I do not endorse) I used the 
suggested phrase.

[This is version /04 of the AI - Editor.]

It seems wrong to say that (by definition!) in a situation like

    package P1 is
       type T1 is private with Type_Invariant => ... ;

       package P2 is
         type T2 is private;
       private
         type T2 is record T1_Comp : T1; end record;
       end P1;

       procedure Foo (X : out P2.T2);
    private
       ...
    end P1;

when we are deciding what type invariant checks to perform as part of a return
from Foo, X.T2 is a component of the view of X.

To me, it seems clear that if we are at a point when we can see only the 
partial view of P2.T2, then saying that X.T2 is a component of the view of X 
will lead to confusion or worse.

So I used a different phrase in the attached v4 variant ("hidden by the 
nominal tag").

[This is version /05 of the AI - Editor.]

That's the one I endorse, although others might suggest better phrases now 
that we seem to have given up on single words like "latent" or "screened".

****************************************************************

From: Tucker Taft
Sent: Thursday, February 21, 2019  11:02 AM

****************************************************************

Questions? Ask the ACAA Technical Agent