Version 1.1 of ai05s/ai05-0242-1.txt
!standard 13.12.1(3/2) 11-02-11 AI05-0242-1/01
!class Amendment 11-02-11
!status work item 11-02-11
!status received 11-02-09
!priority Low
!difficulty Easy
!subject No_Implementation_Units restriction
!summary
A new restriction is defined:
pragma Restrictions(No_Implementation_Units);
!problem
Implementations are allowed to add implementation-defined units as descendants
of the standard packages, and users can do so as well.
For instance, it is not uncommon for implementations to provide additional
containers packages as children of Ada.Containers.
It can be confusing as to whether these units are language-defined. This is
important when creating portable code, as implementation-defined units are
unlikely to be available on other implementations.
!proposal
(See wording.)
!wording
Add after 13.12.1(3/2):
No_Implementation_Units
There is no mention in the context_clause of any implementation-defined
descendants of packages Ada, Interfaces, or System. This restriction
applies only to the current compilation or environment, not the entire
partition.
!discussion
(See proposal.)
!example
pragma Restrictions(No_Implementation_Units);
!ACATS test
Add a ACATS B test for this feature.
!appendix
From: Robert Dewar
Sent: Monday, July 26, 2010 7:46 PM
Implementations are allowed to add grandchildren to Ada etc. And GNAT
takes advantage of this, e.g. to add the encoding packages to earlier
versions of Ada.
But this creates portability problems, we should really have a
restriction to prevent this, in the style of No_Implementation_Pragmas.
How about No_Implementation_Units
?
I am not really suggesting a new AI at this stage, just some guidance
on whether this is a good idea so that implementations can adopt it
(and then we can put it into Ada 2019 :-))
****************************************************************
From: Tucker Taft
Sent: Monday, July 26, 2010 8:14 PM
This sounds like a very good idea.
Users are often confused about what
packages are "standard" Ada and what
are not.
Does this also cover System.* and Interfaces.*?
One rule might be to disallow any package that starts with "Ada", "System",
or "Interfaces" that is not in the reference manual. These are the ones
that confuse users.
****************************************************************
From: Robert Dewar
Sent: Monday, July 26, 2010 8:33 PM
Right, that's what I had in mind.
And the idea would be in particular to forbid use of RM packages in an
inappropriately earlier version of Ada (e.g. using the string encoding packages
in Ada 2005 mode). Of course I know that can't be part of the standard, but
that would be the encouraged usage (and is what GNAT intends to do).
****************************************************************
From: Randy Brukardt
Sent: Thursday, February 10, 2011 1:01 AM
A vaguely related suggestion from back in July:
Robert Dewar has suggested:
How about {a restriction} No_Implementation_Units?
Tucker suggested:
One rule might be to disallow any package that starts with "Ada", "System",
or "Interfaces" that is not in the reference manual. These are the ones that
confuse users.
I was thinking that we could address this in this AI as well (I filed the
mail that way). I realize it would have helped if I had told Bob that at
some point. :-)
Anyway, are there any objections to this idea?? (If there are any, we'll
have to do it as a separate AI.)
****************************************************************
From: Robert Dewar
Sent: Thursday, February 10, 2011 5:23 AM
> One rule might be to disallow any package that starts with "Ada",
> "System", or "Interfaces" that is not in the reference manual. These
> are the ones that confuse users.
Yes, that's my intention exactly for this restriction
****************************************************************
From: Dan Eilers
Sent: Thursday, February 10, 2011 11:35 AM
> One rule might be to disallow any package that starts with "Ada",
> "System", or "Interfaces" that is not in the reference manual. These
> are the ones that confuse users.
There is a related issue of disallowing implementation-dependent indentifiers
declared in package System, such as System.Max_Priority.
****************************************************************
From: Tucker Taft
Sent: Thursday, February 10, 2011 11:53 AM
Good point. These are also sources of non-portability.
In this case, I presume the restriction would be on
*use* of such an identifier, since you probably don't expect there to be a
version of System just sitting around that omits these things.
Perhaps "pragma Restrictions(Pristine);"? ;-)
****************************************************************
From: Bob Duff
Sent: Thursday, February 10, 2011 1:48 PM
> A vaguely related suggestion from back in July:
Very vaguely. ;-)
> Robert Dewar has suggested:
>
> How about {a restriction} No_Implementation_Units?
>
> Tucker suggested:
>
> One rule might be to disallow any package that starts with "Ada",
> "System", or "Interfaces" that is not in the reference manual. These
> are the ones that confuse users.
>
> I was thinking that we could address this in this AI as well (I filed
> the mail that way). I realize it would have helped if I had told Bob
> that at some point. :-)
No need to tell me -- I saw those e-mails in AI05-0153-3.
I deliberately left out No_Implementation_Units, because Robert's e-mail seemed
to make it clear that he's not asking for a standard feature. He's asking for
an informal agreement that folks would implement this restriction. He wrote:
I am not really suggesting a new AI at this stage, just some guidance
on whether this is a good idea so that implementations can adopt it
(and then we can put it into Ada 2019 :-))
> Anyway, are there any objections to this idea?? (If there are any,
> we'll have to do it as a separate AI.)
I'm opposed to putting this feature in the standard at this time.
It just doesn't seem worth the trouble, and it doesn't seem particularly related
to aspects.
But I don't feel strongly about it, and if it goes in, I'd be happy to put it in
this AI.
Dan Eilers wrote:
> There is a related issue of disallowing implementation-dependent
> indentifiers declared in package System, such as System.Max_Priority.
And Tucker Taft replied:
> Good point. These are also sources of non-portability.
> In this case, I presume the restriction would be on
> *use* of such an identifier, since you probably don't expect there to
> be a version of System just sitting around that omits these things.
>
> Perhaps "pragma Restrictions(Pristine);"? ;-)
This goes way, way too far, in my opinion. Ada just has way to many potential
non-portabilities. I mean, any use of Integer is potentially non-portable, and
you can't use String without Integer. A from-scratch language design could do
much better (see Java), but it's too late for Ada.
Please stop inventing new "nice to have" features!
****************************************************************
From: Robert Dewar
Sent: Thursday, February 10, 2011 6:29 PM
> This goes way, way too far, in my opinion. Ada just has way to many
> potential non-portabilities. I mean, any use of Integer is
> potentially non-portable, and you can't use String without Integer. A
> from-scratch language design could do much better (see Java), but it's too late for Ada.
wrt integer, Ada is as portable as Java, Ada Integer means 32 bits on any
platform supporting Java (care to find a realistic counter example?)
****************************************************************
From: Robert Dewar
Sent: Thursday, February 10, 2011 6:47 PM
I believe Randy's compiler for Windows has 16-bit Integer.
He can correct me if I'm wrong.
And some Ada compilers do Integer arithmetic (intermediate results) in 64 bits.
Java is more portable, in that it requires a particular wrong answer on
"overflow". ;-)
And if you don't buy the Integer example, try Long_Integer
-- gcc/gnat has both 32-bit and 64-bit versions (which caused me a big headache
when helping to port it to 64-bit Windows!).
Anyway, so what? My point is I don't want to go tracking down all the potential
non-portabilities, and then have to argue about whether Integer'Last is more or
less portable than Priority'Last.
****************************************************************
From: Randy Brukardt
Sent: Thursday, February 10, 2011 6:53 PM
All Intel-based versions of Janus/Ada have always had Integer as a 16-bit type;
that originally was to keep the binary files created by the various Janus/Ada
compilers intercompatible (this was in the Ada 83 days, before streams). A
related issue was far too much use of "Integer" to mean 16-bits in the runtime
(most of that has been squeezed out in the intervening years).
It would be easy enough to change (essentially, change the definition of
Standard and recompile everything), but even now, a lot of Sequential_IO and
Direct_IO files would be incompatible. I've wanted to make this switchable with
a command line switch, but that turns out to be a lot harder to accomplish.
In any case, it provides a fine test for supposely portable Ada code:
probably 75% of it fails to run on Janus/Ada because it has assumed a range for
Integer. Using a properly declared type fixes that.
****************************************************************
From: Robert Dewar
Sent: Thursday, February 10, 2011 6:58 PM
> All Intel-based versions of Janus/Ada have always had Integer as a
> 16-bit type; that originally was to keep the binary files created by
> the various Janus/Ada compilers intercompatible (this was in the Ada
> 83 days, before streams). A related issue was far too much use of
> "Integer" to mean 16-bits in the runtime (most of that has been
> squeezed out in the intervening years).
Right, but these days that is just not viable in an Ada compiler, so I regard
this as an oddity from the past. Limiting strings to 32K bytes is simply not a
viable choice on any modern architecture. So in practice Integer will always be
32 bits on any reasonable modern architecture.
****************************************************************
From: Dan Eilers
Sent: Thursday, February 10, 2011 7:05 PM
> Anyway, so what? My point is I don't want to go tracking down all the
> potential non-portabilities, and then have to argue about whether
> Integer'Last is more or less portable than Priority'Last.
Just so there's no confusion here, I wasn't referring to "Priority'Last"
being non-portable (even though it will differ between implementations).
I was referring to System.Max_Priority, which is not defined by the language,
but apparently is added by GNAT.
This isn't just a hypothetical potential problem.
A week or two ago, Brad Moore stumbled into this exact problem when he posted
his "Paraffin" code, which unintentionally used System.Max_Priority rather than
Priority'Last.
Given that portability is a major goal of Ada, I think that the easy-to-fix
portability problems deserve serious consideration, even if hard-to-fix problems
remain.
****************************************************************
From: Randy Brukardt
Sent: Thursday, February 10, 2011 7:10 PM
...
> No need to tell me -- I saw those e-mails in AI05-0153-3.
>
> I deliberately left out No_Implementation_Units, because Robert's
> e-mail seemed to make it clear that he's not asking for a standard
> feature. He's asking for an informal agreement that folks would
> implement this restriction.
Robert doesn't have to ask for "informal agreement". He just has to do it, and
the rest of us will have to copy him. ;-)
In any case, this seems to me like an odd omission from the existing
No_Implementation_xxx restrictions, and since we are adding a bunch of other
restrictions, we should fix this clear omission. If nobody else agrees, that's
fine with me.
> > Anyway, are there any objections to this idea?? (If there are any,
> > we'll have to do it as a separate AI.)
>
> I'm opposed to putting this feature in the standard at this time.
> It just doesn't seem worth the trouble, and it doesn't seem
> particularly related to aspects.
>
> But I don't feel strongly about it, and if it goes in, I'd be happy to
> put it in this AI.
OK, but I don't see how we can decide here whether it is in or out; so I think
I'll just make a separate AI and you can vote against it if you like.
> Dan Eilers wrote:
>
> > There is a related issue of disallowing implementation-dependent
> > indentifiers declared in package System, such as System.Max_Priority.
>
> And Tucker Taft replied:
>
> > Good point. These are also sources of non-portability.
> > In this case, I presume the restriction would be on
> > *use* of such an identifier, since you probably don't expect there
> > to be a version of System just sitting around that omits these things.
> >
> > Perhaps "pragma Restrictions(Pristine);"? ;-)
>
> This goes way, way too far, in my opinion. Ada just has way to many
> potential non-portabilities. I mean, any use of Integer is
> potentially non-portable, and you can't use String without Integer. A
> from-scratch language design could do much better (see Java), but it's
> too late for Ada.
I agree with Bob in this case. When you use anything from package System (or
package Standard or package Interfaces for that matter), you are taking a level
of non-portability. If you want to avoid that non-portability, use pragma
No_Dependence. No new features are needed for that.
> Please stop inventing new "nice to have" features!
I don't even believe that this is a "nice to have" feature. System's contents
are inherently non-portable. Using it in the first place means that you want to
do something at a low level. Expecting more than that makes no sense.
To take a particular example, type Address in the 16-bit x86 versions of
Janus/Ada is a record type with Segment and Offset components. Since Ada 83
doesn't have any Address constructor at all, the only way to set an Address
value is to initialize it with an aggregate. (If we had done an Ada 95 compiler
for that system, we would have done some sort of mapping from Integer_Address,
but that would be even less portable).
Indeed, most of our 32-bit x86 versions of Janus/Ada used a 48-bit version of
Address (again with segment and offset parts), since that matches the actual
hardware capabilities. (A lot of malware could have been avoiding if Windows had
put the code and data into different segments!!) We eventually had to get of
that on Windows because of problems with the segment registers getting clobbered
by foreign code.
Anyway, my point is that System is inherently system-dependent. It wouldn't be
usable without some level of that; I don't see any value to picking out
particular things in that package and saying they should be called out by a
restriction.
****************************************************************
From: Dan Eilers
Sent: Thursday, February 10, 2011 7:58 PM
> I don't even believe that this is a "nice to have" feature. System's
> contents are inherently non-portable. Using it in the first place
> means that you want to do something at a low level. Expecting more
> than that makes no sense.
Actually, people intending write fully portable Ada code end up unwittingly
using System.Max_Priority. See the ChameneosRedux benchmark program at:
http://shootout.alioth.debian.org/u32/program.php?test=chameneosredux&lang=gnat
It says:
-- Fully portable :
-- No machine/OS dependency
-- No dependency of GNAT-compiler specific features
and then does:
procedure ChameneosRedux is
pragma Priority (System.Max_Priority);
****************************************************************
From: Tucker Taft
Sent: Thursday, February 10, 2011 8:13 PM
I suspect that if you suggest a reasonable name for the restriction, GNAT folks
might add support for it. Something like:
pragma Restrictions(No_Nonstandard_System_Components);
I don't really agree with Randy, since often the reason to use things in System
is specifically to achieve portability, such as using System.Max_Int, or
System.Default_Bit_Order. So it can be annoying that there are seemingly useful
declarations in package System that are in fact not standard, and there is no
obvious way of realizing that without actually doing a line-by-line comparison
with the version of System in the reference manual.
****************************************************************
From: Randy Brukardt
Sent: Thursday, February 10, 2011 8:40 PM
> and then does:
>
> procedure ChameneosRedux is
> pragma Priority (System.Max_Priority);
Sure, but so what? 90% of the supposedly "portable" code that I've seen has some
compiler dependency. The only code that doesn't have been compiled and debugged
on multiple compilers, and there is very little than that. Most such code
depends on GNAT features, of course, but it works just as well in the reverse:
most of my "portable" code has proven to have some Janus/Ada dependency when
compiled with GNAT or ObjectAda.
I cannot imagine any way to even come close to banning all of these
incompatibilities via a restriction. The biggest problem porting to/from
Janus/Ada is the 16-bittedness of type Integer, but there is no restriction to
handle that. And if you had one to fix that, there would be plenty of other
issues. Including ones of source representation (which no restriction could ever
have an impact on).
In any case, the use of System is inherently non-portable. The program cited
above immediately left the realm of portable code simply by using System.
(Dependence on priorities is non-portable for instance; there is no reason to
assume a compiler supports more than one, and in that case you do not need any
Priority pragmas.)
****************************************************************
From: Randy Brukardt
Sent: Thursday, February 10, 2011 8:51 PM
...
> I don't really agree with Randy, since often the reason to use things
> in System is specifically to achieve portability, such as using
> System.Max_Int, or System.Default_Bit_Order.
> So it can be annoying that there are seemingly useful declarations in
> package System that are in fact not standard, and there is no obvious
> way of realizing that without actually doing a line-by-line comparison
> with the version of System in the reference manual.
Dependence on the things defined by the standard is just as likely to cause
non-portabilities. (The obvious example being the number of bits in Integer, but
it applies to virtually everything in System.) The form of specifying an address
(as a number, or a record, or whatever) is clearly not portable (unless the
compiler follows the implementation advice and supports none, but even then, the
interpretation of Integer_Address is implementation-defined). Unless the
restriction plugged most of these things, it is just providing false hope.
The only Ada code that can be considered portable is that compiled and tested on
more than one Ada compiler. It is quite unlikely that such things would survive
such a gauntlet (and even then, they do). [Keep in mind that we made Claw run on
5 different compilers; it takes quite a concerted effort, even when the code was
constructed to be portable from the beginning.]
It is interesting that this discussion has convinced me that the
No_Implementation_xxx restrictions are a waste of time, because they don't do
anything significant toward making Ada code portable. So now I'm leaning Bob's
way on this one.
****************************************************************
From: Tucker Taft
Sent: Thursday, February 10, 2011 9:42 PM
I think you are taking a narrow view of this.
Apparently your experience is different from mine in this area.
I find it very annoying when people unintentionally use features of a compiler
that are non-standard, thereby making it harder to reuse their code, especially
when there is an equivalent standard way of doing things. For example, using
'Unrestricted_Access when 'Unchecked_Access (or even 'Access) would have worked
fine. Similarly, using Max_Priority rather than Priority'Last.
That is really the purpose of these restrictions:
to catch unintentional uses of non-standard features, be they attributes,
pragmas, units, elements of package Standard, etc. It doesn't suddenly make
your program portable, but it does help to reduce the number of *unnecessary*
non-portabilities.
****************************************************************
From: Randy Brukardt
Sent: Thursday, February 10, 2011 10:06 PM
But this is an endless slippery slope of restrictions. First the obvious ones,
then you add restrictions for non-standard additions to System, then about
non-standard additions to other packages (there are several that allow that),
then any dependence on the contents of the Implementation packages of the Queue
containers, then on non-required types in Standard (Long_Integer, etc.), then on
Standard.Integer itself, then ...
To do this right, you'd need a restriction for everything that is marked
unspecified or implementation-defined in the Standard. Annex M has a list of
more than 140 implementation-defined items. And then there is implementation
advice, unspecified, and the rest. Are we going to add restrictions to cover all
of them? And a significant number of these things can't even be checked at
compile-time.
And then the question is whether people really are going to use all of these
restrictions. That seems doubtful as well.
We could, I suppose, wrap all of these restrictions into a profile, but that
doesn't really help the implementation cost of having to deal with so many
restrictions. (I'm unconvinced that restrictions are the best way to handle this
in any case.)
So I don't buy it. I'm drawing the line at No_Implementation_Units, and I won't
complain if it goes nowhere as well.
****************************************************************
Questions? Ask the ACAA Technical Agent