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 _`
This commit is contained in:
parent
c658d73401
commit
2d4b633be3
16 changed files with 157 additions and 36 deletions
|
@ -157,7 +157,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
};
|
||||
match use_tree.kind {
|
||||
ast::UseTreeKind::Simple(rename, ..) => {
|
||||
let mut ident = use_tree.ident();
|
||||
let mut ident = use_tree.ident().gensym_if_underscore();
|
||||
let mut module_path = prefix;
|
||||
let mut source = module_path.pop().unwrap();
|
||||
let mut type_ns_only = false;
|
||||
|
@ -334,7 +334,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScope<'a>) {
|
||||
let parent = parent_scope.module;
|
||||
let expansion = parent_scope.expansion;
|
||||
let ident = item.ident;
|
||||
let ident = item.ident.gensym_if_underscore();
|
||||
let sp = item.span;
|
||||
let vis = self.resolve_visibility(&item.vis);
|
||||
|
||||
|
@ -628,7 +628,11 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||
|
||||
/// Builds the reduced graph for a single item in an external crate.
|
||||
fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) {
|
||||
let Export { ident, def, vis, span, .. } = child;
|
||||
let Export { ident, def, vis, span } = child;
|
||||
// FIXME: We shouldn't create the gensym here, it should come from metadata,
|
||||
// but metadata cannot encode gensyms currently, so we create it here.
|
||||
// This is only a guess, two equivalent idents may incorrectly get different gensyms here.
|
||||
let ident = ident.gensym_if_underscore();
|
||||
let def_id = def.def_id();
|
||||
let expansion = Mark::root(); // FIXME(jseyfried) intercrate hygiene
|
||||
match def {
|
||||
|
|
|
@ -888,9 +888,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
|||
PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(),
|
||||
};
|
||||
|
||||
let (ident, source_bindings, target_bindings, type_ns_only) = match directive.subclass {
|
||||
SingleImport { source, ref source_bindings, ref target_bindings, type_ns_only, .. } =>
|
||||
(source, source_bindings, target_bindings, type_ns_only),
|
||||
let (ident, target, source_bindings, target_bindings, type_ns_only) =
|
||||
match directive.subclass {
|
||||
SingleImport { source, target, ref source_bindings,
|
||||
ref target_bindings, type_ns_only } =>
|
||||
(source, target, source_bindings, target_bindings, type_ns_only),
|
||||
GlobImport { is_prelude, ref max_vis } => {
|
||||
if directive.module_path.len() <= 1 {
|
||||
// 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> {
|
|||
// Consistency checks, analogous to `finalize_current_module_macro_resolutions`.
|
||||
let initial_def = source_bindings[ns].get().map(|initial_binding| {
|
||||
all_ns_err = false;
|
||||
this.record_use(ident, ns, initial_binding,
|
||||
directive.module_path.is_empty());
|
||||
if target.name == "_" &&
|
||||
initial_binding.is_extern_crate() && !initial_binding.is_import() {
|
||||
this.used_imports.insert((directive.id, TypeNS));
|
||||
}
|
||||
initial_binding.def_ignoring_ambiguity()
|
||||
});
|
||||
let def = binding.def_ignoring_ambiguity();
|
||||
|
|
|
@ -2017,6 +2017,17 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> {
|
||||
match self.token {
|
||||
token::Ident(ident, false) if ident.name == keywords::Underscore.name() => {
|
||||
let span = self.span;
|
||||
self.bump();
|
||||
Ok(Ident::new(ident.name, span))
|
||||
}
|
||||
_ => self.parse_ident(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses qualified path.
|
||||
/// Assumes that the leading `<` has been parsed already.
|
||||
///
|
||||
|
@ -6435,13 +6446,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> {
|
||||
let id = match self.token {
|
||||
token::Ident(ident, false) if ident.name == keywords::Underscore.name() => {
|
||||
self.bump(); // `_`
|
||||
ident.gensym()
|
||||
},
|
||||
_ => self.parse_ident()?,
|
||||
};
|
||||
let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?;
|
||||
self.expect(&token::Colon)?;
|
||||
let ty = self.parse_ty()?;
|
||||
self.expect(&token::Eq)?;
|
||||
|
@ -7726,13 +7731,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
|
||||
if self.eat_keyword(keywords::As) {
|
||||
match self.token {
|
||||
token::Ident(ident, false) if ident.name == keywords::Underscore.name() => {
|
||||
self.bump(); // `_`
|
||||
Ok(Some(ident.gensym()))
|
||||
}
|
||||
_ => self.parse_ident().map(Some),
|
||||
}
|
||||
self.parse_ident_or_underscore().map(Some)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
|
|
|
@ -80,6 +80,10 @@ impl Ident {
|
|||
Ident::new(self.name.gensymed(), self.span)
|
||||
}
|
||||
|
||||
pub fn gensym_if_underscore(self) -> Ident {
|
||||
if self.name == keywords::Underscore.name() { self.gensym() } else { self }
|
||||
}
|
||||
|
||||
pub fn as_str(self) -> LocalInternedString {
|
||||
self.name.as_str()
|
||||
}
|
||||
|
@ -465,7 +469,7 @@ impl Ident {
|
|||
// We see this identifier in a normal identifier position, like variable name or a type.
|
||||
// How was it written originally? Did it use the raw form? Let's try to guess.
|
||||
pub fn is_raw_guess(self) -> bool {
|
||||
self.name != keywords::Invalid.name() &&
|
||||
self.name != keywords::Invalid.name() && self.name != keywords::Underscore.name() &&
|
||||
self.is_reserved() && !self.is_path_segment_keyword()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,5 @@
|
|||
// except according to those terms.
|
||||
|
||||
const _: () = (); //~ ERROR is unstable
|
||||
static _: () = (); //~ ERROR is unstable
|
||||
|
||||
fn main() {}
|
|
@ -6,14 +6,6 @@ LL | const _: () = (); //~ ERROR is unstable
|
|||
|
|
||||
= help: add #![feature(underscore_const_names)] to the crate attributes to enable
|
||||
|
||||
error[E0658]: naming constants with `_` is unstable (see issue #54912)
|
||||
--> $DIR/underscore_const_names_feature_gate.rs:12:1
|
||||
|
|
||||
LL | static _: () = (); //~ ERROR is unstable
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add #![feature(underscore_const_names)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
3
src/test/ui/parser/underscore_static.rs
Normal file
3
src/test/ui/parser/underscore_static.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
// compile-flags: -Z parse-only
|
||||
|
||||
static _: () = (); //~ ERROR expected identifier, found reserved identifier `_`
|
8
src/test/ui/parser/underscore_static.stderr
Normal file
8
src/test/ui/parser/underscore_static.stderr
Normal file
|
@ -0,0 +1,8 @@
|
|||
error: expected identifier, found reserved identifier `_`
|
||||
--> $DIR/underscore_static.rs:3:8
|
||||
|
|
||||
LL | static _: () = (); //~ ERROR expected identifier, found reserved identifier `_`
|
||||
| ^ expected identifier, found reserved identifier
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// force-host
|
||||
// no-prefer-dynamic
|
||||
|
||||
#![crate_type = "proc-macro"]
|
||||
|
||||
extern crate proc_macro;
|
||||
|
||||
use proc_macro::*;
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn duplicate(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let clone = input.clone();
|
||||
input.into_iter().chain(clone.into_iter()).collect()
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#![feature(underscore_imports)]
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! do_nothing {
|
||||
() => ()
|
||||
}
|
||||
|
||||
mod m1 {
|
||||
pub trait InScope1 {
|
||||
fn in_scope1(&self) {}
|
||||
}
|
||||
impl InScope1 for () {}
|
||||
}
|
||||
mod m2 {
|
||||
pub trait InScope2 {
|
||||
fn in_scope2(&self) {}
|
||||
}
|
||||
impl InScope2 for () {}
|
||||
}
|
||||
|
||||
pub use m1::InScope1 as _;
|
||||
pub use m2::InScope2 as _;
|
|
@ -9,10 +9,16 @@
|
|||
// except according to those terms.
|
||||
|
||||
// compile-pass
|
||||
// aux-build:underscore-imports.rs
|
||||
|
||||
#![feature(underscore_imports)]
|
||||
#![warn(unused_imports, unused_extern_crates)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate underscore_imports as _;
|
||||
|
||||
do_nothing!(); // OK
|
||||
|
||||
struct S;
|
||||
|
||||
mod m {
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
warning: unused import: `m::Tr1 as _`
|
||||
--> $DIR/basic.rs:31:9
|
||||
--> $DIR/basic.rs:37:9
|
||||
|
|
||||
LL | use m::Tr1 as _; //~ WARN unused import
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/basic.rs:14:9
|
||||
--> $DIR/basic.rs:15:9
|
||||
|
|
||||
LL | #![warn(unused_imports, unused_extern_crates)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `S as _`
|
||||
--> $DIR/basic.rs:32:9
|
||||
--> $DIR/basic.rs:38:9
|
||||
|
|
||||
LL | use S as _; //~ WARN unused import
|
||||
| ^^^^^^
|
||||
|
|
17
src/test/ui/rfc-2166-underscore-imports/duplicate.rs
Normal file
17
src/test/ui/rfc-2166-underscore-imports/duplicate.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
// compile-pass
|
||||
// aux-build:duplicate.rs
|
||||
|
||||
#![feature(underscore_imports)]
|
||||
|
||||
extern crate duplicate;
|
||||
|
||||
#[duplicate::duplicate]
|
||||
use main as _; // OK
|
||||
|
||||
macro_rules! duplicate {
|
||||
($item: item) => { $item $item }
|
||||
}
|
||||
|
||||
duplicate!(use std as _;); // OK
|
||||
|
||||
fn main() {}
|
11
src/test/ui/rfc-2166-underscore-imports/intercrate.rs
Normal file
11
src/test/ui/rfc-2166-underscore-imports/intercrate.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
// compile-pass
|
||||
// aux-build:underscore-imports.rs
|
||||
|
||||
extern crate underscore_imports;
|
||||
|
||||
use underscore_imports::*;
|
||||
|
||||
fn main() {
|
||||
().in_scope1();
|
||||
().in_scope2();
|
||||
}
|
18
src/test/ui/rfc-2166-underscore-imports/unused-2018.rs
Normal file
18
src/test/ui/rfc-2166-underscore-imports/unused-2018.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
// edition:2018
|
||||
|
||||
#![feature(underscore_imports)]
|
||||
#![deny(unused_imports)]
|
||||
|
||||
mod multi_segment {
|
||||
use core::any; //~ ERROR unused import: `core::any`
|
||||
}
|
||||
|
||||
mod single_segment {
|
||||
use core; //~ ERROR unused import: `core`
|
||||
}
|
||||
|
||||
mod single_segment_underscore {
|
||||
use core as _; // OK
|
||||
}
|
||||
|
||||
fn main() {}
|
20
src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr
Normal file
20
src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr
Normal file
|
@ -0,0 +1,20 @@
|
|||
error: unused import: `core::any`
|
||||
--> $DIR/unused-2018.rs:7:9
|
||||
|
|
||||
LL | use core::any; //~ ERROR unused import: `core::any`
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/unused-2018.rs:4:9
|
||||
|
|
||||
LL | #![deny(unused_imports)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused import: `core`
|
||||
--> $DIR/unused-2018.rs:11:9
|
||||
|
|
||||
LL | use core; //~ ERROR unused import: `core`
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue