While working on RT #131098 Error message for require "./base.pm" is wrong I was trying to understand the search logic in S_require_file() and have provisionally concluded that it seems to make no sense. Or if it does, the docs for do() and require() need expanding. A bit of background. In the Good Old Days before we supported refs in @INC, and before we added the "stop searching @INC on EACCES" behaviour, the file-locating logic for do/require looked roughly like: my $found; my $searchable = $file !~ m{^( / | \./ | \.\./ )}x; if (!$searchable) { $found = load_file($file); } else { for my $prefix (@INC) { next unless load_file("$prefix/$file"); $found = 1; last; } } croak(...) unless $found; i.e. search @INC unless it's a special type of pathname. However, once the facility for having refs in @INC was added, this behaviour was changed; in particular, @INC is still searched (but non-refs are ignored) for "non-searchable" filenames. I.e. the algorithm now looks like: my $found; my $searchable = $file !~ m{^( / | \./ | \.\./ )}x; if (!$searchable) { $found = load_file($file); } if (!$found) { for my $prefix (@INC) { if (ref($prefix)) { ... do stuff with the ref ... } else if ($searchable) { next unless load_file("$prefix/$file"); $found = 1; last; } } } croak(...) unless $found; This is somewhat weird. Ok, I can kind of understand that refs-in-@INC is a "super" mechanism that overrides the normal "this filename isn't searchable" behaviour, but here we get *both* behaviours. For something like require "./foo/bar.pm", we try to load "./foo/bar.pm", and only if that fails, do we process the 'grep ref, @INC' subset of @INC. I would expect that if we're going to search that subset, that we shouldn't try to directly load "./foo/bar.pm" first. Now, the tests in t/op/inccode.t expect that loading "./nosuchfile.pm" will search refs in @INC; but nothing in the test suite fails if we skip loading "./some_existing_file.pm" and proceed directly to scanning @INC. So that may be emergent behaviour. The waters are the further muddied by the new 'stop scanning @INC if EACCES is seen" behaviour. This works on the sensible principle that if we get "permission denied" while trying to load a file when "/dir_we_dont_have_perms_for" is in @INC, then we don't know whether the file exists but we can't load it, or the file doesn't exist, but we don't have read access to directory it's in to know that. So for safety we stop rather than trying further @INC entries. However, the EACCES feature was implemented by changing two of the lines in the pseudo-code above to the equivalent of: - if (!$found) { + if (!$found && !($! == EACCES && !$searchable)) { - next unless load_file("$prefix/$file"); + unless (load_file("$prefix/$file")) { + last if $! == EACCES; + next; + } The second chunk of that diff is what I'd expect. The first just makes the non-searchable filename behaviour with refs-in-@INC even weirder. Now the rules in their totality seem to be: if the filename is searchable: try against every entry in @INC (both plain and ref) stop if we get a match or EACCES; if the filename is non-searchable: try to load it. if EACCES, stop try against every ref entry in @INC The non-searchable stop-on-EACCES behaviour isn't tested for. Does that logic make any sense to anyone? If not, should we change it? (And I'm not suggesting yet that we change it for 5.26). -- Dave's first rule of Opera: If something needs saying, say it: don't warble it.Thread Next