Skip to content

Commit 2d4b633

Browse files
committed
Delay gensym creation for "underscore items" until name resolution
Prohibit `static _` Fis unused import warnings for `use foo as _` Add more tests for `use foo as _`
1 parent c658d73 commit 2d4b633

16 files changed

+157
-36
lines changed

src/librustc_resolve/build_reduced_graph.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
157157
};
158158
match use_tree.kind {
159159
ast::UseTreeKind::Simple(rename, ..) => {
160-
let mut ident = use_tree.ident();
160+
let mut ident = use_tree.ident().gensym_if_underscore();
161161
let mut module_path = prefix;
162162
let mut source = module_path.pop().unwrap();
163163
let mut type_ns_only = false;
@@ -334,7 +334,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
334334
fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScope<'a>) {
335335
let parent = parent_scope.module;
336336
let expansion = parent_scope.expansion;
337-
let ident = item.ident;
337+
let ident = item.ident.gensym_if_underscore();
338338
let sp = item.span;
339339
let vis = self.resolve_visibility(&item.vis);
340340

@@ -628,7 +628,11 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
628628

629629
/// Builds the reduced graph for a single item in an external crate.
630630
fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) {
631-
let Export { ident, def, vis, span, .. } = child;
631+
let Export { ident, def, vis, span } = child;
632+
// FIXME: We shouldn't create the gensym here, it should come from metadata,
633+
// but metadata cannot encode gensyms currently, so we create it here.
634+
// This is only a guess, two equivalent idents may incorrectly get different gensyms here.
635+
let ident = ident.gensym_if_underscore();
632636
let def_id = def.def_id();
633637
let expansion = Mark::root(); // FIXME(jseyfried) intercrate hygiene
634638
match def {

src/librustc_resolve/resolve_imports.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -888,9 +888,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
888888
PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(),
889889
};
890890

891-
let (ident, source_bindings, target_bindings, type_ns_only) = match directive.subclass {
892-
SingleImport { source, ref source_bindings, ref target_bindings, type_ns_only, .. } =>
893-
(source, source_bindings, target_bindings, type_ns_only),
891+
let (ident, target, source_bindings, target_bindings, type_ns_only) =
892+
match directive.subclass {
893+
SingleImport { source, target, ref source_bindings,
894+
ref target_bindings, type_ns_only } =>
895+
(source, target, source_bindings, target_bindings, type_ns_only),
894896
GlobImport { is_prelude, ref max_vis } => {
895897
if directive.module_path.len() <= 1 {
896898
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least
@@ -944,8 +946,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
944946
// Consistency checks, analogous to `finalize_current_module_macro_resolutions`.
945947
let initial_def = source_bindings[ns].get().map(|initial_binding| {
946948
all_ns_err = false;
947-
this.record_use(ident, ns, initial_binding,
948-
directive.module_path.is_empty());
949+
if target.name == "_" &&
950+
initial_binding.is_extern_crate() && !initial_binding.is_import() {
951+
this.used_imports.insert((directive.id, TypeNS));
952+
}
949953
initial_binding.def_ignoring_ambiguity()
950954
});
951955
let def = binding.def_ignoring_ambiguity();

src/libsyntax/parse/parser.rs

+13-14
Original file line numberDiff line numberDiff line change
@@ -2017,6 +2017,17 @@ impl<'a> Parser<'a> {
20172017
}
20182018
}
20192019

2020+
fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> {
2021+
match self.token {
2022+
token::Ident(ident, false) if ident.name == keywords::Underscore.name() => {
2023+
let span = self.span;
2024+
self.bump();
2025+
Ok(Ident::new(ident.name, span))
2026+
}
2027+
_ => self.parse_ident(),
2028+
}
2029+
}
2030+
20202031
/// Parses qualified path.
20212032
/// Assumes that the leading `<` has been parsed already.
20222033
///
@@ -6435,13 +6446,7 @@ impl<'a> Parser<'a> {
64356446
}
64366447

64376448
fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> {
6438-
let id = match self.token {
6439-
token::Ident(ident, false) if ident.name == keywords::Underscore.name() => {
6440-
self.bump(); // `_`
6441-
ident.gensym()
6442-
},
6443-
_ => self.parse_ident()?,
6444-
};
6449+
let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?;
64456450
self.expect(&token::Colon)?;
64466451
let ty = self.parse_ty()?;
64476452
self.expect(&token::Eq)?;
@@ -7726,13 +7731,7 @@ impl<'a> Parser<'a> {
77267731

77277732
fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
77287733
if self.eat_keyword(keywords::As) {
7729-
match self.token {
7730-
token::Ident(ident, false) if ident.name == keywords::Underscore.name() => {
7731-
self.bump(); // `_`
7732-
Ok(Some(ident.gensym()))
7733-
}
7734-
_ => self.parse_ident().map(Some),
7735-
}
7734+
self.parse_ident_or_underscore().map(Some)
77367735
} else {
77377736
Ok(None)
77387737
}

src/libsyntax_pos/symbol.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ impl Ident {
8080
Ident::new(self.name.gensymed(), self.span)
8181
}
8282

83+
pub fn gensym_if_underscore(self) -> Ident {
84+
if self.name == keywords::Underscore.name() { self.gensym() } else { self }
85+
}
86+
8387
pub fn as_str(self) -> LocalInternedString {
8488
self.name.as_str()
8589
}
@@ -465,7 +469,7 @@ impl Ident {
465469
// We see this identifier in a normal identifier position, like variable name or a type.
466470
// How was it written originally? Did it use the raw form? Let's try to guess.
467471
pub fn is_raw_guess(self) -> bool {
468-
self.name != keywords::Invalid.name() &&
472+
self.name != keywords::Invalid.name() && self.name != keywords::Underscore.name() &&
469473
self.is_reserved() && !self.is_path_segment_keyword()
470474
}
471475
}

src/test/ui/underscore_const_names_feature_gate.rs renamed to src/test/ui/feature-gates/underscore_const_names_feature_gate.rs

-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,5 @@
99
// except according to those terms.
1010

1111
const _: () = (); //~ ERROR is unstable
12-
static _: () = (); //~ ERROR is unstable
1312

1413
fn main() {}

src/test/ui/underscore_const_names_feature_gate.stderr renamed to src/test/ui/feature-gates/underscore_const_names_feature_gate.stderr

+1-9
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,6 @@ LL | const _: () = (); //~ ERROR is unstable
66
|
77
= help: add #![feature(underscore_const_names)] to the crate attributes to enable
88

9-
error[E0658]: naming constants with `_` is unstable (see issue #54912)
10-
--> $DIR/underscore_const_names_feature_gate.rs:12:1
11-
|
12-
LL | static _: () = (); //~ ERROR is unstable
13-
| ^^^^^^^^^^^^^^^^^^
14-
|
15-
= help: add #![feature(underscore_const_names)] to the crate attributes to enable
16-
17-
error: aborting due to 2 previous errors
9+
error: aborting due to previous error
1810

1911
For more information about this error, try `rustc --explain E0658`.
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// compile-flags: -Z parse-only
2+
3+
static _: () = (); //~ ERROR expected identifier, found reserved identifier `_`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: expected identifier, found reserved identifier `_`
2+
--> $DIR/underscore_static.rs:3:8
3+
|
4+
LL | static _: () = (); //~ ERROR expected identifier, found reserved identifier `_`
5+
| ^ expected identifier, found reserved identifier
6+
7+
error: aborting due to previous error
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// force-host
2+
// no-prefer-dynamic
3+
4+
#![crate_type = "proc-macro"]
5+
6+
extern crate proc_macro;
7+
8+
use proc_macro::*;
9+
10+
#[proc_macro_attribute]
11+
pub fn duplicate(_: TokenStream, input: TokenStream) -> TokenStream {
12+
let clone = input.clone();
13+
input.into_iter().chain(clone.into_iter()).collect()
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#![feature(underscore_imports)]
2+
3+
#[macro_export]
4+
macro_rules! do_nothing {
5+
() => ()
6+
}
7+
8+
mod m1 {
9+
pub trait InScope1 {
10+
fn in_scope1(&self) {}
11+
}
12+
impl InScope1 for () {}
13+
}
14+
mod m2 {
15+
pub trait InScope2 {
16+
fn in_scope2(&self) {}
17+
}
18+
impl InScope2 for () {}
19+
}
20+
21+
pub use m1::InScope1 as _;
22+
pub use m2::InScope2 as _;

src/test/ui/rfc-2166-underscore-imports/basic.rs

+6
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,16 @@
99
// except according to those terms.
1010

1111
// compile-pass
12+
// aux-build:underscore-imports.rs
1213

1314
#![feature(underscore_imports)]
1415
#![warn(unused_imports, unused_extern_crates)]
1516

17+
#[macro_use]
18+
extern crate underscore_imports as _;
19+
20+
do_nothing!(); // OK
21+
1622
struct S;
1723

1824
mod m {

src/test/ui/rfc-2166-underscore-imports/basic.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
warning: unused import: `m::Tr1 as _`
2-
--> $DIR/basic.rs:31:9
2+
--> $DIR/basic.rs:37:9
33
|
44
LL | use m::Tr1 as _; //~ WARN unused import
55
| ^^^^^^^^^^^
66
|
77
note: lint level defined here
8-
--> $DIR/basic.rs:14:9
8+
--> $DIR/basic.rs:15:9
99
|
1010
LL | #![warn(unused_imports, unused_extern_crates)]
1111
| ^^^^^^^^^^^^^^
1212

1313
warning: unused import: `S as _`
14-
--> $DIR/basic.rs:32:9
14+
--> $DIR/basic.rs:38:9
1515
|
1616
LL | use S as _; //~ WARN unused import
1717
| ^^^^^^
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// compile-pass
2+
// aux-build:duplicate.rs
3+
4+
#![feature(underscore_imports)]
5+
6+
extern crate duplicate;
7+
8+
#[duplicate::duplicate]
9+
use main as _; // OK
10+
11+
macro_rules! duplicate {
12+
($item: item) => { $item $item }
13+
}
14+
15+
duplicate!(use std as _;); // OK
16+
17+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// compile-pass
2+
// aux-build:underscore-imports.rs
3+
4+
extern crate underscore_imports;
5+
6+
use underscore_imports::*;
7+
8+
fn main() {
9+
().in_scope1();
10+
().in_scope2();
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// edition:2018
2+
3+
#![feature(underscore_imports)]
4+
#![deny(unused_imports)]
5+
6+
mod multi_segment {
7+
use core::any; //~ ERROR unused import: `core::any`
8+
}
9+
10+
mod single_segment {
11+
use core; //~ ERROR unused import: `core`
12+
}
13+
14+
mod single_segment_underscore {
15+
use core as _; // OK
16+
}
17+
18+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: unused import: `core::any`
2+
--> $DIR/unused-2018.rs:7:9
3+
|
4+
LL | use core::any; //~ ERROR unused import: `core::any`
5+
| ^^^^^^^^^
6+
|
7+
note: lint level defined here
8+
--> $DIR/unused-2018.rs:4:9
9+
|
10+
LL | #![deny(unused_imports)]
11+
| ^^^^^^^^^^^^^^
12+
13+
error: unused import: `core`
14+
--> $DIR/unused-2018.rs:11:9
15+
|
16+
LL | use core; //~ ERROR unused import: `core`
17+
| ^^^^
18+
19+
error: aborting due to 2 previous errors
20+

0 commit comments

Comments
 (0)