[perl #88486] IO::File does not always export SEEK*
authorFather Chrysostomos <sprout@cpan.org>
Thu, 14 Apr 2011 13:19:07 +0000 (06:19 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Thu, 14 Apr 2011 13:19:07 +0000 (06:19 -0700)
Commit d963bf0 made perl set @IO::File::ISA automagically.

Commit 15e6cdd made filehandle methods load IO::File automagically.

Commit efc5c7c attempted to solve the problem that having IO::Handle
loaded causes IO::File to be bypassed, rendering 15e6cdd only
semi-effective (see [perl #87940]), by requiring IO::File inside
IO::Handle.

That commit ended up breaking several CPAN modules, because IO::File
adds @IO::Seekable::EXPORT to its own exports.

If IO::Seekable is loaded first (before IO::File), before setting up
its @EXPORT it loads IO::Handle, which loads IO::File, which tries to
load IO::Seekable, which is in %INC already, and which is hence wait-
ing for IO::File to load before it sets its own @EXPORT. So IO::File
sees @IO::Seekable::EXPORT empty.

Hence, every piece of code that tries to import SEEK_END from IO::File
will simply not get it if IO::Seekable is already loaded (explicitly
or, e.g., by File::Temp).

This commit hopefully fixes the breakage and the problem that efc5c7c
attempted to fix by loading IO::File only inside IO::Handle::new (the
only method that IO::File overrides).

MANIFEST
META.yml
dist/IO/lib/IO/Handle.pm
dist/IO/t/io_file_export.t [new file with mode: 0644]

index a28ada3..c804dea 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -3009,6 +3009,7 @@ dist/IO/README                    IO extension maintenance notice
 dist/IO/t/io_const.t           See if constants from IO work
 dist/IO/t/io_dir.t             See if directory-related methods from IO work
 dist/IO/t/io_dup.t             See if dup()-related methods from IO work
+dist/IO/t/io_file_export.t     Test IO::File exports
 dist/IO/t/io_file.t            See if binmode()-related methods on IO::File work
 dist/IO/t/io_linenum.t         See if I/O line numbers are tracked correctly
 dist/IO/t/io_multihomed.t      See if INET sockets work with multi-homed hosts
index 4dc98fe..af1423f 100644 (file)
--- a/META.yml
+++ b/META.yml
@@ -77,6 +77,7 @@ no_index:
     - dist/IO/t/io_dir.t
     - dist/IO/t/io_dup.t
     - dist/IO/t/io_file.t
+    - dist/IO/t/io_file_export.t
     - dist/IO/t/io_linenum.t
     - dist/IO/t/io_multihomed.t
     - dist/IO/t/io_pipe.t
index a7431fa..6ca3c8a 100644 (file)
@@ -265,12 +265,6 @@ use Symbol;
 use SelectSaver;
 use IO ();     # Load the XS module
 
-# Since perl will automatically require IO::File if needed, but also
-# initialises IO::File's @ISA as part of the core we must ensure
-# IO::File is loaded if IO::Handle is. This avoids effectively
-# "half-loading" IO::File.
-require IO::File;
-
 require Exporter;
 @ISA = qw(Exporter);
 
@@ -315,7 +309,18 @@ $VERSION = eval $VERSION;
 
 sub new {
     my $class = ref($_[0]) || $_[0] || "IO::Handle";
-    @_ == 1 or croak "usage: $class->new()";
+    if (@_ != 1) {
+       # Since perl will automatically require IO::File if needed, but
+       # also initialises IO::File's @ISA as part of the core we must
+       # ensure IO::File is loaded if IO::Handle is. This avoids effect-
+       # ively "half-loading" IO::File.
+       if ($] > 5.013 && $class eq 'IO::File' && !$INC{"IO/File.pm"}) {
+           require IO::File;
+           shift;
+           return IO::File::->new(@_);
+       }
+       croak "usage: $class->new()";
+    }
     my $io = gensym;
     bless $io, $class;
 }
diff --git a/dist/IO/t/io_file_export.t b/dist/IO/t/io_file_export.t
new file mode 100644 (file)
index 0000000..3d11990
--- /dev/null
@@ -0,0 +1,18 @@
+#!./perl -w
+
+# This script checks that IO::File exports the SEEK* constants if
+# IO::Seekable is loaded first, which was temporarily broken during 5.14
+# code freeze. See [perl #88486].
+
+BEGIN{
+    require($ENV{PERL_CORE} ? "../../t/test.pl" : "./t/test.pl");
+    plan(tests => 3);
+}
+
+use IO::Seekable (); # import nothing
+use IO::File;        # import defaults
+
+# No strict!
+cmp_ok SEEK_END, 'ne', "SEEK_END", 'SEEK_END';
+cmp_ok SEEK_SET, 'ne', "SEEK_SET", 'SEEK_SET';
+cmp_ok SEEK_CUR, 'ne', "SEEK_CUR", 'SEEK_CUR';