remove extern_in_paths.

This commit is contained in:
Mazdak Farrokhzad 2019-01-13 14:18:00 +01:00
parent 75a369c5b1
commit c4f6ef25d2
30 changed files with 62 additions and 233 deletions

View File

@ -1,40 +0,0 @@
# `extern_in_paths`
The tracking issue for this feature is: [#44660]
[#44660]: https://github.com/rust-lang/rust/issues/44660
------------------------
The `extern_in_paths` feature allows to refer to names from other crates "inline", without
introducing `extern crate` items, using keyword `extern`.
For example, `extern::my_crat::a::b` will resolve to path `a::b` in crate `my_crate`.
Absolute paths on 2018 edition (e.g. `::my_crate::a::b`) provide the same effect
and resolve to extern crates (built-in or passed with `--extern`).
```rust,ignore
#![feature(extern_in_paths)]
// Suppose we have a dependency crate `xcrate` available through `Cargo.toml`, or `--extern`
// options, or standard Rust distribution, or some other means.
use extern::xcrate::Z;
fn f() {
use extern::xcrate;
use extern::xcrate as ycrate;
let s = xcrate::S;
assert_eq!(format!("{:?}", s), "S");
let z = ycrate::Z;
assert_eq!(format!("{:?}", z), "Z");
}
fn main() {
let s = extern::xcrate::S;
assert_eq!(format!("{:?}", s), "S");
let z = Z;
assert_eq!(format!("{:?}", z), "Z");
}
```

View File

@ -140,7 +140,7 @@ pub enum ExternCrateSource {
),
// Crate is loaded by `use`.
Use,
/// Crate is implicitly loaded by an absolute or an `extern::` path.
/// Crate is implicitly loaded by an absolute path.
Path,
}

View File

@ -1005,7 +1005,7 @@ enum ModuleOrUniformRoot<'a> {
CrateRootAndExternPrelude,
/// Virtual module that denotes resolution in extern prelude.
/// Used for paths starting with `::` on 2018 edition or `extern::`.
/// Used for paths starting with `::` on 2018 edition.
ExternPrelude,
/// Virtual module that denotes resolution in current scope.
@ -3817,8 +3817,7 @@ impl<'a> Resolver<'a> {
self.resolve_self(&mut ctxt, self.current_module)));
continue;
}
if name == keywords::Extern.name() ||
name == keywords::PathRoot.name() && ident.span.rust_2018() {
if name == keywords::PathRoot.name() && ident.span.rust_2018() {
module = Some(ModuleOrUniformRoot::ExternPrelude);
continue;
}
@ -3985,8 +3984,8 @@ impl<'a> Resolver<'a> {
};
// We're only interested in `use` paths which should start with
// `{{root}}` or `extern` currently.
if first_name != keywords::Extern.name() && first_name != keywords::PathRoot.name() {
// `{{root}}` currently.
if first_name != keywords::PathRoot.name() {
return
}

View File

@ -25,9 +25,9 @@ use syntax_pos::{Span, DUMMY_SP};
use errors::{DiagnosticBuilder, Handler};
use visit::{self, FnKind, Visitor};
use parse::ParseSess;
use symbol::{keywords, Symbol};
use symbol::Symbol;
use std::{env};
use std::env;
macro_rules! set {
($field: ident) => {{
@ -375,9 +375,6 @@ declare_features! (
// Generic associated types (RFC 1598)
(active, generic_associated_types, "1.23.0", Some(44265), None),
// `extern` in paths
(active, extern_in_paths, "1.23.0", Some(55600), None),
// Infer static outlives requirements (RFC 2093).
(active, infer_static_outlives_requirements, "1.26.0", Some(54185), None),
@ -506,6 +503,9 @@ declare_features! (
// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`.
(removed, custom_derive, "1.0.0", Some(29644), None,
Some("subsumed by `#[proc_macro_derive]`")),
// Paths of the form: `extern::foo::bar`
(removed, extern_in_paths, "1.33.0", Some(55600), None,
Some("subsumed by `::foo::bar` paths")),
);
declare_features! (
@ -1829,25 +1829,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
visit::walk_impl_item(self, ii);
}
fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) {
for segment in &path.segments {
// Identifiers we are going to check could come from a legacy macro (e.g., `#[test]`).
// For such macros identifiers must have empty context, because this context is
// used during name resolution and produced names must be unhygienic for compatibility.
// On the other hand, we need the actual non-empty context for feature gate checking
// because it's hygienic even for legacy macros. As previously stated, such context
// cannot be kept in identifiers, so it's kept in paths instead and we take it from
// there while keeping location info from the ident span.
let span = segment.ident.span.with_ctxt(path.span.ctxt());
if segment.ident.name == keywords::Extern.name() {
gate_feature_post!(&self, extern_in_paths, span,
"`extern` in paths is experimental");
}
}
visit::walk_path(self, path);
}
fn visit_vis(&mut self, vis: &'a ast::Visibility) {
if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.node {
gate_feature_post!(&self, crate_visibility_modifier, vis.span,

View File

@ -1299,7 +1299,7 @@ impl<'a> Parser<'a> {
fn token_is_bare_fn_keyword(&mut self) -> bool {
self.check_keyword(keywords::Fn) ||
self.check_keyword(keywords::Unsafe) ||
self.check_keyword(keywords::Extern) && self.is_extern_non_path()
self.check_keyword(keywords::Extern)
}
/// parse a `TyKind::BareFn` type:
@ -4605,10 +4605,6 @@ impl<'a> Parser<'a> {
self.token.is_keyword(keywords::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
}
fn is_extern_non_path(&self) -> bool {
self.token.is_keyword(keywords::Extern) && self.look_ahead(1, |t| t != &token::ModSep)
}
fn is_existential_type_decl(&self) -> bool {
self.token.is_keyword(keywords::Existential) &&
self.look_ahead(1, |t| t.is_keyword(keywords::Type))
@ -4712,12 +4708,10 @@ impl<'a> Parser<'a> {
// like a path (1 token), but it fact not a path.
// `union::b::c` - path, `union U { ... }` - not a path.
// `crate::b::c` - path, `crate struct S;` - not a path.
// `extern::b::c` - path, `extern crate c;` - not a path.
} else if self.token.is_path_start() &&
!self.token.is_qpath_start() &&
!self.is_union_item() &&
!self.is_crate_vis() &&
!self.is_extern_non_path() &&
!self.is_existential_type_decl() &&
!self.is_auto_trait_item() {
let pth = self.parse_path(PathStyle::Expr)?;
@ -7113,8 +7107,7 @@ impl<'a> Parser<'a> {
return Ok(Some(item));
}
if self.check_keyword(keywords::Extern) && self.is_extern_non_path() {
self.bump(); // `extern`
if self.eat_keyword(keywords::Extern) {
if self.eat_keyword(keywords::Crate) {
return Ok(Some(self.parse_item_extern_crate(lo, visibility, attrs)?));
}
@ -7623,7 +7616,7 @@ impl<'a> Parser<'a> {
fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>,
at_end: &mut bool) -> PResult<'a, Option<Mac>>
{
if self.token.is_path_start() && !self.is_extern_non_path() {
if self.token.is_path_start() {
let prev_span = self.prev_span;
let lo = self.span;
let pth = self.parse_path(PathStyle::Mod)?;

View File

@ -478,7 +478,6 @@ impl Ident {
self.name == keywords::Super.name() ||
self.name == keywords::SelfLower.name() ||
self.name == keywords::SelfUpper.name() ||
self.name == keywords::Extern.name() ||
self.name == keywords::Crate.name() ||
self.name == keywords::PathRoot.name() ||
self.name == keywords::DollarCrate.name()

View File

@ -1,12 +1,9 @@
-include ../tools.mk
all: extern_absolute_paths.rs extern_in_paths.rs krate2
all: extern_absolute_paths.rs krate2
$(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018 \
-Z unstable-options --extern krate2
cat $(TMPDIR)/save-analysis/extern_absolute_paths.json | "$(PYTHON)" validate_json.py
$(RUSTC) extern_in_paths.rs -Zsave-analysis --edition=2018 \
-Z unstable-options --extern krate2
cat $(TMPDIR)/save-analysis/extern_in_paths.json | "$(PYTHON)" validate_json.py
krate2: krate2.rs
$(RUSTC) $<

View File

@ -1,7 +0,0 @@
#![feature(extern_in_paths)]
use extern::krate2;
fn main() {
extern::krate2::hello();
}

View File

@ -1,28 +0,0 @@
// run-pass
#![allow(dead_code)]
// aux-build:xcrate.rs
// compile-flags:--extern xcrate
#![feature(extern_in_paths)]
use extern::xcrate::Z;
type A = extern::xcrate::S;
type B = for<'a> extern::xcrate::Tr<'a>;
fn f() {
use extern::xcrate;
use extern::xcrate as ycrate;
let s = xcrate::S;
assert_eq!(format!("{:?}", s), "S");
let z = ycrate::Z;
assert_eq!(format!("{:?}", z), "Z");
}
fn main() {
let s = extern::xcrate::S;
assert_eq!(format!("{:?}", s), "S");
let z = Z;
assert_eq!(format!("{:?}", z), "Z");
assert_eq!(A {}, extern::xcrate::S {});
}

View File

@ -1,5 +0,0 @@
struct S;
fn main() {
let _ = extern::std::vec::Vec::new(); //~ ERROR `extern` in paths is experimental
}

View File

@ -1,11 +0,0 @@
error[E0658]: `extern` in paths is experimental (see issue #55600)
--> $DIR/feature-gate-extern_in_paths.rs:4:13
|
LL | let _ = extern::std::vec::Vec::new(); //~ ERROR `extern` in paths is experimental
| ^^^^^^
|
= help: add #![feature(extern_in_paths)] to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -0,0 +1,3 @@
fn main() {
let s = extern::foo::Bar; //~ ERROR expected expression, found keyword `extern`
}

View File

@ -0,0 +1,8 @@
error: expected expression, found keyword `extern`
--> $DIR/keyword-extern-as-identifier-expr.rs:2:13
|
LL | let s = extern::foo::Bar; //~ ERROR expected expression, found keyword `extern`
| ^^^^^^ expected expression
error: aborting due to previous error

View File

@ -0,0 +1,3 @@
fn main() {
let extern = 0; //~ ERROR expected pattern, found keyword `extern`
}

View File

@ -0,0 +1,8 @@
error: expected pattern, found keyword `extern`
--> $DIR/keyword-extern-as-identifier-pat.rs:2:9
|
LL | let extern = 0; //~ ERROR expected pattern, found keyword `extern`
| ^^^^^^ expected pattern
error: aborting due to previous error

View File

@ -0,0 +1,3 @@
type A = extern::foo::bar; //~ ERROR expected `fn`, found `::`
fn main() {}

View File

@ -0,0 +1,8 @@
error: expected `fn`, found `::`
--> $DIR/keyword-extern-as-identifier-type.rs:1:16
|
LL | type A = extern::foo::bar; //~ ERROR expected `fn`, found `::`
| ^^ expected `fn` here
error: aborting due to previous error

View File

@ -0,0 +1,3 @@
use extern::foo; //~ ERROR expected identifier, found keyword `extern`
fn main() {}

View File

@ -0,0 +1,12 @@
error: expected identifier, found keyword `extern`
--> $DIR/keyword-extern-as-identifier-use.rs:1:5
|
LL | use extern::foo; //~ ERROR expected identifier, found keyword `extern`
| ^^^^^^ expected identifier, found keyword
help: you can escape reserved keywords to use them as identifiers
|
LL | use r#extern::foo; //~ ERROR expected identifier, found keyword `extern`
| ^^^^^^^^
error: aborting due to previous error

View File

@ -1,5 +0,0 @@
#![feature(extern_in_paths)]
fn main() {
let extern = 0; //~ ERROR cannot find unit struct/variant or constant `extern` in this scope
}

View File

@ -1,9 +0,0 @@
error[E0531]: cannot find unit struct/variant or constant `extern` in this scope
--> $DIR/keyword-extern-as-identifier.rs:4:9
|
LL | let extern = 0; //~ ERROR cannot find unit struct/variant or constant `extern` in this scope
| ^^^^^^ not found in this scope
error: aborting due to previous error
For more information about this error, try `rustc --explain E0531`.

View File

@ -1,5 +0,0 @@
#[derive(Debug)]
pub struct S;
#[derive(Debug)]
pub struct Z;

View File

@ -1,5 +0,0 @@
#![feature(extern_in_paths)]
use extern::xcrate::S; //~ ERROR unresolved import `extern::xcrate`
fn main() {}

View File

@ -1,9 +0,0 @@
error[E0432]: unresolved import `extern::xcrate`
--> $DIR/non-existent-1.rs:3:13
|
LL | use extern::xcrate::S; //~ ERROR unresolved import `extern::xcrate`
| ^^^^^^ could not find `xcrate` in `extern`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0432`.

View File

@ -1,6 +0,0 @@
#![feature(extern_in_paths)]
fn main() {
let s = extern::xcrate::S;
//~^ ERROR failed to resolve: could not find `xcrate` in `extern`
}

View File

@ -1,9 +0,0 @@
error[E0433]: failed to resolve: could not find `xcrate` in `extern`
--> $DIR/non-existent-2.rs:4:21
|
LL | let s = extern::xcrate::S;
| ^^^^^^ could not find `xcrate` in `extern`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0433`.

View File

@ -1,5 +0,0 @@
#![feature(extern_in_paths)]
use extern::ycrate; //~ ERROR unresolved import `extern::ycrate`
fn main() {}

View File

@ -1,9 +0,0 @@
error[E0432]: unresolved import `extern::ycrate`
--> $DIR/non-existent-3.rs:3:5
|
LL | use extern::ycrate; //~ ERROR unresolved import `extern::ycrate`
| ^^^^^^^^^^^^^^ no `ycrate` external crate
error: aborting due to previous error
For more information about this error, try `rustc --explain E0432`.

View File

@ -1,13 +0,0 @@
// aux-build:xcrate.rs
// compile-flags:--extern xcrate
#![feature(extern_in_paths)]
use extern; //~ ERROR unresolved import `extern`
//~^ NOTE no `extern` in the root
use extern::*; //~ ERROR cannot glob-import all possible crates
fn main() {
let s = extern::xcrate; //~ ERROR expected value, found module `extern::xcrate`
//~^ NOTE not a value
}

View File

@ -1,22 +0,0 @@
error: cannot glob-import all possible crates
--> $DIR/single-segment.rs:8:5
|
LL | use extern::*; //~ ERROR cannot glob-import all possible crates
| ^^^^^^^^^
error[E0432]: unresolved import `extern`
--> $DIR/single-segment.rs:6:5
|
LL | use extern; //~ ERROR unresolved import `extern`
| ^^^^^^ no `extern` in the root
error[E0423]: expected value, found module `extern::xcrate`
--> $DIR/single-segment.rs:11:13
|
LL | let s = extern::xcrate; //~ ERROR expected value, found module `extern::xcrate`
| ^^^^^^^^^^^^^^ not a value
error: aborting due to 3 previous errors
Some errors occurred: E0423, E0432.
For more information about an error, try `rustc --explain E0423`.