1
Fork 0

Remove use of ast_map.expect_item() and improve diagnostics (fixes #33186)

This commit is contained in:
Jeffrey Seyfried 2016-04-24 21:10:54 +00:00
parent 5a4e0b14e3
commit a70e42a953
2 changed files with 49 additions and 46 deletions

View file

@ -68,7 +68,7 @@ use rustc::hir::intravisit::{self, FnKind, Visitor};
use rustc::hir; use rustc::hir;
use rustc::hir::{Arm, BindByRef, BindByValue, BindingMode, Block}; use rustc::hir::{Arm, BindByRef, BindByValue, BindingMode, Block};
use rustc::hir::Crate; use rustc::hir::Crate;
use rustc::hir::{Expr, ExprAgain, ExprBreak, ExprCall, ExprField}; use rustc::hir::{Expr, ExprAgain, ExprBreak, ExprField};
use rustc::hir::{ExprLoop, ExprWhile, ExprMethodCall}; use rustc::hir::{ExprLoop, ExprWhile, ExprMethodCall};
use rustc::hir::{ExprPath, ExprStruct, FnDecl}; use rustc::hir::{ExprPath, ExprStruct, FnDecl};
use rustc::hir::{ForeignItemFn, ForeignItemStatic, Generics}; use rustc::hir::{ForeignItemFn, ForeignItemStatic, Generics};
@ -163,7 +163,7 @@ enum ResolutionError<'a> {
/// error E0424: `self` is not available in a static method /// error E0424: `self` is not available in a static method
SelfNotAvailableInStaticMethod, SelfNotAvailableInStaticMethod,
/// error E0425: unresolved name /// error E0425: unresolved name
UnresolvedName(&'a str, &'a str, UnresolvedNameContext), UnresolvedName(&'a str, &'a str, UnresolvedNameContext<'a>),
/// error E0426: use of undeclared label /// error E0426: use of undeclared label
UndeclaredLabel(&'a str), UndeclaredLabel(&'a str),
/// error E0427: cannot use `ref` binding mode with ... /// error E0427: cannot use `ref` binding mode with ...
@ -186,12 +186,12 @@ enum ResolutionError<'a> {
/// Context of where `ResolutionError::UnresolvedName` arose. /// Context of where `ResolutionError::UnresolvedName` arose.
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
enum UnresolvedNameContext { enum UnresolvedNameContext<'a> {
/// `PathIsMod(id)` indicates that a given path, used in /// `PathIsMod(parent)` indicates that a given path, used in
/// expression context, actually resolved to a module rather than /// expression context, actually resolved to a module rather than
/// a value. The `id` attached to the variant is the node id of /// a value. The optional expression attached to the variant is the
/// the erroneous path expression. /// the parent of the erroneous path expression.
PathIsMod(ast::NodeId), PathIsMod(Option<&'a Expr>),
/// `Other` means we have no extra information about the context /// `Other` means we have no extra information about the context
/// of the unresolved name error. (Maybe we could eliminate all /// 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>,
match context { match context {
UnresolvedNameContext::Other => { } // no help available UnresolvedNameContext::Other => { } // no help available
UnresolvedNameContext::PathIsMod(id) => { UnresolvedNameContext::PathIsMod(parent) => {
let mut help_msg = String::new(); err.fileline_help(span, &match parent.map(|parent| &parent.node) {
let parent_id = resolver.ast_map.get_parent_node(id); Some(&ExprField(_, ident)) => {
if let Some(hir_map::Node::NodeExpr(e)) = resolver.ast_map.find(parent_id) { format!("To reference an item from the `{module}` module, \
match e.node { use `{module}::{ident}`",
ExprField(_, ident) => { module = path,
help_msg = format!("To reference an item from the \ ident = ident.node)
`{module}` module, use \
`{module}::{ident}`",
module = path,
ident = ident.node);
}
ExprMethodCall(ident, _, _) => {
help_msg = format!("To call a function from the \
`{module}` module, use \
`{module}::{ident}(..)`",
module = path,
ident = ident.node);
}
ExprCall(_, _) => {
help_msg = format!("No function corresponds to `{module}(..)`",
module = path);
}
_ => { } // no help available
} }
} else { Some(&ExprMethodCall(ident, _, _)) => {
help_msg = format!("Module `{module}` cannot be the value of an expression", format!("To call a function from the `{module}` module, \
module = path); use `{module}::{ident}(..)`",
} module = path,
ident = ident.node)
if !help_msg.is_empty() { }
err.fileline_help(span, &help_msg); _ => {
} format!("Module `{module}` cannot be used as an expression",
module = path)
}
});
} }
} }
err err
@ -553,7 +539,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
self.resolve_block(block); self.resolve_block(block);
} }
fn visit_expr(&mut self, expr: &Expr) { fn visit_expr(&mut self, expr: &Expr) {
self.resolve_expr(expr); self.resolve_expr(expr, None);
} }
fn visit_local(&mut self, local: &Local) { fn visit_local(&mut self, local: &Local) {
self.resolve_local(local); self.resolve_local(local);
@ -2850,7 +2836,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} SuggestionType::NotFound } SuggestionType::NotFound
} }
fn resolve_expr(&mut self, expr: &Expr) { fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
// First, record candidate traits for this expression if it could // First, record candidate traits for this expression if it could
// result in the invocation of a method call. // result in the invocation of a method call.
@ -2995,7 +2981,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
UseLexicalScope, UseLexicalScope,
expr.span) { expr.span) {
Success(_) => { Success(_) => {
context = UnresolvedNameContext::PathIsMod(expr.id); context = UnresolvedNameContext::PathIsMod(parent);
}, },
_ => {}, _ => {},
}; };
@ -3069,6 +3055,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} }
} }
} }
ExprField(ref subexpression, _) => {
self.resolve_expr(subexpression, Some(expr));
}
ExprMethodCall(_, ref types, ref arguments) => {
let mut arguments = arguments.iter();
self.resolve_expr(arguments.next().unwrap(), Some(expr));
for argument in arguments {
self.resolve_expr(argument, None);
}
for ty in types.iter() {
self.visit_ty(ty);
}
}
_ => { _ => {
intravisit::walk_expr(self, expr); intravisit::walk_expr(self, expr);

View file

@ -47,10 +47,14 @@ fn h4() -> i32 {
//~| HELP To reference an item from the `a::b` module, use `a::b::J` //~| HELP To reference an item from the `a::b` module, use `a::b::J`
} }
fn h5() -> i32 { fn h5() {
a.b.f() a.b.f();
//~^ ERROR E0425 //~^ ERROR E0425
//~| HELP To reference an item from the `a` module, use `a::b` //~| HELP To reference an item from the `a` module, use `a::b`
let v = Vec::new();
v.push(a::b);
//~^ ERROR E0425
//~| HELP Module `a::b` cannot be used as an expression
} }
fn h6() -> i32 { fn h6() -> i32 {
@ -62,11 +66,11 @@ fn h6() -> i32 {
fn h7() { fn h7() {
a::b a::b
//~^ ERROR E0425 //~^ ERROR E0425
//~| HELP Module `a::b` cannot be the value of an expression //~| HELP Module `a::b` cannot be used as an expression
} }
fn h8() -> i32 { fn h8() -> i32 {
a::b() a::b()
//~^ ERROR E0425 //~^ ERROR E0425
//~| HELP No function corresponds to `a::b(..)` //~| HELP Module `a::b` cannot be used as an expression
} }