Skip to content

use core::prelude::* conflicts with use collections::slice::SliceExt #20513

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

Closed
SimonSapin opened this issue Jan 4, 2015 · 10 comments
Closed

Comments

@SimonSapin
Copy link
Contributor

In Nightly c894171 2015-01-02, it is apparently not possible to use methods from collections::slice::SliceExt such as to_vec in a scope where use core::prelude::*; (very useful in #![no_std] crates) is also used.

Imports can not shadow each other, a name conflict is fatal:

#![no_std]
#![feature(globs)]

extern crate core;
extern crate collections;

use core::prelude::*;
use collections::slice::SliceExt;

fn foo() {
    ['a', 'b'].slice_to(1).to_vec()
}
a.rs:8:5: 8:33 error: a type named `SliceExt` has already been imported in this module
a.rs:8 use collections::slice::SliceExt;
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error

Renaming the trait at import doesn’t help, core methods are now duplicated in the scope:

#![no_std]
#![feature(globs)]

extern crate core;
extern crate collections;

use core::prelude::*;
use collections::slice::SliceExt as CollectionsSliceExt;

fn foo() {
    ['a', 'b'].slice_to(1).to_vec()
}
a.rs:11:16: 11:27 error: multiple applicable methods in scope [E0034]
a.rs:11     ['a', 'b'].slice_to(1).to_vec()
                       ^~~~~~~~~~~
a.rs:11:16: 11:27 note: candidate #1 is defined in an impl of the trait `core::slice::SliceExt` for the type `[_]`
a.rs:11     ['a', 'b'].slice_to(1).to_vec()
                       ^~~~~~~~~~~
a.rs:11:16: 11:27 note: candidate #2 is defined in an impl of the trait `collections::slice::SliceExt` for the type `[_]`
a.rs:11     ['a', 'b'].slice_to(1).to_vec()
                       ^~~~~~~~~~~
error: aborting due to previous error

As a work around when upgrading rust-wtf8, I moved use collections::slice::SliceExt; into the block that uses to_vec but does not use other slice methods.

@nrc
Copy link
Member

nrc commented Jan 4, 2015

This is a feature not a bug, the work around is to only import the items you need from the prelude, rather than using a glob import. This is kind of a pain at the moment and I'm working on a tool to help with it (but 1.0 things prevent that moving very fast right now).

Closing for now, if you have ideas for how to resolve this (without allowing any import shadowing) or I have misunderstood, feel free to reopen.

@nrc nrc closed this as completed Jan 4, 2015
@SimonSapin
Copy link
Contributor Author

This is a feature not a bug, the work around is to only import the items you need from the prelude, rather than using a glob import.

So you’re saying core::prelude is basically useless? That’s unfortunate.

I don’t really have a better suggestion. I’m just saying that using no_std seems more painful than it used to be a hoping there is another way.

@nrc
Copy link
Member

nrc commented Jan 4, 2015

I'm saying core::prelude::* is useless, and only if you want to also import items with the same name as something in the core prelude. The solution is to use core::prelude::{Option, None, Some, ...} and list all the items you do want, which is, admittedly, painful.

To clarify what is going on here, there is already a SliceExt in core::prelude, but it is different to the one in collections::slice, and you want the latter? Perhaps we should not have two SliceExt traits. Or perhaps the core one should not be in the prelude, if it is common to also want to use the collections one.

@SimonSapin
Copy link
Contributor Author

The problem is not the names (which an be changed locally with use foo as bar;), it’s the fact that collections::slice::SliceExt contains both new methods not defined elsewhere (like as_vec) and the methods from core::slice::SliceExt. So when both are in scope (regardless of their local name), we get "multiple applicable methods in scope" errors.

One solution is to only have collections::slice::SliceExt in scope. Since it "re-exports" (kind of) all the core methods, you don’t need the other one. But core::slice::SliceExt is part of core::prelude::*, and that’s what makes core::prelude::* useless, while it was fine until recently. It’s unfortunate.

Is having a single SliceExt trait in std::prelude::v1 is worth making core::prelude::* useless?

To take a step back, I was using #![no_std] because it wasn’t hard and seemed to make the library more useful (usable in more contexts), but now that the runtime was removed maybe it doesn’t matter?

@nrc
Copy link
Member

nrc commented Jan 4, 2015

Worth looking at this RFC issue for the import side: rust-lang/rfcs#553

cc @aturon about the mess with having two overlapping SliceExt traits.

That all sounds worse than I thought. Perhaps it is worth taking SliceExt out of core::Prelude?

@SimonSapin
Copy link
Contributor Author

cc @aturon about the mess with having two overlapping SliceExt traits.

Yes, overlapping traits is the core of the specific issue I encountered here.

Perhaps it is worth taking SliceExt out of core::Prelude?

I don’t know, aside from the overlap with its libcollections friend, SliceExt really belongs in core::prelude.

@aturon
Copy link
Member

aturon commented Jan 4, 2015

So the intent with SliceExt in libcollections was to provide a "facade trait" so that users of std would not need to know anything about how the pieces are broken up in the implementation.

I think a way forward would be to have libcollections provide only the delta, and then have std itself define the facade trait. That way if you're in no_std land you can freely use the crates below std, and otherwise you still see a nice one-trait API.

@alexcrichton thoughts?

@SimonSapin
Copy link
Contributor Author

If a linear hierarchy like libcore ⊂ libcollections ⊂ libstd makes sense, libcollections could also provides its own prelude that could be used instead of core::prelude.

@SimonSapin
Copy link
Contributor Author

(I’m also pondering whether I should bother with no_std: #20537)

@aturon
Copy link
Member

aturon commented Jan 4, 2015

@SimonSapin

If a linear hierarchy like libcore ⊂ libcollections ⊂ libstd makes sense, libcollections could also provides its own prelude that could be used instead of core::prelude.

Very good point! That solution would likely have side benefits for convenient no_std usage. Basically you'd get biggest fraction of std::prelude that's available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants