Hello all, I've run into a behavior with autoload and $LOAD_PATH that is inconsistent across Ruby versions and implementations, and would like clarification on what the correct behavior should be. Consider the two source files below: (root)/foo.rb ------------- $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)) + '/./foo') module Foo autoload :Bar, 'bar' end Foo::Bar (root)/foo/bar.rb ----------------- module Foo; class Bar; end; end An executable, expanded version of this example, along with some annotations, is available at https://github.com/yipdw/autoload-testcase. The above code will unshift a path resembling /a/./foo into $LOAD_PATH. This path is absolute -- it addresses an unambiguous location in the filesystem -- but it is not expanded. This example is a bit silly, but this can happen in less contrived situations, such as loading libraries using File.join(File.dirname(__FILE__), '../a/b') . (I know that File.join(File.dirname(__FILE__), ...) has issues, but that doesn't mean it's illegal Ruby code.) Here are run results for the autoload-testcase example under a variety of Ruby implementations and versions[*]: | Implementation | Result | +--------------------------------------+-------------------+ | Ruby 1.8.7-p330 | resolves Foo::Bar | | Ruby 1.9.2-p0 | raises NameError | | Ruby 1.9.2-p136 | raises NameError | | Rubinius 1.2.0 | resolves Foo::Bar | | JRuby 1.5.6, 1.8 compatibility mode | resolves Foo::Bar | | JRuby 1.5.6, 1.9 compatibility mode | resolves Foo::Bar | A run log is available in the autoload-testcase repository. So I guess my question can be stated as: does it make sense to permit absolute paths having . and .. in $LOAD_PATH? $LOAD_PATH can already contain relative paths; additionally, . and .. are properly expanded for relative paths. Furthermore, most shells will expand . and .. in absolute paths. Therefore, I think the answer is "yes", but I would like input on this, especially as I haven't seen this issue raised anywhere else. (If it has been raised before, please let me know that, too.) Thanks, - David --- [*] The exceptions thrown by Ruby 1.9.2-p0 and 1.9.2-p136 appear to be triggered in part by the algorithm of rb_get_expanded_load_path(void). In r30603 (latest revision as of this writing) the following is present in rb_get_expanded_load_path at load.c:51-66: for (i = 0; i < RARRAY_LEN(load_path); ++i) { VALUE str = rb_check_string_type(RARRAY_PTR(load_path)[i]); if (NIL_P(str) || !rb_is_absolute_path(RSTRING_PTR(str))) goto relative_path_found; } return load_path; relative_path_found: ary = rb_ary_new2(RARRAY_LEN(load_path)); for (i = 0; i < RARRAY_LEN(load_path); ++i) { VALUE path = rb_file_expand_path(RARRAY_PTR(load_path)[i], Qnil); rb_str_freeze(path); rb_ary_push(ary, path); } rb_obj_freeze(ary); return ary; On non-DOSISH systems, rb_is_absolute_path expands to int rb_is_absolute_path(const char *path) { if (path[0] == '/') return 1; return 0; } Therefore, if there are no paths present in $LOAD_PATH for which rb_is_absolute_path returns false, paths such as /a/./b will not be expanded to /a/b by rb_get_expanded_load_path. I haven't yet studied the code long enough to precisely figure out how that behavior interacts with the autoload mechanism and produces the name resolution failure, but it does seem to play a major role.