about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorTim Chevalier <chevalier@alum.wellesley.edu>2013-08-13 17:54:14 -0700
committerTim Chevalier <chevalier@alum.wellesley.edu>2013-08-21 17:17:50 -0700
commitef8a5044ff26c8aab077a421b91231ce132e3ff5 (patch)
treeb095189873434979fe08d344eb89828429a213d1 /src
parent5622ce10fe6d0a06ac935214a729683bc2cc3d2c (diff)
downloadrust-ef8a5044ff26c8aab077a421b91231ce132e3ff5.tar.gz
rust-ef8a5044ff26c8aab077a421b91231ce132e3ff5.zip
rustc: More helpful error message when using a struct type like a function
Closes #6702
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/resolve.rs113
1 files changed, 66 insertions, 47 deletions
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<NodeId>,
 }
 
@@ -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<T>(@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));