Skip to content

Commit 20ee53c

Browse files
committed
Improve path resolution diagnostics
1 parent 7fd331e commit 20ee53c

File tree

1 file changed

+67
-66
lines changed

1 file changed

+67
-66
lines changed

src/librustc_resolve/lib.rs

Lines changed: 67 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1716,9 +1716,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
17161716
match self.resolve_crate_relative_path(prefix.span,
17171717
&prefix.segments,
17181718
TypeNS) {
1719-
Some(def) =>
1719+
Ok(def) =>
17201720
self.record_def(item.id, PathResolution::new(def, 0)),
1721-
None => {
1721+
Err(true) => self.record_def(item.id, err_path_resolution()),
1722+
Err(false) => {
17221723
resolve_error(self,
17231724
prefix.span,
17241725
ResolutionError::FailedToResolve(
@@ -1837,7 +1838,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
18371838
trait_path: &Path,
18381839
path_depth: usize)
18391840
-> Result<PathResolution, ()> {
1840-
if let Some(path_res) = self.resolve_path(id, trait_path, path_depth, TypeNS) {
1841+
self.resolve_path(id, trait_path, path_depth, TypeNS).and_then(|path_res| {
18411842
if let Def::Trait(_) = path_res.base_def {
18421843
debug!("(resolving trait) found trait def: {:?}", path_res);
18431844
Ok(path_res)
@@ -1857,9 +1858,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
18571858
}
18581859
}
18591860
err.emit();
1860-
Err(())
1861+
Err(true)
18611862
}
1862-
} else {
1863+
}).map_err(|error_reported| {
1864+
if error_reported { return }
18631865

18641866
// find possible candidates
18651867
let trait_name = trait_path.segments.last().unwrap().identifier.name;
@@ -1882,8 +1884,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
18821884
);
18831885

18841886
resolve_error(self, trait_path.span, error);
1885-
Err(())
1886-
}
1887+
})
18871888
}
18881889

18891890
fn resolve_generics(&mut self, generics: &Generics) {
@@ -1892,15 +1893,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
18921893
&hir::WherePredicate::BoundPredicate(_) |
18931894
&hir::WherePredicate::RegionPredicate(_) => {}
18941895
&hir::WherePredicate::EqPredicate(ref eq_pred) => {
1895-
let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS);
1896-
if let Some(PathResolution { base_def: Def::TyParam(..), .. }) = path_res {
1897-
self.record_def(eq_pred.id, path_res.unwrap());
1898-
} else {
1899-
resolve_error(self,
1900-
eq_pred.span,
1901-
ResolutionError::UndeclaredAssociatedType);
1896+
self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS).and_then(|path_res| {
1897+
if let PathResolution { base_def: Def::TyParam(..), .. } = path_res {
1898+
Ok(self.record_def(eq_pred.id, path_res))
1899+
} else {
1900+
Err(false)
1901+
}
1902+
}).map_err(|error_reported| {
19021903
self.record_def(eq_pred.id, err_path_resolution());
1903-
}
1904+
if error_reported { return }
1905+
resolve_error(self, eq_pred.span, ResolutionError::UndeclaredAssociatedType);
1906+
}).unwrap_or(());
19041907
}
19051908
}
19061909
}
@@ -2170,21 +2173,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
21702173

21712174
// This is a path in the type namespace. Walk through scopes
21722175
// looking for it.
2173-
match resolution {
2174-
Some(def) => {
2175-
// Write the result into the def map.
2176-
debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}",
2177-
path_names_to_string(path, 0),
2178-
ty.id,
2179-
def);
2180-
self.record_def(ty.id, def);
2181-
}
2182-
None => {
2183-
self.record_def(ty.id, err_path_resolution());
2184-
2185-
// Keep reporting some errors even if they're ignored above.
2186-
self.resolve_path(ty.id, path, 0, TypeNS);
2176+
if let Some(def) = resolution {
2177+
// Write the result into the def map.
2178+
debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}",
2179+
path_names_to_string(path, 0), ty.id, def);
2180+
self.record_def(ty.id, def);
2181+
} else {
2182+
self.record_def(ty.id, err_path_resolution());
21872183

2184+
// Keep reporting some errors even if they're ignored above.
2185+
if let Err(true) = self.resolve_path(ty.id, path, 0, TypeNS) {
2186+
// `resolve_path` already reported the error
2187+
} else {
21882188
let kind = if maybe_qself.is_some() {
21892189
"associated type"
21902190
} else {
@@ -2483,11 +2483,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
24832483

24842484
PatKind::Struct(ref path, _, _) => {
24852485
match self.resolve_path(pat_id, path, 0, TypeNS) {
2486-
Some(definition) => {
2486+
Ok(definition) => {
24872487
self.record_def(pattern.id, definition);
24882488
}
2489-
result => {
2490-
debug!("(resolving pattern) didn't find struct def: {:?}", result);
2489+
Err(true) => self.record_def(pattern.id, err_path_resolution()),
2490+
Err(false) => {
24912491
resolve_error(
24922492
self,
24932493
path.span,
@@ -2554,14 +2554,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
25542554
}
25552555

25562556
let mut resolution = self.with_no_errors(|this| {
2557-
this.resolve_path(id, path, 0, namespace)
2557+
this.resolve_path(id, path, 0, namespace).ok()
25582558
});
25592559
for depth in 1..max_assoc_types {
25602560
if resolution.is_some() {
25612561
break;
25622562
}
25632563
self.with_no_errors(|this| {
2564-
resolution = this.resolve_path(id, path, depth, TypeNS);
2564+
resolution = this.resolve_path(id, path, depth, TypeNS).ok();
25652565
});
25662566
}
25672567
if let Some(Def::Mod(_)) = resolution.map(|r| r.base_def) {
@@ -2574,7 +2574,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
25742574
/// Skips `path_depth` trailing segments, which is also reflected in the
25752575
/// returned value. See `middle::def::PathResolution` for more info.
25762576
fn resolve_path(&mut self, id: NodeId, path: &Path, path_depth: usize, namespace: Namespace)
2577-
-> Option<PathResolution> {
2577+
-> Result<PathResolution, bool /* true if an error was reported */ > {
25782578
let span = path.span;
25792579
let segments = &path.segments[..path.segments.len() - path_depth];
25802580

@@ -2613,14 +2613,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
26132613
//
26142614
// Such behavior is required for backward compatibility.
26152615
// The same fallback is used when `a` resolves to nothing.
2616-
let unqualified_def = resolve_identifier_with_fallback(self, true);
2617-
return unqualified_def.and_then(|def| self.adjust_local_def(def, span)).map(mk_res);
2616+
let def = resolve_identifier_with_fallback(self, true).ok_or(false);
2617+
return def.and_then(|def| self.adjust_local_def(def, span).ok_or(true)).map(mk_res);
26182618
}
26192619

26202620
let unqualified_def = resolve_identifier_with_fallback(self, false);
26212621
let def = self.resolve_module_relative_path(span, segments, namespace);
26222622
match (def, unqualified_def) {
2623-
(Some(d), Some(ref ud)) if d == ud.def => {
2623+
(Ok(d), Some(ref ud)) if d == ud.def => {
26242624
self.session
26252625
.add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
26262626
id,
@@ -2741,7 +2741,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
27412741
span: Span,
27422742
segments: &[hir::PathSegment],
27432743
namespace: Namespace)
2744-
-> Option<Def> {
2744+
-> Result<Def, bool /* true if an error was reported */> {
27452745
let module_path = segments.split_last()
27462746
.unwrap()
27472747
.1
@@ -2762,9 +2762,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
27622762
};
27632763

27642764
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
2765-
return None;
2765+
return Err(true);
27662766
}
2767-
Indeterminate => return None,
2767+
Indeterminate => return Err(false),
27682768
Success(resulting_module) => {
27692769
containing_module = resulting_module;
27702770
}
@@ -2775,7 +2775,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
27752775
result.success().map(|binding| {
27762776
self.check_privacy(containing_module, name, binding, span);
27772777
binding.def().unwrap()
2778-
})
2778+
}).ok_or(false)
27792779
}
27802780

27812781
/// Invariant: This must be called only during main resolution, not during
@@ -2784,7 +2784,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
27842784
span: Span,
27852785
segments: &[hir::PathSegment],
27862786
namespace: Namespace)
2787-
-> Option<Def> {
2787+
-> Result<Def, bool /* true if an error was reported */> {
27882788
let module_path = segments.split_last()
27892789
.unwrap()
27902790
.1
@@ -2810,10 +2810,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
28102810
};
28112811

28122812
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
2813-
return None;
2813+
return Err(true);
28142814
}
28152815

2816-
Indeterminate => return None,
2816+
Indeterminate => return Err(false),
28172817

28182818
Success(resulting_module) => {
28192819
containing_module = resulting_module;
@@ -2825,7 +2825,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
28252825
result.success().map(|binding| {
28262826
self.check_privacy(containing_module, name, binding, span);
28272827
binding.def().unwrap()
2828-
})
2828+
}).ok_or(false)
28292829
}
28302830

28312831
fn with_no_errors<T, F>(&mut self, f: F) -> T
@@ -3040,25 +3040,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
30403040
});
30413041

30423042
self.record_def(expr.id, err_path_resolution());
3043-
match type_res.map(|r| r.base_def) {
3044-
Some(Def::Struct(..)) => {
3045-
let mut err = resolve_struct_error(self,
3046-
expr.span,
3047-
ResolutionError::StructVariantUsedAsFunction(&path_name));
3048-
3049-
let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
3050-
path_name);
3051-
if self.emit_errors {
3052-
err.fileline_help(expr.span, &msg);
3053-
} else {
3054-
err.span_help(expr.span, &msg);
3055-
}
3056-
err.emit();
3057-
}
3058-
_ => {
3059-
// Keep reporting some errors even if they're ignored above.
3060-
self.resolve_path(expr.id, path, 0, ValueNS);
30613043

3044+
if let Ok(Def::Struct(..)) = type_res.map(|r| r.base_def) {
3045+
let error_variant = ResolutionError::StructVariantUsedAsFunction(&path_name);
3046+
let mut err = resolve_struct_error(self, expr.span, error_variant);
3047+
3048+
let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
3049+
path_name);
3050+
3051+
if self.emit_errors {
3052+
err.fileline_help(expr.span, &msg);
3053+
} else {
3054+
err.span_help(expr.span, &msg);
3055+
}
3056+
err.emit();
3057+
} else {
3058+
// Keep reporting some errors even if they're ignored above.
3059+
if let Err(true) = self.resolve_path(expr.id, path, 0, ValueNS) {
3060+
// `resolve_path` already reported the error
3061+
} else {
30623062
let mut method_scope = false;
30633063
self.value_ribs.iter().rev().all(|rib| {
30643064
method_scope = match rib.kind {
@@ -3132,8 +3132,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
31323132
// check to ensure that the path is actually a structure; that
31333133
// is checked later during typeck.
31343134
match self.resolve_path(expr.id, path, 0, TypeNS) {
3135-
Some(definition) => self.record_def(expr.id, definition),
3136-
None => {
3135+
Ok(definition) => self.record_def(expr.id, definition),
3136+
Err(true) => self.record_def(expr.id, err_path_resolution()),
3137+
Err(false) => {
31373138
debug!("(resolving expression) didn't find struct def",);
31383139

31393140
resolve_error(self,

0 commit comments

Comments
 (0)