Skip to content

Commit 725536d

Browse files
committed
ast: Fix module path resolution for sibling modules in root
Currently, the compiler fails to resolve module paths when a file in the root directory (e.g. 'bar.rs') attempts to load a sibling module (e.g. 'foo.rs') if a 'bar/' directory does not exist. The compiler incorrectly assumes that if 'bar.rs' is not 'mod.rs', it must look exclusively in a subdirectory. This patch adds a fallback mechanism in 'Module::process_file_path'. If the subdirectory search fails, it strips the implicit subdirectory and attempts to resolve the module in the parent directory, consistent with Rust 2018 path rules. Fixes #4402 gcc/rust/ChangeLog: * ast/rust-ast.cc (Module::process_file_path): Add fallback search for sibling modules when subdirectory search fails. gcc/testsuite/ChangeLog: * rust/compile/issue-4402.rs: New test. * rust/compile/issue_4402_foo.rs: New test. Signed-off-by: Harishankar <[email protected]>
1 parent b940d2c commit 725536d

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

gcc/rust/ast/rust-ast.cc

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3410,9 +3410,13 @@ Module::process_file_path ()
34103410
auto path_string = filename_from_path_attribute (get_outer_attrs ());
34113411

34123412
std::string including_subdir;
3413+
bool subdir_was_added = false;
34133414
if (path_string.empty () && module_scope.empty ()
34143415
&& get_file_subdir (including_fname, including_subdir))
3415-
current_directory_name += including_subdir + file_separator;
3416+
{
3417+
current_directory_name += including_subdir + file_separator;
3418+
subdir_was_added = true;
3419+
}
34163420

34173421
// Handle inline module declarations adding path components.
34183422
for (auto const &name : module_scope)
@@ -3441,6 +3445,28 @@ Module::process_file_path ()
34413445
+ file_separator + expected_dir_path;
34423446
bool dir_mod_found = file_exists (dir_mod_path);
34433447

3448+
if (!file_mod_found && !dir_mod_found && subdir_was_added)
3449+
{
3450+
size_t suffix_len
3451+
= including_subdir.length () + std::string (file_separator).length ();
3452+
std::string fallback_dir
3453+
= current_directory_name.substr (0, current_directory_name.length ()
3454+
- suffix_len);
3455+
std::string fallback_file = fallback_dir + expected_file_path;
3456+
std::string fallback_dir_mod = fallback_dir + module_name.as_string ()
3457+
+ file_separator + expected_dir_path;
3458+
if (file_exists (fallback_file))
3459+
{
3460+
file_mod_found = true;
3461+
file_mod_path = fallback_file;
3462+
}
3463+
else if (file_exists (fallback_dir_mod))
3464+
{
3465+
dir_mod_found = true;
3466+
dir_mod_path = fallback_dir_mod;
3467+
}
3468+
}
3469+
34443470
bool multiple_candidates_found = file_mod_found && dir_mod_found;
34453471
bool no_candidates_found = !file_mod_found && !dir_mod_found;
34463472

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
use issue_4402_foo::Bar;
2+
pub mod issue_4402_foo;
3+
4+
fn main() {
5+
// use '_a' to silence the unused variable warning
6+
let _a = Bar;
7+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub struct Bar;

0 commit comments

Comments
 (0)