From: Harishankar <[email protected]>

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 Rust-GCC/gccrs#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.
        * rust/compile/compile.exp:Ignore issue_4402_foo.rs

Signed-off-by: Harishankar <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/dc07f2a2bb4e8aae8c5148515f922de8a7ca12e2

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4406

 gcc/rust/ast/rust-ast.cc                     | 28 +++++++++++++++++++-
 gcc/testsuite/rust/compile/compile.exp       | 17 ++++++++++--
 gcc/testsuite/rust/compile/issue-4402.rs     |  9 +++++++
 gcc/testsuite/rust/compile/issue_4402_foo.rs |  1 +
 4 files changed, 52 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-4402.rs
 create mode 100644 gcc/testsuite/rust/compile/issue_4402_foo.rs

diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 37c384949..9813e7795 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -3418,9 +3418,13 @@ Module::process_file_path ()
   auto path_string = filename_from_path_attribute (get_outer_attrs ());
 
   std::string including_subdir;
+  bool subdir_was_added = false;
   if (path_string.empty () && module_scope.empty ()
       && get_file_subdir (including_fname, including_subdir))
-    current_directory_name += including_subdir + file_separator;
+    {
+      current_directory_name += including_subdir + file_separator;
+      subdir_was_added = true;
+    }
 
   // Handle inline module declarations adding path components.
   for (auto const &name : module_scope)
@@ -3449,6 +3453,28 @@ Module::process_file_path ()
                             + file_separator + expected_dir_path;
   bool dir_mod_found = file_exists (dir_mod_path);
 
+  if (!file_mod_found && !dir_mod_found && subdir_was_added)
+    {
+      size_t suffix_len
+       = including_subdir.length () + std::string (file_separator).length ();
+      std::string fallback_dir
+       = current_directory_name.substr (0, current_directory_name.length ()
+                                             - suffix_len);
+      std::string fallback_file = fallback_dir + expected_file_path;
+      std::string fallback_dir_mod = fallback_dir + module_name.as_string ()
+                                    + file_separator + expected_dir_path;
+      if (file_exists (fallback_file))
+       {
+         file_mod_found = true;
+         file_mod_path = fallback_file;
+       }
+      else if (file_exists (fallback_dir_mod))
+       {
+         dir_mod_found = true;
+         dir_mod_path = fallback_dir_mod;
+       }
+    }
+
   bool multiple_candidates_found = file_mod_found && dir_mod_found;
   bool no_candidates_found = !file_mod_found && !dir_mod_found;
 
diff --git a/gcc/testsuite/rust/compile/compile.exp 
b/gcc/testsuite/rust/compile/compile.exp
index 2c3be80b0..41941316d 100644
--- a/gcc/testsuite/rust/compile/compile.exp
+++ b/gcc/testsuite/rust/compile/compile.exp
@@ -28,8 +28,21 @@ dg-init
 set saved-dg-do-what-default ${dg-do-what-default}
 
 set dg-do-what-default "compile"
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.rs]] "" ""
+
+set tests [lsort [glob -nocomplain $srcdir/$subdir/*.rs]]
+set ignore_list [list "issue_4402_foo.rs"]
+
+set tests_to_run [list]
+foreach t $tests {
+    set filename [file tail $t]
+    if {[lsearch -exact $ignore_list $filename] == -1} {
+        lappend tests_to_run $t
+    }
+}
+
+dg-runtest $tests_to_run "" ""
+
 set dg-do-what-default ${saved-dg-do-what-default}
 
 # All done.
-dg-finish
+dg-finish
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/issue-4402.rs 
b/gcc/testsuite/rust/compile/issue-4402.rs
new file mode 100644
index 000000000..0434e12bf
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-4402.rs
@@ -0,0 +1,9 @@
+#![feature(no_core)]
+#![no_core]
+use issue_4402_foo::Bar;
+pub mod issue_4402_foo;
+
+fn main() {
+    // use '_a' to silence the unused variable warning
+    let _a = Bar;
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/issue_4402_foo.rs 
b/gcc/testsuite/rust/compile/issue_4402_foo.rs
new file mode 100644
index 000000000..96266300d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue_4402_foo.rs
@@ -0,0 +1 @@
+pub struct Bar;
\ No newline at end of file

base-commit: b98bdc90724f24e7458b7209499c5a7261afe258
-- 
2.52.0

Reply via email to