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,
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();
if let Some(span) = def {
err.span_note(span, "lint level defined here");
}
- Some(err)
+
+ err
}
pub trait LintContext: Sized {
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,
};
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);
/// 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);
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,
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 */
}
};
},
_ => ()
}
- Some(err)
+ err
}
/// Adds a note if the types come from similarly named crates
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
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)
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,
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);
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()
}
}
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,
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,
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;
}
}
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
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
}
}
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 {
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,
E0435,
"attempt to use a non-constant value in a constant")
}
- })
+ }
}
#[derive(Copy, Clone)]
// 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 {
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.
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.
&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();
}
}
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
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`")
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();
}
}
}
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) => {
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);
}
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);
}
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)
`{}`", 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 \
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);
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 `{}`",
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>,
code: Option<String>,
span: Option<Span>,
children: Vec<SubDiagnostic>,
- cancelled: bool,
}
// For example a note attached to an error.
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);
// 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 {
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,
}
}
// 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!();
}
}
}
+ 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();
}
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();
}
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 {
Warning,
Note,
Help,
+ Cancelled,
}
impl fmt::Display for Level {
Warning => "warning".fmt(f),
Note => "note".fmt(f),
Help => "help".fmt(f),
+ Cancelled => unreachable!(),
}
}
}
Warning => term::color::BRIGHT_YELLOW,
Note => term::color::BRIGHT_GREEN,
Help => term::color::BRIGHT_CYAN,
+ Cancelled => unreachable!(),
}
}
}