Version 1.11 of ai12s/ai12-0378-1.txt

Unformatted version of ai12s/ai12-0378-1.txt version 1.11
Other versions for file ai12s/ai12-0378-1.txt

!standard 6.4.1(13/3)          20-08-28 AI12-0378-1/06
!standard 6.4.1(18/3)
!class Binding Interpretation 20-06-18
!status Amendment 1-2012 20-07-07
!status WG9 Approved 22-06-22
!status ARG Approved 12-1-1 20-09-09
!status work item 20-04-29
!status received 20-03-26
!priority Low
!difficulty Medium
!subject View conversions and out parameters of access types revisited
!summary
In the case of an actual out parameter that is a view conversion between two access types with no common ancestor, an implementation permission is granted allowing implementations to pass in the null value of the formal parameter type instead of the value of the actual parameter.
!question
The legality rule that prevents view conversions of unrelated access types for out parameters is a compatibility problem in practice. When AdaCore implemented this in GNAT, a significant number of tests in their customer regression test suite failed to compile. Should we handle such view conversions in a more compatible way? (Yes.)
!recommendation
(See Summary.)
!wording
Replace 6.4.1(13/3) with:
* For an access type, the formal parameter is initialized from the value of the actual, without checking whether the value satisfies any constraints, predicates, or null exclusions, but including any [Redundant: dynamic] accessibility checks associated with a conversion to the type of the formal parameter.
AARM Ramification: The permission to pass null can be used in any case where an accessibility check could fail, rather than making a check.
Add after RM 6.4.1(18/3):
Implementation Permissions
If the actual parameter in a parameter_association with mode out is a view conversion between two access types that do not share a common ancestor type, the implementation may pass in the null value of the type of the formal parameter instead of the value of the actual parameter. It is implementation-defined under what circumstances the implementation passes in the null value.
Add after AARM 6.4.1(18.i/3):
Inconsistencies with Ada 2012
Correction: Added a permission to pass null so that value passed into an out parameter for access types is well-defined in the case of a view conversion. Null may be passed for any view conversion between unrelated access types; this is important for conversions that may have problematic accessibility or tags. If the permission is used and the out parameter is read before it is written (perhaps to read a bound or discriminant), Constraint_Error may be raised by Ada 202x when it would not have been in Ada 2012. Additionally, if the called subprogram does not write the out parameter at all, the actual object will be overwritten with null (and possibly raise Constraint_Error if the object is null excluding), while the object would be unchanged in Ada 2012. Such cases are thought to be rare, as most out parameters of access types are overwritten before being read. In addition, at least one widely-used Ada compiler already passes null in these cases.
Modify AARM 6.4.1(18.j/4): [to remove any mention of access types - there is no longer any compile-time incompatibility; this also updates the text for AI12-0377-1]
Corrigendum: Added rules to ensure that the value passed into a{n} out parameter for {scalar}[elementary] types is well-defined in the case of a view conversion. The new rules can be incompatible. {View conversions from/} [for a view conversion ]to an unrelated type with the Default_Value aspect specified[,] { are unlikely to occur in existing code, as} the aspect is new in Ada 2012[ so it should be unlikely to occur in existing code]. [for a view conversion to an unrelated access type, the incompatibility is possible as this could be written in Ada 95, but such a view conversion is thought to be rare. in both cases, ]{D}eclaring and passing a temporary rather than a view conversion will eliminate the problem.
!discussion
It's fairly clear that we cannot have the original Legality Rule, as it seems too incompatible. However, this problem occurs not only for access types with different sizes (as outlined in the original AI12-0074-1), but also for any case where the generated code may need to know details about an out parameter. Three such cases were identified in the e-mail attached to AI12-0074-1:
[A] Cases involving discriminant checks; [B] Cases involving tag checks; [C] Cases involving accessibility checks.
These cases can be seen in the test program given at the start of the !appendix for this AI (more on this test program below).
An implementation could assume that all out parameters are unconstrained (and thus making the discriminant checks on every use), thus defanging problem [A]. This would not be problematic, and is in fact the rule since Ada 83, so we don't make any change here. However, the tag and accessibility checks are not normally done at usage sites, so assuming implementations will do the right thing could impose a substantial implementation burden for a very unusual case (but one that is not quite as pathological as we expected in AI12-0074-1).
We created a test program to see what existing compilers do in these cases. The test program is reproduced at the start of the !appendix. The test program includes a few preliminary cases to check what an implementation does in cases not involved with the cases in question, then it tries each of the three problematic examples in turn.
Running the test program on a recent version of GNAT (from February 2020) shows that it side-steps this problem by passing null to any out parameter when the actual is an explicit view conversion. The implicit view conversion of derivation works as expected, however, so we have a case where one cannot write the same thing as the compiler does automatically.
Running the test program on a recent version of ObjectAda (thanks to PTC for providing these results): The discriminant and accessibility cases do not compile (ObjectAda rejects the conversions suggesting an Ada 95 implementation of those). ObjectAda fully supports the derived type cases, including using explicit conversions. The tagged type case causes no errors nor obvious overwriting of memory (but it is not clear what successfully writing the nonexistent component actually did).
Running the test program on a recent version of ApexAda (thanks again to PTC for providing these results): The accessibility cases do not compile (ApexAda rejects the conversion with a static accessibility check). ApexAda fully supports the derived type cases, including using explicit conversions. The discriminant case shows that ApexAda does not assume the constraints of an out parameter, so a check was made and Constraint_Error raised. The tagged type case causes no errors nor obvious overwriting of memory (but it is not clear what successfully writing the nonexistent component actually did).
Running the test program on a recent version of Janus/Ada shows that it fully supports the derived type cases; it assumes that out parameters do not enforce their constraints (so that they are effectively unconstrained and raises Constraint_Error when incorrect); other memory is overwritten by the tagged case (execution is erroneous); and the accessibility case does not compile (Janus/Ada does not yet support dynamic accessibility for stand-alone objects of anonymous access types).
---
These results suggest that having certain problematic cases use the GNAT approach of passing null would not be significantly incompatible in practice, as these cases (tag-check or accessibility-level check issues) can already lead to problems in other Ada compilers. Note that GNAT is the only compiler that passes null currently; other compilers implement the language as defined more closely.
Note that an out parameter can always be null, even if the parameter is declared with a null exclusion. Null exclusions are not checked when the parameter is passed in, and null is passed when the actual is not convertible. An implementation should not assume that null exclusions of an out parameter are enforced before the out parameter is written within the subprogram.
We could have required null to be passed for all out parameters of access types. That might have been a more sensible rule for a new language, but the runtime incompatibility created by generally making such a change would be intolerable, so it is much too late to contemplate that.
Note that there is a potential runtime incompatibility with passing null, in that in the absence of an assignment to the OUT parameter, the parameter will nevertheless be set to null, even if the tag and accessibility checks would have passed. We considered always performing the tag and accessibility checks, even on OUT parameters, but this was felt to introduce a "tripping hazard" where the supposedly irrelevant value of an OUT parameter prior to a call nevertheless could produce an exception at runtime under unusual circumstances. We considered passing in null only if a tag or accessibility check would have failed, but this made the runtime model harder to describe and to implement, for what are considered corner cases. We also considered a legality rule disallowing problematic cases, but we felt the potential incompatibilities would be worse. A compile-time rule that would pass null in only the problematic cases was very complicated.
So we settled on an Implementation Permission to allow implementations to pass null in cases that might be problematic. If the implementation doesn't pass null, then it needs to make the accessibility and tag checks. We allow the "tripping hazard" for accessibility checks in that case, but the tag checks have to be made at each use if null is not passed in. The Implementation Permission includes the magic words "implementation-defined" in order to trigger a documentation requirement as to when null will be passed.
---
As far as converting between access types with different representations, the implementation permission also allows passing null if it involves an out parameter with unrelated types. We don't provide any permission or suggestion related to normal conversions or IN OUT parameters in such a case. We presume implementations will do the (implementation-defined) "right thing" in such cases. Similarly, we expect the implementation will do the "right thing" for related types (most likely, not allowing different representations that could be problematic).
!corrigendum 6.4.1(13/3)
Replace the paragraph:
by:
!corrigendum 6.4.1(18/3)
Insert after the paragraph:
If the nominal subtype of a formal parameter with discriminants is constrained or indefinite, and the parameter is passed by reference, then the execution of the call is erroneous if the value of any discriminant of the actual is changed while the formal parameter exists (that is, before leaving the corresponding callable construct).
the new paragraph:
Implementation Permissions
If the actual parameter in a parameter_association with mode out is a view conversion between two access types that do not share a common ancestor type, the implementation may pass in the null value of the type of the formal parameter instead of the value of the actual parameter. It is implementation-defined under what circumstances the implementation passes in the null value.
!ASIS
No ASIS effect.
!ACATS test
An ACATS C-Test is needed to check that the new rules are enforced, rather than the previous rules. The test program given below can be the basis of an ACATS C-Test.
!appendix

From: Randy Brukardt
Sent: Never [Done April 20, 2020]

[Following is the test program for AI12-0378-1.]

with Ada.Text_IO, Ada.Exceptions;
procedure TestAI74 is
begin

    -- Note: The three "problems" were identified during the work on
    -- AI12-0074-1. We're testing what they do on existing implementations
    -- during a revisit of these rules. Note: All of these "problems"
    -- were made illegal by AI12-0074-1, so a correct Ada 2012 implementation
    -- would reject this program. If so, please try each case individually
    -- to provide us the maximum information about runtime behavior.
    -- Note that many of these cases are allowed by Ada 95 and Ada 2005.

    Ada.Text_IO.Put_Line ("Check some nasty cases related to AI12-0378-1");


    -- Behavior of view conversions and derivation
    -- Note: This example is fully legal, no Ada 2012 compiler (or Ada 95
    -- compiler, for that matter) should reject this.
    declare
       package Nest is
           type T (D : Boolean := False) is -- no partial view
              record
                 case D is
                    when False => Bar : Character;
                    when True  => Foo : Integer;
                 end case;
              end record;

           type Unconstrained_Ref is access all T;

           procedure Q (X : out Unconstrained_Ref);
               -- A primitive of Unconstrained_Ref

           type Derived_Ref is new Unconstrained_Ref;

           -- Inherits Q.

       end Nest;

       package body Nest is
           procedure Q (X : out Unconstrained_Ref) is
           begin
              if X.D then
                  X.Foo := 456;
              else
                  X.Bar := 'B';
              end if;
           end Q;
       end Nest;

       X : aliased Nest.T := (D => False, Bar => 'R');
       X_Ref : Nest.Unconstrained_Ref := X'Access;

       Der_X_Ref : Nest.Derived_Ref := X'Access;

    begin
        -- Direct call to Q:
        begin
          Nest.Q (X_Ref);
          if X.Bar /= 'B' then
             Ada.Text_IO.Put_Line ("** Component not changed");
          else
             Ada.Text_IO.Put_Line ("-- Expected result, no conversion");
          end if;
        exception
          when Err:others =>
             Ada.Text_IO.Put_Line ("** Failed: Exception raised (no conversion) - " &
                                        Ada.Exceptions.Exception_Information (Err));
        end;
        -- View conversion to parent type:
        begin
          X.Bar := 'R';
          Nest.Q (Nest.Unconstrained_Ref (Der_X_Ref));
          if X.Bar /= 'B' then
             Ada.Text_IO.Put_Line ("** Component not changed");
          else
             Ada.Text_IO.Put_Line ("-- Expected result, explicit parent conversion");
          end if;
       exception
          when Err:others =>
             Ada.Text_IO.Put_Line ("** Failed: Exception raised (explicit parent conversion) - " &
                                        Ada.Exceptions.Exception_Information (Err));
       end;
       -- Call to inherited routine (implicit view conversion to parent type):
       begin
          X.Bar := 'R';
          Nest.Q (Der_X_Ref);
          if X.Bar /= 'B' then
             Ada.Text_IO.Put_Line ("** Component not changed");
          else
             Ada.Text_IO.Put_Line ("-- Expected result, inherited routine");
          end if;
       exception
          when Err:others =>
             Ada.Text_IO.Put_Line ("** Failed: Exception raised (inherited routine) - " &
                                        Ada.Exceptions.Exception_Information (Err));
       end;
    end;

    -- A discriminant problem
    declare
       type T (D : Boolean := False) is -- no partial view
          record
             case D is
                when False => Bar : Character;
                when True  => Foo : Integer;
             end case;
          end record;

       type Unconstrained_Ref is access all T;
       type Constrained_Ref is access all T (True);

       X : aliased T := (D => False, Bar => 'R');
       X_Ref : Unconstrained_Ref := X'Access;

       procedure P (X : out Constrained_Ref) is
       begin
          X.Foo := 123;
            --  We don't want to require a discriminant
            --  check here.
       end P;

    begin
       P (Constrained_Ref (X_Ref));
       if X.D /= False then
           Ada.Text_IO.Put_Line ("** Discriminant changed");
       else
           Ada.Text_IO.Put_Line ("?? Possible erroneous execution");
           Ada.Text_IO.Put_Line ("?? X.Bar'Pos = " & Natural'Image (Character'Pos (X.Bar)));
       end if;
    exception
       when Err2:Constraint_Error =>
          Ada.Text_IO.Put_Line ("-- Discriminant check made anyway - " &
                                    Ada.Exceptions.Exception_Information (Err2));
       when Err:others =>
          Ada.Text_IO.Put_Line ("** Exception raised (disc) - " & Ada.Exceptions.Exception_Information (Err));
    end;

    -- A tag problem
    declare
       type Root is tagged null record;
       type Ext is new Root with record F : Integer; end record;

       type Root_Ref is access all Root'Class;
       type Ext_Ref is access all Ext;

       procedure P (X : out Ext_Ref) is
       begin
          X.F := 123;
            -- No tag check is performed here and
            -- we don't want to add one.
          X := null;
       end P;

       R : aliased Root;
       O : Integer := 12;
       Ptr : Root_Ref := R'Access;
    begin
       P (Ext_Ref (Ptr));
       Ada.Text_IO.Put_Line ("?? Possible erroneous execution");
       if R not in Root then
           Ada.Text_IO.Put_Line ("** Object tag changed");
       end if;
       if O /= 12 then
           Ada.Text_IO.Put_Line ("** Following object clobbered to " & Integer'Image(O));
       end if;
    exception
       when Err:others =>
          Ada.Text_IO.Put_Line ("-- Exception raised (tag) - " & Ada.Exceptions.Exception_Information (Err));
    end;

    -- An accessibility problem
    declare
       type Int_Ref is access all Integer;
       Dangler : Int_Ref;
       procedure P (X : out Int_Ref) is
       begin
          Dangler := X;
            -- No accessibility checks are performed here.
            -- We rely here on the invariant that
            -- a value of type Int_Ref cannot designate
            -- an object with a shorter lifetime than Int_Ref.
          X := null;
       end P;

       procedure Q is
          Local_Int : aliased Integer;
          Standalone : access Integer := Local_Int'Access;
       begin
          P (Int_Ref (Standalone));
          null;
       end Q;
    begin
       Q;
       Dangler.all := 123; -- Assigns a non-existent object, can't check this.
       Ada.Text_IO.Put_Line ("?? Likely erroneous execution");
    exception
       when Err:others =>
          Ada.Text_IO.Put_Line ("-- Exception raised (acc) - " & Ada.Exceptions.Exception_Information (Err));
    end;

    Ada.Text_IO.Put_Line ("Test finished");

end TestAI74;

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

From: Randy Brukardt
Sent: Never [Done April 20, 2020]

Here's the results of the above test program when run on GNAT 21.0w-200219:

Check some nasty cases related to AI12-0378-1
-- Expected result, no conversion
** Failed: Exception raised (explicit parent conversion) - raised CONSTRAINT_ERROR : testai74.adb:42 access check failed

-- Expected result, inherited routine
-- Discriminant check made anyway - raised CONSTRAINT_ERROR : testai74.adb:117 access check failed

-- Exception raised (tag) - raised CONSTRAINT_ERROR : testai74.adb:148 access check failed

-- Exception raised (acc) - raised CONSTRAINT_ERROR : testai74.adb:194 access check failed

Test finished

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

From: Randy Brukardt
Sent: Never [Done April 20, 2020]

Here's the results of the above test program when run on Janus/Ada 3.2.2dev (4/20/20):

[Note: Janus/Ada needed the call in the third case commented out, since it
does not support dynamic accessibility for stand-alone objects of an anonymous
access type. Thus the last case is uninteresting as it didn't set Dangler.]

Check some nasty cases related to AI12-0378-1
-- Expected result, no conversion
-- Expected result, explicit parent conversion
-- Expected result, inherited routine
-- Discriminant check made anyway - CONSTRAINT_ERROR
   Variant record field not available
On Line Number 117 In TESTAI74.LOOP.P
Called from line number 123 In TESTAI74

?? Possible erroneous execution
** Following object clobbered to  123
-- Exception raised (acc) - CONSTRAINT_ERROR
   Attempt to reference thru NULL/Uninitialized pointer
On Line Number 194 In TESTAI74

Test finished

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

From: Randy Brukardt
Sent: Never [Done April 21, 2020]

Here's the results of the above test program when run on ObjectAda 10.1
(4/21/20) [thanks to PTC for these results]

[Note: ObjectAda needed the first and third error cases commented out, as it
rejected both of the conversions in those two cases.]

Check some nasty cases related to AI12-0378-1
-- Expected result, no conversion
-- Expected result, explicit parent conversion
-- Expected result, inherited routine
?? Possible erroneous execution
Test finished

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

From: Randy Brukardt
Sent: Never [Done April 21, 2020]

Here's the results of the above test program when run on ApexAda 5.2
(4/21/20) [thanks to PTC for these results]

[Note: ApexAda needed the third error cases commented out, as it
rejected the conversion with a static accessibility failure.]

Check some nasty cases related to AI12-0378-1
-- Expected result, no conversion
-- Expected result, explicit parent conversion
-- Expected result, inherited routine
-- Discriminant check made anyway - CONSTRAINT_ERROR raised at 16#000000000040439B#, Exception Message:
?? Possible erroneous execution
Test finished

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

From: Tucker Taft
Sent: Thursday, March 26, 2020  9:29 AM

AdaCore recently implemented this Corrigendum AI, and bumped into a
significant number of incompatibilities in their customer regression test
suite in the access-type-related part, which disallows view conversions
between unrelated access types on an actual parameter if the formal is mode
"out."  The AI argued that such situations should be rare, but apparently it
is more common than we anticipated.

I would suggest we remove the access-type-related part from this AI, put it
in a separate AI, and consider voting it "no action," or come up with a more
compatible approach (e.g. disallow only if the Sizes for the access types
differ).

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

From: Randy Brukardt
Sent: Tuesday, April 21, 2020  6:51 PM

It turns out that GNAT "solves" this problem by always passing null for an
explicit view conversion of an out parameter. It completely ignores what the
language says to do in such a case.

Probably some solution based on that would be best, although we need to take
care not to break existing code that takes advantage of the language as
written (since that goes back to Ada 95). Unless, of course, none exists; I've
asked implementers about this question in order to see if we get any feedback.

AI12-0377-1 will cover this issue and the other one that Gary posted (they're
both related to AI12-0074-1, which is a Corrigendum AI, and which will need
to be revisited in any case because of the intent to repeal 13.1(10). I'll
post this AI later today.

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

From: Randy Brukardt
Sent: Wednesday, April 22, 2020  1:44 PM

FYI, I asked PTC (and received almost immediately) about their compilers
behavior on the test program. Both of their compilers behaved similarly to
the results I reported for Janus/Ada (including not supporting dynamic
accessibility on SAOAATs), with the exception of ObjectAda rejecting the
conversion in the first test case. Details are found in the posted AI (not the
one attached previously, I got an answer from PTC after I sent the previous
e-mail).

I conclude that taking GNAT's behavior exactly would have a serious risk of
being run-time incompatible with existing code (a risk we shouldn't take). A
more limited form, however, seems to be the right solution (surely we don't
want the erroneous execution that all of the non-GNAT compilers have).

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

[Editor's note: Some of the e-mails in the following thread discussed topics
in both this AI and AI12-0377-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 value is nonnull and belongs to the subtype of the parameter, then}
the formal parameter is initialized from the value of the actual, without
checking whether the value satisfies any predicate

{* otherwise, the the formal parameter is initialized to the null value of the
type of the formal, without checking that the value satisfies any predicate or
any exclusion of the null value.}

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

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

"belongs" only describes constraints, and really only makes sense for related
types. When you are converting *un*related types, there is a bunch of dynamic
checks that are in addition to the constraint checks. For access types, these
are 4.6(24.11-24.17) - seven paragraphs. These are repeated (ugh!) for
memberships in 4.5.2(30.3/4), slightly differently since the result is
True/False rather than raising an exception. I though it was best to piggyback
on that paragraph rather than writing something new that would be forever
wrong.

I had hoped there was a term like "convertible" (but that term is static only)
to cover this, but it doesn't exist. We could try to add one but I thought that
was overkill for this particular fix.

In any case, in your hands now.

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

From: Tucker Taft
Sent: Wednesday, April 29, 2020   4:02 PM

>"belongs" only describes constraints, and really only makes sense for related
>types. When you are converting *un*related types, there is a bunch of dynamic
>checks that are in addition to the constraint checks. For access types, these
>are 4.6(24.11-24.17) - seven paragraphs.

In my RM, those are all legality rules, so would not need to be repeated.  The
dynamic semantics are in (48-50).  And I think some of them could be
simplified in this situation.

>These are repeated (ugh!) for memberships in 4.5.2(30.3/4), slightly
>differently since the result is True/False rather than raising an exception.
>I though it was best to piggyback on that paragraph rather than writing
>something new that would be forever wrong.

I'd like to at least try to come up with some wording that is simpler.  Good
point about "belongs" but it still does some of what we want.  It also seems
more natural to piggyback on wording having to do with conversion, rather than
membership test.  And there is already wording there for view conversion, so
perhaps we should put it all in 4.6, and keep 6.4.1 very simple.

>I had hoped there was a term like "convertible" (but that term is static
>only) to cover this, but it doesn't exist. We could try to add one but I
>thought that was overkill for this particular fix.

Moving most of it to 4.6 from 6.4.1 might help.

>In any case, in your hands now.

OK.

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

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

...
> I had hoped there was a term like "convertible" (but that term is
> static only)

So what? Surely I can use a term of static semantics in describing a dynamic
constraint.

(Seems to me that the term has a perfect fit in context: "convertible"
is reuqired as far as type is concerned plus extra aspect constraints).

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

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

...
>> I had hoped there was a term like "convertible" (but that term is
>> static only)
>
> So what? Surely I can use a term of static semantics in describing a
> dynamic constraint.

Again, this is about dynamic semantics, so we should be able to presume that
legality rules have already been enforced.   I think some of Randy's comments
were about legality rules or static semantics, so don't really apply either.

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

From: Randy Brukardt
Sent: Wednesday, April 29, 2020  6:45 PM

>>"belongs" only describes constraints, and really only makes sense for
>>related types. When you are converting *un*related types, there is a
>>bunch of dynamic checks that are in addition to the constraint checks.
>>For access types, these are 4.6(24.11-24.17) - seven paragraphs.

>In my RM, those are all legality rules, so would not need to be repeated.
>The dynamic semantics are in (48-50).  And I think some of them could be
>simplified in this situation.

Sorry, I'm only talking about the Dynamic Semantics rules, whereever they
are. :-) There are tag and accessibility checks on top of the constraint,
null exclusion, and predicate checks, Here, there's no execution issue with
predicates and it's better to skip them. The null exclusion doesn't change
anything -- those fail if the value is null, but replacing null by null
doesn't change anything so forget that. Constraints can go either way -- we
already have to treat out parameters are unconstrained for other types (in
particular, integer types) so doing so as well for access types (for which
constraints are already strange) isn't a huge issue. (No compiler crashed
that allowed that, both Janus/Ada and ApexAda raised Constraint_Error.
ObjectAda incorrectly banned the conversion, and GNAT of course passed null
for any such conversion, even one that has no semantic effect.) But once we
start making some sort of check, it's probably easier to include constraints
in it -- those are rare anyway.

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

From: Brad Moore
Sent: Wednesday, September 9, 2020  10:04 AM

Sorry, but I missed mentioning this editorial comment for AI12-0378-1

Corrigendum  (just befor Discussion)

"For a view conversion to an unrelated type with the Default_Value aspect 
specified, the aspect is new in Ada 2012 so it should be unlikely to occur in
existing code."

This sentence is weird.

Suggest.

"View conversions to an unrelated type with the Default_Value aspect 
specified, are unlikely to occur in existing code, since the aspect is new 
in Ada 2012."

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

From: Randy Brukardt
Sent: Wednesday, September 9, 2020  4:05 PM

...
> Suggest.
> 
> "View conversions to an unrelated type with the Default_Value aspect 
> specified, are unlikely to occur in existing code, since the aspect is 
> new in Ada 2012."

I don't think the first comma in this replacement ought to be there. That is,

   "View conversions to an unrelated type with the Default_Value 
   aspect specified are unlikely to occur in existing code, 
   since the aspect is new in Ada 2012."

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

From: Brad Moore
Sent: Wednesday, September 9, 2020  4:30 PM

Definitely Agree.

And on an aside,  I notice you put the period after "Ada 2012" inside the 
quotes, which is needed here. :-)

Perhaps that's another reason why we go against the apparent US norm. When 
we are in the businees of wordsmithing, we need to know precisely which 
punctuation is in the wording inside the quotes. It might be confusing in 
certain situations if we were to put punctuation from the outer context inside 
the quotes, but not sure if that is a possibility or not.

TBH, I am not sure what we do in Canada, probably a mixture of the US and 
British style, but it is not something I recall encountering before, so I 
just assumed it was a typo, and not intentional. [Brad is referring to the
discussion filed in AC-00334 - Editor.]

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

Questions? Ask the ACAA Technical Agent