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

RFC: impl-only glob imports #2782

Open
wants to merge 4 commits into
base: master
from

Conversation

@jplatte
Copy link

jplatte commented Oct 12, 2019

Rendered

Currently, one can import everything from a module with use module::*, and one can import all implementations of a trait (thus bringing its methods into scope) with use Trait as _. However, bringing all implementations of traits in a given module into scope is not currently possible. This RFC aims to change that, enabling the syntax use module::trait * as _ to import all implementations of all traits exported from module.

@Centril

This comment has been minimized.

Copy link
Member

Centril commented Oct 12, 2019

@matthieu-m

This comment has been minimized.

Copy link

matthieu-m commented Oct 12, 2019

I'm worried about the use of black-listing:

  • It's convoluted: import everything except those items that need be named, leaving only traits' associated items. It takes some time to wrap your head around the concept.
  • Black-listing seems brittle, evolution-wise. What happens if another kind of items is added with a similar import mechanism as traits? Should they automatically be included as well? Or not? Neither seem satisfying.

I would prefer a white-list approach, instead. Something like use module::*trait* as _ which clearly states that you are importing all traits, and then discarding the items themselves.

As a bonus, I could see myself using use module::*enum|struct* or similar.

@jplatte

This comment has been minimized.

Copy link
Author

jplatte commented Oct 12, 2019

It's convoluted

I agree, that's what I alluded to in the drawbacks section.

What happens if another kind of items is added with a similar import mechanism as traits?

I thought about this when writing the RFC, but considered it unrealistic enough to ignore it. Are you aware of any (pre-)RFCs / proposed changes to the language that would fall into this category?

Something like use module::*trait* as _

This would be a larger change syntax-wise, but seems reasonable. For familiarity reasons, I feel use module::trait * as _ makes more sense though. I'll add that to the alternatives section.

As a bonus, I could see myself using use module::*enum|struct* or similar.

Do you have a (semi-)concrete example of where that would be useful?

@mathstuf

This comment has been minimized.

Copy link

mathstuf commented Oct 12, 2019

use module::*macro* might be one. I don't know if derive (proc?) macros should also be a separate item or not.

@jplatte

This comment has been minimized.

Copy link
Author

jplatte commented Oct 13, 2019

There's also the possibility of using the impl keyword here, since that's really what is imported: trait implementations. However, the implementations that are imported will often come from different places, so maybe it makes more sense to think of this feature as "trait method imports".

A few new syntaxes were also discussed on reddit. Here's a quick overview of the possibilities mentioned so far:

// What the current version of this RFC suggests
use rayon::prelude::* as _;

// @matthieu-m's idea
use rayon::prelude::*trait* as _;

// my first idea for a dedicated syntax
use rayon::prelude::trait * as _;

// /u/peterjoel's first idea
use trait rayon::prelude::* as _;

// /u/peterjoel's second idea
use rayon::prelude::trait as _;

// /u/peterjoel's third idea
use rayon::prelude::* trait as _;

// my second idea
use rayon::prelude::impl * as _;
@the8472

This comment has been minimized.

Copy link

the8472 commented Oct 13, 2019

use trait rayon::prelude::* as _;

That doesn't work for grouped imports. Having the keyword in the tail position of the path would allow you do do rayon::prelude::{trait, Foo} as _;

@clarfon

This comment has been minimized.

Copy link
Contributor

clarfon commented Oct 17, 2019

Another syntax idea:

use impl some::path;

Would not be restricted to wildcards, but would apply to the entire branch. If there are leaves which are not wildcards and not traits, it'll throw a warning that they're unused. This also wouldn't conflict with the existing use path as _; syntax because the latter can be used inside grouping (e.g. use {path, other_path as _}; whereas the former applies to the entire statement.

Real-life examples:

// entire branch
use impl rayon::prelude::*;

// equivalent
use rayon::prelude::ParallelExtend;
use impl rayon::prelude::ParallelIterator;

use rayon::prelude::{ParallelIterator as _, ParallelExtend};

Another way we could potentially do this is to allow prefixing imports with impl to be equivalent to as _, e.g.:

use rayon::prelude::{impl ParallelIterator, ParallelExtend};

Although this could easily be confused with existing impl Trait syntax.

@ExpHP

This comment has been minimized.

Copy link

ExpHP commented Oct 17, 2019

I don't like the phrasing of "importing impls." That sounds like you're referring to the impl blocks defined inside the module, which is not at all what's happening here.

(such a thing exists in Haskell, where you can have "instance-only imports." The notion is pointless for rust, however)

@jplatte jplatte force-pushed the jplatte:master branch from 7263419 to 192b7b9 Nov 2, 2019
@jplatte

This comment has been minimized.

Copy link
Author

jplatte commented Nov 2, 2019

I've rewritten the RFC to use the syntax use module::trait * as _ instead, addressing @matthieu-m's concern about blacklisting and making the construct's meaning more obvious.

@phaazon

This comment has been minimized.

Copy link
Contributor

phaazon commented Nov 5, 2019

Just like use module::Tr as _, it is not immediately obvious what use module::trait * as _ does. It is likely more confusing for newcomers to read than use module::*.

I don’t agree with that statement. use foo::Trait as _ is actually pretty obvious, since it follows the exact same semantics as use foo::anything as something: it renames. Renaming to _ is akin to ignore. So we ignore the trait, but we still have imported it (even though its name is ignored), so the impls are in bound.

However, use foo::* as _ is clearly a different semantics because it does not only rename, but filters too (i.e. it just applies to traits, which is clearly not obvious). The other syntax you gave, use foo::trait as _, is another problem to me because you use a reserved keyword in the place of an item name.

Finally, I really dislike * in use statement on a general basis, so I’m not really into adding more sugar (and hence yield more habitude) around using them, for the very simple reason that I don’t like it when I don’t know what’s in scope, especially traits and types. I guess I prefer to add all the traits to the use statement than using *.

@phaazon

This comment has been minimized.

Copy link
Contributor

phaazon commented Nov 5, 2019

The author of this RFC is not aware of comparable syntax and / or import semantics in other programming languages.

Also, I’m the author of the aforementioned RFC, and I don’t understand your statement. I wrote the RFC you refer to because I’m actually aware and used to do that in Haskell via import Module (). Please provide more information about what you mean by not aware of comparable syntax / import semantics in other programming languages.

EDIT: I guess I just misread that this and thought you were talking about RFC-2166. I’m even more confused now. :D

@jplatte

This comment has been minimized.

Copy link
Author

jplatte commented Nov 5, 2019

@phaazon "this RFC" refers to the RFC you just commented on, RFC 2782. Why are you more confused after realizing it's not RFC 2166? Would you suggest rewording that sentence? Generally, I've seen people write about themselves as "the author of this RFC" in RFCs, rather than using first person (since it's not obvious from an RFC who wrote it).

@phaazon

This comment has been minimized.

Copy link
Contributor

phaazon commented Nov 8, 2019

Yeah first person is to avoid. I tend to use “This current RFC” or “This very RFC” to disambiguate, but I think it’s fine. Forget my confusion, I guess I was tired.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
8 participants
You can’t perform that action at this time.