提交 aaa02b3f 编写于 作者: N Nick Cameron

Refactoring

上级 95dc7efa
......@@ -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);
......
......@@ -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
......
......@@ -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,
......
......@@ -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;
}
}
......
......@@ -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
......
......@@ -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 {
......
......@@ -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.
......
......@@ -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();
}
}
......
......@@ -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
......
......@@ -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();
}
}
}
......
......@@ -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) => {
......
......@@ -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>,
......
......@@ -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!(),
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册