diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 66ebd3081c0..464f29a3393 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -368,7 +368,7 @@ pub fn raw_emit_lint(sess: &Session, lvlsrc: LevelSource, span: Option, 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, msg: &str) - -> Option> { + -> 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 @@ pub trait LintContext: Sized { lint: &'static Lint, span: Option, msg: &str) - -> Option { + -> 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 @@ pub trait LintContext: Sized { lint: &'static Lint, span: Span, msg: &str) - -> Option { + -> 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 @@ pub trait LintContext: Sized { /// 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); diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 5382e328a11..d628227d5e6 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -237,7 +237,7 @@ pub trait ErrorReporting<'tcx> { fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &TypeError<'tcx>) - -> Option>; + -> DiagnosticBuilder<'tcx>; fn check_and_note_conflicting_crates(&self, err: &mut DiagnosticBuilder, @@ -478,11 +478,11 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &TypeError<'tcx>) - -> Option> { + -> 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 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { }, _ => () } - Some(err) + err } /// Adds a note if the types come from similarly named crates @@ -560,11 +560,9 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { 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 diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 81d3d429f26..21a1ee37b7f 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -1281,7 +1281,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { mk_msg: M, actual_ty: String, err: Option<&TypeError<'tcx>>) - -> Option> + -> DiagnosticBuilder<'tcx> where M: FnOnce(Option, String) -> String, { self.type_error_struct_str_with_expected(sp, mk_msg, None, actual_ty, err) @@ -1296,7 +1296,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { where M: FnOnce(Option, 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(&self, @@ -1305,7 +1305,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { expected_ty: Option>, actual_ty: String, err: Option<&TypeError<'tcx>>) - -> Option> + -> DiagnosticBuilder<'tcx> where M: FnOnce(Option, String) -> String, { debug!("hi! expected_ty = {:?}, actual_ty = {}", expected_ty, actual_ty); @@ -1324,9 +1324,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { 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 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { 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(&self, @@ -1345,14 +1345,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { mk_msg: M, actual_ty: Ty<'tcx>, err: Option<&TypeError<'tcx>>) - -> Option> + -> 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, diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 50a672a4b69..7bcf3276da7 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -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; } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 24b346b3b31..09e6f454fb4 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -754,18 +754,17 @@ impl LateLintPass for UnconditionalRecursion { 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 diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 91fed4e5b9c..1d3f2b79844 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -144,9 +144,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { 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, ¬e)); + err.span_note(sp, ¬e); } - err.as_mut().map(|mut e| e.emit()); + err.emit(); child } } @@ -261,10 +261,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { 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 { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 67895ed2131..c2dd764f224 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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> { 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 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // 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 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { 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 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { 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. diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index d7fbe1193b6..996e72bdad3 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -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(); } } diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 07a1da92067..a1b378d84d0 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -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 diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 057671cad5c..90e67944ef9 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -132,17 +132,15 @@ impl<'tcx> CastCheck<'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 @@ impl<'tcx> CastCheck<'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(); } } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 5c0eefd5f85..65b0d589275 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -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 - }; + // 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_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); + 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 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 !unsatisfied_predicates.is_empty() { - let bound_list = unsatisfied_predicates.iter() - .map(|p| format!("`{} : {}`", - p.self_ty(), - p)) - .collect::>() - .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, err, span, rcvr_ty, item_name, - rcvr_expr, out_of_scope_traits); - err.emit(); } + + if !static_sources.is_empty() { + err.fileline_note( + span, + "found defined static methods, maybe a `self` is missing?"); + + report_candidates(fcx, &mut err, span, item_name, static_sources); + } + + if !unsatisfied_predicates.is_empty() { + let bound_list = unsatisfied_predicates.iter() + .map(|p| format!("`{} : {}`", + p.self_ty(), + p)) + .collect::>() + .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) => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 99a72a4c9df..ea08343bbc0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mk_msg: M, actual_ty: Ty<'tcx>, err: Option<&TypeError<'tcx>>) - -> Option> + -> DiagnosticBuilder<'tcx> where M: FnOnce(String) -> String, { self.infcx().type_error_struct(sp, mk_msg, actual_ty, err) @@ -2966,13 +2966,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(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_expr_with_unifier<'a, 'tcx, F>(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 check_expr_with_unifier<'a, 'tcx, F>(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 check_expr_with_unifier<'a, 'tcx, F>(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>, diff --git a/src/libsyntax/errors/mod.rs b/src/libsyntax/errors/mod.rs index 3b75bf9a8bd..3cee14538a9 100644 --- a/src/libsyntax/errors/mod.rs +++ b/src/libsyntax/errors/mod.rs @@ -107,7 +107,6 @@ pub struct DiagnosticBuilder<'a> { code: Option, span: Option, children: Vec, - 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 @@ impl<'a> DiagnosticBuilder<'a> { // 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 @@ impl<'a> DiagnosticBuilder<'a> { 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>, level: Level, - message: &str, - code: Option, - span: Option) -> 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 @@ impl<'a> fmt::Debug for DiagnosticBuilder<'a> { // 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 @@ impl Handler { } } + 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 @@ impl Handler { 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 @@ impl Handler { 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 @@ impl fmt::Display for Level { Warning => "warning".fmt(f), Note => "note".fmt(f), Help => "help".fmt(f), + Cancelled => unreachable!(), } } } @@ -537,6 +571,7 @@ impl Level { Warning => term::color::BRIGHT_YELLOW, Note => term::color::BRIGHT_GREEN, Help => term::color::BRIGHT_CYAN, + Cancelled => unreachable!(), } } }