Closed Bug 1071102 Opened 5 years ago Closed 4 years ago

Remove include of nsRefPtr.h from nsAutoPtr.h

Categories

(Core :: XPCOM, defect)

defect
Not set

Tracking

()

RESOLVED WONTFIX

People

(Reporter: mccr8, Assigned: ayg)

References

Details

(Whiteboard: [please do not write this patch by hand!])

Attachments

(5 files, 5 obsolete files)

Bug 1071100 will split nsRefPtr into its own header file, but leave nsAutoPtr.h including nsRefPtr.h.  Ideally, we want to remove that, because the classes are not really related.

To fix that, we need to add an include of nsRefPtr.h to any file that uses nsRefPtr, and remove any includes of nsAutoPtr.h from files that don't use nsAutoPtr.  This could be done in this bug, or in separate bugs blocking this one if it proves to be easy to work on it piecemeal.

There are currently 811 includes of nsAutoPtr.h in the tree, so this will be a pretty big patch.  I think the right way to do this is to automatically generate it: look at all files that include nsAutoPtr.h, then whether they contain any uses of nsRefPtr or nsAutoPtr, and change the nsAutoPtr.h include as appropriate based on that.  Given my past experience, this will reveal a ton of header bootlegging (say, file A uses nsRefPtr, but does not include nsAutoPtr.h, but instead it includes header B.h, which includes nsAutoPtr.h), so manual fixups will be required.  Perhaps this problem can be avoided using a smarter approach.

(nfroyd suggested this two-stage approach to the header split.)
Whiteboard: [please do not write this patch by hand!]
To be sure that all instances of header bootlegging are fixed, you are going to want to do a non-unified build before uploading the final patch, by adding
  ac_add_options --disable-unified-compilation
to your mozconfig, and then doing a clobber build.  This may not be a great bug for somebody with a slow machine, as it is going to involve a lot of waiting for recompiles.
The following Linux bash script seems to pretty much do the job, although I haven't actually finished compiling.  I'd expect it would need a few minor fixups.

Whenever I write a shell script that gets this complicated, I always wish I had done it in Python instead.

Notes to reusers: Obviously, make sure you fix Bugzilla's inserted newlines.  Change --exclude-dir=obj to match the name of your object dir.  Run from the root of your clone.  I don't guarantee it will work with anything other than GNU sed/grep.

#!/bin/bash
for file in $(grep -RIl 'nsAutoPtr\|nsAutoArrayPtr' --exclude-dir=obj * | grep '\.\(h\|cpp\)' | grep -v 'xpcom/base/nsAutoPtr\.h')
do
  echo $file
  new_includes=$( \
    grep -v '^#include' $file | \
    grep -o '\b\(nsAutoPtr\|nsRefPtr\|nsCOMPtr\|nsAutoArrayPtr\)\b' | \
    sed 's/Array//g;s!nsRefPtr!mozilla\/nsRefPtr!' | \
    sort -u | \
    sed "s/^/#include \"/;s/$/.h\"\\\\/;\$s/\\\\//"
  )
  sed -i "/^#include.*\"\(nsAutoPtr\|mozilla\/nsRefPtr\|nsCOMPtr\)\.h\"/d;" $file
  if [ -n "$new_includes" ]
  then
    sed -i "0,/^#include/s!!\
${new_includes}\\\

#include!" $file
  fi
done

I can't actually take this bug now, because I don't have time to finish it off, but if no one has taken it by late September I'll probably take a look at it again.
Attached patch Patch (obsolete) — Splinter Review
I know you're not technically an owner of this component, but this probably doesn't need real review anyway.  My script needed only two fixups to compile locally (includes added within an #ifdef and an external "C").

https://treeherder.mozilla.org/#/jobs?repo=try&revision=476b3bcd4ebd
Assignee: nobody → ayg
Status: NEW → ASSIGNED
Attachment #8670391 - Flags: review?(continuation)
Are you okay with my reviewing this 1MB patch, Nathan? Feel free to take it if you want. ;)
Flags: needinfo?(nfroyd)
(In reply to Andrew McCreight [:mccr8] from comment #4)
> Are you okay with my reviewing this 1MB patch, Nathan? Feel free to take it
> if you want. ;)

Yes, that's fine.  We should just make you an XPCOM peer.
Flags: needinfo?(nfroyd)
Comment on attachment 8670391 [details] [diff] [review]
Patch

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

Something isn't quite right with your script. I started auditing the files by hand, and I noticed that accessible/base/FocusManager.h actually uses nsRefPtr.h, but you remove the include of nsAutoPtr without adding nsRefPtr. Your try push is also broken on a few platforms, with what looks like similar issues.

I hacked up a crude Python script that does something similar to your shell script to analyze the uses and includes. It doesn't actually make any changes, but feel free to build on it: https://github.com/amccreight/moz-source-tools/blob/master/refptrinclude.py

::: accessible/base/FocusManager.h
@@ -4,5 @@
>  
>  #ifndef mozilla_a11y_FocusManager_h_
>  #define mozilla_a11y_FocusManager_h_
>  
> -#include "nsAutoPtr.h"

This file actually uses nsRefPtr, so it needs to include it.
Attachment #8670391 - Flags: review?(continuation) → review-
Looking at the B2G build failure, your patch is removing the include of nsAutoPtr.h, but the file uses nsAutoPtr.
Though in that instance it is only being used in a declaration as a &, so technically it the template could be forward declared without including nsAutoPtr.h. It is probably not worth making a script sophisticated enough to deal with that.
Attached file New fixup script (obsolete) —
Thanks for the template, it helped a lot.  I just don't know the Python standard libraries well enough to write this sort of thing quickly.
Attached patch Part 1 -- Fix header bootlegging (obsolete) — Splinter Review
Surprisingly, this is the only file I've found that depended only on things included by the *Ptr.h headers.
Attachment #8670901 - Flags: review?(continuation)
This patch is purely autogenerated by the fixup script, no manual fixes.
Attachment #8670391 - Attachment is obsolete: true
Attachment #8670903 - Flags: review?(continuation)
(In reply to :Aryeh Gregor (working until October 13) from comment #9)
> Thanks for the template, it helped a lot.  I just don't know the Python
> standard libraries well enough to write this sort of thing quickly.

I don't know them very well either. I usually just do a web search for something like "python reverse list" and some Stack Overflow answer will turn up. ;)
Attachment #8670897 - Attachment mime type: text/x-python → text/plain
Comment on attachment 8670901 [details] [diff] [review]
Part 1 -- Fix header bootlegging

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

Nice.
Attachment #8670901 - Flags: review?(continuation) → review+
Comment on attachment 8670904 [details] [diff] [review]
Part 3 -- Remove unneeded include from nsAutoPtr.h

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

::: xpcom/base/nsAutoPtr.h
@@ -7,5 @@
>  #ifndef nsAutoPtr_h
>  #define nsAutoPtr_h
>  
>  #include "nsCOMPtr.h"
> -#include "mozilla/nsRefPtr.h"

Hmm. What is this file using nsCOMPtr.h for? nsCOMPtr.h includes nsRefPtr.h, so we're still including it indirectly. Maybe nsCOMPtr_helper needs to be in its own header file, so that nsCOMPtr.h doesn't have to include nsRefPtr.h. Still, this bug is a good step forward.
Attachment #8670904 - Flags: review?(continuation) → review+
Comment on attachment 8670903 [details] [diff] [review]
Part 2 -- Clean up nsAutoPtr includes

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

I think your patch creates some bootlegging. For instance, in HTMLElementAccessibles.h, your patch removes the include of nsRefPtr.h, but HTMLElementAccessibles.cpp does use nsRefPtr.h, so it should get an include added. (In some sense, this was not really bootlegging before, because the header for the .cpp included it.)

I think this stems from the second half of this line in your script:
  if (not toRemove and not toAdd) or ('nsAutoPtr' not in includes and 'nsAutoPtr' not in uses):

Why do you have that in there?

Your try run is orange on b2g again. It looks like the problem is that DBusUtils.h bootlegs nsISupportsImpl.h for NS_INLINE_DECL_THREADSAFE_REFCOUNTING via RefPtr.h, and somehow your patch happens to break that.

You should wait until Nathan's patches in bug 1207245 settle out before landing this, as that is probably going to interfere with this a bit, and it breaks some of the bootlegging which will cause more havok. He landed it but it got backed out for breaking something.

Thanks for working on this. It is a pretty tedious thing to fix.
Attachment #8670903 - Flags: review?(continuation) → review-
(Let me know if you've exceeded your time budget for this project and I can finish it off.)
(In reply to Andrew McCreight [:mccr8] from comment #16)
> I think this stems from the second half of this line in your script:
>   if (not toRemove and not toAdd) or ('nsAutoPtr' not in includes and
> 'nsAutoPtr' not in uses):
> 
> Why do you have that in there?

To reduce the size of the patch and therefore the number of problems I have to fix.  But you're right, it doesn't work.

> Thanks for working on this. It is a pretty tedious thing to fix.

Fixing tedious things is a specialty of mine!  Making nsresult an enum class was immeasurably more tedious -- this is easy, it's mostly scriptable.  :)
Attached file Fixup script v3
Attachment #8670897 - Attachment is obsolete: true
Notable changes in new version -- affects files that don't deal with nsAutoPtr, and has more aggressive comment detection.  I manually checked all the files affected by the latter change and there were no false negatives.  More types of comments needed to be ignored to avoid trying to include nsRefPtr.h in files like AlreadyAddRefed.h (which causes Bad Things).
Attachment #8670901 - Attachment is obsolete: true
Attachment #8671369 - Flags: review?(continuation)
Attachment #8670903 - Attachment is obsolete: true
Attachment #8671372 - Flags: review?(continuation)
Comment on attachment 8671374 [details] [diff] [review]
Part 4, v2 -- Remove unneeded includes from nsAutoPtr.h

Seems we don't need the nsCOMPtr.h include after all.  Try looks green enough that I'm optimistic it will finish green.  Obviously before pushing to inbound I'll adjust for Nathan's work and rerun the script to check for any new fixes needed before pushing.

https://treeherder.mozilla.org/#/jobs?repo=try&revision=073f4865e9c4
Attachment #8671374 - Attachment description: Part 4, v2 -- Remove unneeded includes from nsAuto → Part 4, v2 -- Remove unneeded includes from nsAutoPtr.h
Attachment #8671374 - Flags: review?(continuation)
Attachment #8670904 - Attachment is obsolete: true
Attachment #8671369 - Flags: review?(continuation) → review+
Attachment #8671370 - Flags: review?(continuation) → review+
Attachment #8671374 - Flags: review?(continuation) → review+
This is looking pretty good to me. Sorry for the delay. Nathan said it was okay if this lands ahead of in bug 1207245, if you prefer.

There are still a few remaining issues, I think, having to do with the placement of the #includes. It looks like they are getting inserted before the first #include in the file.

The first problem with this is that it breaks when people include Foo.h in Foo.cpp, in order to check that Foo.h has all of the necessary includes. One example of this is dom/bluetooth/bluedroid/BluetoothSocketMessageWatcher.cpp. A simple fix for this would be to insert it after the first include, rather than before.

The second problem is that a number of the includes are getting inserted inside system-specific #ifdef blocks, like "#if defined(MOZ_WIDGET_GTK)". This is happening in a number of files, such as dom/camera/GonkRecorderProfiles.h, dom/ipc/ContentChild.cpp, dom/media/MediaDecoderStateMachine.cpp and xpcom/base/nsCycleCollector.cpp, but not as many as the previous problem. It looks like things build, but it is a bit unfortunate to leave all of this junk around. Detecting this particular issue may be tricky, given that you have to ignore include guards in headers. I'm not sure what should be done about that.
Attachment #8671372 - Flags: review?(continuation) → review-
(In reply to Andrew McCreight [:mccr8] from comment #26)
> There are still a few remaining issues, I think, having to do with the
> placement of the #includes. It looks like they are getting inserted before
> the first #include in the file.

For files with no existing *Ptr.h includes, yeah.
 
> The first problem with this is that it breaks when people include Foo.h in
> Foo.cpp, in order to check that Foo.h has all of the necessary includes. One
> example of this is
> dom/bluetooth/bluedroid/BluetoothSocketMessageWatcher.cpp. A simple fix for
> this would be to insert it after the first include, rather than before.

I don't understand what this breaks.

> The second problem is that a number of the includes are getting inserted
> inside system-specific #ifdef blocks, like "#if defined(MOZ_WIDGET_GTK)".
> This is happening in a number of files, such as
> dom/camera/GonkRecorderProfiles.h, dom/ipc/ContentChild.cpp,
> dom/media/MediaDecoderStateMachine.cpp and xpcom/base/nsCycleCollector.cpp,
> but not as many as the previous problem. It looks like things build, but it
> is a bit unfortunate to leave all of this junk around. Detecting this
> particular issue may be tricky, given that you have to ignore include guards
> in headers. I'm not sure what should be done about that.

It should be pretty easy to come up with a heuristic that ignores the include guards.

I'm not going to be working for the next six months, so if you (or anyone else) want to finish this up, please do.  Otherwise I guess I'll take it up in six months.
(In reply to :Aryeh Gregor (not working until April 10-May 8) from comment #27)
> I don't understand what this breaks.

Here is the scenario: Foo.h uses nsRefPtr.h, but does not include the nsRefPtr header. Foo.cpp includes Foo.h, after it includes nsRefPtr.h. Foo.cpp compiles just fine, but if somebody else includes Foo.h it may not compile. By putting Foo.h as the first include of Foo.cpp, then we can be sure that at least one place checks that Foo.h does not implicitly rely on extra includes from outside of the file.

> I'm not going to be working for the next six months, so if you (or anyone
> else) want to finish this up, please do.  Otherwise I guess I'll take it up
> in six months.

Alright, thanks. Hopefully I'll find some time in the next six months.
Flags: needinfo?(continuation)
I guess realistically I'm not going to have time to do this in the near term.
Flags: needinfo?(continuation)
Nathan Froyd posted to dev-platform on February 25 saying that he plans to axe nsAutoPtr, à la bug 1229985, so this bug is probably not worth pursuing.
Yeah, I guess that's true. Time spent on this bug would be better spent working towards that.
Status: ASSIGNED → RESOLVED
Closed: 4 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.