-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Compiler crashed with cannot create local mono-item #50865
Comments
BTW, by replacing pub fn run(config: Arc<Config>) -> impl Future<Item = (), Error = io::Error> + Send with pub fn run(config: Arc<Config>) -> Box<Future<Item = (), Error = io::Error> + Send> in |
I see this too in a separate (not open source) codebase. My stack is slightly different: Log hidden by @eddyb (click to expand)
The relevant diff in my code is - -> Box<Future<Item = Option<SysrootEntry>, Error = Never> + Send> {
+ -> impl Future<Item = Option<SysrootEntry>, Error = Never> + Send { Version:
Happens on 1.26.0 stable too (which is where I first noticed it). |
Also met this error. My simplified example: // lib.rs
pub trait Baz{}
pub struct Bar;
impl Baz for Bar{}
pub fn bar<P: Baz>( // Error won't happen if "bar" is not generic
_baz: P,
) {
let draw_data: Vec<u32> = iterate().collect();
}
fn iterate() -> impl Iterator<Item=u32> { // Error won't happen if "iterate" hasn't impl Trait
std::iter::once(0).map(foo)
}
fn foo(input: u32) -> u32 { // Error won't happen if "foo" isn't used in "iterate"
input
} //main.rs
extern crate lib;
fn main() {
lib::bar(lib::Bar); // Error won't happen if bar is called from same crate
} |
In qthree's example, if you make foo public the error doesn't happen. I've looked at the code for rustc_mir::monomorphize::collector::should_monomorphize_locally, and it's checking if the code it needs is something that it should link to, or if it should find it in the mir. In this case it's decided it should find it in the Mir, but it blows up when it doesn't. If you remove the check, then you'll get past compilation but it will fail with a link error to lib::foo. I don't know the compiler internals well, but my gut feeling is that this is a bug somewhere else than where it's actually detected. It seems things are missing from the Mir when using impl Trait. I'd also like to add that this bug has come up a lot for me, basically any time you want to write a library of moderate complexity using futures-await, and then you try to use that library in a program, you will hit this bug. Now at least we know that you can work around it by making everything it blows up on public. Not a great long term solution obviously ... |
Confirmed with cargo --version 1.28.0-nightly (e2348c2db 2018-06-07) and rustc --version 1.28.0-nightly (01cc982 2018-06-24). It happened in a lib+main project. I tried to reproduce it in a single main.rs file, but the same code (impl Trait stuff) compiles fine there on the same tool chain. I can pass the project archive if someone is interested. After rustup update, still the case with rustc 1.28.0-nightly (e3bf634 2018-06-28) running on x86_64-unknown-linux-gnu As I said, it compiles fine in a single main.rs file. As soon as I moved the functions into a lib, it came back. This may be significant. Curious: only one fn Log hidden by @eddyb (click to expand)
|
Nominating for priority assignment. |
Thanks for the bug reports everyone! |
I found the cause for the symptom, although not the root cause yet. The def collector (during compilation of the lib) doesn't realize it doesn't need to export the I have a feeling this is due to the reachability analysis operating on the HIR, while the collector is operating on the MIR and we end up with some incompatibility from that. |
And I found the root cause: zst constants of fn type do not get their functions collected. |
I was about to respond with the details of my error. I'm glad you found out the issue so quick! Thanks @oli-obk ! |
PR incoming shortly ;) |
This is the same old reachability bug, right? I think I asked @petrochenkov and/or @cramertj to look at it but I'm not sure it ever got fixed. I guess people are noticing it now because of the stabilization. |
Minimal repro: // lib.rs
pub fn bar<P>( // Error won't happen if "bar" is not generic
_baz: P,
) {
hide_foo()();
}
fn hide_foo() -> impl Fn() { // Error won't happen if "iterate" hasn't impl Trait or has generics
foo
}
fn foo() { // Error won't happen if "foo" isn't used in "iterate" or has generics
} // main
// aux-build:impl_trait_bug.rs
extern crate impl_trait_bug;
fn main() {
impl_trait_bug::bar(()); // Error won't happen if bar is called from same crate
} |
There is a reachability special-case which allows private impls to work: rust/src/librustc/middle/reachable.rs Lines 336 to 339 in a96c88e
However, this does not apply to functions that may be called statically but not obviously so. EDIT: it seems that the privacy's @petrochenkov Should we merge reachability and |
@Bert-Proesmans , try make the fn's public. That should work around it. |
@jocutajar Thanks for the explicit answer. My issue is similar but not related to functions (all relevant functions were already public). I had to make fields on the offending structure public instead. |
triage: P-high |
visited for triage, leaving assigned to @oli-obk for now. |
@eddyb Got bored and tried something like your proposed solution: merging the output of reachability into the privacy checking query seems to have no effect on the bug here, as in the minimum test case specified above tcx.reachable_set(...) finds no new reachable items. This does turn up many more technically reachable items in libcore and other libraries (which in turn need to be hidden again from lints, stability and so on). Something could maybe turn up if we try to calculate the reachable set while the EmbargoVisitor does its work; I'll keep looking into this. If you have any further ideas then they'd be appreciated. |
visiting for triage. Taking off @oli-obk assignment as they will be very busy with non-Rust stuff very soon. |
@eddyb @petrochenkov would one of you be the right person to try to take on the work here? |
visiting for triage. @oli-obk points out that this is an Putting on "Rust 2018 RC" milestone. |
@nikomatsakis asked me about this issue on internals, copy-pasting the answer here:
|
Visiting for compiler team meeting. @eddyb or @petrochenkov — if either of you have time to pick this off, would be good. (Or to leave some detailed instructions.) Otherwise, we should try to find someone. |
Increasingly, I'm becoming convinced that the problem isn't in privacy or reachability. Using this "fixed" lib.rs: // lib.rs
pub fn bar<P>( // Error won't happen if "bar" is not generic
_baz: P,
) {
hide_foo()();
}
fn hide_foo() -> fn() -> () {
foo
}
fn foo() { // Error won't happen if "foo" isn't used in "iterate" or has generics
} This compiles as expected. We end up getting identical results from both reachabililty and privacy for the inner crate between this and the
where:
A quick test shows the same behaviour for a This suggests that |
Dug into this a little more. It seems this arises from the MIR generation step: using generics, Either we can explicitly mark all items who do not already have an assigned level as having a new privacy level like @petrochenkov suggested (probably visible to only EDIT: fixed truncated comment. This is specifically observed from the pattern/context of lookups made via |
@FelixMcFelix Not sure what you mean about MIR - your comment appears cut off, too. |
@eddyb Using one of the impl Trait examples based on Iterators and comparing it against the equivalent for generics, the main difference seems to be where impl Trait:
Generics:
Not sure if this 100% explains why I think the error stems from here, I'm available on discord if need be (FelixMcFelix#2443). |
…ochenkov Fix rust-lang#50865: ICE on impl-trait returning functions reaching private items Adds a test case as suggested in rust-lang#50865, and implements @petrochenkov's suggestion. Fixes rust-lang#50865. Impl-trait-returning functions are marked under a new (low) access level, which they propagate rather than `AccessLevels::Reachable`. `AccessLevels::is_reachable` returns false for such items (leaving stability analysis unaffected), these items may still be visible to the lints phase however.
Rollup of 16 pull requests Successful merges: - #53311 (Window Mutex: Document that we properly initialize the SRWLock) - #53503 (Discourage overuse of mem::forget) - #53545 (Fix #50865: ICE on impl-trait returning functions reaching private items) - #53559 (add macro check for lint) - #53562 (Lament the invincibility of the Turbofish) - #53563 (use String::new() instead of String::from(""), "".to_string(), "".to_owned() or "".into()) - #53592 (docs: minor stylistic changes to str/string docs) - #53594 (Update RELEASES.md to include clippy-preview) - #53600 (Fix a grammatical mistake in "expected generic arguments" errors) - #53614 (update nomicon and book) - #53617 (tidy: Stop requiring a license header) - #53618 (Add missing fmt examples) - #53636 (Prefer `.nth(n)` over `.skip(n).next()`.) - #53644 (Use SmallVec for SmallCStr) - #53664 (Remove unnecessary closure in rustc_mir/build/mod.rs) - #53666 (Added rustc_codegen_llvm to compiler documentation.)
This fix is available in 1.30.0-nightly |
I also have a similar looking ICE dating back quite a while ago: #51388 and still fails in 1.30. |
Relevant logs:
Log hidden by @eddyb (click to expand)
Reproduce steps:
master
branch of https://github.com/shadowsocks/shadowsocks-rustcargo build
Meta
Backtrace
And I think it also happens in stable rustc 1.26.0.
The text was updated successfully, but these errors were encountered: