From 2a2e1e5c5a1b395c02c22ecaaa05811618a673c9 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 16 Feb 2017 10:56:30 +0100 Subject: [PATCH 01/10] multispan suggestions are broken if created by `span_suggestion` --- src/librustc_errors/diagnostic.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 1b77ead92deb6..8a72e373e7d95 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -155,11 +155,7 @@ impl Diagnostic { /// Prints out a message with a suggested edit of the code. /// /// See `diagnostic::RenderSpan::Suggestion` for more information. - pub fn span_suggestion>(&mut self, - sp: S, - msg: &str, - suggestion: String) - -> &mut Self { + pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self { self.sub(Level::Help, msg, MultiSpan::new(), From 88b38652751813e2cdff453d50990d78dae735bc Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 16 Feb 2017 11:01:57 +0100 Subject: [PATCH 02/10] add span_guess to diagnostic api --- src/librustc_errors/diagnostic.rs | 95 +++++++++++++++++++++---------- 1 file changed, 65 insertions(+), 30 deletions(-) diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 8a72e373e7d95..77a517a481c9a 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -10,9 +10,7 @@ use CodeSuggestion; use Level; -use RenderSpan; -use RenderSpan::Suggestion; -use std::fmt; +use std::{fmt, iter}; use syntax_pos::{MultiSpan, Span}; use snippet::Style; @@ -24,6 +22,19 @@ pub struct Diagnostic { pub code: Option, pub span: MultiSpan, pub children: Vec, + pub code_hints: Option, +} + +#[derive(Clone, Debug, PartialEq)] +pub enum DiagnosticCodeHint { + Suggestion { + msg: String, + sugg: CodeSuggestion, + }, + Guesses { + msg: String, + guesses: Vec, + }, } /// For example a note attached to an error. @@ -32,7 +43,7 @@ pub struct SubDiagnostic { pub level: Level, pub message: Vec<(String, Style)>, pub span: MultiSpan, - pub render_span: Option, + pub render_span: Option, } impl Diagnostic { @@ -47,6 +58,7 @@ impl Diagnostic { code: code, span: MultiSpan::new(), children: vec![], + code_hints: None, } } @@ -109,12 +121,12 @@ impl Diagnostic { } pub fn note(&mut self, msg: &str) -> &mut Self { - self.sub(Level::Note, msg, MultiSpan::new(), None); + self.sub(Level::Note, msg, MultiSpan::new()); self } pub fn highlighted_note(&mut self, msg: Vec<(String, Style)>) -> &mut Self { - self.sub_with_highlights(Level::Note, msg, MultiSpan::new(), None); + self.sub_with_highlights(Level::Note, msg, MultiSpan::new()); self } @@ -122,12 +134,12 @@ impl Diagnostic { sp: S, msg: &str) -> &mut Self { - self.sub(Level::Note, msg, sp.into(), None); + self.sub(Level::Note, msg, sp.into()); self } pub fn warn(&mut self, msg: &str) -> &mut Self { - self.sub(Level::Warning, msg, MultiSpan::new(), None); + self.sub(Level::Warning, msg, MultiSpan::new()); self } @@ -135,12 +147,12 @@ impl Diagnostic { sp: S, msg: &str) -> &mut Self { - self.sub(Level::Warning, msg, sp.into(), None); + self.sub(Level::Warning, msg, sp.into()); self } pub fn help(&mut self , msg: &str) -> &mut Self { - self.sub(Level::Help, msg, MultiSpan::new(), None); + self.sub(Level::Help, msg, MultiSpan::new()); self } @@ -148,7 +160,7 @@ impl Diagnostic { sp: S, msg: &str) -> &mut Self { - self.sub(Level::Help, msg, sp.into(), None); + self.sub(Level::Help, msg, sp.into()); self } @@ -156,16 +168,43 @@ impl Diagnostic { /// /// See `diagnostic::RenderSpan::Suggestion` for more information. pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self { - self.sub(Level::Help, - msg, - MultiSpan::new(), - Some(Suggestion(CodeSuggestion { - msp: sp.into(), - substitutes: vec![suggestion], - }))); + assert!(self.code_hints.is_none(), + "use guesses to assign multiple suggestions to an error"); + self.code_hints = Some(DiagnosticCodeHint::Suggestion { + sugg: CodeSuggestion { + msp: sp.into(), + substitutes: vec![suggestion], + }, + msg: msg.to_owned(), + }); + self + } + + /// Prints out a message with one or multiple suggested edits of the + /// code, which may break the code, require manual intervention + /// or be plain out wrong, but might possibly be the correct solution. + /// + /// See `diagnostic::RenderSpan::Guesses` for more information. + pub fn span_guesses(&mut self, sp: Span, msg: &str, guesses: I) -> &mut Self + where I: IntoIterator + { + assert!(self.code_hints.is_none(), + "cannot attach multiple guesses to the same error"); + let guesses = guesses.into_iter().map(|guess| CodeSuggestion { + msp: sp.into(), + substitutes: vec![guess], + }).collect(); + self.code_hints = Some(DiagnosticCodeHint::Guesses { + guesses: guesses, + msg: msg.to_owned(), + }); self } + pub fn span_guess(&mut self, sp: Span, msg: &str, guess: String) -> &mut Self { + self.span_guesses(sp, msg, iter::once(guess)) + } + pub fn set_span>(&mut self, sp: S) -> &mut Self { self.span = sp.into(); self @@ -201,15 +240,12 @@ impl Diagnostic { fn sub(&mut self, level: Level, message: &str, - span: MultiSpan, - render_span: Option) { - let sub = SubDiagnostic { - level: level, - message: vec![(message.to_owned(), Style::NoStyle)], - span: span, - render_span: render_span, - }; - self.children.push(sub); + span: MultiSpan) { + self.sub_with_highlights( + level, + vec![(message.to_owned(), Style::NoStyle)], + span, + ); } /// Convenience function for internal use, clients should use one of the @@ -217,13 +253,12 @@ impl Diagnostic { fn sub_with_highlights(&mut self, level: Level, message: Vec<(String, Style)>, - span: MultiSpan, - render_span: Option) { + span: MultiSpan) { let sub = SubDiagnostic { level: level, message: message, span: span, - render_span: render_span, + render_span: None, }; self.children.push(sub); } From 4b87fae1dfbbf4c88295b2f7cfe3a5e9583b36df Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 16 Feb 2017 11:03:05 +0100 Subject: [PATCH 03/10] fixup to suggestion api change --- src/librustc_errors/diagnostic_builder.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 7dfea6b8951b0..de241556552d2 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -139,11 +139,11 @@ impl<'a> DiagnosticBuilder<'a> { sp: S, msg: &str) -> &mut Self); - forward!(pub fn span_suggestion>(&mut self, - sp: S, - msg: &str, - suggestion: String) - -> &mut Self); + forward!(pub fn span_suggestion(&mut self, + sp: Span, + msg: &str, + suggestion: String) + -> &mut Self); forward!(pub fn set_span>(&mut self, sp: S) -> &mut Self); forward!(pub fn code(&mut self, s: String) -> &mut Self); From 79caf342bd2da9d095bfe32662c99f3fe848854d Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 16 Feb 2017 11:03:55 +0100 Subject: [PATCH 04/10] fixup to span_guess api changes --- src/librustc_errors/diagnostic_builder.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index de241556552d2..1b5fb96814405 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -146,12 +146,20 @@ impl<'a> DiagnosticBuilder<'a> { -> &mut Self); forward!(pub fn set_span>(&mut self, sp: S) -> &mut Self); forward!(pub fn code(&mut self, s: String) -> &mut Self); + forward!(pub fn span_guess(&mut self, sp: Span, msg: &str, guess: String) -> &mut Self); /// Convenience function for internal use, clients should use one of the /// struct_* methods on Handler. pub fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> { DiagnosticBuilder::new_with_code(handler, level, None, message) } + + pub fn span_guesses(&mut self, sp: Span, msg: &str, guesses: I) -> &mut Self + where I: IntoIterator + { + self.diagnostic.span_guesses(sp, msg, guesses); + self + } /// Convenience function for internal use, clients should use one of the /// struct_* methods on Handler. From 662daf586b07aae763ec75c80a75499ecc6e735e Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 20 Feb 2017 12:52:11 +0100 Subject: [PATCH 05/10] Have `DiagnosticBuilder::cancel` consume `self` and return the inner object by value --- src/libproc_macro/lib.rs | 2 +- src/librustc/traits/error_reporting.rs | 2 +- src/librustc_errors/diagnostic.rs | 9 ------ src/librustc_errors/diagnostic_builder.rs | 23 +++++++++++---- src/librustc_errors/emitter.rs | 32 +++++++++------------ src/librustc_errors/lib.rs | 34 ++++++++++++----------- src/librustc_trans/back/write.rs | 4 +-- src/libsyntax/json.rs | 12 ++++---- 8 files changed, 58 insertions(+), 60 deletions(-) diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index f962c888f42cc..aeee711688bba 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -161,7 +161,7 @@ pub mod __internal { } fn parse_to_lex_err(mut err: DiagnosticBuilder) -> LexError { - err.cancel(); + let _ = err.cancel(); LexError { _inner: () } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 70ca5fe83a932..a4fb89d2a32c2 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -483,7 +483,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.sess.add_lint_diagnostic(EXTRA_REQUIREMENT_IN_IMPL, node_id, (*err).clone()); - err.cancel(); + let _ = err.cancel(); } err diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 77a517a481c9a..8df75e85a26e5 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -62,15 +62,6 @@ impl Diagnostic { } } - /// 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.level = Level::Cancelled; - } - pub fn cancelled(&self) -> bool { self.level == Level::Cancelled } diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 1b5fb96814405..82e7fa0f3df1f 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -15,6 +15,7 @@ use std::fmt::{self, Debug}; use std::ops::{Deref, DerefMut}; use std::thread::panicking; use syntax_pos::{MultiSpan, Span}; +use std::mem; /// Used for emitting structured error messages and other diagnostic information. #[must_use] @@ -95,8 +96,8 @@ impl<'a> DiagnosticBuilder<'a> { } } - self.handler.emitter.borrow_mut().emit(&self); - self.cancel(); + let db = self.cancel(); + self.handler.emitter.borrow_mut().emit(db); self.handler.panic_if_treat_err_as_bug(); // if self.is_fatal() { @@ -174,10 +175,22 @@ impl<'a> DiagnosticBuilder<'a> { } } - pub fn into_diagnostic(mut self) -> Diagnostic { + /// 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`. + /// The function yields the inner Diagnostic by value + pub fn cancel(&mut self) -> Diagnostic { // annoyingly, the Drop impl means we can't actually move - let result = self.diagnostic.clone(); - self.cancel(); + let result = mem::replace(&mut self.diagnostic, Diagnostic { + level: Level::Cancelled, + message: vec![], + code: None, + span: MultiSpan::new(), + children: vec![], + code_hints: None, + }); result } } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 0b0a9e51cacb0..93dae22af2d89 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -25,19 +25,13 @@ use term; /// Emitter trait for emitting errors. pub trait Emitter { /// Emit a structured diagnostic. - fn emit(&mut self, db: &DiagnosticBuilder); + fn emit(&mut self, db: Diagnostic); } impl Emitter for EmitterWriter { - fn emit(&mut self, db: &DiagnosticBuilder) { - let mut primary_span = db.span.clone(); - let mut children = db.children.clone(); - self.fix_multispans_in_std_macros(&mut primary_span, &mut children); - self.emit_messages_default(&db.level, - &db.styled_message(), - &db.code, - &primary_span, - &children); + fn emit(&mut self, mut db: Diagnostic) { + self.fix_multispans_in_std_macros(&mut db.span, &mut db.children); + self.emit_messages_default(db); } } @@ -984,21 +978,21 @@ impl EmitterWriter { } Ok(()) } - fn emit_messages_default(&mut self, - level: &Level, - message: &Vec<(String, Style)>, - code: &Option, - span: &MultiSpan, - children: &Vec) { - let max_line_num = self.get_max_line_num(span, children); + fn emit_messages_default(&mut self, db: Diagnostic) { + let max_line_num = self.get_max_line_num(&db.span, &db.children); let max_line_num_len = max_line_num.to_string().len(); - match self.emit_message_default(span, message, code, level, max_line_num_len, false) { + match self.emit_message_default(&db.span, + &db.message, + &db.code, + &db.level, + max_line_num_len, + false) { Ok(()) => { if !children.is_empty() { let mut buffer = StyledBuffer::new(); draw_col_separator_no_space(&mut buffer, 0, max_line_num_len + 1); - match emit_to_destination(&buffer.render(), level, &mut self.dst) { + match emit_to_destination(&buffer.render(), &db.level, &mut self.dst) { Ok(()) => (), Err(e) => panic!("failed to emit error: {}", e) } diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index d7bd5ed23c2b0..b29314b850939 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -255,32 +255,34 @@ impl Handler { sp: S, msg: &str) -> DiagnosticBuilder<'a> { - let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); - result.set_span(sp); - if !self.can_emit_warnings { - result.cancel(); + if self.can_emit_warnings { + let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); + result.set_span(sp); + result + } else { + self.struct_dummy() } - result } pub fn struct_span_warn_with_code<'a, S: Into>(&'a self, sp: S, msg: &str, code: &str) -> DiagnosticBuilder<'a> { - let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); - result.set_span(sp); - result.code(code.to_owned()); - if !self.can_emit_warnings { - result.cancel(); + if self.can_emit_warnings { + let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); + result.set_span(sp); + result.code(code.to_owned()); + result + } else { + self.struct_dummy() } - result } pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> { - let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); - if !self.can_emit_warnings { - result.cancel(); + if self.can_emit_warnings { + DiagnosticBuilder::new(self, Level::Warning, msg) + } else { + self.struct_dummy() } - result } pub fn struct_span_err<'a, S: Into>(&'a self, sp: S, @@ -326,7 +328,7 @@ impl Handler { } pub fn cancel(&self, err: &mut DiagnosticBuilder) { - err.cancel(); + let _ = err.cancel(); } fn panic_if_treat_err_as_bug(&self) { diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index b717254ef0d25..ad7f6b6555627 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -22,7 +22,7 @@ use {CrateTranslation, ModuleLlvm, ModuleSource, ModuleTranslation}; use util::common::{time, time_depth, set_time_depth}; use util::common::path2cstr; use util::fs::link_or_copy; -use errors::{self, Handler, Level, DiagnosticBuilder}; +use errors::{self, Handler, Level}; use errors::emitter::Emitter; use syntax_pos::MultiSpan; use context::{is_pie_binary, get_reloc_model}; @@ -120,7 +120,7 @@ impl SharedEmitter { } impl Emitter for SharedEmitter { - fn emit(&mut self, db: &DiagnosticBuilder) { + fn emit(&mut self, db: errors::Diagnostic) { self.buffer.lock().unwrap().push(Diagnostic { msg: db.message(), code: db.code.clone(), diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index fd762552248b4..ceb9b9f998e6c 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -22,7 +22,7 @@ use codemap::CodeMap; use syntax_pos::{self, MacroBacktrace, Span, SpanLabel, MultiSpan}; use errors::registry::Registry; -use errors::{DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion, CodeMapper}; +use errors::{self, SubDiagnostic, DiagnosticCodeHint, CodeSuggestion, CodeMapper}; use errors::emitter::Emitter; use std::rc::Rc; @@ -63,8 +63,8 @@ impl JsonEmitter { } impl Emitter for JsonEmitter { - fn emit(&mut self, db: &DiagnosticBuilder) { - let data = Diagnostic::from_diagnostic_builder(db, self); + fn emit(&mut self, db: errors::Diagnostic) { + let data = Diagnostic::from_diagnostic(db, self); if let Err(e) = writeln!(&mut self.dst, "{}", as_json(&data)) { panic!("failed to print diagnostics: {:?}", e); } @@ -149,12 +149,10 @@ struct DiagnosticCode { } impl Diagnostic { - fn from_diagnostic_builder(db: &DiagnosticBuilder, - je: &JsonEmitter) - -> Diagnostic { + fn from_diagnostic(db: errors::Diagnostic, je: &JsonEmitter) -> Diagnostic { Diagnostic { message: db.message(), - code: DiagnosticCode::map_opt_string(db.code.clone(), je), + code: DiagnosticCode::map_opt_string(db.code, je), level: db.level.to_str(), spans: DiagnosticSpan::from_multispan(&db.span, je), children: db.children.iter().map(|c| { From 9c8fcc6213cd5bae815cb543cbc0217ada09045c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 20 Feb 2017 12:53:16 +0100 Subject: [PATCH 06/10] Refactor suggestions into a structured format instead of passing them as just another error type --- src/librustc_errors/diagnostic.rs | 2 +- src/librustc_errors/emitter.rs | 32 ++++++++++--------- src/librustc_errors/lib.rs | 16 +--------- src/libsyntax/json.rs | 51 ++++++++++++------------------- 4 files changed, 40 insertions(+), 61 deletions(-) diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 8df75e85a26e5..afa726268ca02 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -25,7 +25,7 @@ pub struct Diagnostic { pub code_hints: Option, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum DiagnosticCodeHint { Suggestion { msg: String, diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 93dae22af2d89..970f1618d66f1 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -12,8 +12,8 @@ use self::Destination::*; use syntax_pos::{COMMAND_LINE_SP, DUMMY_SP, FileMap, Span, MultiSpan, CharPos}; -use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapper}; -use RenderSpan::*; +use {Level, CodeSuggestion, SubDiagnostic, CodeMapper}; +use {Diagnostic, DiagnosticCodeHint}; use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style}; use styled_buffer::StyledBuffer; @@ -989,7 +989,7 @@ impl EmitterWriter { max_line_num_len, false) { Ok(()) => { - if !children.is_empty() { + if !db.children.is_empty() || db.code_hints.is_some() { let mut buffer = StyledBuffer::new(); draw_col_separator_no_space(&mut buffer, 0, max_line_num_len + 1); match emit_to_destination(&buffer.render(), &db.level, &mut self.dst) { @@ -997,9 +997,22 @@ impl EmitterWriter { Err(e) => panic!("failed to emit error: {}", e) } } - for child in children { + match db.code_hints { + Some(DiagnosticCodeHint::Suggestion { msg, sugg }) => { + match self.emit_suggestion_default(&sugg, + &Level::Help, + &vec![(msg, Style::NoStyle)], + max_line_num_len) { + Err(e) => panic!("failed to emit error: {}", e), + _ => () + } + } + Some(DiagnosticCodeHint::Guesses { .. }) => unimplemented!(), + None => {} + } + for child in db.children { match child.render_span { - Some(FullSpan(ref msp)) => { + Some(ref msp) => { match self.emit_message_default(msp, &child.styled_message(), &None, @@ -1010,15 +1023,6 @@ impl EmitterWriter { _ => () } }, - Some(Suggestion(ref cs)) => { - match self.emit_suggestion_default(cs, - &child.level, - &child.styled_message(), - max_line_num_len) { - Err(e) => panic!("failed to emit error: {}", e), - _ => () - } - }, None => { match self.emit_message_default(&child.span, &child.styled_message(), diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index b29314b850939..53848bd79ad91 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -50,20 +50,6 @@ mod lock; use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION}; use syntax_pos::MacroBacktrace; -#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] -pub enum RenderSpan { - /// A FullSpan renders with both with an initial line for the - /// message, prefixed by file:linenum, followed by a summary of - /// the source code covered by the span. - FullSpan(MultiSpan), - - /// A suggestion renders with both with an initial line for the - /// message, prefixed by file:linenum, followed by a summary - /// of hypothetical source code, where each `String` is spliced - /// into the lines in place of the code covered by each span. - Suggestion(CodeSuggestion), -} - #[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub struct CodeSuggestion { pub msp: MultiSpan, @@ -204,7 +190,7 @@ impl error::Error for ExplicitBug { } } -pub use diagnostic::{Diagnostic, SubDiagnostic}; +pub use diagnostic::{Diagnostic, SubDiagnostic, DiagnosticCodeHint}; pub use diagnostic_builder::DiagnosticBuilder; /// A handler deals with errors; certain errors diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index ceb9b9f998e6c..f7546af34457a 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -150,6 +150,22 @@ struct DiagnosticCode { impl Diagnostic { fn from_diagnostic(db: errors::Diagnostic, je: &JsonEmitter) -> Diagnostic { + let suggestion = match db.code_hints { + Some(DiagnosticCodeHint::Suggestion{ref msg, ref sugg}) => { + use std::borrow::Borrow; + let sugg = Diagnostic { + message: msg.clone(), + code: None, + level: "note", + spans: DiagnosticSpan::from_suggestion(sugg, je), + children: Vec::new(), + rendered: Some(sugg.splice_lines(je.cm.borrow())), + }; + Some(sugg) + }, + Some(DiagnosticCodeHint::Guesses{..}) => unimplemented!(), + None => None, + }; Diagnostic { message: db.message(), code: DiagnosticCode::map_opt_string(db.code, je), @@ -157,22 +173,20 @@ impl Diagnostic { spans: DiagnosticSpan::from_multispan(&db.span, je), children: db.children.iter().map(|c| { Diagnostic::from_sub_diagnostic(c, je) - }).collect(), + }).chain(suggestion).collect(), rendered: None, } } fn from_sub_diagnostic(db: &SubDiagnostic, je: &JsonEmitter) -> Diagnostic { + let msp = db.render_span.as_ref().unwrap_or(&db.span); Diagnostic { message: db.message(), code: None, level: db.level.to_str(), - spans: db.render_span.as_ref() - .map(|sp| DiagnosticSpan::from_render_span(sp, je)) - .unwrap_or_else(|| DiagnosticSpan::from_multispan(&db.span, je)), + spans: DiagnosticSpan::from_multispan(msp, je), children: vec![], - rendered: db.render_span.as_ref() - .and_then(|rsp| je.render(rsp)), + rendered: None, } } } @@ -276,15 +290,6 @@ impl DiagnosticSpan { }) .collect() } - - fn from_render_span(rsp: &RenderSpan, je: &JsonEmitter) -> Vec { - match *rsp { - RenderSpan::FullSpan(ref msp) => - DiagnosticSpan::from_multispan(msp, je), - RenderSpan::Suggestion(ref suggestion) => - DiagnosticSpan::from_suggestion(suggestion, je), - } - } } impl DiagnosticSpanLine { @@ -336,19 +341,3 @@ impl DiagnosticCode { }) } } - -impl JsonEmitter { - fn render(&self, render_span: &RenderSpan) -> Option { - use std::borrow::Borrow; - - match *render_span { - RenderSpan::FullSpan(_) => { - None - } - RenderSpan::Suggestion(ref suggestion) => { - Some(suggestion.splice_lines(self.cm.borrow())) - } - } - } -} - From a4dc25976d5323b296c688e0c9b1d2d9e4da32db Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 20 Feb 2017 13:12:41 +0100 Subject: [PATCH 07/10] Print suggestions after notes and similar --- src/librustc_errors/emitter.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 970f1618d66f1..be9ea18b2d69e 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -997,19 +997,6 @@ impl EmitterWriter { Err(e) => panic!("failed to emit error: {}", e) } } - match db.code_hints { - Some(DiagnosticCodeHint::Suggestion { msg, sugg }) => { - match self.emit_suggestion_default(&sugg, - &Level::Help, - &vec![(msg, Style::NoStyle)], - max_line_num_len) { - Err(e) => panic!("failed to emit error: {}", e), - _ => () - } - } - Some(DiagnosticCodeHint::Guesses { .. }) => unimplemented!(), - None => {} - } for child in db.children { match child.render_span { Some(ref msp) => { @@ -1036,6 +1023,19 @@ impl EmitterWriter { } } } + match db.code_hints { + Some(DiagnosticCodeHint::Suggestion { msg, sugg }) => { + match self.emit_suggestion_default(&sugg, + &Level::Help, + &vec![(msg, Style::NoStyle)], + max_line_num_len) { + Err(e) => panic!("failed to emit error: {}", e), + _ => () + } + } + Some(DiagnosticCodeHint::Guesses { .. }) => unimplemented!(), + None => {} + } } Err(e) => panic!("failed to emit error: {}", e), } From 29a11271f0c5dc0f961560cb07ed4e09f3963c67 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 20 Feb 2017 16:26:07 +0100 Subject: [PATCH 08/10] Remove trailing whitespace found by tidy --- src/librustc_errors/diagnostic_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 82e7fa0f3df1f..e2244a0848e20 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -154,7 +154,7 @@ impl<'a> DiagnosticBuilder<'a> { pub fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> { DiagnosticBuilder::new_with_code(handler, level, None, message) } - + pub fn span_guesses(&mut self, sp: Span, msg: &str, guesses: I) -> &mut Self where I: IntoIterator { From abe3b3bcac2cf4559752377a2d6639f9fda0f715 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 21 Feb 2017 09:41:18 +0100 Subject: [PATCH 09/10] Json expects suggestion text to be "help" not "note" --- src/libsyntax/json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index f7546af34457a..7f49b695d3af4 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -156,7 +156,7 @@ impl Diagnostic { let sugg = Diagnostic { message: msg.clone(), code: None, - level: "note", + level: "help", spans: DiagnosticSpan::from_suggestion(sugg, je), children: Vec::new(), rendered: Some(sugg.splice_lines(je.cm.borrow())), From 79855eec0fe4fdf25dd0f207ff3d73755bea1573 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 21 Feb 2017 16:04:15 +0100 Subject: [PATCH 10/10] Fix some fallout in unit tests --- src/librustc_driver/test.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 5481de1811d78..3ed3723d4141e 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -34,7 +34,7 @@ use syntax::abi::Abi; use syntax::codemap::CodeMap; use errors; use errors::emitter::Emitter; -use errors::{Level, DiagnosticBuilder}; +use errors::{Level, Diagnostic}; use syntax::feature_gate::UnstableFeatures; use syntax::symbol::Symbol; use syntax_pos::DUMMY_SP; @@ -78,7 +78,7 @@ fn remove_message(e: &mut ExpectErrorEmitter, msg: &str, lvl: Level) { } impl Emitter for ExpectErrorEmitter { - fn emit(&mut self, db: &DiagnosticBuilder) { + fn emit(&mut self, db: Diagnostic) { remove_message(self, &db.message(), db.level); for child in &db.children { remove_message(self, &child.message(), child.level);