!standard 6.4.1(13) 10-02-04 AI05-0196-1/02 !class binding interpretation 10-02-03 !status Amendment 2012 10-04-02 !status WG9 Approved 10-06-18 !status ARG Approved 10-0-0 10-02-28 !status work item 10-02-03 !status received 09-12-09 !priority Medium !difficulty Easy !qualifier Omission !subject Null exclusion checks for 'out' parameters !summary Null exclusion checks are not made for OUT parameters when evaluating the actual parameters. !question Does the following program raise Constraint_Error? (No.) procedure M is type Integer_Access is access all Integer; procedure X (Y : out not null Integer_Access) is begin Y := new Integer; end X; A : Integer_Access; -- initially null begin X (A); -- Raise Constraint_Error here? end M; That is, when passing an OUT mode parameter, is the implementation supposed to do a not-null check on the way in? (No.) !recommendation (See summary.) !wording Modify 6.4.1(13): For an access type, the formal parameter is initialized from the value of the actual, without [a constraint check]{checking that the value satisfies any constraint or any exclusion of the null value}; !discussion It would be weird and unfriendly if the prior value of the actual parameter mattered for an OUT parameter. There is no guarantee that an OUT parameter of an access type satisfies any access subtype constraint that applies to the formal, so there seems no reason to expect it to satisfy any null exclusion that might apply. !corrigendum 6.4.1(13) @drepl For an access type, the formal parameter is initialized from the value of the actual, without a constraint check; @dby For an access type, the formal parameter is initialized from the value of the actual, without checking that the value satisfies any constraint or any exclusion of the null value; !ACATS Test Create an ACATS C-test to check that an example like the one in the question does not raise Constraint_Error. !appendix From: Bob Duff Sent: Wednesday, December 9, 2010 4:49 PM Does the following program raise Constraint_Error? procedure M is type Integer_Access is access all Integer; procedure X (Y : out not null Integer_Access) is begin Y := new Integer; end X; A : Integer_Access; -- initially null begin X (A); -- Raise Constraint_Error here? end M; That is, when passing an OUT mode parameter, is the implementation supposed to do a not-null check on the way in? I think the relevant paragraph is 6.4.1(13): 13 For an access type, the formal parameter is initialized from the value of the actual, without a constraint check; It goes out of its way to skip the constraint check, but it doesn't say to skip the not-null check. On the other hand, it doesn't say that there IS a not-null check (and implementations are not supposed to invent checks that the RM doesn't explicitly call for). I think it should be explicit, one way or 'tother. GNAT currently raises C_E for the above example. Some of us at AdaCore find that confusing, because the point of procedure X is to initialize the actual. Others at AdaCore would find the opposite rule confusing, because a "not null" object could be null. I'm on the fence -- I can see both sides of that argument. And just before sending this, I notice that some of us have changed their mind! ;-) **************************************************************** From: Tucker Taft Sent: Wednesday, December 9, 2010 5:03 PM As Bob mentions, paragraph 6.4.1(13) says no constraint check, but doesn't mention null-exclusion checks. But it would be weird in my view, and pretty unfriendly, if the prior value of the actual parameter mattered. Note that there is no guarantee that an OUT parameter of an access type satisfies any access subtype constraint that applies to the formal, so there seems no reason to expect it to satisfy any null exclusion that might apply. So I would say, don't check. Clearly the RM needs some clarification here. **************************************************************** From: Pascal Leroy Sent: Thursday, December 10, 2010 12:23 AM >I think the relevant paragraph is 6.4.1(13): > > 13 For an access type, the formal parameter is initialized from the > value of the actual, without a constraint check; > > It goes out of its way to skip the constraint check, but it doesn't say > to skip the not-null check. On the other hand, it doesn't say > that there IS a not-null check (and implementations are not > supposed to invent checks that the RM doesn't explicitly call for). > I think it should be explicit, one way or 'tother. It has been the intent all along that constraints and null exclusion work similarly, so I think passing in null is just fine. In fact, I can't find in the RM a definition of the phrase "constraint check", so it's unclear to me if the Access_Check related to null exclusion is or is not a "constraint check". It might be better to rephrase this rule using the term "satisfies". **************************************************************** From: Bob Duff Sent: Thursday, December 10, 2010 1:53 PM > It has been the intent all along that constraints and null exclusion > work similarly, so I think passing in null is just fine. OK. > In fact, I can't find in the RM a definition of the phrase "constraint > check", so it's unclear to me if the Access_Check related to null > exclusion is or is not a "constraint check". The term "constraint check" is rather informal. I think its meaning was crystal clear before we invented null_exclusions. Now it's less clear. But a null_exclusion is not a constraint (for obscure language-legalistic reasons), so I'd say "constraint check" does not include the not-null check on null_exclusions. >...It might be better to rephrase this rule using the term >"satisfies". I don't quite see how to do that -- can you show us some wording that uses "satisfies"? I was thinking "..., without a constraint check or null_exclusion check". Still informal, but clear enough. **************************************************************** From: Randy Brukardt Sent: Thursday, December 10, 2010 2:21 PM > I don't quite see how to do that -- can you show us some wording that > uses "satisfies"? I'm not Pascal, but how about: For an access type, the formal parameter is initialized from the value of the actual, without [a constraint check]{checking that the value satisfies any constraint or any null_exclusion}; Humm, safisfies isn't defined for null exclusions. Turn that around: For an access type, the formal parameter is initialized from the value of the actual, without [a constraint check]{checking the value against any null_exclusion or that the value satisfies any constraint}; Longer, but more formal. **************************************************************** From: Pascal Leroy Sent: Thursday, December 10, 2010 2:21 PM I don't quite see how to do that -- can you show us some wording that uses "satisfies"? I was thinking "..., without a constraint check or null_exclusion check". Still informal, but clear enough. I was thinking of replacing the part after the comma in 6.4.1(13) by something like: "No check is made that the actual satisfies the constraints or null exclusion of the formal subtype." But then my wording-crafting skills are a bit rusty these days... **************************************************************** From: Pascal Leroy Sent: Thursday, December 10, 2010 2:26 PM > Humm, safisfies isn't defined for null exclusions. Turn that around: It is, last sentence of 3.10(15/2). **************************************************************** From: Randy Brukardt Sent: Thursday, December 10, 2010 2:43 PM You are right, I've surprised that 4.6(51/2) didn't take advantage of that. (That's what I used as a pattern.) So my suggestion should have been: For an access type, the formal parameter is initialized from the value of the actual, without [a constraint check]{checking that the value satisfies any constraint or any exclusion of the null value}; (echoing the wording of 3.10(15/2)). **************************************************************** From: Tucker Taft Sent: Thursday, December 10, 2010 2:48 PM "satisfies" *is* defined for null exclusions. See last sentence of 3.10(15/2). So I think the simplest might be: For an access type, the formal parameter is initialized from the value of the actual, without [a constraint check]{checking whether the value satisfies any constraint or null_exclusion}; **************************************************************** From: Pascal Leroy Sent: Thursday, December 10, 2010 4:08 PM Technically you don't satisfy a null_exclusion (there may not be any such syntactic construct in sight), you satisfy "an exclusion of the null value". ****************************************************************