Rationale for Ada 2012

John Barnes
Contents   Index   References   Search   Previous   Next 

4.6 Extended return statements

The final topic in this chapter is the extended return statement. This was introduced in Ada 2005 largely to solve problems with limited types. However, some glitches have come to light and these are corrected in Ada 2012.
A description of the reasons for and general properties of the extended return statement will be found in 15.
The syntax for extended return statement in Ada 2005 as found in 5 is
extended_return_statement ::=
   return defining_identifier: [aliased] return_subtype_indication [:= expression] [do
      handled_sequence_of_statements
   end return];
Before going further, it should be mentioned that there was some confusion regarding limited types and so the term immutably limited was introduced in the course of the maintenance of Ada 2005. There were various problems. Basically, limitedness is a property of a view of a type. Thus even in Ada 83 a private type might be limited but the full view found in the private part would not be limited. Ada 95 introduced explicitly limited types. Ada 2005 introduced coextensions and these could even include such obviously limited things as task types thus adding a limited part to what was otherwise a seemingly nonlimited type. It became clear that it was necessary to introduce a term which meant that a type was really and truly limited and could not subsequently become nonlimited for example in a private part or in a child unit. So a type is immutably limited if
it is an explicitly limited record type,
it is a task type, protected type or synchronized interface,
it is a non-formal limited private type that is tagged or has an access discriminant with a default expression,
it is derived from an immutably limited type. 
It was then realised that there were problems with extended return statements containing an explicit aliased. Consequently, it was decided that there was really no need for aliased if there was a rule that immutably limited return objects were implicitly aliased. So aliased was removed from the syntax. However, some users had already written aliased and this would have introduced an irritating incompatibility. So finally it was decided that aliased could be written but only if the type were immutably limited.
Another small problem concerned constants. Thus we might write
return X: T do
   ...    -- compute X
end return;
However, especially in the case of a limited type LT, we might also give the return object an initial value, thus
return X: LT := (A, B, C) do
   ...    -- other stuff
end return;
Now it might be that although the type as a whole is limited one or more of its components might not be and so could be manipulated in the sequence of statements. But if we want to ensure that this does not happen, it would be appropriate to indicate that X was constant. But, almost surely by an oversight, we cannot do that since it is not permitted by the syntax. So the syntax needed changing to permit the addition of constant.
To aid the description the syntax in Ada 2012 is actually written as two productions as follows
extended_return_object_declaration ::=
   defining_identifier: [aliased] [constant] return_subtype_indication [:= expression]
extended_return_statement ::=
   return extended_return_object_declaration [do
      handled_sequence_of_statements
   end return;
The other small change to the extended return statement concerns the subtype given in the profile of the function and that in the extended return statement itself. The result type of the function can be constrained or unconstrained but that given in the extended return statement must be constrained.
This can be illustrated by considering array types. (These examples are from 15.) Suppose we have
type UA is array (Integer range <>) of Float;
subtype CA is UA(1 .. 10);
then we can write
function Make( ... ) return CA is
begin
   ...
   return R: UA(1 .. 10) do    -- statically matches
      ...
   end return;
end Make;
This is allowed because the subtypes statically match.
If the subtype in the function profile is unconstrained then the result must be constrained either by its subtype or by its initial value. For example
function Make( ... ) return UA is
begin
   ...
   return R: UA(1 .. N) do
      ...
   end return;
end Make;
and here the result R is constrained by its subtype. A similar situation can arise with records with discriminants. Thus we can have
type Person(Sex: Gender) is ... ;
function F( ... ) return Person is
begin
   if ... then
      return R: Person(Sex => Male) do
         ...
      end return;
   else
      return R: Person(Sex => Female) do
         ...
      end return;
   end if;
end F;
which shows that we have the possibility of returning a person of either gender.
However, what is missing from Ada 2005 is that we can have analogous situations with tagged types in that a function might wish to return a value of some type in a class.
So we would like to write things such as
function F( ... ) return Object'Class is
begin
   if ... then
      return C: Circle do
         ...
      end return;
   elsif ... then
      return S: Square do
         ...
      end return;
    end if;
end F;
This is not permitted in Ada 2005 which required the types to be the same. This can be overcome by writing
return C: Object'Class := Circle_Func do
   ...
end return;
where Circle_Func is some local function that returns the required object of type Circle.
This is all rather irksome so the wording is changed in Ada 2012 to say that in this situation the subtype in the extended return statement need not be the same as that in the profile but simply must be covered by it. There are also related slight changes to the accessibility rules.

Contents   Index   References   Search   Previous   Next 
© 2011, 2012, 2013 John Barnes Informatics.
Sponsored in part by:
The Ada Resource Association:

    ARA
  AdaCore:


    AdaCore
and   Ada-Europe:

Ada-Europe