Skip to content

Commit d311571

Browse files
committedDec 1, 2018
Auto merge of rust-lang#55275 - petrochenkov:extself, r=eddyb
experiment: Support aliasing local crate root in extern prelude This PR provides some minimally invasive solution for the 2018 edition migration issue described in rust-lang#54647 and affecting proc macro crates. `extern crate NAME as RENAME;` now accepts `NAME`=`self` and interprets it as referring to the local crate. As with other `extern crate` items, `RENAME` in this case gets into extern prelude in accordance with rust-lang#54658, thus resolving rust-lang#54647. ```rust extern crate self as serde; // Adds local crate to extern prelude as `serde` ``` This solution doesn't introduce any new syntax and has minimal maintenance cost, so it can be easily deprecated if something better is found in the future. Closes rust-lang#54647

9 files changed

+89
-10
lines changed
 

‎src/librustc_resolve/build_reduced_graph.rs

+24-4
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use syntax::ext::base::{MacroKind, SyntaxExtension};
4040
use syntax::ext::base::Determinacy::Undetermined;
4141
use syntax::ext::hygiene::Mark;
4242
use syntax::ext::tt::macro_rules;
43-
use syntax::feature_gate::is_builtin_attr;
43+
use syntax::feature_gate::{is_builtin_attr, emit_feature_err, GateIssue};
4444
use syntax::parse::token::{self, Token};
4545
use syntax::std_inject::injected_crate_name;
4646
use syntax::symbol::keywords;
@@ -344,9 +344,23 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
344344
}
345345

346346
ItemKind::ExternCrate(orig_name) => {
347-
let crate_id = self.crate_loader.process_extern_crate(item, &self.definitions);
348-
let module =
349-
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
347+
let module = if orig_name.is_none() && ident.name == keywords::SelfValue.name() {
348+
self.session
349+
.struct_span_err(item.span, "`extern crate self;` requires renaming")
350+
.span_suggestion(item.span, "try", "extern crate self as name;".into())
351+
.emit();
352+
return;
353+
} else if orig_name == Some(keywords::SelfValue.name()) {
354+
if !self.session.features_untracked().extern_crate_self {
355+
emit_feature_err(&self.session.parse_sess, "extern_crate_self", item.span,
356+
GateIssue::Language, "`extern crate self` is unstable");
357+
}
358+
self.graph_root
359+
} else {
360+
let crate_id = self.crate_loader.process_extern_crate(item, &self.definitions);
361+
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
362+
};
363+
350364
self.populate_module_if_necessary(module);
351365
if injected_crate_name().map_or(false, |name| ident.name == name) {
352366
self.injected_crate = Some(module);
@@ -768,6 +782,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
768782
span_err!(self.session, item.span, E0468,
769783
"an `extern crate` loading macros must be at the crate root");
770784
}
785+
if let ItemKind::ExternCrate(Some(orig_name)) = item.node {
786+
if orig_name == keywords::SelfValue.name() {
787+
self.session.span_err(attr.span,
788+
"`macro_use` is not supported on `extern crate self`");
789+
}
790+
}
771791
let ill_formed = |span| span_err!(self.session, span, E0466, "bad macro import");
772792
match attr.meta() {
773793
Some(meta) => match meta.node {

‎src/librustc_typeck/check_unused.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,12 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
113113
true
114114
})
115115
.filter(|&&(def_id, _)| {
116-
let cnum = tcx.extern_mod_stmt_cnum(def_id).unwrap();
117-
!tcx.is_compiler_builtins(cnum)
118-
&& !tcx.is_panic_runtime(cnum)
119-
&& !tcx.has_global_allocator(cnum)
120-
&& !tcx.has_panic_handler(cnum)
116+
tcx.extern_mod_stmt_cnum(def_id).map_or(true, |cnum| {
117+
!tcx.is_compiler_builtins(cnum) &&
118+
!tcx.is_panic_runtime(cnum) &&
119+
!tcx.has_global_allocator(cnum) &&
120+
!tcx.has_panic_handler(cnum)
121+
})
121122
})
122123
.cloned()
123124
.collect();

‎src/libsyntax/feature_gate.rs

+3
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,9 @@ declare_features! (
492492

493493
// `reason = ` in lint attributes and `expect` lint attribute
494494
(active, lint_reasons, "1.31.0", Some(54503), None),
495+
496+
// `extern crate self as foo;` puts local crate root into extern prelude under name `foo`.
497+
(active, extern_crate_self, "1.31.0", Some(54658), None),
495498
);
496499

497500
declare_features! (

‎src/libsyntax/parse/parser.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -6783,7 +6783,11 @@ impl<'a> Parser<'a> {
67836783
let error_msg = "crate name using dashes are not valid in `extern crate` statements";
67846784
let suggestion_msg = "if the original crate name uses dashes you need to use underscores \
67856785
in the code";
6786-
let mut ident = self.parse_ident()?;
6786+
let mut ident = if self.token.is_keyword(keywords::SelfValue) {
6787+
self.parse_path_segment_ident()
6788+
} else {
6789+
self.parse_ident()
6790+
}?;
67876791
let mut idents = vec![];
67886792
let mut replacement = vec![];
67896793
let mut fixed_crate_name = false;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
extern crate self as foo; //~ ERROR `extern crate self` is unstable
2+
3+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0658]: `extern crate self` is unstable (see issue #54658)
2+
--> $DIR/feature-gate-extern_crate_self.rs:1:1
3+
|
4+
LL | extern crate self as foo; //~ ERROR `extern crate self` is unstable
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: add #![feature(extern_crate_self)] to the crate attributes to enable
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(extern_crate_self)]
2+
3+
extern crate self; //~ ERROR `extern crate self;` requires renaming
4+
5+
#[macro_use] //~ ERROR `macro_use` is not supported on `extern crate self`
6+
extern crate self as foo;
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: `extern crate self;` requires renaming
2+
--> $DIR/extern-crate-self-fail.rs:3:1
3+
|
4+
LL | extern crate self; //~ ERROR `extern crate self;` requires renaming
5+
| ^^^^^^^^^^^^^^^^^^ help: try: `extern crate self as name;`
6+
7+
error: `macro_use` is not supported on `extern crate self`
8+
--> $DIR/extern-crate-self-fail.rs:5:1
9+
|
10+
LL | #[macro_use] //~ ERROR `macro_use` is not supported on `extern crate self`
11+
| ^^^^^^^^^^^^
12+
13+
error: aborting due to 2 previous errors
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// compile-pass
2+
3+
#![feature(extern_crate_self)]
4+
5+
extern crate self as foo;
6+
7+
struct S;
8+
9+
mod m {
10+
fn check() {
11+
foo::S; // OK
12+
}
13+
}
14+
15+
fn main() {}

0 commit comments

Comments
 (0)
Please sign in to comment.