Version 1.5 of ai12s/ai12-0377-1.txt

Unformatted version of ai12s/ai12-0377-1.txt version 1.5
Other versions for file ai12s/ai12-0377-1.txt

!standard 6.4.1(5.1/4)          20-04-29 AI12-0377-1/01
!standard 6.4.1(5.2/4)
!standard 6.4.1(5.3/4)
!standard 6.4.1(13.2/4)
!standard 6.4.1(13.3/4)
!class Amendment 20-04-20
!status work item 20-04-20
!status received 20-04-14
!priority Low
!difficulty Medium
!subject View conversions and out parameters of types with Default_Value revisited
!summary
An actual of an out parameter that is a view conversion is illegal if either the target or operand type has Default_Value specified while the other does not. Program_Error is raised if this occurs where one of the types is a generic formal type.
!problem
Consider this example:
procedure View_Conversion_With_Default_Value is
type Defaulted_Integer is new Integer with Default_Value => 123;
procedure P (X : out Integer) is begin null; -- X happens to be unassigned end P;
X : Defaulted_Integer; Y : Defaulted_Integer := 456;
begin P (Integer (X)); -- Deinitialize X?
P (Integer (Y)); -- Deinitialize Y? end View_Conversion_With_Default_Value;
Even though the type of X and Y has specified Default_Value, the value of the actual isn't copied into the formal in this case (it falls under the rule of 6.4.1(15)), leaving the formal parameter uninitialized. Upon return, the value of the formal will be converted to Defaulted_Integer and assigned to the actual object.
If the formal wasn't assigned to within the procedure, as in the above example, then the (uninitialized) value that comes back will deinitialize the actual object, which is the sort of thing that shouldn't normally be possible for an object whose type has a specified Default_Value.
!proposal
(See Summary.)
!wording
Replace 6.4.1(5.1/3) with:
If the mode is out, the actual parameter is a view conversion, and the type of the formal parameter is a scalar type, then either: * neither the target nor operand type have the Default_Value aspect specified; or * there shall exist a type (other than a root numeric type) that is an ancestor of
both the target type and the operand type, and both the target and operand types have the Default_Value aspect specified.
[Author's note: This removes the access part of this rule, and makes a version apply to all view conversions.]
Revert 6.4.1(13.1/4) to its previous version.
Delete 6.4.1(13.2-13.4/4), and AARM 6.4.1(13.d/4).
Add after 6.4.1(15):
* Furthermore, if the type is a scalar type, and the actual parameter is a
view conversion, then if neither:
* neither the target nor operand type have the Default_Value aspect specified; or
* there exists a type (other than a root numeric type) that is an ancestor of both the target type and the operand type, and both the target and operand types have the Default_Value aspect specified
then Program_Error is raised;
!discussion
"Deinitialization" here cannot introduce an invalid value into an object that the compiler assumed to be valid (the conversion back to the actual would still do a subtype check, which would cause Constraint_Error if the value is invalid. Note that the check would be required since one cannot assume anything about out parameters). Even so, it seems dangerous enough that we should take steps to prevent it.
The best solution is to make any view conversion used in an out parameter illegal if one type has Default_Value and the other does not. Note that the repeal of 13.1(10/3) by AI12-0376-1 means that having the types be related no longer prevents problems (as a derived type can define a Default_Value when the parent type does not have one), so we would have to do something with this rule in any case.
The alternative of passing the default value in problematic cases would make the deinitialization noted in the problem worse (since it would clobber the current value of the object unconditionally, even if it would be in range), so that is not a viable solution to this problem.
!ASIS
No ASIS effect.
!ACATS test
An ACATS B-Test is needed to check that the new rules are enforced, rather than the previous rules.
!appendix

From: Gary Dismukes
Sent: Tuesday, April 14, 2020  5:43 PM

Recently, while fixing a GNAT problem related to passing view conversions to 
out-mode parameters when Default_Value is involved (related to the rules added
in AI12-0074), it occurred to me that there's a similar situation that can 
arise when the formal type doesn't have aspect Default_Value, but the type of
the operand of the view conversion does have the aspect.  (AI12-0074 addressed
the case of formal types that specific Default_Value, requiring the type of an
operand of a view conversion actual to also specify Default_Value, and this is
sort of the reverse of that.)

Consider this example, which is a minor variation of the one in the AI:

   procedure View_Conversion_With_Default_Value is

     type Defaulted_Integer is new Integer with Default_Value => 123;

     procedure P (X : out Integer) is
     begin
        null;  -- X happens to be unassigned
     end P;

     X : Defaulted_Integer;
     Y : Defaulted_Integer := 456;

   begin
     P (Integer (X));  -- Deinitialize X?

     P (Integer (Y));  -- Deinitialize Y?
   end View_Conversion_With_Default_Value;

Even though the type of X and Y has specified Default_Value, the value of the 
actual isn't copied into the formal in this case (it falls under the rule of 
6.4.1(15)), leaving the formal parameter uninitialized. Upon return, the value 
of the formal will be converted to Defaulted_Integer and assigned to the actual 
object.

If the formal wasn't assigned to within the procedure, as in the above example, 
then the (uninitialized) value that comes back will deinitialize the actual 
object, which is the sort of thing that shouldn't normally be possible for an
object whose type has a specified Default_Value.

You could argue that you shouldn't have a formal of mode out that isn't 
assigned to, but that's kind of beside the point, because the normal guarantee 
of Default_Value, that variables of the type always have a good value, is 
violated in this case, so we clearly have a safety hazard. To avoid this, the 
rules either need to require the value of the actual to be assigned to the 
formal going in, or such a conversion needs to be rejected.  I was initially 
leaning towards the former, but Tuck has convinced me that this should be 
illegal.  Basically we don't want to impose the penalty of preventing an 
optimization like transforming a procedure with a single elementary out formal 
into a function returning the parameter, just to protect against what is going 
to be the rare case of passing a view conversion of an operand with 
Default_Value.

So it seems that we need to augment the rules of 6.4.1(5.1-5.3), which require 
the type of the operand of a view conversion to have Default_Value when the 
formal's type has Default_Value.  We need to also disallow the case where a 
view conversion operand's type has Default_Value but the formal's type 
doesn't.

I believe we'll also need to add something along the lines of the rules in 
6.4.1(13.1-13.4) that require Program_Error be raised, to address call cases 
within generic bodies when formal types are involved (those rules were also 
added by AI12-0074).

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

From: Tucker Taft
Sent: Tuesday, April 14, 2020  7:49 PM

We have discussed this internally at AdaCore, and concluded that we should
make it illegal to pass a scalar type with Default_Value in a view conversion
to an OUT formal parameter without a Default_Value.  Requiring "copy in" is 
not practical given the way that OUT parameters of a scalar type are sometimes
implemented (such as transforming the procedure to a function and returning 
the OUT parameter as a function result).

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

From: Randy Brukardt
Sent: Tuesday, April 21, 2020  7:57 PM

> Recently, while fixing a GNAT problem related to passing view 
> conversions to out-mode parameters when Default_Value is 
> involved (related to the rules added in AI12-0074), it 
> occurred to me that there's a similar situation that can 
> arise when the formal type doesn't have aspect Default_Value, 
> but the type of the operand of the view conversion does have 
> the aspect.  (AI12-0074 addressed the case of formal types 
> that specific Default_Value, requiring the type of an operand 
> of a view conversion actual to also specify Default_Value, 
> and this is sort of the reverse of that.)

I'm not throughly convinced that this problem (in any form) is worth worrying 
about, since it can't cause an invalid value to be introduced to the program 
(at least in a correct implementation). If the implementation is assuming that
the actual object is valid, then a constraint check is necessary at the back 
assignment and that would prevent any invalid values from being stored. The 
value would indeed be junk, but that's what was written (and it happens for 
all scalar out parameters).

Anyway, assuming that we do want to keep this illegal in any case, we need to 
cover *this* case as well. Attached is an attempt at doing that, and also 
handling the access problem (with a solution close to what GNAT is currently 
doing).

I suspect that the AI and especially the wording will need some wordsmithing.

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

[Editor's note: Some of the e-mails in the following thread discussed topics
in both this AI and AI12-0378-1. The e-mails were split and filed in the
appropriate AI to avoid confusion.]

From: Tucker Taft
Sent: Wednesday, April 29, 2020  11:34 AM

Wording suggestion:

If the mode is out, the actual parameter is a view conversion, and the type 
of the formal parameter is a scalar type, then either:

  * the target and operand type do not have the Default_Value aspect
    specified; or 
  
  * the target and operand type both have the Default_Value aspect
    specified, and there shall exist a type (other than a root numeric
    type) that is an ancestor of both the target type and the operand type.
    
****************************************************************

From: Randy Brukardt
Sent: Wednesday, April 29, 2020  3:32 PM

BTW, Claire, if you could provide an example of the problem that you were 
concerned about with the AI12-0377-1 proposal, it would be appreciated.

My incomplete understanding of your concern made it appear that the only 
solution would be to ban all view conversions of types with Default_Value
unless the defaults were the same. That would prevent declaring (or at 
least using) any derived types with different defaults (if there are 
primitive operations) -- but that was specifically the case that Arno wanted 
us to allow as he has customer code that depends upon it. It doesn't seem 
possible to thread that needle!

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

From: Erhard Ploedereder
Sent: Wednesday, April 29, 2020  4:57 PM

>     If the mode is out, the actual parameter is a view conversion, and
>     the type of
>     the formal parameter is a scalar type, then either:
> 
>       * the target and operand type do not have the Default_Value aspect
>         specified; or

I doubt that a Float and a Boolean, both without a Default_Value, are o.k. 
in a view conversion :-)  (There is a convertability constraint missing).

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

From: Tucker Taft
Sent: Wednesday, April 29, 2020  5:18 PM

...
>>    If the mode is out, the actual parameter is a view conversion, and
>>    the type of
>>    the formal parameter is a scalar type, then either:
>> 
>>      * the target and operand type do not have the Default_Value aspect
>>        specified; or
> 
> I doubt that a Float and a Boolean, both without a Default_Value, are 
> o.k. in a view conversion :-)  (There is a convertability constraint 
> missing).
 
This is the dynamic semantics.  The legality rules have already done their 
thing, so we only need to explain what happens with legal view conversions.

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

From: Erhard Ploedereder
Sent: Thursday, April 30, 2020  8:46 AM

>> I doubt that a Float and a Boolean, both without a Default_Value, are 
>> o.k. in a view conversion :-)  (There is a convertability constraint 
>> missing).
>>
> This is the dynamic semantics.  The legality rules have already done their
> thing, so we only need to explain what happens with legal view conversions.
> 

o.k. Understood. Or maybe only half of it, because the next bullet
   
>   * the target and operand type both have the Default_Value aspect
>     specified, and there shall exist a type (other than a root numeric
>     type) that is an ancestor of both the target type and the operand type.

includes a compatibility constraint as well, which ought to have been checked 
by static semantics as well. (That part of the wording triggered my comment in
the first place, a "why here, but not there?"-question).

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

From: Claire Dross
Sent: Thursday, April 30, 2020  3:28 AM

Honestly, I think I will need some help to understand the rationale of the 
rules for passing of OUT parameters with default values. Yesterday, we said 
that we did not want a null procedure to deinitialize a scalar variable whose
type has a Default_Value aspect. But I don't really understand why. Surely 
null procedures will deinitialize variables which don't have this aspect, and
this is a bounded error, right? So to say it otherwise, I think

   procedure P (X : out T) is
   begin
      null;
   end P;

where T is an integer type without a Default_Value is wrong. Why should we do 
anything to support correctly (reject correctly) the corner case of call to 
such a function on a view conversion?

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

From: Jeff Cousins
Sent: Thursday, April 30, 2020  3:57 AM

To be honest, I agree with Claire. To not assign anything to an out parameter 
is plain wrong so I don't see why we should go to a lot of trouble to get it 
to return something sensible in certain circumstances. (A former colleague 
used somewhat stronger language).

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

From: Tucker Taft
Sent: Thursday, April 30, 2020  8:08 AM

One of the fundamental "promises" associated with types with a default, is 
they never become de-initialized.

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

From: Erhard Ploedereder
Sent: Thursday, April 30, 2020  8:28 AM

To me, the foremost reason in favor of the AI is that I would like to rely on 
the fact that any variable with specified default_value is guaranteed to 
always be initialized. No buts, ifs, and whens, or special cases or corners 
that I need to check for after all.

Just like non-null types .... no buts, ifs, except whens....

And as to risk: a deinitialized Integer is almost as bad as a deinitialized 
access value. All I need to do is use it as index into an array, where 
matching subtype properties are statically established and hence the index 
check unnecessary. (I can even exploit that security hole by placing the 
"right value" into place by a preceeding call.)

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

From: Claire Dross
Sent: Thursday, April 30, 2020  8:51 AM

> To me, the foremost reason in favor of the AI is that I would like to
> rely on the fact that any variable with specified default_value is
> guaranteed to always be initialized. No buts, ifs, and whens, or special
> cases or corners that I need to check for after all.

But do we achieve that by the above?  
Here is an example:

procedure Test_Out_Param with SPARK_Mode is
   type My_Neg is new Integer range Integer'First .. -1 with
     Default_Value => -1;
   type My_Pos is new Integer range 1 .. Integer'Last with
     Default_Value => 1;

   procedure P (X : out My_Neg) is
   begin
      null;
   end P;

   Y : My_Pos;
begin
   P (My_Neg (Y));
end Test_Out_Param;

With the change proposed in this AI, I get that after a call to P, Y 
indeed is still properly initialized. But what about inside P? Certainly
X is not in the bounds of My_Neg, and the fact that its initial value is set 
by the default of some other type or not does not change anything about 
that...

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

From: Tucker Taft
Sent: Thursday, April 30, 2020  9:04 AM

Being initialized, but out of range, and having a random uninitialized value, 
are two different things.  A compiler cannot assume an OUT parameter is 
initialized to an in-range value.  But if it has a default, it can assume it 
is not a random bit pattern, so a constraint check, for example, will have a 
well-defined result.

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

From: Bob Duff
Sent: Thursday, April 30, 2020  9:20 AM

> To me, the foremost reason in favor of the AI is that I would like to 
> rely on the fact that any variable with specified default_value is 
> guaranteed to always be initialized. No buts, ifs, and whens, or 
> special cases or corners that I need to check for after all.
> 
> Just like non-null types .... no buts, ifs, except whens....

Right, that's the property this AI is trying to preserve.

> And as to risk: a deinitialized Integer is almost as bad as a 
> deinitialized access value. All I need to do is use it as index into 
> an array, where matching subtype properties are statically established 
> and hence the index check unnecessary. (I can even exploit that 
> security hole by placing the "right value" into place by a preceeding 
> call.)

True in Ada 83, but now it's a bounded error, so "A(I) := ..."
must either modify some element of A, or raise an exception if I is invalid.

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

From: Claire Dross
Sent: Thursday, April 30, 2020  9:22 AM

> Being initialized, but out of range, and having a random uninitialized 
> value, are two different things.  A compiler cannot assume an OUT parameter 
> is initialized to an in-range value.  But if it has a default, it can 
> assume it is not a random bit pattern, so a constraint check, for example, 
> will have a well-defined result.

I must say the difference on integer types does not seem obvious to me. And 
the problem raised by Erhard seems to still occur?

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

From: Bob Duff
Sent: Thursday, April 30, 2020  11:49 AM

> I must say the difference on integer types does not seem obvious to 
> me. And the problem raised by Erhard seems to still occur?

No, adding to your earlier example:

procedure Test_Out_Param with SPARK_Mode is
   type My_Neg is new Integer range Integer'First .. -1 with
     Default_Value => -1;
   type My_Pos is new Integer range 1 .. Integer'Last with
     Default_Value => 1;

   A : array (My_Neg range -1 .. -1) of Integer := (others => 0);

   procedure P (X : out My_Neg) is
   begin
      A (X) := 123; -- Constraint_Error raised here.
   end P;

   Y : My_Pos;
begin
   P (My_Neg (Y));
end Test_Out_Param;

The above is required to raise C_E rather than trash some memory location.
GNAT does that correctly (at least for this example).

The compiler is not allowed to eliminate checks based purely on the subtype's 
range -- it must also prove that the value is valid. This was an Ada 95 
change.

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

From: Bob Duff
Sent: Thursday, April 30, 2020  11:53 AM

Here's another variation on that example:

procedure Test_Out_Param with SPARK_Mode is
   type My_Neg is new Integer range Integer'First .. -1 with
     Default_Value => -1;
   type My_Pos is new Integer range 1 .. Integer'Last with
     Default_Value => 1;

   procedure P (X : out My_Neg) is
   begin
      X := -1;
   end P;

   Y : My_Pos;
begin
   P (My_Neg (Y)); -- Constraint_Error raised on copy back.
end Test_Out_Param;

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

From: Randy Brukardt
Sent: Thursday, April 30, 2020  2:02 PM

>Just like non-null types .... no buts, ifs, except whens....

Actually, there is one "but" with null exclusions, one that I noticed working 
on this AI:

    Ptr : Some_Ptr := null;

    procedure P (A : out not null Some_Ptr) is
        -- Can't assume that A is not null here.
    end P;

    P (Ptr);

A null exclusion on an out parameter cannot be assumed to be true, since there 
is no way to initialize it with a non-null value if the actual is in fact null 
(as in this example). We surely don't want to be conjuring a junk object out 
of the ether just so we can pass it on the possible chance that someone might 
read it. And we don't want to be raising exceptions for passing a value that 
probably never will be used.

Which probably goes to show that there is no rule that has no exceptions. :-)

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

From: Tucker Taft
Sent: Thursday, April 30, 2020  2:16 PM

For OUT parameters, you generally have to assume the constraints are *not* 
satisfied on the way in.  The point about having a default value, as do all 
access objects, is that you can presume it has a *well defined* value.  The 
constraints on an "out" parameter are checked only on the way "out" so you 
should interpret an out parameter as always being a completely unconstrained 
object initially, that has some constraints you had better satisfy before you
do a return.

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

From: Randy Brukardt
Sent: Thursday, April 30, 2020  2:45 PM

Right. But that means that whatever you can assume about every other object 
in an Ada program does not apply to "out" parameters. (with the exception of
the tag and accessibility checks that would be impossible to properly check 
on a usage, the focus of AI12-0378-1, the split from AI12-0377-1 as requested
yesterday). My point to Erhard's statement is that there is always a "but" 
when it comes to "out" parameters.

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

From: Richard Wai
Sent: Thursday, April 30, 2020  2:59 PM

I always saw such null excluded out parameters as expressing a contract on 
the subprogram. So a null exclusion on an “out” parameter is a contract which
states that the subprogram promises to set the parameter to something not null.
Similarly if you had an out parameter of some constrained subtype, that’s a 
contract on the subprogram to produce a value of that subtype.

I don’t see anything wrong with this:

Type Day is (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday);

Subtype Workday is Day range Monday .. Friday;

Procedure Next_Meeting (On_Day: out Workday);

My_Busy_Day: Day := Saturday;

Next_Meeting (My_Busy_Day);

The contract is that Next_Meeting should only give me a Workday. But I 
shouldn’t be stopped from using a parameter of Day, especially if it is not 
already set to a value in the range of Workday..

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

From: Erhard Ploedereder
Sent: Friday, May 1, 2020  8:10 AM

Interesting ....  but maybe there was a bug in the example? The semantics 
that you describe seems too be "in out" semantics.

See --  for inserts and remarks ...

>> I must say the difference on integer types does not seem obvious to 
>> me. And the problem raised by Erhard seems to still occur?
> 
> No, adding to your earlier example:
> 
> procedure Test_Out_Param with SPARK_Mode is
>    type My_Neg is new Integer range Integer'First .. -1 with
>      Default_Value => -1;
>    type My_Pos is new Integer range 1 .. Integer'Last with
>      Default_Value => 1;
> 
>    A : array (My_Neg range -1 .. -1) of Integer := (others => 0);

-- added another array
     B : array (My_Pos range 1 .. 1) of Integer := (others => 0);
> 
>    procedure P (X : out My_Neg) is
>    begin
>       A (X) := 123; -- Constraint_Error raised here.

-- I would have expected that the Default_Value -1 applies and A(-1)
-- is perfectly fine, but
        B (X) := 123; -- has to raise Constraint_Error for B(-1)

>    end P;
> 
>    Y : My_Pos;
> begin
>    P (My_Neg (Y));

-- has to raise Constraint_Error on the way out, when X (=-1) gets
-- written to Y per copy semantics for scalars

> end Test_Out_Param;

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

From: Bob Duff
Sent: Friday, May 1, 2020  10:28 AM

> Interesting ....  but maybe there was a bug in the example? The 
> semantics that you describe seems too be "in out" semantics.

Right, 'out' parameters sometimes pass information IN, which is strange.

> >       A (X) := 123; -- Constraint_Error raised here.
> 
> -- I would have expected that the Default_Value -1 applies and A(-1)
> -- is perfectly fine, but

That's not an unreasonable expectation, but I guess that's not what language 
designers decided.  The goal was "if it has a default, it can't get 
deinitialized", and never mind if the default is outside the bounds of the 
subtype, as we see in these weird 'out' param cases.

>         B (X) := 123; -- has to raise Constraint_Error for B(-1)
> 
> >    end P;
> >
> >    Y : My_Pos;
> > begin
> >    P (My_Neg (Y));
> 
> -- has to raise Constraint_Error on the way out, when X (=-1) gets
> -- written to Y per copy semantics for scalars

If it were assigned to -1 inside the procedure, then it would raise C_E on copy 
back.  But if it's not assigned at all (which is a weird thing to do), then it 
remains +1, which copies back without C_E.

Not sure I would have designed it that way...

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

From: Erhard Ploedereder
Sent: Friday, May 1, 2020  11:16 AM

> Right, 'out' parameters sometimes pass information IN, which is 
> strange.

Well, yes, sometimes, but not the value in the scalar case with copy 
semantics. My reading of the Manual says that the value is uninitialized
in the absence of Default_Value (8.6.1 (15)), or initialized to a specfified
Default_Value (8.6.1.(13)). There is no third case. In consequence, the final
value is just that if X is not assigned to in the body.

So, your expectation that "1" from Y arrives at X is not justified by 
anything in the manual, or is it? And, if the actual value were always passed 
in, the Default_Value on out parameters would never engage and hence be 
utterly useless.

It may be strange that it always engages for scalar outs, but I much prefer 
that to deinitialized variables despite an assertion to the contrary.

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

From: Randy Brukardt
Sent: Friday, May 1, 2020  12:29 PM

>> Right, 'out' parameters sometimes pass information IN, which is
>> strange.

>Well, yes, sometimes, but not the value in the scalar case with copy
>semantics.
>My reading of the Manual says that the value is uninitialized in the
>absence of Default_Value (8.6.1 (15)), 

You mean 6.4.1(15).
 
>or initialized to a specfified
>Default_Value (8.6.1.(13)).

6.4.1(13) is about access types (and is one the the rules we need to change 
slightly). 

6.4.1(13.1/4) is about types with Default_Value and it does not say that. 
It says the value of the actual is passed it without any check. That's the 
semantics that Ichbiah picked for out parameters like access and composites.

I suppose we *could* have done something different regardless (it was a 
totally new feature), but it's getting rather late to change basic semantics 
of an Ada 2012 feature. Especially to silently change the semantics of 
existing, legal code -- that's the worst kind of incompatibility.

>There is no third case. In consequence, the
>final value is just that if X is not assigned to in the body.

That's true, but you have dreamed up semantics that doesn't exist in the RM.

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

From: Erhard Ploedereder
Sent: Friday, May 1, 2020  6:05 PM

Sorry that I mistyped the references. I meant 6.4.1. in both cases.
Here they are again in corrected form:

My reading of the Manual says that the value is uninitialized in the absence
of Default_Value (6.4.1 (15)), or initialized to ... (6.4.1.(13.1/4)).

But you are right. I imagined semantics that never existed. I didn't even read 
the sentence to its conclusion because it was so obvious what the initial 
value would be. It is hard to believe that the semantics of Default_Value for
out parameters are so misleading -- the type says that the default initial 
value is 1, and then means that the initial value is taken from the actual.

Ok. Case closed for me, since the RM is consistent albeit very surprising.

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

From: Tucker Taft
Sent: Saturday, May 2, 2020  7:46 AM

>To be honest, I agree with Claire. To not assign anything to an out 
>parameter is plain wrong so I don't see why we should go to a lot of trouble 
>to get it to return something sensible in certain circumstances. (A former 
>colleague used somewhat stronger language).

I remember Bob Morgan used to say something like: "Just because it is 
erroneous doesn't mean we should generate code that deletes the disk."

The fact is that most programs contain code whose execution might result in 
erroneous execution or produce a bounded error. 

We provide certain guarantees so that even though the code may be buggy, you 
know the consequences are limited.  Ada's access types have always made the 
guarantee that an access value is never complete junk.  When we introduced the 
Default_Value aspect, our goal was to make the same guarantee, namely that a 
value of a type with a Default_Value is never complete junk.  You may believe 
that was a mistake, but we made it many years ago, and at this point, I think 
we should not withdraw that guarantee.

We have discovered a corner case with view conversions.  I don't think that 
means we should say: the guarantee holds except in certain corner cases.  We 
should come up with a reasonable rule for this corner case.

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

From: Tullio Vardanega
Sent: Saturday, May 2, 2020  7:51 AM

This is my view also. Not a view conversion, though.

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

From: Claire Dross
Sent: Monday, May 4, 2020  1:50 AM

>I don’t see anything wrong with this:
>
>Type Day is (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday);
>
>Subtype Workday is Day range Monday .. Friday;
>
>Procedure Next_Meeting (On_Day: out Workday);
>
>My_Busy_Day: Day := Saturday;
>
>Next_Meeting (My_Busy_Day);
>
>The contract is that Next_Meeting should only give me a Workday. But I 
>shouldn’t be stopped from using a parameter of Day, especially if it is not 
>already set to a value in the range of Workday..

What is more dubious is that nothing prevents me from not setting On_Day to a 
Workday in Next_Meeting, and so, even if day has a default value. 

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

From: Erhard Ploedereder
Sent: Friday, May 1, 2020  8:10 AM

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

Questions? Ask the ACAA Technical Agent