From 06d9cc1d7a8582ff844c21a3fafe09dc97f22895 Mon Sep 17 00:00:00 2001 From: P1start Date: Fri, 29 Aug 2014 18:55:35 +1200 Subject: [PATCH] Add help diagnostic messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds ‘help’ diagnostic messages to rustc. This is used for anything that provides help to the user, particularly the `--explain` messages that were previously integrated into the relevant error message. --- src/librustc/driver/session.rs | 6 ++++ src/librustc/middle/borrowck/mod.rs | 4 +++ .../middle/typeck/infer/error_reporting.rs | 2 +- src/librustc/middle/typeck/infer/test.rs | 4 +-- src/libsyntax/diagnostic.rs | 35 +++++++++++++------ src/libsyntax/ext/base.rs | 4 +++ src/libsyntax/parse/parser.rs | 3 ++ ...me-inference-give-expl-lifetime-param-2.rs | 2 +- ...me-inference-give-expl-lifetime-param-3.rs | 4 +-- ...time-inference-give-expl-lifetime-param.rs | 10 +++--- 10 files changed, 52 insertions(+), 22 deletions(-) diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 6f020184b336d..afc30589d4dde 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -97,12 +97,18 @@ impl Session { pub fn span_end_note(&self, sp: Span, msg: &str) { self.diagnostic().span_end_note(sp, msg) } + pub fn span_help(&self, sp: Span, msg: &str) { + self.diagnostic().span_help(sp, msg) + } pub fn fileline_note(&self, sp: Span, msg: &str) { self.diagnostic().fileline_note(sp, msg) } pub fn note(&self, msg: &str) { self.diagnostic().handler().note(msg) } + pub fn help(&self, msg: &str) { + self.diagnostic().handler().note(msg) + } pub fn span_bug(&self, sp: Span, msg: &str) -> ! { self.diagnostic().span_bug(sp, msg) } diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 0d584a7664f67..586c9c5624dac 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -624,6 +624,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.span_end_note(s, m); } + pub fn span_help(&self, s: Span, m: &str) { + self.tcx.sess.span_help(s, m); + } + pub fn bckerr_to_string(&self, err: &BckError) -> String { match err.code { err_mutbl => { diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index b5b4cc80faac1..858d0d89deaf7 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -1407,7 +1407,7 @@ impl<'a, 'tcx> ErrorReportingHelpers for InferCtxt<'a, 'tcx> { opt_explicit_self, generics); let msg = format!("consider using an explicit lifetime \ parameter as shown: {}", suggested_fn); - self.tcx.sess.span_note(span, msg.as_slice()); + self.tcx.sess.span_help(span, msg.as_slice()); } fn report_inference_failure(&self, diff --git a/src/librustc/middle/typeck/infer/test.rs b/src/librustc/middle/typeck/infer/test.rs index c0236cefca3f9..1915c5ef6e1c7 100644 --- a/src/librustc/middle/typeck/infer/test.rs +++ b/src/librustc/middle/typeck/infer/test.rs @@ -35,7 +35,7 @@ use middle::typeck::infer::lub::Lub; use middle::typeck::infer::glb::Glb; use syntax::codemap; use syntax::codemap::{Span, CodeMap, DUMMY_SP}; -use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note}; +use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note, Help}; use syntax::{ast, ast_map}; use util::ppaux::{ty_to_string, UserString}; @@ -59,7 +59,7 @@ struct ExpectErrorEmitter { fn remove_message(e: &mut ExpectErrorEmitter, msg: &str, lvl: Level) { match lvl { Bug | Fatal | Error => { } - Warning | Note => { return; } + Warning | Note | Help => { return; } } debug!("Error: {}", msg); diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index faa3946b74d0f..3b7ee5b28e050 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -105,6 +105,9 @@ impl SpanHandler { pub fn span_end_note(&self, sp: Span, msg: &str) { self.handler.custom_emit(&self.cm, FullSpan(sp), msg, Note); } + pub fn span_help(&self, sp: Span, msg: &str) { + self.handler.emit(Some((&self.cm, sp)), msg, Help); + } pub fn fileline_note(&self, sp: Span, msg: &str) { self.handler.custom_emit(&self.cm, FileLine(sp), msg, Note); } @@ -164,6 +167,9 @@ impl Handler { pub fn note(&self, msg: &str) { self.emit.borrow_mut().emit(None, msg, None, Note); } + pub fn help(&self, msg: &str) { + self.emit.borrow_mut().emit(None, msg, None, Help); + } pub fn bug(&self, msg: &str) -> ! { self.emit.borrow_mut().emit(None, msg, None, Bug); fail!(ExplicitBug); @@ -216,6 +222,7 @@ pub enum Level { Error, Warning, Note, + Help, } impl fmt::Show for Level { @@ -227,6 +234,7 @@ impl fmt::Show for Level { Fatal | Error => "error".fmt(f), Warning => "warning".fmt(f), Note => "note".fmt(f), + Help => "help".fmt(f), } } } @@ -236,7 +244,8 @@ impl Level { match self { Bug | Fatal | Error => term::color::BRIGHT_RED, Warning => term::color::BRIGHT_YELLOW, - Note => term::color::BRIGHT_GREEN + Note => term::color::BRIGHT_GREEN, + Help => term::color::BRIGHT_CYAN, } } } @@ -293,15 +302,6 @@ fn print_diagnostic(dst: &mut EmitterWriter, topic: &str, lvl: Level, Some(code) => { let style = term::attr::ForegroundColor(term::color::BRIGHT_MAGENTA); try!(print_maybe_styled(dst, format!(" [{}]", code.clone()).as_slice(), style)); - match dst.registry.as_ref().and_then(|registry| registry.find_description(code)) { - Some(_) => { - try!(write!(&mut dst.dst, - " (pass `--explain {}` to see a detailed explanation)", - code - )); - } - None => () - } } None => () } @@ -401,7 +401,20 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan, try!(highlight_lines(dst, cm, sp, lvl, lines)); } } - print_macro_backtrace(dst, cm, sp) + try!(print_macro_backtrace(dst, cm, sp)); + match code { + Some(code) => + match dst.registry.as_ref().and_then(|registry| registry.find_description(code)) { + Some(_) => { + try!(print_diagnostic(dst, ss.as_slice(), Help, + format!("pass `--explain {}` to see a detailed \ + explanation", code).as_slice(), None)); + } + None => () + }, + None => (), + } + Ok(()) } fn highlight_lines(err: &mut EmitterWriter, diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 6e25b6b73ade6..5cad132688a03 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -575,6 +575,10 @@ impl<'a> ExtCtxt<'a> { self.print_backtrace(); self.parse_sess.span_diagnostic.span_note(sp, msg); } + pub fn span_help(&self, sp: Span, msg: &str) { + self.print_backtrace(); + self.parse_sess.span_diagnostic.span_help(sp, msg); + } pub fn bug(&self, msg: &str) -> ! { self.print_backtrace(); self.parse_sess.span_diagnostic.handler().bug(msg); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f41362cad4185..d4ca285e4dbfa 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -959,6 +959,9 @@ impl<'a> Parser<'a> { pub fn span_note(&mut self, sp: Span, m: &str) { self.sess.span_diagnostic.span_note(sp, m) } + pub fn span_help(&mut self, sp: Span, m: &str) { + self.sess.span_diagnostic.span_help(sp, m) + } pub fn bug(&mut self, m: &str) -> ! { self.sess.span_diagnostic.span_bug(self.span, m) } diff --git a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs index a210c5d2f0e40..7c514b4e16f07 100644 --- a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs +++ b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs @@ -22,7 +22,7 @@ impl<'r> Itble<'r, uint, Range> for (uint, uint) { } fn check<'r, I: Iterator, T: Itble<'r, uint, I>>(cont: &T) -> bool { -//~^ NOTE: consider using an explicit lifetime parameter as shown: fn check<'r, I: Iterator, T: Itble<'r, uint, I>>(cont: &'r T) -> bool +//~^ HELP: consider using an explicit lifetime parameter as shown: fn check<'r, I: Iterator, T: Itble<'r, uint, I>>(cont: &'r T) -> bool let cont_iter = cont.iter(); //~ ERROR: cannot infer let result = cont_iter.fold(Some(0u16), |state, val| { state.map_or(None, |mask| { diff --git a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-3.rs b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-3.rs index 21bd676a225f7..29265b8750ca7 100644 --- a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-3.rs +++ b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-3.rs @@ -12,7 +12,7 @@ struct Bar<'x, 'y, 'z> { bar: &'y int, baz: int } fn bar1<'a>(x: &Bar) -> (&'a int, &'a int, &'a int) { -//~^ NOTE: consider using an explicit lifetime parameter as shown: fn bar1<'b, 'c, 'a>(x: &'a Bar<'b, 'a, 'c>) -> (&'a int, &'a int, &'a int) +//~^ HELP: consider using an explicit lifetime parameter as shown: fn bar1<'b, 'c, 'a>(x: &'a Bar<'b, 'a, 'c>) -> (&'a int, &'a int, &'a int) (x.bar, &x.baz, &x.baz) //~^ ERROR: cannot infer //~^^ ERROR: cannot infer @@ -20,7 +20,7 @@ fn bar1<'a>(x: &Bar) -> (&'a int, &'a int, &'a int) { } fn bar2<'a, 'b, 'c>(x: &Bar<'a, 'b, 'c>) -> (&'a int, &'a int, &'a int) { -//~^ NOTE: consider using an explicit lifetime parameter as shown: fn bar2<'a, 'c>(x: &'a Bar<'a, 'a, 'c>) -> (&'a int, &'a int, &'a int) +//~^ HELP: consider using an explicit lifetime parameter as shown: fn bar2<'a, 'c>(x: &'a Bar<'a, 'a, 'c>) -> (&'a int, &'a int, &'a int) (x.bar, &x.baz, &x.baz) //~^ ERROR: cannot infer //~^^ ERROR: cannot infer diff --git a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs index b7da4d73489bd..4abf045501c26 100644 --- a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs +++ b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs @@ -12,23 +12,23 @@ struct Foo<'x> { bar: int } fn foo1<'a>(x: &Foo) -> &'a int { -//~^ NOTE: consider using an explicit lifetime parameter as shown: fn foo1<'a>(x: &'a Foo) -> &'a int +//~^ HELP: consider using an explicit lifetime parameter as shown: fn foo1<'a>(x: &'a Foo) -> &'a int &x.bar //~ ERROR: cannot infer } fn foo2<'a, 'b>(x: &'a Foo) -> &'b int { -//~^ NOTE: consider using an explicit lifetime parameter as shown: fn foo2<'a>(x: &'a Foo) -> &'a int +//~^ HELP: consider using an explicit lifetime parameter as shown: fn foo2<'a>(x: &'a Foo) -> &'a int &x.bar //~ ERROR: cannot infer } fn foo3<'a>(x: &Foo) -> (&'a int, &'a int) { -//~^ NOTE: consider using an explicit lifetime parameter as shown: fn foo3<'a>(x: &'a Foo) -> (&'a int, &'a int) +//~^ HELP: consider using an explicit lifetime parameter as shown: fn foo3<'a>(x: &'a Foo) -> (&'a int, &'a int) (&x.bar, &x.bar) //~ ERROR: cannot infer //~^ ERROR: cannot infer } fn foo4<'a, 'b>(x: &'a Foo) -> (&'b int, &'a int, &'b int) { -//~^ NOTE: consider using an explicit lifetime parameter as shown: fn foo4<'a>(x: &'a Foo) -> (&'a int, &'a int, &'a int) +//~^ HELP: consider using an explicit lifetime parameter as shown: fn foo4<'a>(x: &'a Foo) -> (&'a int, &'a int, &'a int) (&x.bar, &x.bar, &x.bar) //~ ERROR: cannot infer //~^ ERROR: cannot infer } @@ -37,7 +37,7 @@ struct Cat<'x, T> { cat: &'x int, t: T } struct Dog<'y> { dog: &'y int } fn cat2<'x, 'y>(x: Cat<'x, Dog<'y>>) -> &'x int { -//~^ NOTE: consider using an explicit lifetime parameter as shown: fn cat2<'x>(x: Cat<'x, Dog<'x>>) -> &'x int +//~^ HELP: consider using an explicit lifetime parameter as shown: fn cat2<'x>(x: Cat<'x, Dog<'x>>) -> &'x int x.t.dog //~ ERROR: cannot infer }