Version 1.1 of acs/ac-00194.txt

Unformatted version of acs/ac-00194.txt version 1.1
Other versions for file acs/ac-00194.txt

!standard 3.9.3(8)          10-02-22 AC95-00194/01
!class confirmation 10-02-22
!status received no action 10-02-22
!status received 10-02-15
!subject Assignment to abstract view conversions
!summary
!appendix

!topic Assignment to abstract view conversion of concrete object?
!reference 3.9.3(8), 5.2(3)
!from Adam Beneschan 10-02-15
!discussion

This is from a question on comp.lang.ada.  A questioner tried to write code like
this:

   procedure Init (XL : Excel_Out_Stream'Class ...) is
   begin
      ...
      Excel_Out_Stream(XL) := ...
      ...
   end Init;

Excel_Out_Stream is an abstract tagged type with 14 components, and the intent
was to copy something into those components.

However, this is illegal by 3.9.3(8), which says "The type of the target of an
assignment operation (see 5.2) shall not be abstract". My reading of 5.2 is that
an assignment operation is part of the semantics of an assignment_statement
(AARM 5.2(3.b) says as much), so one can't get around this illegality by saying
this is an assignment_statement and not an "assignment operation".

Assuming that it really is illegal, though, should it be?  Offhand, I can't
think of any case where having the left side of an assignment *statement* be an
abstract type could cause any problems, since the left side must always be a
view of some object with a concrete type.

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

From: Randy Brukardt
Date: Monday, February 15, 2010  6:07 PM

> Assuming that it really is illegal, though, should it be?
> Offhand, I can't think of any case where having the left side of an
> assignment
> *statement* be an abstract type could cause any problems, since the
> left side must always be a view of some object with a concrete type.

I suspect it is illegal because of the (admittedly tiny) chance that the type
has an Adjust routine that is abstract. Calling that would be bad, of course.
This would look something like:

     with Ada.Finalization;
     package Foo is
         type Root_Foo is abstract new Ada.Finalization.Controlled with private;
         procedure Adjust (Obj : in out Root_Foo) is abstract;
     end Foo;

     with Foo;
     procedure Bar (Obj : Foo.Root_Foo'Class) is
     begin
         ...
         Foo.Root_Foo(Obj) := ... -- Calls abstract Adjust.
     end Bar;

I suppose one could try to have a rule to detect such a case more directly
(given that it isn't very likely, and that hiding abstract subprograms is
prohibited by 3.9.3(10), so doing so wouldn't break privacy). But I have to
wonder how important this could be, as assigning *part* of the components of an
object seems dangerous at best. If there are any extension components which
depend on the root components, changing just the root components could really
lousy things up. That's of course possible in a number of other ways, but this
one seems particularly risky in that any problem wouldn't show up until some
extension was created where the values of the components depended on those of
the root part's components -- which could be years later.

OT3H, methodolgical restrictions aren't usually that good of an idea, and I
doubt that we're going to make this illegal in the concrete case (even though it
is equality dubious). And it's annoying to have to assign 14 components
one-by-one.

Still, I don't see any great reasons to work too hard in this case (and there is
a chance that there are other problems with the abstract assignment that I
didn't think of).

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

Questions? Ask the ACAA Technical Agent