Version 1.1 of ai05s/ai05-0228-1.txt

Unformatted version of ai05s/ai05-0228-1.txt version 1.1
Other versions for file ai05s/ai05-0228-1.txt

!standard 3.3.1(10)          10-10-22 AI05-0228-1/01
!standard 3.3.1(21)
!class Amendment 10-10-22
!status work item 10-10-22
!status received 10-10-22
!priority Medium
!difficulty Easy
!subject Default initial values for types
!summary
(See proposal.)
!problem
The new predicate (see AI05-0153-1) and invariant (see AI05-0146-1) aspects provide unreliable results for objects that are not initialized. This can be prevented when a default initial value is provided.
It is easy to provide a default initial value for record types, and access types have one defined by the language, but for other kinds of types, it is impossible.
This seems bizarre, given that implementations have the capability of doing default initialization (as for record and access types).
!proposal
Add an aspect Default_Value, that can be used on all types.
!wording
Modify 3.3.1(10):
For an object_declaration without an initialization expression, any initial values for the object or its subcomponents are determined by the implicit initial values defined for its nominal subtype{. If the subtype has the Default_Value aspect specified, the implicit initial value is the value of that aspect. Otherwise, the value is determined}[,] as follows:
Modify 3.3.1(21):
There is no implicit initial value for a scalar subtype{ unless the Default_Value aspect has been specified for the type}. In the absence of an explicit initialization{ or the explicit specification of the Default_Value aspect}, a newly created scalar object might have a value that does not belong to its subtype (see 13.9.1 and H.1).
Add after 3.3.1(21): [Better place for this?]
Static Semantics
For a full type, the following language-defined aspect may be specified with an aspect_specification:
Default_Value
This aspect shall be specified by an expression, called an *default value expression*. Type_Invariant may be specified on a full_type_declaration.
Name Resolution
The expected type for a default value expression is the type defined by the full_type_declaration.
Dynamic Semantics
The default value expression is evaluated at the first freezing point of the type, and the result becomes the value of the aspect for the type.
!discussion
It is important that the default initial value be something that makes sense for the type. Simply initializing everything to zero is just as likely to cover bugs as eliminate them.
However, if a type has a value specifically that means "Unknown" or "Undefined", it makes perfect sense to initialize all objects to that value. That would greatly reduce the chances of invalid objects of the type existing.
!examples
Providing a default initial value for an enumeration type with an unknown value:
type Item_State is (Unknown, Fooey, Blarch, ...) with Default_Value => Unknown;
Providing a default initial value for an access type with a null exclusion (in Ada 2005, any default initialized object of this type would raise Constraint_Error):
type My_Access is not null access My_Rec with Default_Value => Unknown_Ptr; Unknown_Ptr : constant My_Access := new My_Rec'(Kind => Unknown);
This is taking advantage of the deferred resolution of aspects.
!ACATS test
ACATS tests would be needed for this aspect.
!appendix

[Editor's note: This thread forked off of a discussion of predicates.]

From: Robert Dewar
Sent: Wednesday, October 13, 2010  11:21 AM

> Well, yeah.  We get a lot of support calls about uninit vars.
> Too bad there's no language feature to prevent those bugs.

All language features that "fix" uninitialized variables are evil. Requiring
default initialization or providing default implicit initialization are
particularly evil in my view.

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

From: Bob Duff
Sent: Wednesday, October 13, 2010  12:33 PM

> All language features that "fix" uninitialized variables are evil.

I won't touch that with a barge pole.  ;-)

Anyway, it's irrelevant to my point, which is that uninit vars are a loophole in
constraints, so the argument "predicates must be loophole-free, because
constraints are" is bogus.

>... Requiring default initialization or providing default  implicit
>initialization are particularly evil in my view.

I certainly agree with that.

Too bad JDI didn't (I'm talking about access types).

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

From: Tucker Taft
Sent: Wednesday, October 13, 2010  1:01 PM

>> ... Requiring default initialization or providing default implicit
>> initialization are particularly evil in my view.
>
> I certainly agree with that.
>
> Too bad JDI didn't (I'm talking about access types).

The default initial value of "null" for an access type seems OK, since you get
an exception if you try to use it as though it had a usable non-null value.

It is a default initial value of zero that is dangerous, since it is not
distinguishable from a "true" initial value of zero.  If there were a "null"
value for all types, which corresponded roughly to a floating point signaling
NaN, that would be fine in my view.  You would get notified if you tried to do
anything that presumed the object had an "intentional" initial value.

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

From: Randy Brukardt
Sent: Wednesday, October 13, 2010  1:50 PM

Right. The annoying thing is that Ada doesn't have a way to set a default
initial value for scalar and array types, for those cases where there is an
"obviously" bad value. For instance, many of my enumeration types have an value
of "unknown" or something like that. It's purpose is exactly to provide a value
for those cases where something has gone wrong or nothing has been calculated
yet. Typically, it would be used (manually of course) as a default initial value
for objects; it would be nice to be able to force all objects to start with that
value rather than random garbage. Ada compilers clearly have the mechanism to
deal with default initializations (because of access types and record
components), so it is annoying that the programmer can't use that when it is
appropriate.

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

From: Robert Dewar
Sent: Wednesday, October 13, 2010  5:29 PM

TW, on the IM 7040, there was a great instruction intended only for system
diagnostics to set parity wrong on a specified word.

WATFor fortran used this to initialize all uninitialized variables (under some
option flag). And you got a parity error if you tried to load the value.

BTW, I don't think it is worth spending too much time on different checking
modes. Compilers will likely provide different checking modes anyway, whatever
the standard says.

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

From: Robert Dewar
Sent: Wednesday, October 13, 2010  5:27 PM

>> It is a default initial value of zero that is dangerous, since it is
>> not distinguishable from a "true" initial value of zero.  If there
>> were a "null" value for all types, which corresponded roughly to a
>> floating point signaling NaN, that would be fine in my view.  You
>> would get notified if you tried to do anything that presumed the
>> object had an "intentional" initial value.

Big overhead in the array case having to check, and the trouble is that you MUST
be able to have 32 tc integers, represented in the obvious way. It would be a
menace if Ada insisted on stealing one value.

> Ada
> compilers clearly have the mechanism to deal with default
> initializations (because of access types and record components), so it
> is annoying that the programmer can't use that when it is appropriate.

Good point, I think I will invent a pragma. In fact the obvious pragma to extend
is

pragma Initialize_Scalars;

and allow the usage

pragma Initialize_Scalars (local_type_NAME);

20 minutes work to allow this!

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

From: Randy Brukardt
Sent: Wednesday, October 13, 2010  5:44 PM

> >> It is a default initial value of zero that is dangerous, since it
> >> is not distinguishable from a "true" initial value of zero.  If
> >> there were a "null" value for all types, which corresponded roughly
> >> to a floating point signaling NaN, that would be fine in my view.
> >> You would get notified if you tried to do anything that presumed
> >> the object had an "intentional" initial value.
>
> Big overhead in the array case having to check, and the trouble is
> that you MUST be able to have 32 tc integers, represented in the
> obvious way. It would be a menace if Ada insisted on stealing one
> value.

I agree that it doesn't make sense to do it in all cases; it's just odd to not
have the capability when it is useful. [That's Tucker's quote, BTW.]

> > Ada
> > compilers clearly have the mechanism to deal with default
> > initializations (because of access types and record components), so
> > it is annoying that the programmer can't use that when it is appropriate.
>
> Good point, I think I will invent a pragma. In fact the obvious pragma
> to extend is
>
> pragma Initialize_Scalars;
>
> and allow the usage
>
> pragma Initialize_Scalars (local_type_NAME);
>
> 20 minutes work to allow this!

At one point, someone suggested having an aspect for this purpose. That would
look something like:

    type Item_State is (Unknown, Fooey, Blarch, ...) with Default_Initial_Value => Unknown;

This seems like a good use for an aspect, given that it isn't something that
ought to be dependent on the view of the type (or subtype, if we wanted to allow
that).

The (minor) advantage of the aspect over the pragma is that it allows the
default value to be specified; that might be helpful if the "Unknown" value is
not the first one in the enumeration.

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

From: Robert Dewar
Sent: Wednesday, October 13, 2010  6:00 PM

Well we could allow a default value for Initialize_Scalars or some other pragma.
IS in GNAT is not always the lowest value, and can in fact be changed at link
time or even execution time (the idea is to try different initial values and see
if has an observable effect

A disadvantage of an aspect if that is the only mechanism is that it is
restricted to Ada 2012 mode. We have a lot of customers still stuck at Ada 95
(partly because of the high level of incompatibility between Ada 95 and Ada
2005).

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

From: Tucker Taft
Sent: Wednesday, October 13, 2010  6:10 PM

I believe we already discussed something along these lines in the recent ARG
meeting.  Didn't we invent an aspect spec like "with Default => blah"? Or am I
dreaming that?

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

From: Randy Brukardt
Sent: Wednesday, October 13, 2010  6:37 PM

I think we invented it, but I don't think anyone took ownership of it and got it
added to the agenda. As such, it is now too late (it wasn't included in the
scope approved by WG 9), unless someone can figure out a reason why we need to
add it for one of the existing AIs.

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

From: Robert Dewar
Sent: Wednesday, October 13, 2010  6:47 PM

Sounds good to me, I think I will implement the aspect and the corresponding
pragma, so it really doesn't matter too much if it gets into the standard. It's
a good idea!

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

From: Jean-Pierre Rosen
Sent: Thursday, October 14, 2010  3:48 AM

I was about to suggest an aspect too, but Randy shot first...

> A disadvantage of an aspect if that is the only mechanism is that it
> is restricted to Ada 2012 mode. We have a lot of customers still stuck
> at Ada 95 (partly because of the high level of incompatibility between
> Ada 95 and Ada 2005).

OTOH, people will move to the new versions if the benefits balance the
disagreements. Providing nice features in the most recent modes is a way to push
them.

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

From: Robert Dewar
Sent: Thursday, October 14, 2010  6:13 PM

Well in fact in GNAT we systematically provide pragmas to match all aspects in
any case, the way the internal implementation of aspects work is to translate to
the corresponding pragma or attribute definition clause. So for example, we now
have pragma predicate and pragma invariant in GNAT.

We are more in the business of providing useful features to people than pushing
them to use the latest version of Ada. As I say, the biggest barrier is the
rather fierce upwards incompatibility of Ada 2005, this has resulted in a
barrier for several large users (the issue with return of limited stuff).

We have talked about a mode which would provide Ada 95 + all compatible
features, but this is quite a bit of work.

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

Questions? Ask the ACAA Technical Agent