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

Make extern mod xxx optional #11811

Closed
liigo opened this issue Jan 26, 2014 · 32 comments
Closed

Make extern mod xxx optional #11811

liigo opened this issue Jan 26, 2014 · 32 comments

Comments

@liigo
Copy link
Contributor

liigo commented Jan 26, 2014

@brson suggested me open a new issue on this idea, "it seems worth exploring", he said. He don't want this to get buried in #11745 too. See comments in #11787.

The Problem

To use a crate in rust, at least two lines are required currently:

extern mod xxx;
use xxx::a::b;

In a large project, we need to use many crates, particularly after extra's dissolution (#11787). The more crates we need, the more lines extern mod xxx need to write, which is a pain:

extern mod crate1; // do we really need to write this?
extern mod crate2; 
extern mod crate3;
extern mod crate4;
......
use crate1::*; // compiler can infers "extern mod crate1" from here
use crate2::*;
use crate3::*;
use crate4::*;
......

The Solution

Since we must write lines such as use xxx::a::b, the compiler should always knows I'm using the crate xxx. So the extern mod xxx is redundant, it should be optional, unless compiler got ambiguity in non-common situations.

@emberian
Copy link
Member

I never want to be linked to crates by using an import. Additionally, this is trivially broken in the face of glob reexports. I feel like the ever-so-slight cost in extra lines is an extremely small price for ease of recognition of shadowing, as well as explicitly knowing what I'm linking to.

@sinistersnare
Copy link
Contributor

Is is possible that we can have syntax such as:

extern mod {crate1, crate2, crate3, crate4};

as opposed to:

extern mod crate1; // do we really need to write this?
extern mod crate2; 
extern mod crate3;
extern mod crate4;

This way it keeps the explicitness of every crate in use, while removing all of the supposed extra extern mod's created by the pull request that started this.

@emberian
Copy link
Member

yeah that'd be nice actually.

On Sun, Jan 26, 2014 at 12:39 AM, Davis Silverman
notifications@github.comwrote:

Is is possible that we can have syntax such as:

extern mod {crate1, crate2, crate3, crate4};

as opposed to:

extern mod crate1; // do we really need to write this?
extern mod crate2;
extern mod crate3;
extern mod crate4;


Reply to this email directly or view it on GitHubhttps://github.com//issues/11811#issuecomment-33309880
.

@pcwalton
Copy link
Contributor

I don't like this. use is for namespace management; extern mod is for linking. The information that use needs is different from the information that extern mod (which really should be extern crate) needs. This is inherent to having a two-level namespace system. I strongly suspect that conflating the two concepts will just lead to more confusion down the road.

However, I'd be totally fine with extern mod {foo, bar, baz};

@adrientetar
Copy link
Contributor

As others said, extern mod is not redundant and it has a different use than use. Adding stacked declarations would solve the problem through without risking conflicts or auto-linking.

@gdonval
Copy link

gdonval commented Jan 26, 2014

Then why not make that crystal clear? link crate {foo, bar}; or link extern crate {foo, bar}; seems clearer in its purpose than the current extern mod which seems superflous (to me at least) because one doesn't not what it is used for.

After all, in python, a simple import is all it takes. Why bother with declaring twice something that can be declared only once?

By making it clear that this is required in the linking process, this decision makes much more sense. People coming from C wouldn't complain that much if they knew this is similar to their beloved "-l" linker argument.

By the way, I don't know if that really makes sense, but I've seen a lot of in-crate link-args wouldn't it be more convenient to use extern "C" mod {foo, bar}; or link "C" crate {foo, bar}; to link C libs to the current crate instead of #[link-args="-lfoo,-lbar"]?

@thestinger
Copy link
Contributor

A mod statement includes a file or a block of code as a module. The extern mod statement includes an external library as a module. An extern mod statement is not used to link to C ABI libraries. Both mod and extern mod bring a module into the tree under the name given in the statement.

The term "crate" is cute Rust jargon, but it's not going to help in understanding the language. If we're worried about clarity then we should drop the usage of "crate" completely and call them libraries.

@thestinger
Copy link
Contributor

I opened #11819 to cover the issue of multiple inclusions per statement. This issue should stay on the topic of removing mod and extern mod or be closed.

@huonw
Copy link
Member

huonw commented Jan 26, 2014

By the way, I don't know if that really makes sense, but I've seen a lot of in-crate link-args wouldn't it be more convenient to use extern "C" mod {foo, bar}; or link "C" crate {foo, bar}; to link C libs to the current crate instead of #[link-args="-lfoo,-lbar"]?

It's now #[link(name="foo")] extern { ... }, and there's #2124 open about adding a feature to read C headers. It could possibly look something like #[header(name="foo.h", link_name="bar")] extern mod baz;.

@thestinger
Copy link
Contributor

@huonw: I think it would probably link to the module name by default, as it does for Rust crates. The header is just the missing data to make it into a proper extern mod.

@huonw
Copy link
Member

huonw commented Jan 26, 2014

That would certainly work too.

@liigo
Copy link
Contributor Author

liigo commented Jan 26, 2014

After making extern mod xxx optional, you can still always write it explicitly. But even it is absence, the compiler can infers exactly the correct extern crates to be linked in, no one crate less, no one crate more. Even you write these by hands, you can't do any more than compiler. What's the reason you oppose making it optional? Examples?

@thestinger
Copy link
Contributor

How will the compiler distinguish between a module called foo and an external module called foo? Will it priortize local modules over external ones?

Anyway, I don't understand why extern mod foo would be optional but mod foo wouldn't be. You need to present a coherent plan rather than just stating it should be optional without thinking about how to do it.

@liigo
Copy link
Contributor Author

liigo commented Jan 26, 2014

The compiler can not distinguish between two modules both named foo, no matter whether extern mod x is optional or not. @thetinger

@thestinger
Copy link
Contributor

It can distinguish between with mod foo and extern mod foo. You can include them in different places in the module tree.

@thestinger
Copy link
Contributor

Do you want mod foo to be optional too, or just extern mod?

@liigo
Copy link
Contributor Author

liigo commented Jan 26, 2014

I don't care whether or not mod foo to be optional.

@thestinger
Copy link
Contributor

Why do you see it as a different case than extern mod foo? Both are used to include modules in the tree.

@liigo
Copy link
Contributor Author

liigo commented Jan 26, 2014

mod foo is used to include .rs file, i think, rustc need it to compiles the crate.
but for extern mod foo, compiler can infer which crate should be linked in, from the use statements, or from which types and functions used in the source code.

@thestinger
Copy link
Contributor

Both the mod foo and extern mod foo statements include a module in the module tree. For the module including the sub-module, there's no difference between an internal and external module. A use statement can refer to a name in either an internal or external module with no differences in syntax.

Both are required to compile the crate if they're unused. I don't see why you think there's a difference in terms of what can be inferred between internal and external modules.

@pnkfelix
Copy link
Member

I agree with pcwalton's comment and cmr's comment.

I vaguely recall past discussion of changing how extern mod is denoted, e.g. via extern crate or perhaps crate as pcwalton suggests. But that is very different from removing any way to express this linkage directive, which is what this ticket is describing. (That's just me echo'ing strcat's comment that we should keep the ticket's topic on track.)

(One big reason that I do not like the idea of inferring external linkage from the existing uses of use is that I think it will lead in the common case to cryptic compiler error messages, or worse, outright linkage mistakes, in response to user typos.)

@liigo
Copy link
Contributor Author

liigo commented Jan 26, 2014

@thestinger: I don't think there's a difference in terms of what can be inferred between internal and external modules. Why distinguish between them? If a type or function can't be found in internal mod, it should be linked to external crate. use x::a::b::c implies using external crate x.

@pnkfelix
Copy link
Member

@liigo would the use x::a::b::c that implies linking to external crate x be required to solely appear at the topmost part of the file (i.e. the place where one imports uses that are scoped across the file)? Or would it also be allowed in more narrow scopes, like so:

[... large collection of definitions ; no uses or definitions of `mod x` nor `extern mod x` ...]
fn foo() {
   use x::a::b::c; // is this legal and implies linking to external `mod x`?  Or is it illegal?
   ...
}

@liigo
Copy link
Contributor Author

liigo commented Jan 27, 2014

@pnkfelix

use x::a::b::c; // is this legal and implies linking to external `mod x`?  Or is it illegal?

Here, x maybe a local module, or external crate. Compiler should first try to make sure that a::b::c is really resides in "local module" x. If yes, it's a local module. If not, then it must be considered as an "external crate" x, and compiler do some checks, and add an extern mod x automatically. If a::b::c both resides in local mod x and external crate x, it's a compile (or link) error.

@metajack
Copy link
Contributor

This seems to make the assumption that the common case will not be to use extern mod foo = "github.com/some-org/foo#1.0";.

Even if it can figure out that use x::a::b::c; is not referring to a module, how is it to get any info about the crate metadata for x? I guess you could always have an extern mod directive explicitly, but if these will be necessary most of the time, why add more magic to use?

In any case, I think we need more information about the packaging system before a clear path for extern mod and use will be visible.

@liigo
Copy link
Contributor Author

liigo commented Jan 27, 2014

If crate files are in local file system, rustc can find them. And you can
always use extern mod statements explicitly.
2014年1月27日 下午2:55于 "Jack Moffitt" notifications@github.com写道:

This seems to make the assumption that the common case will not be to use extern
mod foo = "github.com/some-org/foo#1.0";.

Even if it can figure out that use x::a::b::c; is not referring to a
module, how is it to get any info about the crate metadata for x? I guess
you could always have an extern mod directive explicitly, but if these
will be necessary most of the time, why add more magic to use?

In any case, I think we need more information about the packaging system
before a clear path for extern mod and use will be visible.


Reply to this email directly or view it on GitHubhttps://github.com//issues/11811#issuecomment-33345292
.

@pczarn
Copy link
Contributor

pczarn commented Jan 27, 2014

I agree that the proposed solution introduces some confusion and ambiguity.

The syntax extern mod {foo, bar, baz}; diverges from current use declaration syntax. I don't like it as long as I can't write use {a, b, c};.

To make clear that xxx is an external crate, I'd like to have use extern xxx::a::b;

@adrientetar
Copy link
Contributor

@pczarn You can write use x::y::{a, b, c} already, that's #10806.

use extern sounds good; it makes repeating extern for every use statements through.

@emberian
Copy link
Member

You can write use {a, b, c}.

On Mon, Jan 27, 2014 at 12:30 PM, Piotr notifications@github.com wrote:

I agree that the proposed solution introduces some confusion and ambiguity.

The syntax extern mod {foo, bar, baz}; diverges from current usedeclaration syntax. I don't like it as long as I can't write use
{a, b, c};.

To make clear that xxx is an external crate, I'd like to have use extern
xxx::a::b;


Reply to this email directly or view it on GitHubhttps://github.com//issues/11811#issuecomment-33399002
.

@thestinger
Copy link
Contributor

The conversation about allowing multiple modules per extern mod or mod statement belongs in #11819.

@pnkfelix
Copy link
Member

While doing separate archaeology, I happened to run into this RFC from 1.5 years ago:

[rust-dev] RFC: Load external crates with "use"
https://mail.mozilla.org/pipermail/rust-dev/2012-September/002357.html

It might be useful for the proponent(s) of this feature to read over the discussion thread there.

@alexcrichton
Copy link
Member

Closing, a change such as this now needs to go through the official RFC process

flip1995 pushed a commit to flip1995/rust that referenced this issue Nov 16, 2023
…shearth

disallow calls to `LintContext::struct_span_lint` and `TyCtxt::struct_span_lint_hir`

`LintContext::struct_span_lint` and `TyCtxt::struct_span_lint_hir` don't show the link to the clippy documentation, see: rust-lang#11805

In rust-lang#11810, the last few calls to those methods were replaced with `span_lint_*`. It seems like we should just disallow them altogether so that no new code tries to use them.

The existing `disallowed_methods` lint makes this easy.

changelog: none
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