]> git.lizzy.rs Git - rust.git/commitdiff
Refactoring
authorNick Cameron <ncameron@mozilla.com>
Wed, 23 Dec 2015 06:27:20 +0000 (19:27 +1300)
committerNick Cameron <ncameron@mozilla.com>
Wed, 30 Dec 2015 01:27:59 +0000 (14:27 +1300)
13 files changed:
src/librustc/lint/context.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/infer/mod.rs
src/librustc_driver/test.rs
src/librustc_lint/builtin.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_trans/trans/base.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/libsyntax/errors/mod.rs

index 66ebd3081c0c76bcd3dc210a72ef1c385063585f..464f29a33937f053c0ba9ae191b5b7ddd5667219 100644 (file)
@@ -368,7 +368,7 @@ pub fn raw_emit_lint(sess: &Session,
                      lvlsrc: LevelSource,
                      span: Option<Span>,
                      msg: &str) {
-    raw_struct_lint(sess, lint, lvlsrc, span, msg).map(|mut e| e.emit());
+    raw_struct_lint(sess, lint, lvlsrc, span, msg).emit();
 }
 
 pub fn raw_struct_lint<'a>(sess: &'a Session,
@@ -376,10 +376,10 @@ pub fn raw_struct_lint<'a>(sess: &'a Session,
                            lvlsrc: LevelSource,
                            span: Option<Span>,
                            msg: &str)
-                           -> Option<DiagnosticBuilder<'a>> {
+                           -> DiagnosticBuilder<'a> {
     let (mut level, source) = lvlsrc;
     if level == Allow {
-        return None;
+        return sess.diagnostic().struct_dummy();
     }
 
     let name = lint.name_lower();
@@ -416,7 +416,8 @@ pub fn raw_struct_lint<'a>(sess: &'a Session,
     if let Some(span) = def {
         err.span_note(span, "lint level defined here");
     }
-    Some(err)
+
+    err
 }
 
 pub trait LintContext: Sized {
@@ -456,9 +457,9 @@ fn lookup(&self,
               lint: &'static Lint,
               span: Option<Span>,
               msg: &str)
-              -> Option<DiagnosticBuilder> {
+              -> DiagnosticBuilder {
         let (level, src) = match self.level_src(lint) {
-            None => return None,
+            None => return self.sess().diagnostic().struct_dummy(),
             Some(pair) => pair,
         };
 
@@ -474,17 +475,14 @@ fn struct_span_lint(&self,
                         lint: &'static Lint,
                         span: Span,
                         msg: &str)
-                        -> Option<DiagnosticBuilder> {
+                        -> DiagnosticBuilder {
         self.lookup(lint, Some(span), msg)
     }
 
     /// Emit a lint and note at the appropriate level, for a particular span.
     fn span_lint_note(&self, lint: &'static Lint, span: Span, msg: &str,
                       note_span: Span, note: &str) {
-        let mut err = match self.lookup(lint, Some(span), msg) {
-            Some(e) => e,
-            None => return
-        };
+        let mut err = self.lookup(lint, Some(span), msg);
         if self.current_level(lint) != Level::Allow {
             if note_span == span {
                 err.fileline_note(note_span, note);
@@ -498,10 +496,7 @@ fn span_lint_note(&self, lint: &'static Lint, span: Span, msg: &str,
     /// Emit a lint and help at the appropriate level, for a particular span.
     fn span_lint_help(&self, lint: &'static Lint, span: Span,
                       msg: &str, help: &str) {
-        let mut err = match self.lookup(lint, Some(span), msg) {
-            Some(e) => e,
-            None => return
-        };
+        let mut err = self.lookup(lint, Some(span), msg);
         self.span_lint(lint, span, msg);
         if self.current_level(lint) != Level::Allow {
             err.span_help(span, help);
index 5382e328a113b1e1521db1e6cfdb17d82ca0bcd7..d628227d5e63cacad504cbc7c232eb909502c4cb 100644 (file)
@@ -237,7 +237,7 @@ fn process_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)
     fn report_type_error(&self,
                          trace: TypeTrace<'tcx>,
                          terr: &TypeError<'tcx>)
-                         -> Option<DiagnosticBuilder<'tcx>>;
+                         -> DiagnosticBuilder<'tcx>;
 
     fn check_and_note_conflicting_crates(&self,
                                          err: &mut DiagnosticBuilder,
@@ -478,11 +478,11 @@ fn append_to_same_regions(same_regions: &mut Vec<SameRegions>,
     fn report_type_error(&self,
                          trace: TypeTrace<'tcx>,
                          terr: &TypeError<'tcx>)
-                         -> Option<DiagnosticBuilder<'tcx>> {
+                         -> DiagnosticBuilder<'tcx> {
         let expected_found_str = match self.values_str(&trace.values) {
             Some(v) => v,
             None => {
-                return None; /* derived error */
+                return self.tcx.sess.diagnostic().struct_dummy(); /* derived error */
             }
         };
 
@@ -507,7 +507,7 @@ fn report_type_error(&self,
             },
             _ => ()
         }
-        Some(err)
+        err
     }
 
     /// Adds a note if the types come from similarly named crates
@@ -560,11 +560,9 @@ fn report_and_explain_type_error(&self,
                                      trace: TypeTrace<'tcx>,
                                      terr: &TypeError<'tcx>) {
         let span = trace.origin.span();
-        let err = self.report_type_error(trace, terr);
-        err.map(|mut err| {
-            self.tcx.note_and_explain_type_err(&mut err, terr, span);
-            err.emit();
-        });
+        let mut err = self.report_type_error(trace, terr);
+        self.tcx.note_and_explain_type_err(&mut err, terr, span);
+        err.emit();
     }
 
     /// Returns a string of the form "expected `{}`, found `{}`", or None if this is a derived
index 81d3d429f26b87e07586afc0296a250fdacb4969..21a1ee37b7f436c1e8fb772e9ad2511263193a76 100644 (file)
@@ -1281,7 +1281,7 @@ pub fn type_error_struct_str<M>(&self,
                                     mk_msg: M,
                                     actual_ty: String,
                                     err: Option<&TypeError<'tcx>>)
-                                    -> Option<DiagnosticBuilder<'tcx>>
+                                    -> DiagnosticBuilder<'tcx>
         where M: FnOnce(Option<String>, String) -> String,
     {
         self.type_error_struct_str_with_expected(sp, mk_msg, None, actual_ty, err)
@@ -1296,7 +1296,7 @@ pub fn type_error_message_str_with_expected<M>(&self,
         where M: FnOnce(Option<String>, String) -> String,
     {
         self.type_error_struct_str_with_expected(sp, mk_msg, expected_ty, actual_ty, err)
-            .map(|mut e| e.emit());
+            .emit();
     }
 
     pub fn type_error_struct_str_with_expected<M>(&self,
@@ -1305,7 +1305,7 @@ pub fn type_error_struct_str_with_expected<M>(&self,
                                                   expected_ty: Option<Ty<'tcx>>,
                                                   actual_ty: String,
                                                   err: Option<&TypeError<'tcx>>)
-                                                  -> Option<DiagnosticBuilder<'tcx>>
+                                                  -> DiagnosticBuilder<'tcx>
         where M: FnOnce(Option<String>, String) -> String,
     {
         debug!("hi! expected_ty = {:?}, actual_ty = {}", expected_ty, actual_ty);
@@ -1324,9 +1324,9 @@ pub fn type_error_struct_str_with_expected<M>(&self,
             if let Some(err) = err {
                 self.tcx.note_and_explain_type_err(&mut db, err, sp);
             }
-            Some(db)
+            db
         } else {
-            None
+            self.tcx.sess.diagnostic().struct_dummy()
         }
     }
 
@@ -1337,7 +1337,7 @@ pub fn type_error_message<M>(&self,
                                  err: Option<&TypeError<'tcx>>)
         where M: FnOnce(String) -> String,
     {
-        self.type_error_struct(sp, mk_msg, actual_ty, err).map(|mut e| e.emit());
+        self.type_error_struct(sp, mk_msg, actual_ty, err).emit();
     }
 
     pub fn type_error_struct<M>(&self,
@@ -1345,14 +1345,14 @@ pub fn type_error_struct<M>(&self,
                                 mk_msg: M,
                                 actual_ty: Ty<'tcx>,
                                 err: Option<&TypeError<'tcx>>)
-                                -> Option<DiagnosticBuilder<'tcx>>
+                                -> DiagnosticBuilder<'tcx>
         where M: FnOnce(String) -> String,
     {
         let actual_ty = self.resolve_type_vars_if_possible(&actual_ty);
 
         // Don't report an error if actual type is TyError.
         if actual_ty.references_error() {
-            return None;
+            return self.tcx.sess.diagnostic().struct_dummy();
         }
 
         self.type_error_struct_str(sp,
index 50a672a4b69e700414629c453f10dd460010a89b..7bcf3276da7a450693eb3994a5d628b66d838536 100644 (file)
@@ -60,7 +60,7 @@ struct ExpectErrorEmitter {
 fn remove_message(e: &mut ExpectErrorEmitter, msg: &str, lvl: Level) {
     match lvl {
         Level::Bug | Level::Fatal | Level::Error => {}
-        Level::Warning | Level::Note | Level::Help => {
+        _ => {
             return;
         }
     }
index 24b346b3b317f0a2eb964475a67cb12d98e30411..09e6f454fb4f51c5ffaccba9fdccff42e83da4b7 100644 (file)
@@ -754,18 +754,17 @@ fn check_fn(&mut self, cx: &LateContext, fn_kind: FnKind, _: &hir::FnDecl,
         if !reached_exit_without_self_call && !self_call_spans.is_empty() {
             let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION, sp,
                                              "function cannot return without recurring");
-            let mut db = db.as_mut();
 
             // FIXME #19668: these could be span_lint_note's instead of this manual guard.
             if cx.current_level(UNCONDITIONAL_RECURSION) != Level::Allow {
                 // offer some help to the programmer.
                 for call in &self_call_spans {
-                    db = db.map(|db| db.span_note(*call, "recursive call site"));
+                    db.span_note(*call, "recursive call site");
                 }
-                db = db.map(|db| db.fileline_help(sp, "a `loop` may express intention \
-                                                       better if this is on purpose"));
+                db.fileline_help(sp, "a `loop` may express intention \
+                                      better if this is on purpose");
             }
-            db.map(|db| db.emit());
+            db.emit();
         }
 
         // all done
index 91fed4e5b9cf350c477c16f6a6fc8a4bb8f0b186..1d3f2b79844ea0094120458537cc139239d58055 100644 (file)
@@ -144,9 +144,9 @@ fn add_child(&self,
 
                 if let Some(sp) = child[ns].span() {
                     let note = format!("first definition of {} `{}` here", ns_str, name);
-                    err.as_mut().map(|mut e| e.span_note(sp, &note));
+                    err.span_note(sp, &note);
                 }
-                err.as_mut().map(|mut e| e.emit());
+                err.emit();
                 child
             }
         }
@@ -261,10 +261,9 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                                           mod_spans[0],
                                           ResolutionError::SelfImportCanOnlyAppearOnceInTheList);
                             for other_span in mod_spans.iter().skip(1) {
-                                e.as_mut().map(|mut e| e.span_note(*other_span,
-                                                          "another `self` import appears here"));
+                                e.span_note(*other_span, "another `self` import appears here");
                             }
-                            e.as_mut().map(|mut e| e.emit());
+                            e.emit();
                         }
 
                         for source_item in source_items {
index 67895ed21317490d033e12e4c59d2759cb0e1f85..c2dd764f224b2e45839b225f807807f485ca5504 100644 (file)
@@ -216,18 +216,18 @@ pub enum UnresolvedNameContext {
 fn resolve_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
                                        span: syntax::codemap::Span,
                                        resolution_error: ResolutionError<'b>) {
-    resolve_struct_error(resolver, span, resolution_error).map(|mut e| e.emit());
+    resolve_struct_error(resolver, span, resolution_error).emit();
 }
 
 fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
                                               span: syntax::codemap::Span,
                                               resolution_error: ResolutionError<'b>)
-                                              -> Option<DiagnosticBuilder<'a>> {
+                                              -> DiagnosticBuilder<'a> {
     if !resolver.emit_errors {
-        return None;
+        return resolver.session.diagnostic().struct_dummy();
     }
 
-    Some(match resolution_error {
+    match resolution_error {
         ResolutionError::TypeParametersFromOuterFunction => {
             struct_span_err!(resolver.session,
                              span,
@@ -532,7 +532,7 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
                              E0435,
                              "attempt to use a non-constant value in a constant")
         }
-    })
+    }
 }
 
 #[derive(Copy, Clone)]
@@ -2202,10 +2202,10 @@ fn resolve_trait_reference(&mut self,
 
                 // If it's a typedef, give a note
                 if let DefTy(..) = path_res.base_def {
-                    err.as_mut().map(|mut e| e.span_note(trait_path.span,
-                                                      "`type` aliases cannot be used for traits"));
+                    err.span_note(trait_path.span,
+                                  "`type` aliases cannot be used for traits");
                 }
-                err.as_mut().map(|mut e| e.emit());
+                err.emit();
                 Err(())
             }
         } else {
@@ -3493,11 +3493,11 @@ fn resolve_expr(&mut self, expr: &Expr) {
                         let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
                                           path_name);
                         if self.emit_errors {
-                            err.as_mut().map(|mut e| e.fileline_help(expr.span, &msg));
+                            err.fileline_help(expr.span, &msg);
                         } else {
-                            err.as_mut().map(|mut e| e.span_help(expr.span, &msg));
+                            err.span_help(expr.span, &msg);
                         }
-                        err.as_mut().map(|mut e| e.emit());
+                        err.emit();
                         self.record_def(expr.id, err_path_resolution());
                     } else {
                         // Write the result into the def map.
@@ -3534,11 +3534,11 @@ fn resolve_expr(&mut self, expr: &Expr) {
                             let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
                                               path_name);
                             if self.emit_errors {
-                                err.as_mut().map(|mut e| e.fileline_help(expr.span, &msg));
+                                err.fileline_help(expr.span, &msg);
                             } else {
-                                err.as_mut().map(|mut e| e.span_help(expr.span, &msg));
+                                err.span_help(expr.span, &msg);
                             }
-                            err.as_mut().map(|mut e| e.emit());
+                            err.emit();
                         }
                         _ => {
                             // Keep reporting some errors even if they're ignored above.
index d7fbe1193b6ba8f55c052156d8d36aa3ce4744bb..996e72bdad3250e55adc87a102e26125c5c13f9f 100644 (file)
@@ -2213,11 +2213,9 @@ fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &hir::EnumDef, sp: Span,
                               &format!("enum variant is more than three times larger ({} bytes) \
                                         than the next largest (ignoring padding)",
                                        largest))
-            .map(|mut e| {
-                e.span_note(enum_def.variants[largest_index].span,
+            .span_note(enum_def.variants[largest_index].span,
                        "this variant is the largest")
-                 .emit();
-            });
+            .emit();
     }
 }
 
index 07a1da9206750e68a799d82f4effdb96d87a0d26..a1b378d84d0010faf8f9a1fbbb3a4c1c612d748f 100644 (file)
@@ -232,20 +232,19 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
             let mut err = fcx.type_error_struct(call_expr.span, |actual| {
                 format!("expected function, found `{}`", actual)
             }, callee_ty, None);
-            let mut err = err.as_mut();
 
             if let hir::ExprCall(ref expr, _) = call_expr.node {
                 let tcx = fcx.tcx();
                 if let Some(pr) = tcx.def_map.borrow().get(&expr.id) {
                     if pr.depth == 0 && pr.base_def != def::DefErr {
                         if let Some(span) = tcx.map.span_if_local(pr.def_id()) {
-                            err = err.map(|e| e.span_note(span, "defined here"));
+                            err.span_note(span, "defined here");
                         }
                     }
                 }
             }
 
-            err.map(|e| e.emit());
+            err.emit();
 
             // This is the "default" function signature, used in case of error.
             // In that case, we check each argument against "error" in order to
index 057671cad5cf4a54e2313ad496f5ca54051adecb..90e67944ef90481474fb4f1caf713b6c2aa8348e 100644 (file)
@@ -132,17 +132,15 @@ fn report_cast_error<'a>(&self, fcx: &FnCtxt<'a, 'tcx>,
                             actual,
                             fcx.infcx().ty_to_string(self.cast_ty))
                 }, self.expr_ty, None)
-                    .map(|mut err| {
-                        err.fileline_help(self.span,
-                            &format!("cast through {} first", match e {
-                                CastError::NeedViaPtr => "a raw pointer",
-                                CastError::NeedViaThinPtr => "a thin pointer",
-                                CastError::NeedViaInt => "an integer",
-                                CastError::NeedViaUsize => "a usize",
-                                _ => unreachable!()
-                            }));
-                        err.emit();
-                    });
+                    .fileline_help(self.span,
+                        &format!("cast through {} first", match e {
+                            CastError::NeedViaPtr => "a raw pointer",
+                            CastError::NeedViaThinPtr => "a thin pointer",
+                            CastError::NeedViaInt => "an integer",
+                            CastError::NeedViaUsize => "a usize",
+                            _ => unreachable!()
+                        }))
+                    .emit();
             }
             CastError::CastToBool => {
                 struct_span_err!(fcx.tcx().sess, self.span, E0054, "cannot cast as `bool`")
@@ -174,10 +172,8 @@ fn report_cast_error<'a>(&self, fcx: &FnCtxt<'a, 'tcx>,
                             actual,
                             fcx.infcx().ty_to_string(self.cast_ty))
                 }, self.expr_ty, None)
-                    .map(|mut err| {
-                        err.fileline_note(self.span, "vtable kinds may not match");
-                        err.emit();
-                    });
+                    .fileline_note(self.span, "vtable kinds may not match")
+                    .emit();
             }
         }
     }
index 5c0eefd5f85d4dba632530133265ff298d5ffb8f..65b0d5892756c2790735810db1a975f6daace4a3 100644 (file)
@@ -69,103 +69,101 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 rcvr_ty,
                 None);
 
-            if let Some(ref mut err) = err {
-                // If the item has the name of a field, give a help note
-                if let (&ty::TyStruct(def, substs), Some(expr)) = (&rcvr_ty.sty, rcvr_expr) {
-                    if let Some(field) = def.struct_variant().find_field_named(item_name) {
-                        let expr_string = match cx.sess.codemap().span_to_snippet(expr.span) {
-                            Ok(expr_string) => expr_string,
-                            _ => "s".into() // Default to a generic placeholder for the
-                                            // expression when we can't generate a string
-                                            // snippet
-                        };
-
-                        macro_rules! span_stored_function {
-                            () => {
-                                err.span_note(span,
-                                              &format!("use `({0}.{1})(...)` if you meant to call \
-                                                        the function stored in the `{1}` field",
-                                                       expr_string, item_name));
-                            }
+            // If the item has the name of a field, give a help note
+            if let (&ty::TyStruct(def, substs), Some(expr)) = (&rcvr_ty.sty, rcvr_expr) {
+                if let Some(field) = def.struct_variant().find_field_named(item_name) {
+                    let expr_string = match cx.sess.codemap().span_to_snippet(expr.span) {
+                        Ok(expr_string) => expr_string,
+                        _ => "s".into() // Default to a generic placeholder for the
+                                        // expression when we can't generate a string
+                                        // snippet
+                    };
+
+                    macro_rules! span_stored_function {
+                        () => {
+                            err.span_note(span,
+                                          &format!("use `({0}.{1})(...)` if you meant to call \
+                                                    the function stored in the `{1}` field",
+                                                   expr_string, item_name));
                         }
+                    }
 
-                        macro_rules! span_did_you_mean {
-                            () => {
-                                err.span_note(span, &format!("did you mean to write `{0}.{1}`?",
-                                                             expr_string, item_name));
-                            }
+                    macro_rules! span_did_you_mean {
+                        () => {
+                            err.span_note(span, &format!("did you mean to write `{0}.{1}`?",
+                                                         expr_string, item_name));
                         }
+                    }
 
-                        // Determine if the field can be used as a function in some way
-                        let field_ty = field.ty(cx, substs);
+                    // Determine if the field can be used as a function in some way
+                    let field_ty = field.ty(cx, substs);
 
-                        match field_ty.sty {
-                            // Not all of these (e.g. unsafe fns) implement FnOnce
-                            // so we look for these beforehand
-                            ty::TyClosure(..) | ty::TyBareFn(..) => {
-                                span_stored_function!();
-                            }
-                            // If it's not a simple function, look for things which implement FnOnce
-                            _ => {
-                                if let Ok(fn_once_trait_did) =
-                                        cx.lang_items.require(FnOnceTraitLangItem) {
-                                    let infcx = fcx.infcx();
-                                    infcx.probe(|_| {
-                                        let fn_once_substs =
-                                            Substs::new_trait(vec![infcx.next_ty_var()],
-                                                              Vec::new(),
-                                                              field_ty);
-                                        let trait_ref =
-                                          ty::TraitRef::new(fn_once_trait_did,
-                                                            cx.mk_substs(fn_once_substs));
-                                        let poly_trait_ref = trait_ref.to_poly_trait_ref();
-                                        let obligation = Obligation::misc(span,
-                                                                          fcx.body_id,
-                                                                          poly_trait_ref
-                                                                             .to_predicate());
-                                        let mut selcx = SelectionContext::new(infcx);
-
-                                        if selcx.evaluate_obligation(&obligation) {
-                                            span_stored_function!();
-                                        } else {
-                                            span_did_you_mean!();
-                                        }
-                                    });
-                                } else {
-                                    span_did_you_mean!();
-                                }
+                    match field_ty.sty {
+                        // Not all of these (e.g. unsafe fns) implement FnOnce
+                        // so we look for these beforehand
+                        ty::TyClosure(..) | ty::TyBareFn(..) => {
+                            span_stored_function!();
+                        }
+                        // If it's not a simple function, look for things which implement FnOnce
+                        _ => {
+                            if let Ok(fn_once_trait_did) =
+                                    cx.lang_items.require(FnOnceTraitLangItem) {
+                                let infcx = fcx.infcx();
+                                infcx.probe(|_| {
+                                    let fn_once_substs =
+                                        Substs::new_trait(vec![infcx.next_ty_var()],
+                                                          Vec::new(),
+                                                          field_ty);
+                                    let trait_ref =
+                                      ty::TraitRef::new(fn_once_trait_did,
+                                                        cx.mk_substs(fn_once_substs));
+                                    let poly_trait_ref = trait_ref.to_poly_trait_ref();
+                                    let obligation = Obligation::misc(span,
+                                                                      fcx.body_id,
+                                                                      poly_trait_ref
+                                                                         .to_predicate());
+                                    let mut selcx = SelectionContext::new(infcx);
+
+                                    if selcx.evaluate_obligation(&obligation) {
+                                        span_stored_function!();
+                                    } else {
+                                        span_did_you_mean!();
+                                    }
+                                });
+                            } else {
+                                span_did_you_mean!();
                             }
                         }
                     }
                 }
+            }
 
-                if !static_sources.is_empty() {
-                    err.fileline_note(
-                        span,
-                        "found defined static methods, maybe a `self` is missing?");
-
-                    report_candidates(fcx, err, span, item_name, static_sources);
-                }
+            if !static_sources.is_empty() {
+                err.fileline_note(
+                    span,
+                    "found defined static methods, maybe a `self` is missing?");
 
-                if !unsatisfied_predicates.is_empty() {
-                    let bound_list = unsatisfied_predicates.iter()
-                        .map(|p| format!("`{} : {}`",
-                                         p.self_ty(),
-                                         p))
-                        .collect::<Vec<_>>()
-                        .join(", ");
-                    err.fileline_note(
-                        span,
-                        &format!("the method `{}` exists but the \
-                                 following trait bounds were not satisfied: {}",
-                                 item_name,
-                                 bound_list));
-                }
+                report_candidates(fcx, &mut err, span, item_name, static_sources);
+            }
 
-                suggest_traits_to_import(fcx, err, span, rcvr_ty, item_name,
-                                         rcvr_expr, out_of_scope_traits);
-                err.emit();
+            if !unsatisfied_predicates.is_empty() {
+                let bound_list = unsatisfied_predicates.iter()
+                    .map(|p| format!("`{} : {}`",
+                                     p.self_ty(),
+                                     p))
+                    .collect::<Vec<_>>()
+                    .join(", ");
+                err.fileline_note(
+                    span,
+                    &format!("the method `{}` exists but the \
+                             following trait bounds were not satisfied: {}",
+                             item_name,
+                             bound_list));
             }
+
+            suggest_traits_to_import(fcx, &mut err, span, rcvr_ty, item_name,
+                                     rcvr_expr, out_of_scope_traits);
+            err.emit();
         }
 
         MethodError::Ambiguity(sources) => {
index 99a72a4c9df10f9deef75e4ff10b8ffcbf6adc7b..ea08343bbc04c998bc3bd3895b07f58b9097f8ef 100644 (file)
@@ -1051,16 +1051,16 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             if t_cast.is_trait() {
                 match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
                     Ok(s) => {
-                        err.as_mut().unwrap().span_suggestion(t_span,
-                                                              "try casting to a reference instead:",
-                                                              format!("&{}{}", mtstr, s));
+                        err.span_suggestion(t_span,
+                                            "try casting to a reference instead:",
+                                            format!("&{}{}", mtstr, s));
                     },
                     Err(_) =>
-                        span_help!(err.as_mut().unwrap(), t_span,
+                        span_help!(err, t_span,
                                    "did you mean `&{}{}`?", mtstr, tstr),
                 }
             } else {
-                span_help!(err.as_mut().unwrap(), span,
+                span_help!(err, span,
                            "consider using an implicit coercion to `&{}{}` instead",
                            mtstr, tstr);
             }
@@ -1068,20 +1068,20 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         ty::TyBox(..) => {
             match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
                 Ok(s) => {
-                    err.as_mut().unwrap().span_suggestion(t_span,
+                    err.span_suggestion(t_span,
                                                           "try casting to a `Box` instead:",
                                                            format!("Box<{}>", s));
                 },
                 Err(_) =>
-                    span_help!(err.as_mut().unwrap(), t_span, "did you mean `Box<{}>`?", tstr),
+                    span_help!(err, t_span, "did you mean `Box<{}>`?", tstr),
             }
         }
         _ => {
-            span_help!(err.as_mut().unwrap(), e_span,
+            span_help!(err, e_span,
                        "consider using a box or reference as appropriate");
         }
     }
-    err.map(|mut e| e.emit());
+    err.emit();
     fcx.write_error(id);
 }
 
@@ -1630,7 +1630,7 @@ pub fn type_error_struct<M>(&self,
                                 mk_msg: M,
                                 actual_ty: Ty<'tcx>,
                                 err: Option<&TypeError<'tcx>>)
-                                -> Option<DiagnosticBuilder<'tcx>>
+                                -> DiagnosticBuilder<'tcx>
         where M: FnOnce(String) -> String,
     {
         self.infcx().type_error_struct(sp, mk_msg, actual_ty, err)
@@ -2966,13 +2966,12 @@ fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                                `{}`", field.node, actual)
                                    },
                                    expr_t, None)
-                .unwrap()
                 .fileline_help(field.span,
                                "maybe a `()` to call it is missing? \
                                If not, try an anonymous function")
                 .emit();
         } else {
-            fcx.type_error_struct(
+            let mut err = fcx.type_error_struct(
                 expr.span,
                 |actual| {
                     format!("attempted access of field `{}` on \
@@ -2981,13 +2980,11 @@ fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                             field.node,
                             actual)
                 },
-                expr_t, None)
-            .map(|mut e| {
-                if let ty::TyStruct(def, _) = expr_t.sty {
-                    suggest_field_names(&mut e, def.struct_variant(), field, vec![]);
-                }
-                e.emit();
-            });
+                expr_t, None);
+            if let ty::TyStruct(def, _) = expr_t.sty {
+                suggest_field_names(&mut err, def.struct_variant(), field, vec![]);
+            }
+            err.emit();
         }
 
         fcx.write_error(expr.id);
@@ -3089,7 +3086,7 @@ fn report_unknown_field<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                       variant: ty::VariantDef<'tcx>,
                                       field: &hir::Field,
                                       skip_fields: &[hir::Field]) {
-        fcx.type_error_struct(
+        let mut err = fcx.type_error_struct(
             field.name.span,
             |actual| if let ty::TyEnum(..) = ty.sty {
                 format!("struct variant `{}::{}` has no field named `{}`",
@@ -3099,13 +3096,11 @@ fn report_unknown_field<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         actual, field.name.node)
             },
             ty,
-            None)
-        .map(|mut e| {
-            // prevent all specified fields from being suggested
-            let skip_fields = skip_fields.iter().map(|ref x| x.name.node.as_str());
-            suggest_field_names(&mut e, variant, &field.name, skip_fields.collect());
-            e.emit();
-        });
+            None);
+        // prevent all specified fields from being suggested
+        let skip_fields = skip_fields.iter().map(|ref x| x.name.node.as_str());
+        suggest_field_names(&mut err, variant, &field.name, skip_fields.collect());
+        err.emit();
     }
 
     fn check_expr_struct_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
index 3b75bf9a8bd40458835f6dc7f0988e09f452db83..3cee14538a905d23c11b9fbc94dd415f70681d79 100644 (file)
@@ -107,7 +107,6 @@ pub struct DiagnosticBuilder<'a> {
     code: Option<String>,
     span: Option<Span>,
     children: Vec<SubDiagnostic>,
-    cancelled: bool,
 }
 
 // For example a note attached to an error.
@@ -121,12 +120,12 @@ struct SubDiagnostic {
 impl<'a> DiagnosticBuilder<'a> {
     // Emit the diagnostic.
     pub fn emit(&mut self) {
-        if self.cancelled {
+        if self.cancelled() {
             return;
         }
 
-        self.cancel();
         self.emitter.borrow_mut().emit_struct(&self);
+        self.cancel();
 
         // if self.is_fatal() {
         //     panic!(FatalError);
@@ -135,8 +134,15 @@ pub fn emit(&mut self) {
 
     // Cancel the diagnostic (a structured diagnostic must either be emitted or
     // cancelled or it will panic when dropped).
+    // BEWARE: if this DiagnosticBuilder is an error, then creating it will
+    // bump the error count on the Handler and cancelling it won't undo that.
+    // If you want to decrement the error count you should use `Handler::cancel`.
     pub fn cancel(&mut self) {
-        self.cancelled = true;
+        self.level = Level::Cancelled;
+    }
+
+    pub fn cancelled(&self) -> bool {
+        self.level == Level::Cancelled
     }
 
     pub fn is_fatal(&self) -> bool {
@@ -204,21 +210,28 @@ pub fn fileline_help(&mut self ,
         self
     }
 
+    pub fn span(&mut self, sp: Span) -> &mut Self {
+        self.span = Some(sp);
+        self
+    }
+
+    pub fn code(&mut self, s: String) -> &mut Self {
+        self.code = Some(s);
+        self
+    }
+
     // Convenience function for internal use, clients should use one of the
     // struct_* methods on Handler.
     fn new(emitter: &'a RefCell<Box<Emitter>>,
            level: Level,
-           message: &str,
-           code: Option<String>,
-           span: Option<Span>) -> DiagnosticBuilder<'a>  {
+           message: &str) -> DiagnosticBuilder<'a>  {
         DiagnosticBuilder {
             emitter: emitter,
             level: level,
             message: message.to_owned(),
-            code: code,
-            span: span,
+            code: None,
+            span: None,
             children: vec![],
-            cancelled: false,
         }
     }
 
@@ -249,7 +262,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 // we emit a bug.
 impl<'a> Drop for DiagnosticBuilder<'a> {
     fn drop(&mut self) {
-        if !self.cancelled {
+        if !self.cancelled() {
             self.emitter.borrow_mut().emit(None, "Error constructed but not emitted", None, Bug);
             panic!();
         }
@@ -290,11 +303,16 @@ pub fn with_emitter(can_emit_warnings: bool,
         }
     }
 
+    pub fn struct_dummy<'a>(&'a self) -> DiagnosticBuilder<'a> {
+        DiagnosticBuilder::new(&self.emit, Level::Cancelled, "")
+    }
+
     pub fn struct_span_warn<'a>(&'a self,
                                 sp: Span,
                                 msg: &str)
-                                -> DiagnosticBuilder<'a>  {
-        let mut result = DiagnosticBuilder::new(&self.emit, Level::Warning, msg, None, Some(sp));
+                                -> DiagnosticBuilder<'a> {
+        let mut result = DiagnosticBuilder::new(&self.emit, Level::Warning, msg);
+        result.span(sp);
         if !self.can_emit_warnings {
             result.cancel();
         }
@@ -304,19 +322,17 @@ pub fn struct_span_warn_with_code<'a>(&'a self,
                                           sp: Span,
                                           msg: &str,
                                           code: &str)
-                                          -> DiagnosticBuilder<'a>  {
-        let mut result = DiagnosticBuilder::new(&self.emit,
-                                                Level::Warning,
-                                                msg,
-                                                Some(code.to_owned()),
-                                                Some(sp));
+                                          -> DiagnosticBuilder<'a> {
+        let mut result = DiagnosticBuilder::new(&self.emit, Level::Warning, msg);
+        result.span(sp);
+        result.code(code.to_owned());
         if !self.can_emit_warnings {
             result.cancel();
         }
         result
     }
-    pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a>  {
-        let mut result = DiagnosticBuilder::new(&self.emit, Level::Warning, msg, None, None);
+    pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+        let mut result = DiagnosticBuilder::new(&self.emit, Level::Warning, msg);
         if !self.can_emit_warnings {
             result.cancel();
         }
@@ -325,42 +341,58 @@ pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a>  {
     pub fn struct_span_err<'a>(&'a self,
                                sp: Span,
                                msg: &str)
-                               -> DiagnosticBuilder<'a>  {
+                               -> DiagnosticBuilder<'a> {
         self.bump_err_count();
-        DiagnosticBuilder::new(&self.emit, Level::Error, msg, None, Some(sp))
+        let mut result = DiagnosticBuilder::new(&self.emit, Level::Error, msg);
+        result.span(sp);
+        result
     }
     pub fn struct_span_err_with_code<'a>(&'a self,
                                          sp: Span,
                                          msg: &str,
                                          code: &str)
-                                         -> DiagnosticBuilder<'a>  {
-        // FIXME (and below) this is potentially inaccurate, since the DiagnosticBuilder
-        // might be cancelled.
+                                         -> DiagnosticBuilder<'a> {
         self.bump_err_count();
-        DiagnosticBuilder::new(&self.emit, Level::Error, msg, Some(code.to_owned()), Some(sp))
+        let mut result = DiagnosticBuilder::new(&self.emit, Level::Error, msg);
+        result.span(sp);
+        result.code(code.to_owned());
+        result
     }
-    pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a>  {
+    pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
         self.bump_err_count();
-        DiagnosticBuilder::new(&self.emit, Level::Error, msg, None, None)
+        DiagnosticBuilder::new(&self.emit, Level::Error, msg)
     }
     pub fn struct_span_fatal<'a>(&'a self,
                                  sp: Span,
                                  msg: &str)
-                                 -> DiagnosticBuilder<'a>  {
+                                 -> DiagnosticBuilder<'a> {
         self.bump_err_count();
-        DiagnosticBuilder::new(&self.emit, Level::Fatal, msg, None, Some(sp))
+        let mut result = DiagnosticBuilder::new(&self.emit, Level::Fatal, msg);
+        result.span(sp);
+        result
     }
     pub fn struct_span_fatal_with_code<'a>(&'a self,
                                            sp: Span,
                                            msg: &str,
                                            code: &str)
-                                           -> DiagnosticBuilder<'a>  {
+                                           -> DiagnosticBuilder<'a> {
         self.bump_err_count();
-        DiagnosticBuilder::new(&self.emit, Level::Fatal, msg, Some(code.to_owned()), Some(sp))
+        let mut result = DiagnosticBuilder::new(&self.emit, Level::Fatal, msg);
+        result.span(sp);
+        result.code(code.to_owned());
+        result
     }
-    pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a>  {
+    pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
         self.bump_err_count();
-        DiagnosticBuilder::new(&self.emit, Level::Fatal, msg, None, None)
+        DiagnosticBuilder::new(&self.emit, Level::Fatal, msg)
+    }
+
+    pub fn cancel(&mut self, err: &mut DiagnosticBuilder) {
+        if err.level == Level::Error || err.level == Level::Fatal {
+            assert!(self.has_errors());
+            self.err_count.set(self.err_count.get() + 1);
+        }
+        err.cancel();
     }
 
     pub fn span_fatal(&self, sp: Span, msg: &str) -> FatalError {
@@ -514,6 +546,7 @@ pub enum Level {
     Warning,
     Note,
     Help,
+    Cancelled,
 }
 
 impl fmt::Display for Level {
@@ -526,6 +559,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             Warning => "warning".fmt(f),
             Note => "note".fmt(f),
             Help => "help".fmt(f),
+            Cancelled => unreachable!(),
         }
     }
 }
@@ -537,6 +571,7 @@ fn color(self) -> term::color::Color {
             Warning => term::color::BRIGHT_YELLOW,
             Note => term::color::BRIGHT_GREEN,
             Help => term::color::BRIGHT_CYAN,
+            Cancelled => unreachable!(),
         }
     }
 }