Skip to content

Commit a70e42a

Browse files
committed
Remove use of ast_map.expect_item() and improve diagnostics (fixes #33186)
1 parent 5a4e0b1 commit a70e42a

File tree

2 files changed

+49
-46
lines changed

2 files changed

+49
-46
lines changed

src/librustc_resolve/lib.rs

+41-42
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ use rustc::hir::intravisit::{self, FnKind, Visitor};
6868
use rustc::hir;
6969
use rustc::hir::{Arm, BindByRef, BindByValue, BindingMode, Block};
7070
use rustc::hir::Crate;
71-
use rustc::hir::{Expr, ExprAgain, ExprBreak, ExprCall, ExprField};
71+
use rustc::hir::{Expr, ExprAgain, ExprBreak, ExprField};
7272
use rustc::hir::{ExprLoop, ExprWhile, ExprMethodCall};
7373
use rustc::hir::{ExprPath, ExprStruct, FnDecl};
7474
use rustc::hir::{ForeignItemFn, ForeignItemStatic, Generics};
@@ -163,7 +163,7 @@ enum ResolutionError<'a> {
163163
/// error E0424: `self` is not available in a static method
164164
SelfNotAvailableInStaticMethod,
165165
/// error E0425: unresolved name
166-
UnresolvedName(&'a str, &'a str, UnresolvedNameContext),
166+
UnresolvedName(&'a str, &'a str, UnresolvedNameContext<'a>),
167167
/// error E0426: use of undeclared label
168168
UndeclaredLabel(&'a str),
169169
/// error E0427: cannot use `ref` binding mode with ...
@@ -186,12 +186,12 @@ enum ResolutionError<'a> {
186186

187187
/// Context of where `ResolutionError::UnresolvedName` arose.
188188
#[derive(Clone, PartialEq, Eq, Debug)]
189-
enum UnresolvedNameContext {
190-
/// `PathIsMod(id)` indicates that a given path, used in
189+
enum UnresolvedNameContext<'a> {
190+
/// `PathIsMod(parent)` indicates that a given path, used in
191191
/// expression context, actually resolved to a module rather than
192-
/// a value. The `id` attached to the variant is the node id of
193-
/// the erroneous path expression.
194-
PathIsMod(ast::NodeId),
192+
/// a value. The optional expression attached to the variant is the
193+
/// the parent of the erroneous path expression.
194+
PathIsMod(Option<&'a Expr>),
195195

196196
/// `Other` means we have no extra information about the context
197197
/// of the unresolved name error. (Maybe we could eliminate all
@@ -419,39 +419,25 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
419419

420420
match context {
421421
UnresolvedNameContext::Other => { } // no help available
422-
UnresolvedNameContext::PathIsMod(id) => {
423-
let mut help_msg = String::new();
424-
let parent_id = resolver.ast_map.get_parent_node(id);
425-
if let Some(hir_map::Node::NodeExpr(e)) = resolver.ast_map.find(parent_id) {
426-
match e.node {
427-
ExprField(_, ident) => {
428-
help_msg = format!("To reference an item from the \
429-
`{module}` module, use \
430-
`{module}::{ident}`",
431-
module = path,
432-
ident = ident.node);
433-
}
434-
ExprMethodCall(ident, _, _) => {
435-
help_msg = format!("To call a function from the \
436-
`{module}` module, use \
437-
`{module}::{ident}(..)`",
438-
module = path,
439-
ident = ident.node);
440-
}
441-
ExprCall(_, _) => {
442-
help_msg = format!("No function corresponds to `{module}(..)`",
443-
module = path);
444-
}
445-
_ => { } // no help available
422+
UnresolvedNameContext::PathIsMod(parent) => {
423+
err.fileline_help(span, &match parent.map(|parent| &parent.node) {
424+
Some(&ExprField(_, ident)) => {
425+
format!("To reference an item from the `{module}` module, \
426+
use `{module}::{ident}`",
427+
module = path,
428+
ident = ident.node)
446429
}
447-
} else {
448-
help_msg = format!("Module `{module}` cannot be the value of an expression",
449-
module = path);
450-
}
451-
452-
if !help_msg.is_empty() {
453-
err.fileline_help(span, &help_msg);
454-
}
430+
Some(&ExprMethodCall(ident, _, _)) => {
431+
format!("To call a function from the `{module}` module, \
432+
use `{module}::{ident}(..)`",
433+
module = path,
434+
ident = ident.node)
435+
}
436+
_ => {
437+
format!("Module `{module}` cannot be used as an expression",
438+
module = path)
439+
}
440+
});
455441
}
456442
}
457443
err
@@ -553,7 +539,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
553539
self.resolve_block(block);
554540
}
555541
fn visit_expr(&mut self, expr: &Expr) {
556-
self.resolve_expr(expr);
542+
self.resolve_expr(expr, None);
557543
}
558544
fn visit_local(&mut self, local: &Local) {
559545
self.resolve_local(local);
@@ -2850,7 +2836,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
28502836
} SuggestionType::NotFound
28512837
}
28522838

2853-
fn resolve_expr(&mut self, expr: &Expr) {
2839+
fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
28542840
// First, record candidate traits for this expression if it could
28552841
// result in the invocation of a method call.
28562842

@@ -2995,7 +2981,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
29952981
UseLexicalScope,
29962982
expr.span) {
29972983
Success(_) => {
2998-
context = UnresolvedNameContext::PathIsMod(expr.id);
2984+
context = UnresolvedNameContext::PathIsMod(parent);
29992985
},
30002986
_ => {},
30012987
};
@@ -3069,6 +3055,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
30693055
}
30703056
}
30713057
}
3058+
ExprField(ref subexpression, _) => {
3059+
self.resolve_expr(subexpression, Some(expr));
3060+
}
3061+
ExprMethodCall(_, ref types, ref arguments) => {
3062+
let mut arguments = arguments.iter();
3063+
self.resolve_expr(arguments.next().unwrap(), Some(expr));
3064+
for argument in arguments {
3065+
self.resolve_expr(argument, None);
3066+
}
3067+
for ty in types.iter() {
3068+
self.visit_ty(ty);
3069+
}
3070+
}
30723071

30733072
_ => {
30743073
intravisit::walk_expr(self, expr);

src/test/compile-fail/suggest-path-instead-of-mod-dot-item.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,14 @@ fn h4() -> i32 {
4747
//~| HELP To reference an item from the `a::b` module, use `a::b::J`
4848
}
4949

50-
fn h5() -> i32 {
51-
a.b.f()
50+
fn h5() {
51+
a.b.f();
5252
//~^ ERROR E0425
5353
//~| HELP To reference an item from the `a` module, use `a::b`
54+
let v = Vec::new();
55+
v.push(a::b);
56+
//~^ ERROR E0425
57+
//~| HELP Module `a::b` cannot be used as an expression
5458
}
5559

5660
fn h6() -> i32 {
@@ -62,11 +66,11 @@ fn h6() -> i32 {
6266
fn h7() {
6367
a::b
6468
//~^ ERROR E0425
65-
//~| HELP Module `a::b` cannot be the value of an expression
69+
//~| HELP Module `a::b` cannot be used as an expression
6670
}
6771

6872
fn h8() -> i32 {
6973
a::b()
7074
//~^ ERROR E0425
71-
//~| HELP No function corresponds to `a::b(..)`
75+
//~| HELP Module `a::b` cannot be used as an expression
7276
}

0 commit comments

Comments
 (0)