Skip to content

Commit 700d3e2

Browse files
committed
Auto merge of #33190 - jseyfried:improve_diagnostics, r=nrc
resolve: improve diagnostics and lay groundwork for resolving before ast->hir This PR improves diagnostics in `resolve` and lays some groundwork for resolving before ast->hir. More specifically, - It removes an API in `resolve` intended for external refactoring tools (see #27493) that appears not to be in active use. The API is incompatible with resolving before ast->hir, but could be rewritten in a more compatible and less intrusive way. - It improves the diagnostics for pattern bindings that conflict with `const`s. - It improves the diagnostics for modules used as expressions (fixes #33186). - It refactors away some uses of the hir map, which is unavavailable before ast->hir lowering. r? @eddyb
2 parents 855fb61 + a70e42a commit 700d3e2

File tree

3 files changed

+73
-126
lines changed

3 files changed

+73
-126
lines changed

src/librustc_resolve/lib.rs

+63-120
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};
@@ -97,17 +97,6 @@ mod check_unused;
9797
mod build_reduced_graph;
9898
mod resolve_imports;
9999

100-
// Perform the callback, not walking deeper if the return is true
101-
macro_rules! execute_callback {
102-
($node: expr, $walker: expr) => (
103-
if let Some(ref callback) = $walker.callback {
104-
if callback($node, &mut $walker.resolved) {
105-
return;
106-
}
107-
}
108-
)
109-
}
110-
111100
enum SuggestionType {
112101
Macro(String),
113102
Function(token::InternedString),
@@ -152,7 +141,7 @@ enum ResolutionError<'a> {
152141
/// error E0413: declaration shadows an enum variant or unit-like struct in scope
153142
DeclarationShadowsEnumVariantOrUnitLikeStruct(Name),
154143
/// error E0414: only irrefutable patterns allowed here
155-
OnlyIrrefutablePatternsAllowedHere(DefId, Name),
144+
OnlyIrrefutablePatternsAllowedHere(Name),
156145
/// error E0415: identifier is bound more than once in this parameter list
157146
IdentifierBoundMoreThanOnceInParameterList(&'a str),
158147
/// error E0416: identifier is bound more than once in the same pattern
@@ -174,7 +163,7 @@ enum ResolutionError<'a> {
174163
/// error E0424: `self` is not available in a static method
175164
SelfNotAvailableInStaticMethod,
176165
/// error E0425: unresolved name
177-
UnresolvedName(&'a str, &'a str, UnresolvedNameContext),
166+
UnresolvedName(&'a str, &'a str, UnresolvedNameContext<'a>),
178167
/// error E0426: use of undeclared label
179168
UndeclaredLabel(&'a str),
180169
/// error E0427: cannot use `ref` binding mode with ...
@@ -197,12 +186,12 @@ enum ResolutionError<'a> {
197186

198187
/// Context of where `ResolutionError::UnresolvedName` arose.
199188
#[derive(Clone, PartialEq, Eq, Debug)]
200-
enum UnresolvedNameContext {
201-
/// `PathIsMod(id)` indicates that a given path, used in
189+
enum UnresolvedNameContext<'a> {
190+
/// `PathIsMod(parent)` indicates that a given path, used in
202191
/// expression context, actually resolved to a module rather than
203-
/// a value. The `id` attached to the variant is the node id of
204-
/// the erroneous path expression.
205-
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>),
206195

207196
/// `Other` means we have no extra information about the context
208197
/// of the unresolved name error. (Maybe we could eliminate all
@@ -334,22 +323,18 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
334323
or unit-like struct in scope",
335324
name)
336325
}
337-
ResolutionError::OnlyIrrefutablePatternsAllowedHere(did, name) => {
326+
ResolutionError::OnlyIrrefutablePatternsAllowedHere(name) => {
338327
let mut err = struct_span_err!(resolver.session,
339328
span,
340329
E0414,
341330
"only irrefutable patterns allowed here");
342331
err.span_note(span,
343332
"there already is a constant in scope sharing the same \
344333
name as this pattern");
345-
if let Some(sp) = resolver.ast_map.span_if_local(did) {
346-
err.span_note(sp, "constant defined here");
347-
}
348334
if let Some(binding) = resolver.current_module
349335
.resolve_name_in_lexical_scope(name, ValueNS) {
350-
if binding.is_import() {
351-
err.span_note(binding.span, "constant imported here");
352-
}
336+
let participle = if binding.is_import() { "imported" } else { "defined" };
337+
err.span_note(binding.span, &format!("constant {} here", participle));
353338
}
354339
err
355340
}
@@ -434,39 +419,25 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
434419

435420
match context {
436421
UnresolvedNameContext::Other => { } // no help available
437-
UnresolvedNameContext::PathIsMod(id) => {
438-
let mut help_msg = String::new();
439-
let parent_id = resolver.ast_map.get_parent_node(id);
440-
if let Some(hir_map::Node::NodeExpr(e)) = resolver.ast_map.find(parent_id) {
441-
match e.node {
442-
ExprField(_, ident) => {
443-
help_msg = format!("To reference an item from the \
444-
`{module}` module, use \
445-
`{module}::{ident}`",
446-
module = path,
447-
ident = ident.node);
448-
}
449-
ExprMethodCall(ident, _, _) => {
450-
help_msg = format!("To call a function from the \
451-
`{module}` module, use \
452-
`{module}::{ident}(..)`",
453-
module = path,
454-
ident = ident.node);
455-
}
456-
ExprCall(_, _) => {
457-
help_msg = format!("No function corresponds to `{module}(..)`",
458-
module = path);
459-
}
460-
_ => { } // 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)
461429
}
462-
} else {
463-
help_msg = format!("Module `{module}` cannot be the value of an expression",
464-
module = path);
465-
}
466-
467-
if !help_msg.is_empty() {
468-
err.fileline_help(span, &help_msg);
469-
}
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+
});
470441
}
471442
}
472443
err
@@ -559,22 +530,18 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
559530
self.visit_item(self.ast_map.expect_item(item.id))
560531
}
561532
fn visit_item(&mut self, item: &Item) {
562-
execute_callback!(hir_map::Node::NodeItem(item), self);
563533
self.resolve_item(item);
564534
}
565535
fn visit_arm(&mut self, arm: &Arm) {
566536
self.resolve_arm(arm);
567537
}
568538
fn visit_block(&mut self, block: &Block) {
569-
execute_callback!(hir_map::Node::NodeBlock(block), self);
570539
self.resolve_block(block);
571540
}
572541
fn visit_expr(&mut self, expr: &Expr) {
573-
execute_callback!(hir_map::Node::NodeExpr(expr), self);
574-
self.resolve_expr(expr);
542+
self.resolve_expr(expr, None);
575543
}
576544
fn visit_local(&mut self, local: &Local) {
577-
execute_callback!(hir_map::Node::NodeLocal(&local.pat), self);
578545
self.resolve_local(local);
579546
}
580547
fn visit_ty(&mut self, ty: &Ty) {
@@ -597,7 +564,6 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
597564
variant: &hir::Variant,
598565
generics: &Generics,
599566
item_id: ast::NodeId) {
600-
execute_callback!(hir_map::Node::NodeVariant(variant), self);
601567
if let Some(ref dis_expr) = variant.node.disr_expr {
602568
// resolve the discriminator expr as a constant
603569
self.with_constant_rib(|this| {
@@ -613,7 +579,6 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
613579
variant.span);
614580
}
615581
fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem) {
616-
execute_callback!(hir_map::Node::NodeForeignItem(foreign_item), self);
617582
let type_parameters = match foreign_item.node {
618583
ForeignItemFn(_, ref generics) => {
619584
HasTypeParameters(generics, FnSpace, ItemRibKind)
@@ -1080,11 +1045,6 @@ pub struct Resolver<'a, 'tcx: 'a> {
10801045
used_imports: HashSet<(NodeId, Namespace)>,
10811046
used_crates: HashSet<CrateNum>,
10821047

1083-
// Callback function for intercepting walks
1084-
callback: Option<Box<Fn(hir_map::Node, &mut bool) -> bool>>,
1085-
// The intention is that the callback modifies this flag.
1086-
// Once set, the resolver falls out of the walk, preserving the ribs.
1087-
resolved: bool,
10881048
privacy_errors: Vec<PrivacyError<'a>>,
10891049

10901050
arenas: &'a ResolverArenas<'a>,
@@ -1186,8 +1146,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
11861146
make_glob_map: make_glob_map == MakeGlobMap::Yes,
11871147
glob_map: NodeMap(),
11881148

1189-
callback: None,
1190-
resolved: false,
11911149
privacy_errors: Vec::new(),
11921150

11931151
arenas: arenas,
@@ -1758,13 +1716,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
17581716

17591717
f(self);
17601718

1761-
match type_parameters {
1762-
HasTypeParameters(..) => {
1763-
if !self.resolved {
1764-
self.type_ribs.pop();
1765-
}
1766-
}
1767-
NoTypeParameters => {}
1719+
if let HasTypeParameters(..) = type_parameters {
1720+
self.type_ribs.pop();
17681721
}
17691722
}
17701723

@@ -1773,9 +1726,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
17731726
{
17741727
self.label_ribs.push(Rib::new(NormalRibKind));
17751728
f(self);
1776-
if !self.resolved {
1777-
self.label_ribs.pop();
1778-
}
1729+
self.label_ribs.pop();
17791730
}
17801731

17811732
fn with_constant_rib<F>(&mut self, f: F)
@@ -1784,10 +1735,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
17841735
self.value_ribs.push(Rib::new(ConstantItemRibKind));
17851736
self.type_ribs.push(Rib::new(ConstantItemRibKind));
17861737
f(self);
1787-
if !self.resolved {
1788-
self.type_ribs.pop();
1789-
self.value_ribs.pop();
1790-
}
1738+
self.type_ribs.pop();
1739+
self.value_ribs.pop();
17911740
}
17921741

17931742
fn resolve_function(&mut self, rib_kind: RibKind<'a>, declaration: &FnDecl, block: &Block) {
@@ -1813,10 +1762,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
18131762

18141763
debug!("(resolving function) leaving function");
18151764

1816-
if !self.resolved {
1817-
self.label_ribs.pop();
1818-
self.value_ribs.pop();
1819-
}
1765+
self.label_ribs.pop();
1766+
self.value_ribs.pop();
18201767
}
18211768

18221769
fn resolve_trait_reference(&mut self,
@@ -1950,9 +1897,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
19501897
self_type_rib.bindings.insert(keywords::SelfType.name(), self_def);
19511898
self.type_ribs.push(self_type_rib);
19521899
f(self);
1953-
if !self.resolved {
1954-
self.type_ribs.pop();
1955-
}
1900+
self.type_ribs.pop();
19561901
}
19571902

19581903
fn resolve_implementation(&mut self,
@@ -2117,9 +2062,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
21172062
walk_list!(self, visit_expr, &arm.guard);
21182063
self.visit_expr(&arm.body);
21192064

2120-
if !self.resolved {
2121-
self.value_ribs.pop();
2122-
}
2065+
self.value_ribs.pop();
21232066
}
21242067

21252068
fn resolve_block(&mut self, block: &Block) {
@@ -2141,12 +2084,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
21412084
intravisit::walk_block(self, block);
21422085

21432086
// Move back up.
2144-
if !self.resolved {
2145-
self.current_module = orig_module;
2146-
self.value_ribs.pop();
2147-
if let Some(_) = anonymous_module {
2148-
self.type_ribs.pop();
2149-
}
2087+
self.current_module = orig_module;
2088+
self.value_ribs.pop();
2089+
if let Some(_) = anonymous_module {
2090+
self.type_ribs.pop();
21502091
}
21512092
debug!("(resolving block) leaving block");
21522093
}
@@ -2289,12 +2230,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
22892230
depth: 0,
22902231
});
22912232
}
2292-
FoundConst(def, name) => {
2233+
FoundConst(_, name) => {
22932234
resolve_error(
22942235
self,
22952236
pattern.span,
2296-
ResolutionError::OnlyIrrefutablePatternsAllowedHere(def.def_id(),
2297-
name)
2237+
ResolutionError::OnlyIrrefutablePatternsAllowedHere(name)
22982238
);
22992239
self.record_def(pattern.id, err_path_resolution());
23002240
}
@@ -2896,7 +2836,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
28962836
} SuggestionType::NotFound
28972837
}
28982838

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

@@ -3041,7 +2981,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
30412981
UseLexicalScope,
30422982
expr.span) {
30432983
Success(_) => {
3044-
context = UnresolvedNameContext::PathIsMod(expr.id);
2984+
context = UnresolvedNameContext::PathIsMod(parent);
30452985
},
30462986
_ => {},
30472987
};
@@ -3115,6 +3055,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
31153055
}
31163056
}
31173057
}
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+
}
31183071

31193072
_ => {
31203073
intravisit::walk_expr(self, expr);
@@ -3588,7 +3541,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
35883541

35893542
let krate = ast_map.krate();
35903543
let arenas = Resolver::arenas();
3591-
let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, &arenas, None);
3544+
let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, &arenas);
35923545

35933546
resolver.resolve_crate(krate);
35943547

@@ -3608,25 +3561,15 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
36083561
}
36093562
}
36103563

3611-
/// Builds a name resolution walker to be used within this module,
3612-
/// or used externally, with an optional callback function.
3613-
///
3614-
/// The callback takes a &mut bool which allows callbacks to end a
3615-
/// walk when set to true, passing through the rest of the walk, while
3616-
/// preserving the ribs + current module. This allows resolve_path
3617-
/// calls to be made with the correct scope info. The node in the
3618-
/// callback corresponds to the current node in the walk.
3564+
/// Builds a name resolution walker.
36193565
fn create_resolver<'a, 'tcx>(session: &'a Session,
36203566
ast_map: &'a hir_map::Map<'tcx>,
36213567
krate: &'a Crate,
36223568
make_glob_map: MakeGlobMap,
3623-
arenas: &'a ResolverArenas<'a>,
3624-
callback: Option<Box<Fn(hir_map::Node, &mut bool) -> bool>>)
3569+
arenas: &'a ResolverArenas<'a>)
36253570
-> Resolver<'a, 'tcx> {
36263571
let mut resolver = Resolver::new(session, ast_map, make_glob_map, arenas);
36273572

3628-
resolver.callback = callback;
3629-
36303573
resolver.build_reduced_graph(krate);
36313574

36323575
resolve_imports::resolve_imports(&mut resolver);

0 commit comments

Comments
 (0)