Improve path resolution diagnostics
This commit is contained in:
parent
7fd331e166
commit
20ee53c2f1
@ -1716,9 +1716,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
match self.resolve_crate_relative_path(prefix.span,
|
match self.resolve_crate_relative_path(prefix.span,
|
||||||
&prefix.segments,
|
&prefix.segments,
|
||||||
TypeNS) {
|
TypeNS) {
|
||||||
Some(def) =>
|
Ok(def) =>
|
||||||
self.record_def(item.id, PathResolution::new(def, 0)),
|
self.record_def(item.id, PathResolution::new(def, 0)),
|
||||||
None => {
|
Err(true) => self.record_def(item.id, err_path_resolution()),
|
||||||
|
Err(false) => {
|
||||||
resolve_error(self,
|
resolve_error(self,
|
||||||
prefix.span,
|
prefix.span,
|
||||||
ResolutionError::FailedToResolve(
|
ResolutionError::FailedToResolve(
|
||||||
@ -1837,7 +1838,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
trait_path: &Path,
|
trait_path: &Path,
|
||||||
path_depth: usize)
|
path_depth: usize)
|
||||||
-> Result<PathResolution, ()> {
|
-> Result<PathResolution, ()> {
|
||||||
if let Some(path_res) = self.resolve_path(id, trait_path, path_depth, TypeNS) {
|
self.resolve_path(id, trait_path, path_depth, TypeNS).and_then(|path_res| {
|
||||||
if let Def::Trait(_) = path_res.base_def {
|
if let Def::Trait(_) = path_res.base_def {
|
||||||
debug!("(resolving trait) found trait def: {:?}", path_res);
|
debug!("(resolving trait) found trait def: {:?}", path_res);
|
||||||
Ok(path_res)
|
Ok(path_res)
|
||||||
@ -1857,9 +1858,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit();
|
||||||
Err(())
|
Err(true)
|
||||||
}
|
}
|
||||||
} else {
|
}).map_err(|error_reported| {
|
||||||
|
if error_reported { return }
|
||||||
|
|
||||||
// find possible candidates
|
// find possible candidates
|
||||||
let trait_name = trait_path.segments.last().unwrap().identifier.name;
|
let trait_name = trait_path.segments.last().unwrap().identifier.name;
|
||||||
@ -1882,8 +1884,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
resolve_error(self, trait_path.span, error);
|
resolve_error(self, trait_path.span, error);
|
||||||
Err(())
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_generics(&mut self, generics: &Generics) {
|
fn resolve_generics(&mut self, generics: &Generics) {
|
||||||
@ -1892,15 +1893,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
&hir::WherePredicate::BoundPredicate(_) |
|
&hir::WherePredicate::BoundPredicate(_) |
|
||||||
&hir::WherePredicate::RegionPredicate(_) => {}
|
&hir::WherePredicate::RegionPredicate(_) => {}
|
||||||
&hir::WherePredicate::EqPredicate(ref eq_pred) => {
|
&hir::WherePredicate::EqPredicate(ref eq_pred) => {
|
||||||
let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS);
|
self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS).and_then(|path_res| {
|
||||||
if let Some(PathResolution { base_def: Def::TyParam(..), .. }) = path_res {
|
if let PathResolution { base_def: Def::TyParam(..), .. } = path_res {
|
||||||
self.record_def(eq_pred.id, path_res.unwrap());
|
Ok(self.record_def(eq_pred.id, path_res))
|
||||||
} else {
|
} else {
|
||||||
resolve_error(self,
|
Err(false)
|
||||||
eq_pred.span,
|
}
|
||||||
ResolutionError::UndeclaredAssociatedType);
|
}).map_err(|error_reported| {
|
||||||
self.record_def(eq_pred.id, err_path_resolution());
|
self.record_def(eq_pred.id, err_path_resolution());
|
||||||
}
|
if error_reported { return }
|
||||||
|
resolve_error(self, eq_pred.span, ResolutionError::UndeclaredAssociatedType);
|
||||||
|
}).unwrap_or(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2170,21 +2173,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
|
|
||||||
// This is a path in the type namespace. Walk through scopes
|
// This is a path in the type namespace. Walk through scopes
|
||||||
// looking for it.
|
// looking for it.
|
||||||
match resolution {
|
if let Some(def) = resolution {
|
||||||
Some(def) => {
|
// Write the result into the def map.
|
||||||
// Write the result into the def map.
|
debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}",
|
||||||
debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}",
|
path_names_to_string(path, 0), ty.id, def);
|
||||||
path_names_to_string(path, 0),
|
self.record_def(ty.id, def);
|
||||||
ty.id,
|
} else {
|
||||||
def);
|
self.record_def(ty.id, err_path_resolution());
|
||||||
self.record_def(ty.id, def);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
self.record_def(ty.id, err_path_resolution());
|
|
||||||
|
|
||||||
// Keep reporting some errors even if they're ignored above.
|
|
||||||
self.resolve_path(ty.id, path, 0, TypeNS);
|
|
||||||
|
|
||||||
|
// Keep reporting some errors even if they're ignored above.
|
||||||
|
if let Err(true) = self.resolve_path(ty.id, path, 0, TypeNS) {
|
||||||
|
// `resolve_path` already reported the error
|
||||||
|
} else {
|
||||||
let kind = if maybe_qself.is_some() {
|
let kind = if maybe_qself.is_some() {
|
||||||
"associated type"
|
"associated type"
|
||||||
} else {
|
} else {
|
||||||
@ -2483,11 +2483,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
|
|
||||||
PatKind::Struct(ref path, _, _) => {
|
PatKind::Struct(ref path, _, _) => {
|
||||||
match self.resolve_path(pat_id, path, 0, TypeNS) {
|
match self.resolve_path(pat_id, path, 0, TypeNS) {
|
||||||
Some(definition) => {
|
Ok(definition) => {
|
||||||
self.record_def(pattern.id, definition);
|
self.record_def(pattern.id, definition);
|
||||||
}
|
}
|
||||||
result => {
|
Err(true) => self.record_def(pattern.id, err_path_resolution()),
|
||||||
debug!("(resolving pattern) didn't find struct def: {:?}", result);
|
Err(false) => {
|
||||||
resolve_error(
|
resolve_error(
|
||||||
self,
|
self,
|
||||||
path.span,
|
path.span,
|
||||||
@ -2554,14 +2554,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut resolution = self.with_no_errors(|this| {
|
let mut resolution = self.with_no_errors(|this| {
|
||||||
this.resolve_path(id, path, 0, namespace)
|
this.resolve_path(id, path, 0, namespace).ok()
|
||||||
});
|
});
|
||||||
for depth in 1..max_assoc_types {
|
for depth in 1..max_assoc_types {
|
||||||
if resolution.is_some() {
|
if resolution.is_some() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
self.with_no_errors(|this| {
|
self.with_no_errors(|this| {
|
||||||
resolution = this.resolve_path(id, path, depth, TypeNS);
|
resolution = this.resolve_path(id, path, depth, TypeNS).ok();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if let Some(Def::Mod(_)) = resolution.map(|r| r.base_def) {
|
if let Some(Def::Mod(_)) = resolution.map(|r| r.base_def) {
|
||||||
@ -2574,7 +2574,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
/// Skips `path_depth` trailing segments, which is also reflected in the
|
/// Skips `path_depth` trailing segments, which is also reflected in the
|
||||||
/// returned value. See `middle::def::PathResolution` for more info.
|
/// returned value. See `middle::def::PathResolution` for more info.
|
||||||
fn resolve_path(&mut self, id: NodeId, path: &Path, path_depth: usize, namespace: Namespace)
|
fn resolve_path(&mut self, id: NodeId, path: &Path, path_depth: usize, namespace: Namespace)
|
||||||
-> Option<PathResolution> {
|
-> Result<PathResolution, bool /* true if an error was reported */ > {
|
||||||
let span = path.span;
|
let span = path.span;
|
||||||
let segments = &path.segments[..path.segments.len() - path_depth];
|
let segments = &path.segments[..path.segments.len() - path_depth];
|
||||||
|
|
||||||
@ -2613,14 +2613,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
//
|
//
|
||||||
// Such behavior is required for backward compatibility.
|
// Such behavior is required for backward compatibility.
|
||||||
// The same fallback is used when `a` resolves to nothing.
|
// The same fallback is used when `a` resolves to nothing.
|
||||||
let unqualified_def = resolve_identifier_with_fallback(self, true);
|
let def = resolve_identifier_with_fallback(self, true).ok_or(false);
|
||||||
return unqualified_def.and_then(|def| self.adjust_local_def(def, span)).map(mk_res);
|
return def.and_then(|def| self.adjust_local_def(def, span).ok_or(true)).map(mk_res);
|
||||||
}
|
}
|
||||||
|
|
||||||
let unqualified_def = resolve_identifier_with_fallback(self, false);
|
let unqualified_def = resolve_identifier_with_fallback(self, false);
|
||||||
let def = self.resolve_module_relative_path(span, segments, namespace);
|
let def = self.resolve_module_relative_path(span, segments, namespace);
|
||||||
match (def, unqualified_def) {
|
match (def, unqualified_def) {
|
||||||
(Some(d), Some(ref ud)) if d == ud.def => {
|
(Ok(d), Some(ref ud)) if d == ud.def => {
|
||||||
self.session
|
self.session
|
||||||
.add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
|
.add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
|
||||||
id,
|
id,
|
||||||
@ -2741,7 +2741,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
segments: &[hir::PathSegment],
|
segments: &[hir::PathSegment],
|
||||||
namespace: Namespace)
|
namespace: Namespace)
|
||||||
-> Option<Def> {
|
-> Result<Def, bool /* true if an error was reported */> {
|
||||||
let module_path = segments.split_last()
|
let module_path = segments.split_last()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.1
|
.1
|
||||||
@ -2762,9 +2762,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
|
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
|
||||||
return None;
|
return Err(true);
|
||||||
}
|
}
|
||||||
Indeterminate => return None,
|
Indeterminate => return Err(false),
|
||||||
Success(resulting_module) => {
|
Success(resulting_module) => {
|
||||||
containing_module = resulting_module;
|
containing_module = resulting_module;
|
||||||
}
|
}
|
||||||
@ -2775,7 +2775,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
result.success().map(|binding| {
|
result.success().map(|binding| {
|
||||||
self.check_privacy(containing_module, name, binding, span);
|
self.check_privacy(containing_module, name, binding, span);
|
||||||
binding.def().unwrap()
|
binding.def().unwrap()
|
||||||
})
|
}).ok_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invariant: This must be called only during main resolution, not during
|
/// Invariant: This must be called only during main resolution, not during
|
||||||
@ -2784,7 +2784,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
segments: &[hir::PathSegment],
|
segments: &[hir::PathSegment],
|
||||||
namespace: Namespace)
|
namespace: Namespace)
|
||||||
-> Option<Def> {
|
-> Result<Def, bool /* true if an error was reported */> {
|
||||||
let module_path = segments.split_last()
|
let module_path = segments.split_last()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.1
|
.1
|
||||||
@ -2810,10 +2810,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
|
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
|
||||||
return None;
|
return Err(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Indeterminate => return None,
|
Indeterminate => return Err(false),
|
||||||
|
|
||||||
Success(resulting_module) => {
|
Success(resulting_module) => {
|
||||||
containing_module = resulting_module;
|
containing_module = resulting_module;
|
||||||
@ -2825,7 +2825,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
result.success().map(|binding| {
|
result.success().map(|binding| {
|
||||||
self.check_privacy(containing_module, name, binding, span);
|
self.check_privacy(containing_module, name, binding, span);
|
||||||
binding.def().unwrap()
|
binding.def().unwrap()
|
||||||
})
|
}).ok_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_no_errors<T, F>(&mut self, f: F) -> T
|
fn with_no_errors<T, F>(&mut self, f: F) -> T
|
||||||
@ -3040,25 +3040,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
self.record_def(expr.id, err_path_resolution());
|
self.record_def(expr.id, err_path_resolution());
|
||||||
match type_res.map(|r| r.base_def) {
|
|
||||||
Some(Def::Struct(..)) => {
|
|
||||||
let mut err = resolve_struct_error(self,
|
|
||||||
expr.span,
|
|
||||||
ResolutionError::StructVariantUsedAsFunction(&path_name));
|
|
||||||
|
|
||||||
let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
|
if let Ok(Def::Struct(..)) = type_res.map(|r| r.base_def) {
|
||||||
path_name);
|
let error_variant = ResolutionError::StructVariantUsedAsFunction(&path_name);
|
||||||
if self.emit_errors {
|
let mut err = resolve_struct_error(self, expr.span, error_variant);
|
||||||
err.fileline_help(expr.span, &msg);
|
|
||||||
} else {
|
let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
|
||||||
err.span_help(expr.span, &msg);
|
path_name);
|
||||||
}
|
|
||||||
err.emit();
|
if self.emit_errors {
|
||||||
|
err.fileline_help(expr.span, &msg);
|
||||||
|
} else {
|
||||||
|
err.span_help(expr.span, &msg);
|
||||||
}
|
}
|
||||||
_ => {
|
err.emit();
|
||||||
// Keep reporting some errors even if they're ignored above.
|
} else {
|
||||||
self.resolve_path(expr.id, path, 0, ValueNS);
|
// Keep reporting some errors even if they're ignored above.
|
||||||
|
if let Err(true) = self.resolve_path(expr.id, path, 0, ValueNS) {
|
||||||
|
// `resolve_path` already reported the error
|
||||||
|
} else {
|
||||||
let mut method_scope = false;
|
let mut method_scope = false;
|
||||||
self.value_ribs.iter().rev().all(|rib| {
|
self.value_ribs.iter().rev().all(|rib| {
|
||||||
method_scope = match rib.kind {
|
method_scope = match rib.kind {
|
||||||
@ -3132,8 +3132,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
// check to ensure that the path is actually a structure; that
|
// check to ensure that the path is actually a structure; that
|
||||||
// is checked later during typeck.
|
// is checked later during typeck.
|
||||||
match self.resolve_path(expr.id, path, 0, TypeNS) {
|
match self.resolve_path(expr.id, path, 0, TypeNS) {
|
||||||
Some(definition) => self.record_def(expr.id, definition),
|
Ok(definition) => self.record_def(expr.id, definition),
|
||||||
None => {
|
Err(true) => self.record_def(expr.id, err_path_resolution()),
|
||||||
|
Err(false) => {
|
||||||
debug!("(resolving expression) didn't find struct def",);
|
debug!("(resolving expression) didn't find struct def",);
|
||||||
|
|
||||||
resolve_error(self,
|
resolve_error(self,
|
||||||
|
Loading…
Reference in New Issue
Block a user