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

Refactoring

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