Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resolve: Avoid emitting redundant path resolution errors #32789

Merged
merged 3 commits into from
Apr 7, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 69 additions & 66 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1716,9 +1716,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
match self.resolve_crate_relative_path(prefix.span,
&prefix.segments,
TypeNS) {
Some(def) =>
Ok(def) =>
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,
prefix.span,
ResolutionError::FailedToResolve(
Expand Down Expand Up @@ -1837,7 +1838,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
trait_path: &Path,
path_depth: usize)
-> 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 {
debug!("(resolving trait) found trait def: {:?}", path_res);
Ok(path_res)
Expand All @@ -1857,9 +1858,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
err.emit();
Err(())
Err(true)
}
} else {
}).map_err(|error_reported| {
if error_reported { return }

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

resolve_error(self, trait_path.span, error);
Err(())
}
})
}

fn resolve_generics(&mut self, generics: &Generics) {
Expand All @@ -1892,15 +1893,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&hir::WherePredicate::BoundPredicate(_) |
&hir::WherePredicate::RegionPredicate(_) => {}
&hir::WherePredicate::EqPredicate(ref eq_pred) => {
let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS);
if let Some(PathResolution { base_def: Def::TyParam(..), .. }) = path_res {
self.record_def(eq_pred.id, path_res.unwrap());
} else {
resolve_error(self,
eq_pred.span,
ResolutionError::UndeclaredAssociatedType);
self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS).and_then(|path_res| {
if let PathResolution { base_def: Def::TyParam(..), .. } = path_res {
Ok(self.record_def(eq_pred.id, path_res))
} else {
Err(false)
}
}).map_err(|error_reported| {
self.record_def(eq_pred.id, err_path_resolution());
}
if error_reported { return }
let error_variant = ResolutionError::UndeclaredAssociatedType;
resolve_error(self, eq_pred.span, error_variant);
}).unwrap_or(());
}
}
}
Expand Down Expand Up @@ -2170,21 +2174,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {

// This is a path in the type namespace. Walk through scopes
// looking for it.
match resolution {
Some(def) => {
// Write the result into the def map.
debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}",
path_names_to_string(path, 0),
ty.id,
def);
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);
if let Some(def) = resolution {
// Write the result into the def map.
debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}",
path_names_to_string(path, 0), ty.id, def);
self.record_def(ty.id, def);
} else {
self.record_def(ty.id, err_path_resolution());

// 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() {
"associated type"
} else {
Expand Down Expand Up @@ -2483,11 +2484,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {

PatKind::Struct(ref path, _, _) => {
match self.resolve_path(pat_id, path, 0, TypeNS) {
Some(definition) => {
Ok(definition) => {
self.record_def(pattern.id, definition);
}
result => {
debug!("(resolving pattern) didn't find struct def: {:?}", result);
Err(true) => self.record_def(pattern.id, err_path_resolution()),
Err(false) => {
resolve_error(
self,
path.span,
Expand Down Expand Up @@ -2554,14 +2555,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}

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 {
if resolution.is_some() {
break;
}
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) {
Expand All @@ -2574,7 +2575,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// Skips `path_depth` trailing segments, which is also reflected in the
/// returned value. See `middle::def::PathResolution` for more info.
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 segments = &path.segments[..path.segments.len() - path_depth];

Expand Down Expand Up @@ -2613,14 +2614,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
//
// Such behavior is required for backward compatibility.
// The same fallback is used when `a` resolves to nothing.
let unqualified_def = resolve_identifier_with_fallback(self, true);
return unqualified_def.and_then(|def| self.adjust_local_def(def, span)).map(mk_res);
let def = resolve_identifier_with_fallback(self, true).ok_or(false);
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 def = self.resolve_module_relative_path(span, segments, namespace);
match (def, unqualified_def) {
(Some(d), Some(ref ud)) if d == ud.def => {
(Ok(d), Some(ref ud)) if d == ud.def => {
self.session
.add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
id,
Expand Down Expand Up @@ -2741,7 +2742,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
span: Span,
segments: &[hir::PathSegment],
namespace: Namespace)
-> Option<Def> {
-> Result<Def, bool /* true if an error was reported */> {
let module_path = segments.split_last()
.unwrap()
.1
Expand All @@ -2762,9 +2763,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
};

resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
return None;
return Err(true);
}
Indeterminate => return None,
Indeterminate => return Err(false),
Success(resulting_module) => {
containing_module = resulting_module;
}
Expand All @@ -2775,7 +2776,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
result.success().map(|binding| {
self.check_privacy(containing_module, name, binding, span);
binding.def().unwrap()
})
}).ok_or(false)
}

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

resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
return None;
return Err(true);
}

Indeterminate => return None,
Indeterminate => return Err(false),

Success(resulting_module) => {
containing_module = resulting_module;
Expand All @@ -2825,7 +2826,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
result.success().map(|binding| {
self.check_privacy(containing_module, name, binding, span);
binding.def().unwrap()
})
}).ok_or(false)
}

fn with_no_errors<T, F>(&mut self, f: F) -> T
Expand Down Expand Up @@ -3040,25 +3041,26 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
});

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 */ }}`?",
path_name);
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.
self.resolve_path(expr.id, path, 0, ValueNS);

if let Ok(Def::Struct(..)) = type_res.map(|r| r.base_def) {
let error_variant =
ResolutionError::StructVariantUsedAsFunction(&path_name);
let mut err = resolve_struct_error(self, expr.span, error_variant);

let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
path_name);

if self.emit_errors {
err.fileline_help(expr.span, &msg);
} else {
err.span_help(expr.span, &msg);
}
err.emit();
} else {
// 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;
self.value_ribs.iter().rev().all(|rib| {
method_scope = match rib.kind {
Expand Down Expand Up @@ -3132,8 +3134,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// check to ensure that the path is actually a structure; that
// is checked later during typeck.
match self.resolve_path(expr.id, path, 0, TypeNS) {
Some(definition) => self.record_def(expr.id, definition),
None => {
Ok(definition) => self.record_def(expr.id, definition),
Err(true) => self.record_def(expr.id, err_path_resolution()),
Err(false) => {
debug!("(resolving expression) didn't find struct def",);

resolve_error(self,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@ extern crate macro_crate_test;
fn main() {
macro_crate_test::foo();
//~^ ERROR failed to resolve. Use of undeclared type or module `macro_crate_test`
//~^^ ERROR unresolved name `macro_crate_test::foo`
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/bad-module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern: unresolved name
// error-pattern: failed to resolve. Use of undeclared type or module `thing`

fn main() { let foo = thing::len(Vec::new()); }
1 change: 0 additions & 1 deletion src/test/compile-fail/bad-type-env-capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,5 @@

fn foo<T>() {
fn bar(b: T) { } //~ ERROR can't use type parameters from outer
//~^ ERROR type name `T` is undefined or not in scope
}
fn main() { }
2 changes: 1 addition & 1 deletion src/test/compile-fail/export-fully-qualified.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern: unresolved name
// error-pattern: failed to resolve. Use of undeclared type or module `foo`

// In this test baz isn't resolved when called as foo.baz even though
// it's called from inside foo. This is somewhat surprising and may
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/export2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern: unresolved name
// error-pattern: failed to resolve. Use of undeclared type or module `bar`

mod foo {
pub fn x() { bar::x(); }
Expand Down
1 change: 0 additions & 1 deletion src/test/compile-fail/inner-static-type-parameter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ enum Bar<T> { What } //~ ERROR parameter `T` is never used
fn foo<T>() {
static a: Bar<T> = Bar::What;
//~^ ERROR cannot use an outer type parameter in this context
//~| ERROR type name `T` is undefined or not in scope
}

fn main() {
Expand Down
1 change: 0 additions & 1 deletion src/test/compile-fail/issue-12796.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ trait Trait {
fn outer(&self) {
fn inner(_: &Self) {
//~^ ERROR can't use type parameters from outer function
//~^^ ERROR use of `Self` outside of an impl or trait
}
}
}
Expand Down
1 change: 0 additions & 1 deletion src/test/compile-fail/issue-3021-b.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ fn siphash(k0 : u64) {
impl siphash {
pub fn reset(&mut self) {
self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
//~^ ERROR unresolved name `k0`
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions src/test/compile-fail/issue-3021-c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ fn siphash<T>() {
trait t {
fn g(&self, x: T) -> T; //~ ERROR can't use type parameters from outer function; try using
//~^ ERROR can't use type parameters from outer function; try using
//~^^ ERROR type name `T` is undefined or not in scope
//~^^^ ERROR type name `T` is undefined or not in scope
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/test/compile-fail/issue-3021-d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ fn siphash(k0 : u64, k1 : u64) {
impl siphash for SipState {
fn reset(&self) {
self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
//~^ ERROR unresolved name `k0`
self.v1 = k1 ^ 0x646f72616e646f6d; //~ ERROR can't capture dynamic environment
//~^ ERROR unresolved name `k1`
}
fn result(&self) -> u64 { return mk_result(self); }
}
Expand Down
1 change: 0 additions & 1 deletion src/test/compile-fail/issue-3021.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ fn siphash(k0 : u64) {
impl SipHash for SipState {
fn reset(&self) {
self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
//~^ ERROR unresolved name `k0`
}
}
panic!();
Expand Down
1 change: 0 additions & 1 deletion src/test/compile-fail/issue-3214.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
fn foo<T>() {
struct foo {
x: T, //~ ERROR can't use type parameters from outer function;
//~^ ERROR type name `T` is undefined or not in scope
}

impl<T> Drop for foo<T> {
Expand Down
1 change: 0 additions & 1 deletion src/test/compile-fail/issue-3521-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ fn main() {

static y: isize = foo + 1;
//~^ ERROR attempt to use a non-constant value in a constant
//~| ERROR unresolved name `foo`

println!("{}", y);
}
3 changes: 1 addition & 2 deletions src/test/compile-fail/issue-3521.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ fn main() {
enum Stuff {
Bar = foo
//~^ ERROR attempt to use a non-constant value in a constant
//~| ERROR unresolved name `foo`
//~^^^ ERROR constant evaluation error: non-constant path in constant expression
//~^^ ERROR constant evaluation error: non-constant path in constant expression
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the const evaluation error triggering for DefError? Could we suppress that, too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe so -- I'll look into it.

}

println!("{}", Stuff::Bar);
Expand Down
Loading