From 90f5cfdfbd3c9e39f897fd2271c7b1c7fdaae58e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 19 Nov 2017 17:05:29 +0300 Subject: [PATCH] Report special messages for path segment keywords in wrong positions --- src/librustc_resolve/lib.rs | 36 +++++++++++++++---- src/librustc_resolve/resolve_imports.rs | 10 ++++-- .../compile-fail/dollar-crate-is-keyword-2.rs | 4 +-- .../crate-path-non-absolute.rs | 2 +- .../crate-visibility-ambiguity.rs | 2 +- .../keyword-crate-as-identifier.rs | 2 +- src/test/compile-fail/super-at-top-level.rs | 3 +- .../compile-fail/use-super-global-path.rs | 6 ++-- 8 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 5cf09d0d89aa..42c31a6e47ea 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2865,12 +2865,13 @@ impl<'a> Resolver<'a> { debug!("resolve_path ident {} {:?}", i, ident); let is_last = i == path.len() - 1; let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; + let name = ident.node.name; - if i == 0 && ns == TypeNS && ident.node.name == keywords::SelfValue.name() { + if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() { let mut ctxt = ident.node.ctxt.modern(); module = Some(self.resolve_self(&mut ctxt, self.current_module)); continue - } else if allow_super && ns == TypeNS && ident.node.name == keywords::Super.name() { + } else if allow_super && ns == TypeNS && name == keywords::Super.name() { let mut ctxt = ident.node.ctxt.modern(); let self_module = match i { 0 => self.resolve_self(&mut ctxt, self.current_module), @@ -2887,19 +2888,42 @@ impl<'a> Resolver<'a> { allow_super = false; if ns == TypeNS { - if (i == 0 && ident.node.name == keywords::CrateRoot.name()) || - (i == 1 && ident.node.name == keywords::Crate.name() && + if (i == 0 && name == keywords::CrateRoot.name()) || + (i == 1 && name == keywords::Crate.name() && path[0].node.name == keywords::CrateRoot.name()) { // `::a::b` or `::crate::a::b` module = Some(self.resolve_crate_root(ident.node.ctxt.modern())); continue - } else if i == 0 && ident.node.name == keywords::DollarCrate.name() { + } else if i == 0 && name == keywords::DollarCrate.name() { // `$crate::a::b` module = Some(self.resolve_crate_root(ident.node.ctxt)); continue } } + // Report special messages for path segment keywords in wrong positions. + if name == keywords::CrateRoot.name() && i != 0 || + name == keywords::DollarCrate.name() && i != 0 || + name == keywords::SelfValue.name() && i != 0 || + name == keywords::SelfType.name() && i != 0 || + name == keywords::Super.name() && i != 0 || + name == keywords::Crate.name() && i != 1 && + path[0].node.name != keywords::CrateRoot.name() { + let name_str = if name == keywords::CrateRoot.name() { + format!("crate root") + } else { + format!("`{}`", name) + }; + let msg = if i == 1 && path[0].node.name == keywords::CrateRoot.name() { + format!("global paths cannot start with {}", name_str) + } else if i == 0 && name == keywords::Crate.name() { + format!("{} can only be used in absolute paths", name_str) + } else { + format!("{} in paths can only be used in start position", name_str) + }; + return PathResult::Failed(ident.span, msg, false); + } + let binding = if let Some(module) = module { self.resolve_ident_in_module(module, ident.node, ns, false, record_used, path_span) } else if opt_ns == Some(MacroNS) { @@ -2948,7 +2972,7 @@ impl<'a> Resolver<'a> { let msg = if module.and_then(ModuleData::def) == self.graph_root.def() { let is_mod = |def| match def { Def::Mod(..) => true, _ => false }; let mut candidates = - self.lookup_import_candidates(ident.node.name, TypeNS, is_mod); + self.lookup_import_candidates(name, TypeNS, is_mod); candidates.sort_by_key(|c| (c.path.segments.len(), c.path.to_string())); if let Some(candidate) = candidates.get(0) { format!("Did you mean `{}`?", candidate.path) diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index bcbabd700946..d72253e5a8a4 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -606,10 +606,16 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let module_result = self.resolve_path(&module_path, None, true, span); let module = match module_result { PathResult::Module(module) => module, - PathResult::Failed(span, msg, _) => { + PathResult::Failed(span, msg, false) => { + resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); + return None; + } + PathResult::Failed(span, msg, true) => { let (mut self_path, mut self_result) = (module_path.clone(), None); if !self_path.is_empty() && - !token::Ident(self_path[0].node).is_path_segment_keyword() + !token::Ident(self_path[0].node).is_path_segment_keyword() && + !(self_path.len() > 1 && + token::Ident(self_path[1].node).is_path_segment_keyword()) { self_path[0].node.name = keywords::SelfValue.name(); self_result = Some(self.resolve_path(&self_path, None, false, span)); diff --git a/src/test/compile-fail/dollar-crate-is-keyword-2.rs b/src/test/compile-fail/dollar-crate-is-keyword-2.rs index ac96279d6146..87a290380358 100644 --- a/src/test/compile-fail/dollar-crate-is-keyword-2.rs +++ b/src/test/compile-fail/dollar-crate-is-keyword-2.rs @@ -13,8 +13,8 @@ mod a {} macro_rules! m { () => { use a::$crate; //~ ERROR unresolved import `a::$crate` - use a::$crate::b; //~ ERROR unresolved import `a::$crate` - type A = a::$crate; //~ ERROR cannot find type `$crate` in module `a` + use a::$crate::b; //~ ERROR `$crate` in paths can only be used in start position + type A = a::$crate; //~ ERROR `$crate` in paths can only be used in start position } } diff --git a/src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs b/src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs index 11841e6e3efb..75c2a5f5bc47 100644 --- a/src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs +++ b/src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs @@ -14,7 +14,7 @@ struct S; mod m { fn f() { - let s = crate::S; //~ ERROR undeclared type or module `crate` + let s = crate::S; //~ ERROR `crate` can only be used in absolute paths } } diff --git a/src/test/compile-fail/rfc-2126-crate-paths/crate-visibility-ambiguity.rs b/src/test/compile-fail/rfc-2126-crate-paths/crate-visibility-ambiguity.rs index cb587ecc8545..8c5a971c2f75 100644 --- a/src/test/compile-fail/rfc-2126-crate-paths/crate-visibility-ambiguity.rs +++ b/src/test/compile-fail/rfc-2126-crate-paths/crate-visibility-ambiguity.rs @@ -15,7 +15,7 @@ mod m { pub struct Z; pub struct S1(crate (::m::Z)); // OK pub struct S2(::crate ::m::Z); // OK - pub struct S3(crate ::m::Z); //~ ERROR undeclared type or module `crate` + pub struct S3(crate ::m::Z); //~ ERROR `crate` can only be used in absolute paths } fn main() { diff --git a/src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs b/src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs index b4a650efebe3..2c94f7b0f59d 100644 --- a/src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs +++ b/src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs @@ -11,5 +11,5 @@ #![feature(crate_in_paths)] fn main() { - let crate = 0; //~ ERROR cannot find unit struct/variant or constant `crate` in this scope + let crate = 0; //~ ERROR `crate` can only be used in absolute paths } diff --git a/src/test/compile-fail/super-at-top-level.rs b/src/test/compile-fail/super-at-top-level.rs index 4db673e2006f..c607711c44f3 100644 --- a/src/test/compile-fail/super-at-top-level.rs +++ b/src/test/compile-fail/super-at-top-level.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::f; //~ ERROR unresolved import `super` [E0432] - //~^ There are too many initial `super`s. +use super::f; //~ ERROR There are too many initial `super`s fn main() { } diff --git a/src/test/compile-fail/use-super-global-path.rs b/src/test/compile-fail/use-super-global-path.rs index 24d3bccdf24e..fc1a72f6f2b9 100644 --- a/src/test/compile-fail/use-super-global-path.rs +++ b/src/test/compile-fail/use-super-global-path.rs @@ -14,11 +14,11 @@ struct S; struct Z; mod foo { - use ::super::{S, Z}; //~ ERROR unresolved import `super` + use ::super::{S, Z}; //~ ERROR global paths cannot start with `super` pub fn g() { - use ::super::main; //~ ERROR unresolved import `super` - main(); + use ::super::main; //~ ERROR global paths cannot start with `super` + main(); //~ ERROR cannot find function `main` in this scope } }