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

Rust stable 1.30 allows use of extern crates without declaration #55478

Closed
jrobsonchase opened this issue Oct 29, 2018 · 11 comments
Closed

Rust stable 1.30 allows use of extern crates without declaration #55478

jrobsonchase opened this issue Oct 29, 2018 · 11 comments
Assignees
Labels
A-resolve Area: Path resolution T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@jrobsonchase
Copy link

Example crate(s): https://github.com/jrobsonchase/cloud_to_butt

It appears that rust stable 1.30 allows the use of absolute paths to items from other crates without the extern crate declaration. This works in code, but not in use statements.

I originally thought it was just a proc-macro crate problem since that's where I noticed it first, but it shows up in both. See https://github.com/jrobsonchase/cloud_to_butt/blob/master/src/lib.rs#L28 and https://github.com/jrobsonchase/cloud_to_butt/blob/master/cloud/src/main.rs#L10. Both contain full paths to syn/proc_macro2 items that shouldn't be available since there's been no extern crate for either.

my rustc version:

rustc 1.30.0 (da5f414c2 2018-10-24)
@jrobsonchase jrobsonchase changed the title Rust stable 1.30 proc-macro crates allow use of extern crates without declaration Rust stable 1.30 allows use of extern crates without declaration Oct 29, 2018
@petrochenkov
Copy link
Contributor

This is by design, crate names passed with --extern are put into prelude and available from the whole crate without imports for compatibility with 2018 edition, but also for convenience.

This is what the "Module system improvements" section in the announce blog post attempted to convey.

@jrobsonchase
Copy link
Author

jrobsonchase commented Oct 29, 2018 via email

@petrochenkov
Copy link
Contributor

petrochenkov commented Oct 29, 2018

@jrobsonchase
Yes, use on 2015 edition still uses paths relative to the crate root, so for use my_crate::foo; to work my_crate must be somehow defined in the crate root, usually via extern crate my_crate;.
On 2018 edition imports will be able to work without extern crate my_crate; items too, making extern crate nearly obsolete.

So, on 2015, I think, there's now a choice between two guidelines on how to use extern crate items:

  1. Add extern crate items only if necessary for imports, and
  2. Add extern crate for all used crates for consistency (or to support older versions of rustc).

@jrobsonchase
Copy link
Author

jrobsonchase commented Oct 29, 2018 via email

@petrochenkov
Copy link
Contributor

it's intended behavior to be able to use things from
dependency crates without extern crate as long as you use the full path

Yes, "full path" -> "relative path starting with a crate name" to be precise.

but as soon as you want to refactor and bring things into local scope with
use, then you need extern crate as well

Correct.

If so, I find that to be an
extremely unintuitive intermediate step between 2015's "you must always
have extern crate declarations" and 2018's "you almost never need extern crate."

In this case you may want to follow the guideline 2. and use extern crate for everything.

@petrochenkov
Copy link
Contributor

FWIW, unresolved imports still explicitly recommend adding an extern crate item:

error[E0432]: unresolved import `my_crate`
 --> src/main.rs:1:5
  |
1 | use my_crate::foo;
  |     ^^^^^^^^ Maybe a missing `extern crate my_crate;`?

so it's clear what to do when a person unfamiliar with the rules encounters this error.

@jrobsonchase
Copy link
Author

jrobsonchase commented Oct 29, 2018 via email

@petrochenkov
Copy link
Contributor

Because some_crate::do_something() and use some_crate::do_something are resolved very differently (relative paths vs absolute paths).
(That was always a source of confusion, and the whole 2018 module system overhaul started from the desire to remove this distinction.)

(By the way, other prelude names behave very similarly, i.e. you can write Vec::new(), but not use Vec;, println!(...), but not use println;).

@petrochenkov
Copy link
Contributor

My plan so far is to implement fallback from crate-relative names (crate::foo) to extern crates (extern::foo) in imports (use foo::bar) on 2015 edition and make crater experiment.
If everything is good, we'll be able to support use my_crate::bar imports on Rust 2015 as well as on Rust 2018.

@petrochenkov petrochenkov self-assigned this Dec 18, 2018
bors added a commit that referenced this issue Jan 18, 2019
[WIP] resolve: Fallback to extern crates in absolute paths on 2015 edition

TODO: Run crater, fix diagnostics

This PR changes the resolution scheme for imports and absolute paths from

| Local edition | Global edition | Imports (`use foo;`)                                 | Absolute paths (`::foo`)                                 |
| ------------- |----------------|-----------------------------------------|------------------------------------------------|
| 2018          | Any            | Uniform                                 | Extern prelude                                 |
| 2015          | 2015           | Crate-relative                          | Crate-relative                                 |
| 2015          | 2018           | Crate-relative with fallback to Uniform | Crate-relative with fallback to Extern prelude |

(which was introduced in #56053) to

| Local edition | Global edition | Imports (`use foo;`)                                 | Absolute paths (`::foo`)                                 |
| ------------- |----------------|-----------------------------------------|------------------------------------------------|
| 2018          | Any            | Uniform                                 | Extern prelude                                 |
| 2015          | Any            | Crate-relative with fallback to Extern prelude                          | Crate-relative with fallback to Extern prelude                                 |

(with `use foo;` still desugaring into `use ::foo;` on 2015 edition).

This way we
- Get rid of the special case "2015 macro used on 2018 edition".
- Resolve the issue discussed in #55478, i.e. "on 2015 edition you don't need `extern crate` until you need `use`, then you need `extern crate`". With this change `use my_crate::foo` and `let x = ::my_crate::foo` work without needing `extern crate` consistently with `let x = my_crate::foo`.

r? @Centril
@petrochenkov
Copy link
Contributor

My plan so far is to implement fallback from crate-relative names (crate::foo) to extern crates (extern::foo) in imports (use foo::bar) on 2015 edition and make crater experiment.

#57745 is implementation of that plan.

@jonas-schievink jonas-schievink added A-resolve Area: Path resolution T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 27, 2019
@petrochenkov
Copy link
Contributor

There was not enough interest in addressing this issue in #57745, closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-resolve Area: Path resolution T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants