diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 496e0c2a477..2e8748e4ff8 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -831,6 +831,7 @@ pub fn Resolver(session: Session, trait_map: HashMap::new(), used_imports: HashSet::new(), + emit_errors: true, intr: session.intr() }; @@ -888,6 +889,11 @@ pub struct Resolver { export_map2: ExportMap2, trait_map: TraitMap, + // Whether or not to print error messages. Can be set to true + // when getting additional info for error message suggestions, + // so as to avoid printing duplicate errors + emit_errors: bool, + used_imports: HashSet, } @@ -1072,7 +1078,7 @@ impl Resolver { // Return an error here by looking up the namespace that // had the duplicate. let ns = ns.unwrap(); - self.session.span_err(sp, + self.resolve_error(sp, fmt!("duplicate definition of %s `%s`", namespace_error_to_str(duplicate_type), self.session.str_of(name))); @@ -2074,7 +2080,7 @@ impl Resolver { self.import_path_to_str( import_directive.module_path, *import_directive.subclass)); - self.session.span_err(import_directive.span, msg); + self.resolve_error(import_directive.span, msg); } Indeterminate => { // Bail out. We'll come around next time. @@ -2445,12 +2451,12 @@ impl Resolver { let span = directive.span; if resolve_fail { - self.session.span_err(span, fmt!("unresolved import: there is no `%s` in `%s`", + self.resolve_error(span, fmt!("unresolved import: there is no `%s` in `%s`", self.session.str_of(source), self.module_to_str(containing_module))); return Failed; } else if priv_fail { - self.session.span_err(span, fmt!("unresolved import: found `%s` in `%s` but it is \ + self.resolve_error(span, fmt!("unresolved import: found `%s` in `%s` but it is \ private", self.session.str_of(source), self.module_to_str(containing_module))); return Failed; @@ -2617,14 +2623,14 @@ impl Resolver { hi: span.lo + BytePos(segment_name.len()), expn_info: span.expn_info, }; - self.session.span_err(span, + self.resolve_error(span, fmt!("unresolved import. maybe \ a missing `extern mod \ %s`?", segment_name)); return Failed; } - self.session.span_err(span, fmt!("unresolved import: could not find `%s` in \ + self.resolve_error(span, fmt!("unresolved import: could not find `%s` in \ `%s`.", segment_name, module_name)); return Failed; } @@ -2642,7 +2648,7 @@ impl Resolver { match type_def.module_def { None => { // Not a module. - self.session.span_err(span, + self.resolve_error(span, fmt!("not a \ module `%s`", self.session. @@ -2658,7 +2664,7 @@ impl Resolver { module_def.kind) { (ImportSearch, TraitModuleKind) | (ImportSearch, ImplModuleKind) => { - self.session.span_err( + self.resolve_error( span, "cannot import from a trait \ or type implementation"); @@ -2671,7 +2677,7 @@ impl Resolver { } None => { // There are no type bindings at all. - self.session.span_err(span, + self.resolve_error(span, fmt!("not a module `%s`", self.session.str_of( name))); @@ -2723,7 +2729,7 @@ impl Resolver { let mpath = self.idents_to_str(module_path); match mpath.rfind(':') { Some(idx) => { - self.session.span_err(span, fmt!("unresolved import: could not find `%s` \ + self.resolve_error(span, fmt!("unresolved import: could not find `%s` \ in `%s`", // idx +- 1 to account for the colons // on either side @@ -2759,8 +2765,7 @@ impl Resolver { module_path[0]); match result { Failed => { - self.session.span_err(span, - "unresolved name"); + self.resolve_error(span, "unresolved name"); return Failed; } Indeterminate => { @@ -3140,11 +3145,11 @@ impl Resolver { if index != import_count { let sn = self.session.codemap.span_to_snippet(imports[index].span).unwrap(); if sn.contains("::") { - self.session.span_err(imports[index].span, "unresolved import"); + self.resolve_error(imports[index].span, "unresolved import"); } else { let err = fmt!("unresolved import (maybe you meant `%s::*`?)", sn.slice(0, sn.len())); - self.session.span_err(imports[index].span, err); + self.resolve_error(imports[index].span, err); } } @@ -3409,7 +3414,7 @@ impl Resolver { // named function item. This is not allowed, so we // report an error. - self.session.span_err( + self.resolve_error( span, "can't capture dynamic environment in a fn item; \ use the || { ... } closure form instead"); @@ -3417,7 +3422,7 @@ impl Resolver { // This was an attempt to use a type parameter outside // its scope. - self.session.span_err(span, + self.resolve_error(span, "attempt to use a type \ argument out of scope"); } @@ -3432,7 +3437,7 @@ impl Resolver { // named function item. This is not allowed, so we // report an error. - self.session.span_err( + self.resolve_error( span, "can't capture dynamic environment in a fn item; \ use the || { ... } closure form instead"); @@ -3440,7 +3445,7 @@ impl Resolver { // This was an attempt to use a type parameter outside // its scope. - self.session.span_err(span, + self.resolve_error(span, "attempt to use a type \ argument out of scope"); } @@ -3449,7 +3454,7 @@ impl Resolver { } ConstantItemRibKind => { // Still doesn't deal with upvars - self.session.span_err(span, + self.resolve_error(span, "attempt to use a non-constant \ value in a constant"); @@ -3846,7 +3851,7 @@ impl Resolver { }; let msg = fmt!("attempt to %s a nonexistent trait `%s`", usage_str, path_str); - self.session.span_err(trait_reference.path.span, msg); + self.resolve_error(trait_reference.path.span, msg); } Some(def) => { debug!("(resolving trait) found trait def: %?", def); @@ -3867,7 +3872,7 @@ impl Resolver { match ident_map.find(&ident) { Some(&prev_field) => { let ident_str = self.session.str_of(ident); - self.session.span_err(field.span, + self.resolve_error(field.span, fmt!("field `%s` is already declared", ident_str)); self.session.span_note(prev_field.span, "Previously declared here"); @@ -4052,7 +4057,7 @@ impl Resolver { for (&key, &binding_0) in map_0.iter() { match map_i.find(&key) { None => { - self.session.span_err( + self.resolve_error( p.span, fmt!("variable `%s` from pattern #1 is \ not bound in pattern #%u", @@ -4060,7 +4065,7 @@ impl Resolver { } Some(binding_i) => { if binding_0.binding_mode != binding_i.binding_mode { - self.session.span_err( + self.resolve_error( binding_i.span, fmt!("variable `%s` is bound with different \ mode in pattern #%u than in pattern #1", @@ -4072,7 +4077,7 @@ impl Resolver { for (&key, &binding) in map_i.iter() { if !map_0.contains_key(&key) { - self.session.span_err( + self.resolve_error( binding.span, fmt!("variable `%s` from pattern #%u is \ not bound in pattern #1", @@ -4185,7 +4190,7 @@ impl Resolver { self.record_def(path_id, def); } None => { - self.session.span_err + self.resolve_error (ty.span, fmt!("use of undeclared type name `%s`", self.idents_to_str(path.idents))); } @@ -4253,7 +4258,7 @@ impl Resolver { self.record_def(pattern.id, def); } FoundStructOrEnumVariant(_) => { - self.session.span_err(pattern.span, + self.resolve_error(pattern.span, fmt!("declaration of `%s` \ shadows an enum \ variant or unit-like \ @@ -4273,7 +4278,7 @@ impl Resolver { self.record_def(pattern.id, def); } FoundConst(_) => { - self.session.span_err(pattern.span, + self.resolve_error(pattern.span, "only refutable patterns \ allowed here"); } @@ -4327,7 +4332,7 @@ impl Resolver { // Then this is a duplicate variable // in the same disjunct, which is an // error - self.session.span_err(pattern.span, + self.resolve_error(pattern.span, fmt!("Identifier `%s` is bound more \ than once in the same pattern", path_to_str(path, self.session @@ -4367,14 +4372,14 @@ impl Resolver { self.record_def(pattern.id, def); } Some(_) => { - self.session.span_err( + self.resolve_error( path.span, fmt!("`%s` is not an enum variant or constant", self.session.str_of( *path.idents.last()))); } None => { - self.session.span_err(path.span, + self.resolve_error(path.span, "unresolved enum variant"); } } @@ -4395,14 +4400,14 @@ impl Resolver { self.record_def(pattern.id, def); } Some(_) => { - self.session.span_err( + self.resolve_error( path.span, fmt!("`%s` is not an enum variant, struct or const", self.session.str_of( *path.idents.last()))); } None => { - self.session.span_err(path.span, + self.resolve_error(path.span, "unresolved enum variant, \ struct or const"); } @@ -4441,7 +4446,7 @@ impl Resolver { result => { debug!("(resolving pattern) didn't find struct \ def: %?", result); - self.session.span_err( + self.resolve_error( path.span, fmt!("`%s` does not name a structure", self.idents_to_str(path.idents))); @@ -4661,7 +4666,7 @@ impl Resolver { path.span, PathPublicOnlySearch) { Failed => { - self.session.span_err(path.span, + self.resolve_error(path.span, fmt!("use of undeclared module `%s`", self.idents_to_str( module_path_idents))); @@ -4729,7 +4734,7 @@ impl Resolver { path.span, PathPublicOrPrivateSearch) { Failed => { - self.session.span_err(path.span, + self.resolve_error(path.span, fmt!("use of undeclared module `::%s`", self.idents_to_str( module_path_idents))); @@ -4855,6 +4860,19 @@ impl Resolver { } } + fn with_no_errors(@mut self, f: &fn() -> T) -> T { + self.emit_errors = false; + let rs = f(); + self.emit_errors = true; + rs + } + + fn resolve_error(@mut self, span: span, s: &str) { + if self.emit_errors { + self.session.span_err(span, s); + } + } + pub fn find_best_match_for_name(@mut self, name: &str, max_distance: uint) @@ -4954,7 +4972,7 @@ impl Resolver { // out here. match def { def_method(*) => { - self.session.span_err(expr.span, + self.resolve_error(expr.span, "first-class methods \ are not supported"); self.session.span_note(expr.span, @@ -4971,7 +4989,7 @@ impl Resolver { let wrong_name = self.idents_to_str( path.idents); if self.name_exists_in_scope_struct(wrong_name) { - self.session.span_err(expr.span, + self.resolve_error(expr.span, fmt!("unresolved name `%s`. \ Did you mean `self.%s`?", wrong_name, @@ -4980,12 +4998,13 @@ impl Resolver { else { // Be helpful if the name refers to a struct // (The pattern matching def_tys where the id is in self.structs - // matches on regular structs while excluding tuple- and - // enum-like structs, which wouldn't result in this error.) - match self.resolve_path(expr.id, path, TypeNS, false, visitor) { + // matches on regular structs while excluding tuple- and enum-like + // structs, which wouldn't result in this error.) + match self.with_no_errors(|| + self.resolve_path(expr.id, path, TypeNS, false, visitor)) { Some(def_ty(struct_id)) if self.structs.contains(&struct_id) => { - self.session.span_err(expr.span, + self.resolve_error(expr.span, fmt!("`%s` is a structure name, but this expression \ uses it like a function name", wrong_name)); @@ -4998,13 +5017,13 @@ impl Resolver { // of stupid suggestions match self.find_best_match_for_name(wrong_name, 5) { Some(m) => { - self.session.span_err(expr.span, + self.resolve_error(expr.span, fmt!("unresolved name `%s`. \ Did you mean `%s`?", wrong_name, m)); } None => { - self.session.span_err(expr.span, + self.resolve_error(expr.span, fmt!("unresolved name `%s`.", wrong_name)); } @@ -5041,7 +5060,7 @@ impl Resolver { result => { debug!("(resolving expression) didn't find struct \ def: %?", result); - self.session.span_err( + self.resolve_error( path.span, fmt!("`%s` does not name a structure", self.idents_to_str(path.idents))); @@ -5070,7 +5089,7 @@ impl Resolver { match self.search_ribs(self.label_ribs, label, expr.span, DontAllowCapturingSelf) { None => - self.session.span_err(expr.span, + self.resolve_error(expr.span, fmt!("use of undeclared label \ `%s`", self.session.str_of( @@ -5089,7 +5108,7 @@ impl Resolver { expr_self => { match self.resolve_self_value_in_local_ribs(expr.span) { None => { - self.session.span_err(expr.span, + self.resolve_error(expr.span, "`self` is not allowed in \ this context") } @@ -5320,7 +5339,7 @@ impl Resolver { match pat_binding_mode { bind_infer => {} bind_by_ref(*) => { - self.session.span_err( + self.resolve_error( pat.span, fmt!("cannot use `ref` binding mode with %s", descr));