Reputation: 8940
I am encountering a puzzling error when creating a tuple-like struct somewhere in my Rust project.
I boiled my issue down to the following snippet:
mod parent {
pub struct X(u32);
mod child {
use crate::X;
fn f() {
let x = X(42);
}
}
}
use parent::X;
In my head, this snippet should compile just fine. X
is public, and its field is visibile within parent
, so all its children (including child::f
) should be able to access it. However, when I go and compile that snippet, I get
error[E0423]: expected function, tuple struct or tuple variant, found struct `X`
--> src/main.rs:8:21
|
8 | let x = X(42);
| ^
For more information about this error, try `rustc --explain E0423`.
error: could not compile `playground` (bin "playground" test) due to 1 previous error
Weirdly enough, the error message mentions the compiler expecting a "tuple variant", but finding X
instead. But, X
is a tuple variant!
The problem disappears when I use
super::X
instead of crate::X
.
mod parent {
pub struct X(u32);
mod child {
use super::X;
fn f() {
let x = X(42);
}
}
}
use parent::X;
This is even more puzzling to me. Why would the correctness of my snippet depend on the specific path I use to use
X
? In my mind, X
is X
, wherever I import it from.
The problem also disappears when I give X
named fields:
mod parent {
pub struct X {
x: u32,
}
mod child {
use crate::X;
fn f() {
let x = X { x: 42 };
}
}
}
use parent::X;
Note that I am using use crate::X
in this snippet, just as in the first one! Why would this error appear only with tuple-like structs? I am very confused. I am usually not one to ever doubt the correctness of the Rust compiler, but I have to admit that today my faith is being tested.
Any insight on what I might be missing?
Upvotes: 5
Views: 95
Reputation: 27322
This is the same problem as in #74139.
Imports filter away names that are private at the import point, that's a pretty fundamental rule. The
Foo
's constructor is private tomod a
, so it's filtered away.So this is not a bug, but the error should probably have a note mentioning the private constructor. Such note is emitted in some other cases but not in this one.
Only the private function X
(each tuple struct implicitly defines a constructor function in addition to the struct itself) is filtered out so using regular struct syntax does work (for both struct types):
mod parent {
pub struct X(u32);
mod child {
use crate::X;
fn f() {
let x = X{ 0: 42 };
}
}
}
use parent::X;
Upvotes: 6