Closed Bug 1295825 Opened 8 years ago Closed 8 years ago

Add a [must_use] attribute to XPIDL

Categories

(Core :: XPCOM, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla51
Tracking Status
firefox51 --- fixed

People

(Reporter: n.nethercote, Assigned: n.nethercote)

References

(Blocks 1 open bug)

Details

Attachments

(4 files)

I tried adding MOZ_MUST_USE to NS_IMETHOD in bug 1292440. I have concluded that is too blunt an instrument to be practical.

The obvious alternative is to add a new annotation to XPIDL that adds MOZ_MUST_USE to the generated declarations. The obvious name for this is [must_use]. It can apply equally well to methods and attributes.
Summary: Add a [must_use] attributes to XPIDL → Add a [must_use] attribute to XPIDL
To write this patch I just looked for all the places where |nostdcall| occurred
and did something appropriate for |must_use|.

I'm pretty sure this doesn't have any bad interactions with existing
attributes. The only one of interest is [infallible]. If you use [infallible,
must_use] on an XPIDL attribute, you end up with this generated code:

> /* [infallible,must_use] attribute boolean allowMedia; */
> MOZ_MUST_USE NS_IMETHOD GetAllowMedia(bool *aAllowMedia) = 0;
> inline bool GetAllowMedia()
> {
>   bool result;
>   mozilla::DebugOnly<nsresult> rv = GetAllowMedia(&result);
>   MOZ_ASSERT(NS_SUCCEEDED(rv));
>   return result;
> }
> MOZ_MUST_USE NS_IMETHOD SetAllowMedia(bool aAllowMedia) = 0;

It's not a useful combination -- you're forced to check the
guaranteed-to-be-NS_OK return value if you use the first overloading of
GetAllowMedia() -- but it's a coherent one. So I don't think it needs to be
disallowed or otherwise treated specially.
Attachment #8781794 - Flags: review?(nfroyd)
Assignee: nobody → n.nethercote
Status: NEW → ASSIGNED
I'm partway through a patch that adds [must_use] throughout nsIFile.idl, but
fixing all the missing checks is turning out to be a large amount of work.
Here's a patch that is less compelling but much smaller, to demonstrate how
[must_use] works.
Attachment #8781868 - Flags: review?(nfroyd)
Another not especially compelling example :)
Attachment #8781873 - Flags: review?(nfroyd)
Attached file Example generated code: nsIPipe.h (deleted) —
Here's the generated code for nsIPipe.h, in case it's helpful.
A piece of advance bikeshedding. In a declaration like this:

> MOZ_MUST_USE nsresult Foo(Blah aBlah);

the MOZ_MUST_USE clearly applies to the |nsresult|, which is good.

In a declaration like this:

> [must_use] void init(in nsIFile file);

the [must_use] looks like it applies to the |void|, which doesn't make sense. You have to understand that it's applying to the implicit |nsresult| return value.

With that in mind, maybe [must_use] isn't the best name. Perhaps [must_check] would be better? Or perhaps sticking with a name that mirrors MOZ_MUST_USE would be better. I'm not sure. Suggestions welcome.
Blocks: 1296164
Another thought: it would be useful to have an annotation that represents the opposite of [must_use]. It might be called [need_not_use]. The rationale being that without it, if you see a method/attribute without a [must_use] annotation, it's unclear if not checking the result is reasonable, or is this just a method/attribute that nobody has looked at yet. The annotation would have no effect, it would be essentially a comment. (I've already written some comments in some patches saying "this doesn't need a [must_use] annotation because ignoring the result is common and reasonable". This annotation would be a more concise version of that.)
(In reply to Nicholas Nethercote [:njn] from comment #5)
> A piece of advance bikeshedding. In a declaration like this:
> 
> > MOZ_MUST_USE nsresult Foo(Blah aBlah);
> 
> the MOZ_MUST_USE clearly applies to the |nsresult|, which is good.
> 
> In a declaration like this:
> 
> > [must_use] void init(in nsIFile file);
> 
> the [must_use] looks like it applies to the |void|, which doesn't make
> sense. You have to understand that it's applying to the implicit |nsresult|
> return value.
> 
> With that in mind, maybe [must_use] isn't the best name. Perhaps
> [must_check] would be better? Or perhaps sticking with a name that mirrors
> MOZ_MUST_USE would be better. I'm not sure. Suggestions welcome.

Yeah, I have this concern too.  The only problem is that making it more clear requires something like:

  [cxx_must_use_nsresult] void init(...);

which is a bit of a mouthful, though at least makes it clear to JS people looking at the IDL that you don't have to worry about what the attribute means for your JS implementation.  Or maybe:

  [cxx_must_use] void init(...);

would be OK?
Comment on attachment 8781794 [details] [diff] [review]
(part 1) - Add a [must_use] attribute to XPIDL

Review of attachment 8781794 [details] [diff] [review]:
-----------------------------------------------------------------

I think what we get for [infallible] things are OK.

For broader context: I talked to Nick offline about the possibility of making this a class-level attribute, and his response was that it's too big of a hammer; it's similar to declaring MOZ_MUST_USE on NS_IMETHOD.  I'm not too keen on adding a bunch of clutter to the IDL to add this attribute on Every. Single. Method., but I'm not sure there's a better way to do things yet.  This attribute at least has the virtue of letting us convert things incrementally, and maybe there will be some obvious conventions that come out of it once we have experience converting things ([check_all_nsresult] class attribute + [need_not_check] on particular methods?  who knows?).

comment 7 has my contribution to the bikeshed.  I vote for [cxx_must_use].
Attachment #8781794 - Flags: review?(nfroyd) → review+
Attachment #8781868 - Flags: review?(nfroyd) → review+
Attachment #8781873 - Flags: review?(nfroyd) → review+
> > In a declaration like this:
> > 
> > > [must_use] void init(in nsIFile file);
> > 
> > the [must_use] looks like it applies to the |void|, which doesn't make
> > sense. You have to understand that it's applying to the implicit |nsresult|
> > return value.

After writing this, I realized that all the properties (binaryname, deprecated, noscript, etc.) could be interpreted this way. Which indicates it's the wrong way to think about it; anything appearing in the square brackets really applies to the entire method declaration.

Whether or not that changes your desire for the cxx_ prefix, I don't know.
> Whether or not that changes your desire for the cxx_ prefix, I don't know.

Also, most of the other attributes are C++ specific, too: notxpcom, infallible, nostdcom, binaryname, etc. So for consistency they should also have cxx_ prefixes, but of course they don't. So I'm now going to argue that must_use shouldn't have a cxx_ prefix either. Thoughts?
Flags: needinfo?(nfroyd)
(In reply to Nicholas Nethercote [:njn] from comment #10)
> > Whether or not that changes your desire for the cxx_ prefix, I don't know.
> 
> Also, most of the other attributes are C++ specific, too: notxpcom,
> infallible, nostdcom, binaryname, etc. So for consistency they should also
> have cxx_ prefixes, but of course they don't. So I'm now going to argue that
> must_use shouldn't have a cxx_ prefix either. Thoughts?

That's a good point.  Let's go with [must_use].
Flags: needinfo?(nfroyd)
I updated https://developer.mozilla.org/en-US/docs/Mozilla/XPIDL accordingly. I also added documentation for [infallible], which was missing.
Depends on: 1297133
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: