Skip to content

Commit 90f5cfd

Browse files
committed
Report special messages for path segment keywords in wrong positions
1 parent 2e9b89d commit 90f5cfd

8 files changed

+47
-18
lines changed

src/librustc_resolve/lib.rs

+30-6
Original file line numberDiff line numberDiff line change
@@ -2865,12 +2865,13 @@ impl<'a> Resolver<'a> {
28652865
debug!("resolve_path ident {} {:?}", i, ident);
28662866
let is_last = i == path.len() - 1;
28672867
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
2868+
let name = ident.node.name;
28682869

2869-
if i == 0 && ns == TypeNS && ident.node.name == keywords::SelfValue.name() {
2870+
if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() {
28702871
let mut ctxt = ident.node.ctxt.modern();
28712872
module = Some(self.resolve_self(&mut ctxt, self.current_module));
28722873
continue
2873-
} else if allow_super && ns == TypeNS && ident.node.name == keywords::Super.name() {
2874+
} else if allow_super && ns == TypeNS && name == keywords::Super.name() {
28742875
let mut ctxt = ident.node.ctxt.modern();
28752876
let self_module = match i {
28762877
0 => self.resolve_self(&mut ctxt, self.current_module),
@@ -2887,19 +2888,42 @@ impl<'a> Resolver<'a> {
28872888
allow_super = false;
28882889

28892890
if ns == TypeNS {
2890-
if (i == 0 && ident.node.name == keywords::CrateRoot.name()) ||
2891-
(i == 1 && ident.node.name == keywords::Crate.name() &&
2891+
if (i == 0 && name == keywords::CrateRoot.name()) ||
2892+
(i == 1 && name == keywords::Crate.name() &&
28922893
path[0].node.name == keywords::CrateRoot.name()) {
28932894
// `::a::b` or `::crate::a::b`
28942895
module = Some(self.resolve_crate_root(ident.node.ctxt.modern()));
28952896
continue
2896-
} else if i == 0 && ident.node.name == keywords::DollarCrate.name() {
2897+
} else if i == 0 && name == keywords::DollarCrate.name() {
28972898
// `$crate::a::b`
28982899
module = Some(self.resolve_crate_root(ident.node.ctxt));
28992900
continue
29002901
}
29012902
}
29022903

2904+
// Report special messages for path segment keywords in wrong positions.
2905+
if name == keywords::CrateRoot.name() && i != 0 ||
2906+
name == keywords::DollarCrate.name() && i != 0 ||
2907+
name == keywords::SelfValue.name() && i != 0 ||
2908+
name == keywords::SelfType.name() && i != 0 ||
2909+
name == keywords::Super.name() && i != 0 ||
2910+
name == keywords::Crate.name() && i != 1 &&
2911+
path[0].node.name != keywords::CrateRoot.name() {
2912+
let name_str = if name == keywords::CrateRoot.name() {
2913+
format!("crate root")
2914+
} else {
2915+
format!("`{}`", name)
2916+
};
2917+
let msg = if i == 1 && path[0].node.name == keywords::CrateRoot.name() {
2918+
format!("global paths cannot start with {}", name_str)
2919+
} else if i == 0 && name == keywords::Crate.name() {
2920+
format!("{} can only be used in absolute paths", name_str)
2921+
} else {
2922+
format!("{} in paths can only be used in start position", name_str)
2923+
};
2924+
return PathResult::Failed(ident.span, msg, false);
2925+
}
2926+
29032927
let binding = if let Some(module) = module {
29042928
self.resolve_ident_in_module(module, ident.node, ns, false, record_used, path_span)
29052929
} else if opt_ns == Some(MacroNS) {
@@ -2948,7 +2972,7 @@ impl<'a> Resolver<'a> {
29482972
let msg = if module.and_then(ModuleData::def) == self.graph_root.def() {
29492973
let is_mod = |def| match def { Def::Mod(..) => true, _ => false };
29502974
let mut candidates =
2951-
self.lookup_import_candidates(ident.node.name, TypeNS, is_mod);
2975+
self.lookup_import_candidates(name, TypeNS, is_mod);
29522976
candidates.sort_by_key(|c| (c.path.segments.len(), c.path.to_string()));
29532977
if let Some(candidate) = candidates.get(0) {
29542978
format!("Did you mean `{}`?", candidate.path)

src/librustc_resolve/resolve_imports.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -606,10 +606,16 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
606606
let module_result = self.resolve_path(&module_path, None, true, span);
607607
let module = match module_result {
608608
PathResult::Module(module) => module,
609-
PathResult::Failed(span, msg, _) => {
609+
PathResult::Failed(span, msg, false) => {
610+
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
611+
return None;
612+
}
613+
PathResult::Failed(span, msg, true) => {
610614
let (mut self_path, mut self_result) = (module_path.clone(), None);
611615
if !self_path.is_empty() &&
612-
!token::Ident(self_path[0].node).is_path_segment_keyword()
616+
!token::Ident(self_path[0].node).is_path_segment_keyword() &&
617+
!(self_path.len() > 1 &&
618+
token::Ident(self_path[1].node).is_path_segment_keyword())
613619
{
614620
self_path[0].node.name = keywords::SelfValue.name();
615621
self_result = Some(self.resolve_path(&self_path, None, false, span));

src/test/compile-fail/dollar-crate-is-keyword-2.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ mod a {}
1313
macro_rules! m {
1414
() => {
1515
use a::$crate; //~ ERROR unresolved import `a::$crate`
16-
use a::$crate::b; //~ ERROR unresolved import `a::$crate`
17-
type A = a::$crate; //~ ERROR cannot find type `$crate` in module `a`
16+
use a::$crate::b; //~ ERROR `$crate` in paths can only be used in start position
17+
type A = a::$crate; //~ ERROR `$crate` in paths can only be used in start position
1818
}
1919
}
2020

src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ struct S;
1414

1515
mod m {
1616
fn f() {
17-
let s = crate::S; //~ ERROR undeclared type or module `crate`
17+
let s = crate::S; //~ ERROR `crate` can only be used in absolute paths
1818
}
1919
}
2020

src/test/compile-fail/rfc-2126-crate-paths/crate-visibility-ambiguity.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ mod m {
1515
pub struct Z;
1616
pub struct S1(crate (::m::Z)); // OK
1717
pub struct S2(::crate ::m::Z); // OK
18-
pub struct S3(crate ::m::Z); //~ ERROR undeclared type or module `crate`
18+
pub struct S3(crate ::m::Z); //~ ERROR `crate` can only be used in absolute paths
1919
}
2020

2121
fn main() {

src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
#![feature(crate_in_paths)]
1212

1313
fn main() {
14-
let crate = 0; //~ ERROR cannot find unit struct/variant or constant `crate` in this scope
14+
let crate = 0; //~ ERROR `crate` can only be used in absolute paths
1515
}

src/test/compile-fail/super-at-top-level.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use super::f; //~ ERROR unresolved import `super` [E0432]
12-
//~^ There are too many initial `super`s.
11+
use super::f; //~ ERROR There are too many initial `super`s
1312

1413
fn main() {
1514
}

src/test/compile-fail/use-super-global-path.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ struct S;
1414
struct Z;
1515

1616
mod foo {
17-
use ::super::{S, Z}; //~ ERROR unresolved import `super`
17+
use ::super::{S, Z}; //~ ERROR global paths cannot start with `super`
1818

1919
pub fn g() {
20-
use ::super::main; //~ ERROR unresolved import `super`
21-
main();
20+
use ::super::main; //~ ERROR global paths cannot start with `super`
21+
main(); //~ ERROR cannot find function `main` in this scope
2222
}
2323
}
2424

0 commit comments

Comments
 (0)