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

Re-exporting items using a glob breaks if the module imports another module #4865

Closed
z0w0 opened this issue Feb 10, 2013 · 17 comments · Fixed by #27547
Closed

Re-exporting items using a glob breaks if the module imports another module #4865

z0w0 opened this issue Feb 10, 2013 · 17 comments · Fixed by #27547
Labels
A-resolve Area: Name resolution P-medium Medium priority

Comments

@z0w0
Copy link
Contributor

z0w0 commented Feb 10, 2013

priv mod say {
    pub fn hello() { io::println(~"hello"); }
}

pub mod hello {
    use say;

    pub fn hello() {
        say::hello();
    }
}

pub use hello::*; // doesn't work - `pub use hello::hello;` does

fn main() {
    hello();
}

Results in this error when compiling:

error: failed to resolve imports
a.rs:13:8: 13:17 error: unresolved import
a.rs:13 pub use hello::*; // doesn't work - `pub use hello::hello;` does
                ^~~~~~~~~
a.rs:6:5: 6:9 error: unresolved import
a.rs:6  use say;
            ^~~~

As mentioned in the code, explicitly re-exporting items works but is not a good alternative for when you have hundreds of items (including variants) in a module. Changing the say module to public doesn't fix it.

@catamorphism
Copy link
Contributor

Not critical for 0.7. Nominating for milestone 1, well-defined.

@graydon
Copy link
Contributor

graydon commented May 2, 2013

accepted for well defined - promises made by the resolve pass need to be written down

@Blei
Copy link
Contributor

Blei commented Jul 9, 2013

Still applies. Here's the updated source code:

pub use hello::*; // doesn't work - `pub use hello::hello;` does

pub mod say {
    pub fn hello() { println("hello"); }
}

pub mod hello {
    use say;

    pub fn hello() {
        say::hello();
    }
}

fn main() {
    hello();
}

The error is now:

blerg2.rs:1:8: 1:17 error: unresolved import
blerg2.rs:1 pub use hello::*; // doesn't work - `pub use hello::hello;` does
                    ^~~~~~~~~
blerg2.rs:8:8: 8:11 error: unresolved import (maybe you meant `say::*`?)
blerg2.rs:8     use say;
                    ^~~
error: aborting due to 2 previous errors

The error about say goes away when changing the glob to a single import.

@Blei
Copy link
Contributor

Blei commented Jul 9, 2013

And here's a failing cross-crate example that's very probably related, so I thought I'd add it here instead of opening a new issue.

// foo.rs
pub use foo::*;

mod foo {
    pub fn foo() { println("foo"); }
}
// bar.rs
extern mod foo;
use foo::*;

fn main() {
    foo();
}

Compilation:

% rustc --lib foo.rs
warning: missing crate link meta `name`, using `foo` as default
warning: missing crate link meta `vers`, using `0.0` as default
% rustc -L. bar.rs
error: linking with `cc` failed with code 1
note: cc arguments: -L/home/philipp/programming/rust/x86_64-unknown-linux-gnu/stage2/lib/rustc/x86_64-unknown-linux-gnu/lib -m64 -o bar bar.o -L/home/philipp/programming/rust/x86_64-unknown-linux-gnu/stage2/lib/rustc/x86_64-unknown-linux-gnu/lib -lstd-6c65cf4b443341b1-0.8-pre -L. -lfoo-15fb3a718ea23983-0.0 -lrustrt -lrt -lpthread -L. -lrt -ldl -lm -lmorestack -lrustrt -Wl,-rpath,$ORIGIN/../../programming/rust/x86_64-unknown-linux-gnu/stage2/lib/rustc/x86_64-unknown-linux-gnu/lib -Wl,-rpath,$ORIGIN/. -Wl,-rpath,/home/philipp/programming/rust/x86_64-unknown-linux-gnu/stage2/lib/rustc/x86_64-unknown-linux-gnu/lib -Wl,-rpath,/home/philipp/tmp/6477/. -Wl,-rpath,/usr/local/lib/rustc/x86_64-unknown-linux-gnu/lib
note: bar.o: In function `main::_c6c3cd618d2fde1::_0$x2e0':
bar.rc:(.text+0x2c): undefined reference to `foo::foo::_15bec6257b8bff78::_0$x2e0'
collect2: Fehler: ld gab 1 als Ende-Status zurück

error: aborting due to previous error

@thestinger
Copy link
Contributor

This is still an issue.

@alexcrichton
Copy link
Member

@Blei, your second test case (which fails with a linker error), I believe was fixed by #9791.

Otherwise I believe that this is another facet of glob imports having circular references causing problems. The imports at the top level of the crate cannot be considered resolved until the glob is resolved, but the glob cannot get resolved until mod hello is resolved. Now this method can't quite get resolved because use say looks up imports in the global module, which is still waiting on being resolved, hence the circular dependency.

This is one of the reasons why globs are currently behind a feature flag. Their behavior is subtle and unexpected in certain ways, along with them not always having the best error messages.

Regardless, leaving open for now as it still reproduces.

@pcwalton
Copy link
Contributor

Globs are feature gated. Nominating to remove from backcompat-lang.

@pnkfelix
Copy link
Member

revised Priority to P-low

@emberian
Copy link
Member

Another example (stripped down) from gl-rs:

#![crate_type = "lib"]

#![feature(globs)]

extern crate libc;

use std::mem;

use self::types::*;

pub mod types {
    use libc;
}

mod storage {
    use libc;
}

mod failing {
    use libc;
    use super::types::*;
}

emberian added a commit to brendanzab/gl-rs that referenced this issue Jul 31, 2014
Shuffles around how exactly libc is used to work around a nasty bug in glob
imports. Unfortunately now requires users of the syntax extension to have an
`extern crate libc`.
@steveklabnik
Copy link
Member

Triage: globs are un-feature gated, but this issue still persists.

@steveklabnik
Copy link
Member

Re-nominating because of that

@pnkfelix
Copy link
Member

polish issue, 1.0 P-high. (Note that we believe this and other glob bugs we know of are "only" rejecting valid programs, and thus the associated bug can be fixed backwards compatibly.)

If someone knows of a case where an invalid program is accepted due to glob bugs, that would be much more severe.

@pnkfelix pnkfelix added this to the 1.0 milestone Feb 12, 2015
@pnkfelix pnkfelix added P-medium Medium priority and removed P-low Low priority I-nominated labels Feb 12, 2015
@pnkfelix
Copy link
Member

pnkfelix commented Apr 2, 2015

P-high 1.1

@kali
Copy link
Contributor

kali commented May 3, 2015

I reached this point while reducing an issue, I think it is the same problem, and the testcase is somewhat simpler.

pub mod a {
  use b::*;
}

pub mod b {
  use a::*;
}

use a::*;

fn main() {
}

@gbersac
Copy link

gbersac commented May 3, 2015

Still apply. Spend two days getting mad because of this bug. Note that there is no need for the modules to reference each others directly :

pub mod a {
    use b::fn_b;
    use c::*;

    pub fn fn_a(){
    }
}

pub mod b {
    use a::fn_a;
    use c::*;

    pub fn fn_b(){
    }
}

pub mod c{
    pub fn fn_c(){
    }
}

use a::fn_a;
use b::fn_b;

fn main() {
}

Here the star imports (mod::*) are not the modules themself, but another module, the module c.

@pnkfelix
Copy link
Member

@gbersac 's test case seems especially frustrating; as he noted, the reported error is for imports that are not glob imports, and yet for some reason the presence of the unrelated glob imports is causing the resolution of the circular non-glob imports to fail.

@brson
Copy link
Contributor

brson commented Jun 12, 2015

The final case here is solved by #26242

elinorbgr added a commit to elinorbgr/rust that referenced this issue Aug 5, 2015
When resolving 'use' statements, only consider pub imports of the
target module as blocking.

Closes rust-lang#4865
bors added a commit that referenced this issue Aug 10, 2015
As noted in my previous PR #27439 , the import resolution algorithm has two cases where it bails out:

- The algorithm will delay an import if the module containing the target of the import still has unresolved glob imports
- The algorithm will delay a glob import of the target module still has unresolved imports

This PR alters the behaviour to only bail out when the above described unresolved imports are `pub`, as non-pub imports don't affect the result anyway.

It is still possible to fail the algorithm with examples like
```rust
pub mod a {
    pub use b::*;
}

pub mod b {
    pub use a::*;
}
```
but such configurations cannot be resolved in any meaningful way, as these are cyclic imports.

Closes #4865
calebcartwright pushed a commit to calebcartwright/rust that referenced this issue Jul 26, 2021
On stable, running with `--help|-h` shows information about `file-lines`
which is a nightly-only option. This commit removes all mention of
`file-lines` from the help message on stable.

There is room for improvement here; perhaps a new struct called, e.g.,
`StableOptions` could be added to complement the existing
`GetOptsOptions` struct. `StableOptions` could have a field for each
field in `GetOptsOptions`, with each field's value being a `bool` that
specifies whether or not the option exists on stable. Or is this adding
too much complexity?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-resolve Area: Name resolution P-medium Medium priority
Projects
None yet
Development

Successfully merging a pull request may close this issue.