Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent submodule search starting point when the parent module is added by path attribute #10588

Closed
watson-github opened this issue Apr 21, 2022 · 1 comment
Labels
C-bug Category: bug

Comments

@watson-github
Copy link

Problem

I create two projects, cargo new module_test1 and cargo new module_test2. And then I add some files into the source directory.Finally, the source directory structure are as follows.

module_test1/src/
├── city_a/
│   ├── college/
│   ├── college.rs
│   └── mod.rs
├── city_b/
│   └── mod.rs
└── main.rs
module_test2/src/
├── city_a
│   ├── college
│   │   └── mod.rs
│   └── mod.rs
├── city_b
│   └── mod.rs
└── main.rs

The difference between the two directories are

$diff -r module_test1/src/ module_test2/src/
Only in module_test2/src/city_a/college: mod.rs
Only in module_test1/src/city_a: college.rs
diff -r module_test1/src/city_b/mod.rs module_test2/src/city_b/mod.rs
1c1
< #[path="../city_a/college.rs"]
---
> #[path="../city_a/college/mod.rs"]

When I build module_test1, I get these error messages:

Compiling module_test1 v0.1.0 (/home/pear/rust_programming_language/projects/module_test1)
error[E0583]: file not found for module `math`
--> src/city_a/college.rs:1:1
 |
1 | mod math;
 | ^^^^^^^^^
 |
 = help: to create the module `math`, create file "src/city_a/college/math.rs" or "src/city_a/college/math/mod.rs"

error[E0583]: file not found for module `math`
--> src/city_b/../city_a/college.rs:1:1
 |
1 | mod math;
 | ^^^^^^^^^
 |
 = help: to create the module `math`, create file "src/city_b/../city_a/math.rs" or "src/city_b/../city_a/math/mod.rs"

For more information about this error, try `rustc --explain E0583`.
error: could not compile `module_test1` due to 2 previous errors

While I build module_test2, I get these error messages:

Compiling module_test2 v0.1.0 (/home/pear/rust_programming_language/projects/module_test2)
error[E0583]: file not found for module `math`
 --> src/city_a/college/mod.rs:1:1
  |
1 | mod math;
  | ^^^^^^^^^
  |
  = help: to create the module `math`, create file "src/city_a/college/math.rs" or "src/city_a/college/math/mod.rs"

error[E0583]: file not found for module `math`
 --> src/city_b/../city_a/college/mod.rs:1:1
  |
1 | mod math;
  | ^^^^^^^^^
  |
  = help: to create the module `math`, create file "src/city_b/../city_a/college/math.rs" or "src/city_b/../city_a/college/math/mod.rs"

For more information about this error, try `rustc --explain E0583`.
error: could not compile `module_test2` due to 2 previous errors

For module_test2, the error message is reasonable. Only one file needs to be created to eliminate the errors.
However, for module_test1, two files are needed to eliminate the errors. If I add these two files, the module college will have two submodules named math under the same level. And the two submodules may have different implementation.
These two submodules are in different module path. One is crate::city_a::college::math. And the other is crate::city_b::college::math. It is still confusing because the parent module is actually same.

I expect that the error message of module_test1 is same as module_test2. Only one file is needed for the submodule.

Steps

  1. Create two projets with command cargo new module_test1 and cargo new module_test2.
  2. Make sub-folders in the source folder src/ in both projects with command mkdir -p city_a/college and mkdir -p city_b.
  3. Create mod.rs in src/city_a/ and src/city_a/ in both projects with command touch city_a/mod.rs city_b/mod.rs.
  4. Create college.rs in src/city_a for project module_test1 with command touch city_a/college.rs.
  5. Create mod.rs in src/city_a/college/ for project module_test2 with command touch city_a/college/mod.rs.
  6. Add two lines in main.rs for both projects:
mod city_a; 
mod city_b;
  1. Add one line in city_a/mod.rs for both projects:
    mod college;
  2. Add two lines in city_b/mod.rs for module_test1:
#[path="../city_a/college.rs"]
mod college;
  1. Add two lines in city_b/mod.rs for module_test2:
#[path="../city_a/college/mod.rs"]
mod college;
  1. Add one line in city_a/college.rs for module_test1 and city_a/college/mod.rs for module_test2:
    mod math;
  2. Build the two projects.

Possible Solution(s)

No response

Notes

I guess the reason behind this phenomenon is that college.rs in module_test1 is considered as non-mod-rs module. There is such description in The Rust Reference book.
"For path attributes inside inline module blocks, the relative location of the file path depends on the kind of source file the path attribute is located in. "mod-rs" source files are root modules (such as lib.rs or main.rs) and modules with files named mod.rs. "non-mod-rs" source files are all other module files. Paths for path attributes inside inline module blocks in a mod-rs file are relative to the directory of the mod-rs file including the inline module components as directories. For non-mod-rs files, it is the same except the path starts with a directory with the name of the non-mod-rs module."
The use case is not exactly path attribute inside inline module. Maybe the implementation is similar.

I also notice another thing. Another possible solution for module_test1 is to add inline module math into the module college. That is to say, change the content of city_a/college.rs in module_test1 from mod math; to mod math{}. Both error messages will disappear.

Version

$ cargo version --verbose
cargo 1.60.0 (d1fd9fe 2022-03-01)
release: 1.60.0
commit-hash: d1fd9fe2c40a1a56af9132b5c92ab963ac7ae422
commit-date: 2022-03-01
host: x86_64-unknown-linux-gnu
libgit2: 1.3.0 (sys:0.13.23 vendored)
libcurl: 7.80.0-DEV (sys:0.4.51+curl-7.80.0 vendored ssl:OpenSSL/1.1.1m)
os: Ubuntu 20.04 (focal) [64-bit]
@watson-github watson-github added the C-bug Category: bug label Apr 21, 2022
@ehuss
Copy link
Contributor

ehuss commented Apr 21, 2022

Thanks for putting together the reproduction. This is just how module resolution works once loaded from a #[path] attribute. The subsequent modules will be relative to the file in the #[path] attribute. The exact rules aren't currently documented (see rust-lang/reference#573).

I don't entirely see why you would be creating duplicate modules this way. I'm not sure if you are doing that just for illustrative purposes. Usually a module should only be defined once (with mod). I would also suggest avoiding #[path] attributes altogether if possible.

There was a proposal to change this behavior (rust-lang/lang-team#89) but it was rejected.

Closing as this isn't a cargo issue, and changing its behavior has been rejected on the lang-side.

@ehuss ehuss closed this as completed Apr 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bug
Projects
None yet
Development

No branches or pull requests

2 participants