comp.lang.ada
 help / color / mirror / Atom feed
* Accessibility check failed
@ 2014-08-11  2:12 hreba
  2014-08-11  5:32 ` Jeffrey Carter
  2014-08-11 19:56 ` sbelmont700
  0 siblings, 2 replies; 20+ messages in thread
From: hreba @ 2014-08-11  2:12 UTC (permalink / raw)


One more beginner's question.

I wrote a linear list of abstract items.
There is an abstract type Iterator with an abstract method Proc which 
can be called with a class wide item type. Procedure Iterate calls Proc 
with each item of the list.

For a test I declared a concrete extension extension of Gen.Lists.ItemD.
I also declare a concrete extension of Iterator called Writer and a 
concrete method Proc.

Everything compiles, but at runtime the line

          i:= Item(itm);

in Proc generates a "accessibility check failed" error.

I checked with a debugger that itm is not null and that its actual 
(dynamic) type is that of the concrete extension.

So what is wrong?

A more complete extract of my program follows.

---------------------

package Gen.Lists is

    type ItemD is abstract tagged private;
    type List is limited private;

    type Iterator is abstract tagged null record;
    procedure Proc (iter: in out Iterator; itm: access ItemD'Class) is 
abstract;
    procedure Iterate (ic: in out Iterator'Class; l: List);

end Gen.Lists;

--------------------

with Gen.Lists;

package test_lists_aux is

    type ItemD is new Gen.Lists.ItemD with
       record
          ch:	Character;
       end record;
    type Item is access all ItemD;

    type Writer is new Gen.Lists.Iterator with null record;
    procedure Proc (w: in out Writer; itm: access Gen.Lists.ItemD'Class);

end test_lists_aux;

-----------------

with Ada.Text_IO;	use Ada.Text_IO;

package body test_lists_aux is

    procedure Proc (w: in out Writer; itm: access Gen.Lists.ItemD'Class) is
       i: Item;
    begin
       if itm.all in ItemD then
          i:= Item(itm);
       end if;
       Put (i.ch);
       --Put (Item(itm).ch);
    end Proc;

end test_lists_aux;


-- 
Frank Hrebabetzky		+55 / 48 / 3235 1106
Florianopolis, Brazil


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Accessibility check failed
  2014-08-11  2:12 Accessibility " hreba
@ 2014-08-11  5:32 ` Jeffrey Carter
  2014-08-11 16:45   ` hreba
  2014-08-11 19:56 ` sbelmont700
  1 sibling, 1 reply; 20+ messages in thread
From: Jeffrey Carter @ 2014-08-11  5:32 UTC (permalink / raw)


On 08/10/2014 07:12 PM, hreba wrote:
>
> in Proc generates a "accessibility check failed" error.

Accessibility checks are a major can of worms and why you should always avoid 
visible access types if at all possible. This is aggravated by the use of 
anonymous access types.

> So what is wrong?

The simple answer is unnecessary use of a visible access type, in this case an 
anonymous access type.

-- 
Jeff Carter
"Little blondes with long hair and short skirts and
boots and big chests and bright, witty, and perceptive."
Play It Again, Sam
128

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Accessibility check failed
  2014-08-11  5:32 ` Jeffrey Carter
@ 2014-08-11 16:45   ` hreba
  2014-08-11 16:55     ` Jeffrey Carter
  0 siblings, 1 reply; 20+ messages in thread
From: hreba @ 2014-08-11 16:45 UTC (permalink / raw)


On 08/11/2014 02:32 AM, Jeffrey Carter wrote:
> On 08/10/2014 07:12 PM, hreba wrote:
>>
>> in Proc generates a "accessibility check failed" error.
>
> Accessibility checks are a major can of worms and why you should always
> avoid visible access types if at all possible. This is aggravated by the
> use of anonymous access types.
>
>> So what is wrong?
>
> The simple answer is unnecessary use of a visible access type, in this
> case an anonymous access type.
>

Ok, the idea is to have an iteration where an abstract procedure is 
applied on each element of a list, class-wide. Together with the 
concrete extension of the list element a concrete iterator with a 
concrete method Proc shall be defined.

How do I change my program into proper Ada style?
-- 
Frank Hrebabetzky		+55 / 48 / 3235 1106
Florianopolis, Brazil


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Accessibility check failed
  2014-08-11 16:45   ` hreba
@ 2014-08-11 16:55     ` Jeffrey Carter
  2014-08-12 11:57       ` hreba
  0 siblings, 1 reply; 20+ messages in thread
From: Jeffrey Carter @ 2014-08-11 16:55 UTC (permalink / raw)


On 08/11/2014 09:45 AM, hreba wrote:
>
> How do I change my program into proper Ada style?

Change your parameter mode from "access T'Class" to "in T'Class".

-- 
Jeff Carter
"If a sperm is wasted, God gets quite irate."
Monty Python's the Meaning of Life
56


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Accessibility check failed
  2014-08-11  2:12 Accessibility " hreba
  2014-08-11  5:32 ` Jeffrey Carter
@ 2014-08-11 19:56 ` sbelmont700
  2014-08-11 20:17   ` Jeffrey Carter
  1 sibling, 1 reply; 20+ messages in thread
From: sbelmont700 @ 2014-08-11 19:56 UTC (permalink / raw)


On Sunday, August 10, 2014 10:12:37 PM UTC-4, hreba wrote:
> 
> So what is wrong?
> 

What's probably happening is that the item you are passing in is declared at the procedure level.  A check is done when you do the cast to make sure that no dangling references could potentially happen.  If you declare it at a higher scope, I would wager success.

For instance:

procedure main is

   x : aliased test_lists_aux.ItemD := (Gen.Lists.ItemD with ch => '!');
   x_p : test_lists_aux.Item := new test_lists_aux.ItemD'(Gen.Lists.ItemD with ch => '!');
   y : test_lists_aux.Writer;


begin

   test_lists_aux.Proc (w   => y,
                        itm => x_p);  -- pass, lifetime is forever

   test_lists_aux.Proc (w   => y,
                        itm => x'access); -- fail, lifetime is only this scope

end test;


-sb

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Accessibility check failed
  2014-08-11 19:56 ` sbelmont700
@ 2014-08-11 20:17   ` Jeffrey Carter
  2014-08-11 20:28     ` sbelmont700
  0 siblings, 1 reply; 20+ messages in thread
From: Jeffrey Carter @ 2014-08-11 20:17 UTC (permalink / raw)


On 08/11/2014 12:56 PM, sbelmont700@gmail.com wrote:
>
> procedure main is
>
>     x : aliased test_lists_aux.ItemD := (Gen.Lists.ItemD with ch => '!');
>     x_p : test_lists_aux.Item := new test_lists_aux.ItemD'(Gen.Lists.ItemD with ch => '!');
>     y : test_lists_aux.Writer;
>
>
> begin
>
>     test_lists_aux.Proc (w   => y,
>                          itm => x_p);  -- pass, lifetime is forever

No, lifetime is until Main returns. Main can be withed and called from something 
else, or call itself recursively, possibly indirectly, so this is treated as 
having a lifetime less than forever even if we know it will be around for the 
life of the program.

-- 
Jeff Carter
"If a sperm is wasted, God gets quite irate."
Monty Python's the Meaning of Life
56

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Accessibility check failed
  2014-08-11 20:17   ` Jeffrey Carter
@ 2014-08-11 20:28     ` sbelmont700
  2014-08-11 21:14       ` Jeffrey Carter
  0 siblings, 1 reply; 20+ messages in thread
From: sbelmont700 @ 2014-08-11 20:28 UTC (permalink / raw)


On Monday, August 11, 2014 4:17:07 PM UTC-4, Jeffrey Carter wrote:
> 
> No, lifetime is until Main returns. Main can be withed and called from something 
> 
> else, or call itself recursively, possibly indirectly, so this is treated as 
> 
> having a lifetime less than forever even if we know it will be around for the 
> 
> life of the program.
> 

I suppose the better comment would be: "pass, lifetime is long enough"


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Accessibility check failed
  2014-08-11 20:28     ` sbelmont700
@ 2014-08-11 21:14       ` Jeffrey Carter
  0 siblings, 0 replies; 20+ messages in thread
From: Jeffrey Carter @ 2014-08-11 21:14 UTC (permalink / raw)


On 08/11/2014 01:28 PM, sbelmont700@gmail.com wrote:
>
> I suppose the better comment would be: "pass, lifetime is long enough"

Have you tried it?

-- 
Jeff Carter
"If a sperm is wasted, God gets quite irate."
Monty Python's the Meaning of Life
56


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Accessibility check failed
  2014-08-11 16:55     ` Jeffrey Carter
@ 2014-08-12 11:57       ` hreba
  0 siblings, 0 replies; 20+ messages in thread
From: hreba @ 2014-08-12 11:57 UTC (permalink / raw)


On 08/11/2014 01:55 PM, Jeffrey Carter wrote:
> On 08/11/2014 09:45 AM, hreba wrote:
>>
>> How do I change my program into proper Ada style?
>
> Change your parameter mode from "access T'Class" to "in T'Class".
>

Thanks
-- 
Frank Hrebabetzky		+55 / 48 / 3235 1106
Florianopolis, Brazil

^ permalink raw reply	[flat|nested] 20+ messages in thread

* accessibility check failed
@ 2015-11-29 18:03 Serge Robyns
  2015-11-29 18:37 ` Jeffrey R. Carter
                   ` (3 more replies)
  0 siblings, 4 replies; 20+ messages in thread
From: Serge Robyns @ 2015-11-29 18:03 UTC (permalink / raw)


I'm facing a "mysterious" accessibility check failed error.

I'm having the following function:

   overriding function Get_Client
     (Self        : not null access T_Data_Store;
      Client_Name : in              T_Client_Name)
      return T_Client'Class
   is
      Cursor : Client_Map.Cursor;
   begin
      Cursor := Self.Clients.Find (Client_Name);
      if Cursor = Client_Map.No_Element then
         return T_Client_DAO'(No_Client
                                  with Store => Self);
      end if;
      return T_Client_DAO'(T_Client (Client_Map.Element (Cursor))
                               with Store => Self);
   end Get_Client;

The definition of T_Client_DAO is:
   type T_Client_DAO is new T_Client with record
      Store : access T_Abstract_Data_Store'Class;
   end record;

T_Client is the object with is methods.  T_Abstract_Data_Store is the assembly of Factory interfaces (see below for an example).

The idea is to return a copy of the client record and store with it a reference to the data store class from which the object came from.  This will allow to use my_object.change_XYZ to update the object and it's representation into the store through that reference.

Researching the web for the accessibility check failed all refers to returning a reference to a local variable which is indeed disappearing on the execution of the return statement.  But in my case, I'm just storing the reference I did receive from the parent.

I did find a suggestion to replace anonymous access types to named ones but that does not compile for the interface class for which the above function is an implementation.
 
   type Factory is limited interface;
   type Factory_Access is access Factory;

   function Get_Client
     (Self        : Factory_Access;
      Client_Name : in T_Instrument_Name)
      return T_Client'Class
     is abstract;

with:
warning: abstract subprogram is not dispatching or overriding

However when using not null access T_Factory instead it does compile.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: accessibility check failed
  2015-11-29 18:03 accessibility check failed Serge Robyns
@ 2015-11-29 18:37 ` Jeffrey R. Carter
  2015-11-29 19:00   ` Serge Robyns
  2015-11-29 19:15 ` Dmitry A. Kazakov
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 20+ messages in thread
From: Jeffrey R. Carter @ 2015-11-29 18:37 UTC (permalink / raw)


On 11/29/2015 11:03 AM, Serge Robyns wrote:
> I'm facing a "mysterious" accessibility check failed error.
> 
> I'm having the following function:
> 
>    overriding function Get_Client
>      (Self        : not null access T_Data_Store;
>       Client_Name : in              T_Client_Name)
>       return T_Client'Class

If you avoid both programming by extension and anonymous access-to-object types
your code will be simpler, clearer, and you will avoid mysterious error msgs.

If you further follow the design rule of no public access types things will be
even better.

-- 
Jeff Carter
"Ah, go away or I'll kill ya."
Never Give a Sucker an Even Break
100


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: accessibility check failed
  2015-11-29 18:37 ` Jeffrey R. Carter
@ 2015-11-29 19:00   ` Serge Robyns
  2015-11-29 22:32     ` Jeffrey R. Carter
  0 siblings, 1 reply; 20+ messages in thread
From: Serge Robyns @ 2015-11-29 19:00 UTC (permalink / raw)


On Sunday, 29 November 2015 19:37:07 UTC+1, Jeffrey R. Carter  wrote:
> If you avoid both programming by extension and anonymous access-to-object types
> your code will be simpler, clearer, and you will avoid mysterious error msgs.
> 
> If you further follow the design rule of no public access types things will be
> even better.

I'm trying to understand if this is a sarcastic comment or a genuine advise?

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: accessibility check failed
  2015-11-29 18:03 accessibility check failed Serge Robyns
  2015-11-29 18:37 ` Jeffrey R. Carter
@ 2015-11-29 19:15 ` Dmitry A. Kazakov
  2015-11-29 22:40 ` Serge Robyns
  2015-12-01 20:17 ` sbelmont700
  3 siblings, 0 replies; 20+ messages in thread
From: Dmitry A. Kazakov @ 2015-11-29 19:15 UTC (permalink / raw)


On Sun, 29 Nov 2015 10:03:25 -0800 (PST), Serge Robyns wrote:

> I'm facing a "mysterious" accessibility check failed error.

Nothing mysterious anonymous access + checks is an endless source of
problems in Ada.

> I'm having the following function:
> 
>    overriding function Get_Client
>      (Self        : not null access T_Data_Store;
>       Client_Name : in              T_Client_Name)
>       return T_Client'Class
>    is
>       Cursor : Client_Map.Cursor;
>    begin
>       Cursor := Self.Clients.Find (Client_Name);
>       if Cursor = Client_Map.No_Element then
>          return T_Client_DAO'(No_Client
>                                   with Store => Self);

Try Self.all'Unchecked_Access.

(Don't feel guilty about Unchecked_Access, all means are good in the holly
war against evil access checks... (:-))

> Researching the web for the accessibility check failed all refers to
> returning a reference to a local variable which is indeed disappearing on
> the execution of the return statement.  But in my case, I'm just storing
> the reference I did receive from the parent.

Yes, but how much up you pass that reference? The rules are too crude. Most
of alarms they generate are false alarms. I don't remember a case
accessibility check indeed helped to detect a bug.

> I did find a suggestion to replace anonymous access types to named ones
> but  that does not compile for the interface class for which the above
> function is an implementation.
 
It is a poor advice when you design a reusable component. Anonymous access
type is the most general type of reference imposing least constraint on the
clients. Thus it is the type to be used in all interfaces.

In the implementations a named access type is indeed the best and safest
choice.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: accessibility check failed
  2015-11-29 19:00   ` Serge Robyns
@ 2015-11-29 22:32     ` Jeffrey R. Carter
  2015-11-29 22:53       ` Serge Robyns
  0 siblings, 1 reply; 20+ messages in thread
From: Jeffrey R. Carter @ 2015-11-29 22:32 UTC (permalink / raw)


On 11/29/2015 12:00 PM, Serge Robyns wrote:
> On Sunday, 29 November 2015 19:37:07 UTC+1, Jeffrey R. Carter  wrote:
>> If you avoid both programming by extension and anonymous access-to-object types
>> your code will be simpler, clearer, and you will avoid mysterious error msgs.
>>
>> If you further follow the design rule of no public access types things will be
>> even better.
> 
> I'm trying to understand if this is a sarcastic comment or a genuine advise?

It's quite genuine. The most common problems posted on here of the "Why am I
getting this msg?" or "Why doesn't this do what it should?" sort relate to
anonymous access types and programming by extension. I conclude that they were
mistakes and should not have been added to the language. My aversion to
programming by extension goes back to the early 1990s when it was proposed for
Ada 9X. I experimented with the proposals and found that it makes code harder to
read than equivalent code without it.

Access types are notoriously error-prone, so any necessary use of them should be
hidden as deeply as possible (and given the unbounded containers, there are very
few necessary uses). Using public access types and foisting what should be
hidden onto the clients of the pkgs in which they appear may make them easier to
write, but harder to use, and increases errors in the overall program. Avoiding
public access types is a design rule I follow scrupulously.

-- 
Jeff Carter
"Ah, go away or I'll kill ya."
Never Give a Sucker an Even Break
100


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: accessibility check failed
  2015-11-29 18:03 accessibility check failed Serge Robyns
  2015-11-29 18:37 ` Jeffrey R. Carter
  2015-11-29 19:15 ` Dmitry A. Kazakov
@ 2015-11-29 22:40 ` Serge Robyns
  2015-12-01 20:17 ` sbelmont700
  3 siblings, 0 replies; 20+ messages in thread
From: Serge Robyns @ 2015-11-29 22:40 UTC (permalink / raw)


On Sunday, 29 November 2015 19:03:28 UTC+1, Serge Robyns  wrote:
> I'm facing a "mysterious" accessibility check failed error.

I've managed to resolve my issue.  It does work without using unchecked_access.

However, during my attempts to understand I managed to create a stupid dummy program with 2 versions of implementing a store.  One does not die, the other dies with accessibility error.  I can send a zip to whomever wants to "study" it.

Here is the main specifications with the main differences:

with Abstract_Store; use Abstract_Store;

with Clients; use Clients;
with Clients.DAO; use Clients.DAO;

package Store is

   type T_Store is limited new T_Asbtract_Store with
      record
         Clients : aliased T_Client_Store;
      end record;

   overriding procedure Store_Client
     (Self   : not null access T_Store;
      Client : in              T_Client'Class);

   overriding function Get_Client
     (Self   : not null access T_Store;
      Id     : in              Integer)
      return T_Client'Class;

   type T_Store_2 is new T_Client_Store
     and T_Asbtract_Store with null record;

end Store;

T_Store does not "die" whereas T_Store_2 does on the return of Get_Client.
In the case of T_Store the overriding function for T_Store is just performing a "return Self.Clients.Get_Client (Id);"  In the case of T_Store_2 it does call the function directly through inheritance.

T_Store requires me to write use a lot of "keystrokes" (writing the redirection calls) which I was hoping to save with T_Store_2.

Serge

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: accessibility check failed
  2015-11-29 22:32     ` Jeffrey R. Carter
@ 2015-11-29 22:53       ` Serge Robyns
  2015-11-30  2:04         ` Jeffrey R. Carter
  2015-11-30 23:22         ` Randy Brukardt
  0 siblings, 2 replies; 20+ messages in thread
From: Serge Robyns @ 2015-11-29 22:53 UTC (permalink / raw)


On Sunday, 29 November 2015 23:32:30 UTC+1, Jeffrey R. Carter  wrote:
> On 11/29/2015 12:00 PM, Serge Robyns wrote:
> > On Sunday, 29 November 2015 19:37:07 UTC+1, Jeffrey R. Carter  wrote:
> It's quite genuine. The most common problems posted on here of the "Why am I
> getting this msg?" or "Why doesn't this do what it should?" sort relate to
> anonymous access types and programming by extension. I conclude that they were
> mistakes and should not have been added to the language. My aversion to
> programming by extension goes back to the early 1990s when it was proposed for
> Ada 9X. I experimented with the proposals and found that it makes code harder to
> read than equivalent code without it.
> 
> Access types are notoriously error-prone, so any necessary use of them should be
> hidden as deeply as possible (and given the unbounded containers, there are very
> few necessary uses). Using public access types and foisting what should be
> hidden onto the clients of the pkgs in which they appear may make them easier to
> write, but harder to use, and increases errors in the overall program. Avoiding
> public access types is a design rule I follow scrupulously.
> 
> -- 

In my case I'm trying to build an interface to hide implementation details.  The code provided is using containers as a store but should also be able to use any kind of (R)DBMS for all or part of the data.  And hence this is where the beauty of OO comes but does indeed require to use access type to "keep" track of things.

I admit I'm trying to implement some patterns that typically relies on "references".  What would be the alternative to a Bridge pattern.

Ada brings a lot of value with tagged types which other OO languages to fail to have, at least AFAIK.  For example, Ada will check the tag type when allocating/converting from 'Class return to whatever.  In my case X := T_ABC_DAO (func (xyz)); it will check that func(p) return T_ABC'Class has indeed returned something that is a T_ABC_DOA.

I do admit that OO brings more "indirection" than strait code but then often people implement something similar by building their own dispatches or alike.

Serge

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: accessibility check failed
  2015-11-29 22:53       ` Serge Robyns
@ 2015-11-30  2:04         ` Jeffrey R. Carter
  2015-11-30 23:22         ` Randy Brukardt
  1 sibling, 0 replies; 20+ messages in thread
From: Jeffrey R. Carter @ 2015-11-30  2:04 UTC (permalink / raw)


On 11/29/2015 03:53 PM, Serge Robyns wrote:
> 
> In my case I'm trying to build an interface to hide implementation details.
> The code provided is using containers as a store but should also be able to
> use any kind of (R)DBMS for all or part of the data.  And hence this is where
> the beauty of OO comes but does indeed require to use access type to "keep"
> track of things.

There's nothing beautiful about code that is harder to understand than it has to
be. And little is uglier than pkgs that force their clients to use access types.

My rules for access types:

1. Don't use them
2. If you think you need them, think again
3. If you still think you need them, see if you can use an existing abstraction
(such as containers) to avoid them
4. If you still think you need them, encapsulate and hide them

> I admit I'm trying to implement some patterns that typically relies on
> "references".  What would be the alternative to a Bridge pattern.

Some of the gnag-of-4 design patters are ways to work around the limitation of
the languages used. An example is the singleton pattern, which is a work around
for the lack of modules. In Ada, it's simply a pkg. I'm not familiar with the
bridge pattern, but Wikipedia says it's for decoupling an abstraction from its
implementation. Such decoupling allows the implementation to change without
impacting the rest of the system, and is the reason for information hiding. In
Ada, information hiding is provided by pkgs. The abstraction is represented by a
pkg spec and its implementation is in the body. The body can change without
impacting the rest of the system. For example, the implementation can change
from storing things in a container to storing them in a disk-based DBMS.

References are often needed, but they often need not be access values.

-- 
Jeff Carter
"Ah, go away or I'll kill ya."
Never Give a Sucker an Even Break
100

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: accessibility check failed
  2015-11-29 22:53       ` Serge Robyns
  2015-11-30  2:04         ` Jeffrey R. Carter
@ 2015-11-30 23:22         ` Randy Brukardt
  2015-12-01  9:38           ` Serge Robyns
  1 sibling, 1 reply; 20+ messages in thread
From: Randy Brukardt @ 2015-11-30 23:22 UTC (permalink / raw)


"Serge Robyns" <serge.robyns@gmail.com> wrote in message 
news:29d3244c-1769-4cb7-8af3-e1b20eb2e1e2@googlegroups.com...
...
>In my case I'm trying to build an interface to hide implementation details. 
>The
>code provided is using containers as a store but should also be able to use 
>any
>kind of (R)DBMS for all or part of the data.  And hence this is where the
>beauty of OO comes but does indeed require to use access type to "keep"
>track of things.

You rarely need explicit access types in an Ada interface, as "in out T" and 
"access T" are essentially the same for any tagged type T. Ada always allows 
taking 'Access (or 'Unchecked_Access) of a tagged type parameter.

Claw ("Class Library for Ada and Windows", see rrsoftware.com) uses almost 
no access types in its public interface, yet almost everything is 
referential under the covers. Works fine, and puts all of the pain on the 
implementor of the library (where it belongs) and not on the clients (like 
access types do). (The one place where we had to use an access type was in a 
single function return where return-by-copy didn't have the proper effect. 
That's pretty rare.)

To answer your original question, once you use anonymous access types, all 
accessibility checks become dynamic. That is, the accessibility of the 
actual object is checked, no matter how many levels it's passed through. 
Most likely, someone is operating on a local object and made a call on the 
routine that's failing. Bob Duff calls that a "tripping hazard", and it 
means that you can never reliably save anonymous access parameters outside 
of the original subprogram (you can do it in the subprogram with a local 
anonymous access object -- a hack on top of a hack, IMHO).

In Ada 2012, you can "protect" an anonymous access with a precondition using 
a membership test (but warning: these aren't tested in the ACATS and I don't 
know if anyone has implemented them correctly). Something like:

    type Global_Access is access all Object;

    function Something (Acc : access Object; ...) return ...
        with Pre => Acc in Global_Access;

In this case, if the object designated by Acc isn't defined globally, the 
precondition will fail, so you can safely assign Acc to an object of 
Global_Access in the body of Something. But, of course, that exposes part of 
your implementation in the precondition, so it's not clear that's a good 
thing.

                                 Randy.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: accessibility check failed
  2015-11-30 23:22         ` Randy Brukardt
@ 2015-12-01  9:38           ` Serge Robyns
  0 siblings, 0 replies; 20+ messages in thread
From: Serge Robyns @ 2015-12-01  9:38 UTC (permalink / raw)


On Tuesday, 1 December 2015 00:22:50 UTC+1, Randy Brukardt  wrote:
> You rarely need explicit access types in an Ada interface, as "in out T" and 
> "access T" are essentially the same for any tagged type T. Ada always allows 
> taking 'Access (or 'Unchecked_Access) of a tagged type parameter.

Initially I was using in/out and then I wanted to uni-formalize the interface because I need to take the access somewhere.  Now I'm rewriting it as per some previous suggestion without requiring to store the access parameter.

The only thing I do now wished it would be possible is to use multiple inheritance when merging all DOA class implementing their respective interfaces (in plural).


type abstract_interface is new limited interface and I1 and I2 and ....;
-- Below is not Ada
type concrete is new abstract_interface with I1_Impl and I2_Impl and ...;

Now I'm using mixin's but this require to write all overrides to call their respective implementations.
type concrete is new abstract_interface with record
I1 : T_I1_Impl;
I2 : T_I2_Impl;
....
end record;

> Claw ("Class Library for Ada and Windows", see rrsoftware.com) uses almost 
> no access types in its public interface, yet almost everything is 
> referential under the covers. Works fine, and puts all of the pain on the 
> implementor of the library (where it belongs) and not on the clients (like 
> access types do). (The one place where we had to use an access type was in a 
> single function return where return-by-copy didn't have the proper effect. 
> That's pretty rare.)

I'll attempt to build my interface the same way.
However I need to be able to change the returned object and have it reflected in the store.

> To answer your original question, once you use anonymous access types, all 
> accessibility checks become dynamic. That is, the accessibility of the 
> actual object is checked, no matter how many levels it's passed through. 
> Most likely, someone is operating on a local object and made a call on the 
> routine that's failing. Bob Duff calls that a "tripping hazard", and it 
> means that you can never reliably save anonymous access parameters outside 
> of the original subprogram (you can do it in the subprogram with a local 
> anonymous access object -- a hack on top of a hack, IMHO).

Now I do understand better why I found references on the web suggesting using named access types instead of anonymous. 

I've given the ARM section 3.10.2 a read to understand better this whole thing.  All I can say is that it isn't certainly not late evening lecture.  And I my case, I'm using a return and a qualified expression in one statement, for which I found a lot of "rules".

> In Ada 2012, you can "protect" an anonymous access with a precondition using 
> a membership test (but warning: these aren't tested in the ACATS and I don't 
> know if anyone has implemented them correctly). Something like:
> 
>     type Global_Access is access all Object;
> 
>     function Something (Acc : access Object; ...) return ...
>         with Pre => Acc in Global_Access;
> 
> In this case, if the object designated by Acc isn't defined globally, the 
> precondition will fail, so you can safely assign Acc to an object of 
> Global_Access in the body of Something. But, of course, that exposes part of 
> your implementation in the precondition, so it's not clear that's a good 
> thing.

Thanks.

Serge


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: accessibility check failed
  2015-11-29 18:03 accessibility check failed Serge Robyns
                   ` (2 preceding siblings ...)
  2015-11-29 22:40 ` Serge Robyns
@ 2015-12-01 20:17 ` sbelmont700
  3 siblings, 0 replies; 20+ messages in thread
From: sbelmont700 @ 2015-12-01 20:17 UTC (permalink / raw)


On Sunday, November 29, 2015 at 1:03:28 PM UTC-5, Serge Robyns wrote:
> 
> The idea is to return a copy of the client record and store with it a reference to the data store class from which the object came from.  This will allow to use my_object.change_XYZ to update the object and it's representation into the store through that reference.
> 

You seem to be implementing an abstract container of abstract objects, and so without wading into the OOP/AAT debates, that's one of the few legitimate uses of return-by-anonymous-access, e.g.

overriding function Get_Client
  (Self        : T_Data_Store; 
   Client_Name : T_Client_Name) return access T_Client'Class

Now there's no DAO object at all, and you save yourself *lots* of keystrokes.  Or, better yet, use the dubious 'accessor' pattern to wrap the return value to further protect it (i.e. an access discriminant).

But as was said, as a general rule, AAT's are specialized tools for specialized jobs with special rules and special effects, so be sure you understand the *ALL* the implications before you use them.

-sb

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2015-12-01 20:17 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-29 18:03 accessibility check failed Serge Robyns
2015-11-29 18:37 ` Jeffrey R. Carter
2015-11-29 19:00   ` Serge Robyns
2015-11-29 22:32     ` Jeffrey R. Carter
2015-11-29 22:53       ` Serge Robyns
2015-11-30  2:04         ` Jeffrey R. Carter
2015-11-30 23:22         ` Randy Brukardt
2015-12-01  9:38           ` Serge Robyns
2015-11-29 19:15 ` Dmitry A. Kazakov
2015-11-29 22:40 ` Serge Robyns
2015-12-01 20:17 ` sbelmont700
  -- strict thread matches above, loose matches on Subject: below --
2014-08-11  2:12 Accessibility " hreba
2014-08-11  5:32 ` Jeffrey Carter
2014-08-11 16:45   ` hreba
2014-08-11 16:55     ` Jeffrey Carter
2014-08-12 11:57       ` hreba
2014-08-11 19:56 ` sbelmont700
2014-08-11 20:17   ` Jeffrey Carter
2014-08-11 20:28     ` sbelmont700
2014-08-11 21:14       ` Jeffrey Carter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox