]> git.lizzy.rs Git - rust.git/blob - src/librustc_errors/lib.rs
prevent error message interleaving on win/unix
[rust.git] / src / librustc_errors / lib.rs
1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #![crate_name = "rustc_errors"]
12 #![unstable(feature = "rustc_private", issue = "27812")]
13 #![crate_type = "dylib"]
14 #![crate_type = "rlib"]
15 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
16       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
17       html_root_url = "https://doc.rust-lang.org/nightly/")]
18 #![cfg_attr(not(stage0), deny(warnings))]
19
20 #![feature(custom_attribute)]
21 #![allow(unused_attributes)]
22 #![feature(rustc_private)]
23 #![feature(staged_api)]
24 #![feature(question_mark)]
25 #![feature(range_contains)]
26 #![feature(libc)]
27 #![feature(unicode)]
28
29 extern crate serialize;
30 extern crate term;
31 #[macro_use] extern crate log;
32 #[macro_use] extern crate libc;
33 extern crate rustc_unicode;
34 extern crate serialize as rustc_serialize; // used by deriving
35 extern crate syntax_pos;
36
37 pub use emitter::ColorConfig;
38
39 use self::Level::*;
40 use self::RenderSpan::*;
41
42 use emitter::{Emitter, EmitterWriter};
43
44 use std::cell::{RefCell, Cell};
45 use std::{error, fmt};
46 use std::rc::Rc;
47 use std::thread::panicking;
48
49 pub mod emitter;
50 pub mod snippet;
51 pub mod registry;
52 pub mod styled_buffer;
53 mod lock;
54
55 use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION };
56 use syntax_pos::{MacroBacktrace};
57
58 #[derive(Clone)]
59 pub enum RenderSpan {
60     /// A FullSpan renders with both with an initial line for the
61     /// message, prefixed by file:linenum, followed by a summary of
62     /// the source code covered by the span.
63     FullSpan(MultiSpan),
64
65     /// A suggestion renders with both with an initial line for the
66     /// message, prefixed by file:linenum, followed by a summary
67     /// of hypothetical source code, where each `String` is spliced
68     /// into the lines in place of the code covered by each span.
69     Suggestion(CodeSuggestion),
70 }
71
72 #[derive(Clone)]
73 pub struct CodeSuggestion {
74     pub msp: MultiSpan,
75     pub substitutes: Vec<String>,
76 }
77
78 pub trait CodeMapper {
79     fn lookup_char_pos(&self, pos: BytePos) -> Loc;
80     fn span_to_lines(&self, sp: Span) -> FileLinesResult;
81     fn span_to_string(&self, sp: Span) -> String;
82     fn span_to_filename(&self, sp: Span) -> FileName;
83     fn macro_backtrace(&self, span: Span) -> Vec<MacroBacktrace>;
84 }
85
86 impl CodeSuggestion {
87     /// Returns the assembled code suggestion.
88     pub fn splice_lines(&self, cm: &CodeMapper) -> String {
89         use syntax_pos::{CharPos, Loc, Pos};
90
91         fn push_trailing(buf: &mut String, line_opt: Option<&str>,
92                          lo: &Loc, hi_opt: Option<&Loc>) {
93             let (lo, hi_opt) = (lo.col.to_usize(), hi_opt.map(|hi|hi.col.to_usize()));
94             if let Some(line) = line_opt {
95                 if line.len() > lo {
96                     buf.push_str(match hi_opt {
97                         Some(hi) => &line[lo..hi],
98                         None => &line[lo..],
99                     });
100                 }
101                 if let None = hi_opt {
102                     buf.push('\n');
103                 }
104             }
105         }
106
107         let mut primary_spans = self.msp.primary_spans().to_owned();
108
109         assert_eq!(primary_spans.len(), self.substitutes.len());
110         if primary_spans.is_empty() {
111             return format!("");
112         }
113
114         // Assumption: all spans are in the same file, and all spans
115         // are disjoint. Sort in ascending order.
116         primary_spans.sort_by_key(|sp| sp.lo);
117
118         // Find the bounding span.
119         let lo = primary_spans.iter().map(|sp| sp.lo).min().unwrap();
120         let hi = primary_spans.iter().map(|sp| sp.hi).min().unwrap();
121         let bounding_span = Span { lo: lo, hi: hi, expn_id: NO_EXPANSION };
122         let lines = cm.span_to_lines(bounding_span).unwrap();
123         assert!(!lines.lines.is_empty());
124
125         // To build up the result, we do this for each span:
126         // - push the line segment trailing the previous span
127         //   (at the beginning a "phantom" span pointing at the start of the line)
128         // - push lines between the previous and current span (if any)
129         // - if the previous and current span are not on the same line
130         //   push the line segment leading up to the current span
131         // - splice in the span substitution
132         //
133         // Finally push the trailing line segment of the last span
134         let fm = &lines.file;
135         let mut prev_hi = cm.lookup_char_pos(bounding_span.lo);
136         prev_hi.col = CharPos::from_usize(0);
137
138         let mut prev_line = fm.get_line(lines.lines[0].line_index);
139         let mut buf = String::new();
140
141         for (sp, substitute) in primary_spans.iter().zip(self.substitutes.iter()) {
142             let cur_lo = cm.lookup_char_pos(sp.lo);
143             if prev_hi.line == cur_lo.line {
144                 push_trailing(&mut buf, prev_line, &prev_hi, Some(&cur_lo));
145             } else {
146                 push_trailing(&mut buf, prev_line, &prev_hi, None);
147                 // push lines between the previous and current span (if any)
148                 for idx in prev_hi.line..(cur_lo.line - 1) {
149                     if let Some(line) = fm.get_line(idx) {
150                         buf.push_str(line);
151                         buf.push('\n');
152                     }
153                 }
154                 if let Some(cur_line) = fm.get_line(cur_lo.line - 1) {
155                     buf.push_str(&cur_line[.. cur_lo.col.to_usize()]);
156                 }
157             }
158             buf.push_str(substitute);
159             prev_hi = cm.lookup_char_pos(sp.hi);
160             prev_line = fm.get_line(prev_hi.line - 1);
161         }
162         push_trailing(&mut buf, prev_line, &prev_hi, None);
163         // remove trailing newline
164         buf.pop();
165         buf
166     }
167 }
168
169 /// Used as a return value to signify a fatal error occurred. (It is also
170 /// used as the argument to panic at the moment, but that will eventually
171 /// not be true.)
172 #[derive(Copy, Clone, Debug)]
173 #[must_use]
174 pub struct FatalError;
175
176 impl fmt::Display for FatalError {
177     fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
178         write!(f, "parser fatal error")
179     }
180 }
181
182 impl error::Error for FatalError {
183     fn description(&self) -> &str {
184         "The parser has encountered a fatal error"
185     }
186 }
187
188 /// Signifies that the compiler died with an explicit call to `.bug`
189 /// or `.span_bug` rather than a failed assertion, etc.
190 #[derive(Copy, Clone, Debug)]
191 pub struct ExplicitBug;
192
193 impl fmt::Display for ExplicitBug {
194     fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
195         write!(f, "parser internal bug")
196     }
197 }
198
199 impl error::Error for ExplicitBug {
200     fn description(&self) -> &str {
201         "The parser has encountered an internal bug"
202     }
203 }
204
205 /// Used for emitting structured error messages and other diagnostic information.
206 #[must_use]
207 #[derive(Clone)]
208 pub struct DiagnosticBuilder<'a> {
209     handler: &'a Handler,
210     pub level: Level,
211     pub message: String,
212     pub code: Option<String>,
213     pub span: MultiSpan,
214     pub children: Vec<SubDiagnostic>,
215 }
216
217 /// For example a note attached to an error.
218 #[derive(Clone)]
219 pub struct SubDiagnostic {
220     pub level: Level,
221     pub message: String,
222     pub span: MultiSpan,
223     pub render_span: Option<RenderSpan>,
224 }
225
226 impl<'a> DiagnosticBuilder<'a> {
227     /// Emit the diagnostic.
228     pub fn emit(&mut self) {
229         if self.cancelled() {
230             return;
231         }
232
233         self.handler.emitter.borrow_mut().emit(&self);
234         self.cancel();
235         self.handler.panic_if_treat_err_as_bug();
236
237         // if self.is_fatal() {
238         //     panic!(FatalError);
239         // }
240     }
241
242     /// Cancel the diagnostic (a structured diagnostic must either be emitted or
243     /// cancelled or it will panic when dropped).
244     /// BEWARE: if this DiagnosticBuilder is an error, then creating it will
245     /// bump the error count on the Handler and cancelling it won't undo that.
246     /// If you want to decrement the error count you should use `Handler::cancel`.
247     pub fn cancel(&mut self) {
248         self.level = Level::Cancelled;
249     }
250
251     pub fn cancelled(&self) -> bool {
252         self.level == Level::Cancelled
253     }
254
255     pub fn is_fatal(&self) -> bool {
256         self.level == Level::Fatal
257     }
258
259     /// Add a span/label to be included in the resulting snippet.
260     /// This is pushed onto the `MultiSpan` that was created when the
261     /// diagnostic was first built. If you don't call this function at
262     /// all, and you just supplied a `Span` to create the diagnostic,
263     /// then the snippet will just include that `Span`, which is
264     /// called the primary span.
265     pub fn span_label(&mut self, span: Span, label: &fmt::Display)
266                       -> &mut DiagnosticBuilder<'a> {
267         self.span.push_span_label(span, format!("{}", label));
268         self
269     }
270
271     pub fn note_expected_found(&mut self,
272                                label: &fmt::Display,
273                                expected: &fmt::Display,
274                                found: &fmt::Display)
275                                -> &mut DiagnosticBuilder<'a>
276     {
277         // For now, just attach these as notes
278         self.note(&format!("expected {} `{}`", label, expected));
279         self.note(&format!("   found {} `{}`", label, found));
280         self
281     }
282
283     pub fn note(&mut self, msg: &str) -> &mut DiagnosticBuilder<'a> {
284         self.sub(Level::Note, msg, MultiSpan::new(), None);
285         self
286     }
287     pub fn span_note<S: Into<MultiSpan>>(&mut self,
288                                          sp: S,
289                                          msg: &str)
290                                          -> &mut DiagnosticBuilder<'a> {
291         self.sub(Level::Note, msg, sp.into(), None);
292         self
293     }
294     pub fn warn(&mut self, msg: &str) -> &mut DiagnosticBuilder<'a> {
295         self.sub(Level::Warning, msg, MultiSpan::new(), None);
296         self
297     }
298     pub fn span_warn<S: Into<MultiSpan>>(&mut self,
299                                          sp: S,
300                                          msg: &str)
301                                          -> &mut DiagnosticBuilder<'a> {
302         self.sub(Level::Warning, msg, sp.into(), None);
303         self
304     }
305     pub fn help(&mut self , msg: &str) -> &mut DiagnosticBuilder<'a> {
306         self.sub(Level::Help, msg, MultiSpan::new(), None);
307         self
308     }
309     pub fn span_help<S: Into<MultiSpan>>(&mut self,
310                                          sp: S,
311                                          msg: &str)
312                                          -> &mut DiagnosticBuilder<'a> {
313         self.sub(Level::Help, msg, sp.into(), None);
314         self
315     }
316     /// Prints out a message with a suggested edit of the code.
317     ///
318     /// See `diagnostic::RenderSpan::Suggestion` for more information.
319     pub fn span_suggestion<S: Into<MultiSpan>>(&mut self,
320                                                sp: S,
321                                                msg: &str,
322                                                suggestion: String)
323                                                -> &mut DiagnosticBuilder<'a> {
324         self.sub(Level::Help, msg, MultiSpan::new(), Some(Suggestion(CodeSuggestion {
325             msp: sp.into(),
326             substitutes: vec![suggestion],
327         })));
328         self
329     }
330
331     pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
332         self.span = sp.into();
333         self
334     }
335
336     pub fn code(&mut self, s: String) -> &mut Self {
337         self.code = Some(s);
338         self
339     }
340
341     pub fn message(&self) -> &str {
342         &self.message
343     }
344
345     pub fn level(&self) -> Level {
346         self.level
347     }
348
349     /// Convenience function for internal use, clients should use one of the
350     /// struct_* methods on Handler.
351     fn new(handler: &'a Handler,
352            level: Level,
353            message: &str) -> DiagnosticBuilder<'a> {
354         DiagnosticBuilder::new_with_code(handler, level, None, message)
355     }
356
357     /// Convenience function for internal use, clients should use one of the
358     /// struct_* methods on Handler.
359     fn new_with_code(handler: &'a Handler,
360            level: Level,
361            code: Option<String>,
362            message: &str) -> DiagnosticBuilder<'a> {
363         DiagnosticBuilder {
364             handler: handler,
365             level: level,
366             message: message.to_owned(),
367             code: code,
368             span: MultiSpan::new(),
369             children: vec![],
370         }
371     }
372
373     /// Convenience function for internal use, clients should use one of the
374     /// public methods above.
375     fn sub(&mut self,
376            level: Level,
377            message: &str,
378            span: MultiSpan,
379            render_span: Option<RenderSpan>) {
380         let sub = SubDiagnostic {
381             level: level,
382             message: message.to_owned(),
383             span: span,
384             render_span: render_span,
385         };
386         self.children.push(sub);
387     }
388 }
389
390 impl<'a> fmt::Debug for DiagnosticBuilder<'a> {
391     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
392         self.message.fmt(f)
393     }
394 }
395
396 /// Destructor bomb - a DiagnosticBuilder must be either emitted or cancelled or
397 /// we emit a bug.
398 impl<'a> Drop for DiagnosticBuilder<'a> {
399     fn drop(&mut self) {
400         if !panicking() && !self.cancelled() {
401             let mut db = DiagnosticBuilder::new(self.handler,
402                                                 Bug,
403                                                 "Error constructed but not emitted");
404             db.emit();
405             panic!();
406         }
407     }
408 }
409
410 /// A handler deals with errors; certain errors
411 /// (fatal, bug, unimpl) may cause immediate exit,
412 /// others log errors for later reporting.
413 pub struct Handler {
414     err_count: Cell<usize>,
415     emitter: RefCell<Box<Emitter>>,
416     pub can_emit_warnings: bool,
417     treat_err_as_bug: bool,
418     continue_after_error: Cell<bool>,
419     delayed_span_bug: RefCell<Option<(MultiSpan, String)>>,
420 }
421
422 impl Handler {
423     pub fn with_tty_emitter(color_config: ColorConfig,
424                             can_emit_warnings: bool,
425                             treat_err_as_bug: bool,
426                             cm: Option<Rc<CodeMapper>>)
427                             -> Handler {
428         let emitter = Box::new(EmitterWriter::stderr(color_config, cm));
429         Handler::with_emitter(can_emit_warnings, treat_err_as_bug, emitter)
430     }
431
432     pub fn with_emitter(can_emit_warnings: bool,
433                         treat_err_as_bug: bool,
434                         e: Box<Emitter>) -> Handler {
435         Handler {
436             err_count: Cell::new(0),
437             emitter: RefCell::new(e),
438             can_emit_warnings: can_emit_warnings,
439             treat_err_as_bug: treat_err_as_bug,
440             continue_after_error: Cell::new(true),
441             delayed_span_bug: RefCell::new(None),
442         }
443     }
444
445     pub fn set_continue_after_error(&self, continue_after_error: bool) {
446         self.continue_after_error.set(continue_after_error);
447     }
448
449     pub fn struct_dummy<'a>(&'a self) -> DiagnosticBuilder<'a> {
450         DiagnosticBuilder::new(self, Level::Cancelled, "")
451     }
452
453     pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self,
454                                                     sp: S,
455                                                     msg: &str)
456                                                     -> DiagnosticBuilder<'a> {
457         let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
458         result.set_span(sp);
459         if !self.can_emit_warnings {
460             result.cancel();
461         }
462         result
463     }
464     pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(&'a self,
465                                                               sp: S,
466                                                               msg: &str,
467                                                               code: &str)
468                                                               -> DiagnosticBuilder<'a> {
469         let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
470         result.set_span(sp);
471         result.code(code.to_owned());
472         if !self.can_emit_warnings {
473             result.cancel();
474         }
475         result
476     }
477     pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
478         let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
479         if !self.can_emit_warnings {
480             result.cancel();
481         }
482         result
483     }
484     pub fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
485                                                    sp: S,
486                                                    msg: &str)
487                                                    -> DiagnosticBuilder<'a> {
488         self.bump_err_count();
489         let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
490         result.set_span(sp);
491         result
492     }
493     pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
494                                                              sp: S,
495                                                              msg: &str,
496                                                              code: &str)
497                                                              -> DiagnosticBuilder<'a> {
498         self.bump_err_count();
499         let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
500         result.set_span(sp);
501         result.code(code.to_owned());
502         result
503     }
504     pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
505         self.bump_err_count();
506         DiagnosticBuilder::new(self, Level::Error, msg)
507     }
508     pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self,
509                                                      sp: S,
510                                                      msg: &str)
511                                                      -> DiagnosticBuilder<'a> {
512         self.bump_err_count();
513         let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg);
514         result.set_span(sp);
515         result
516     }
517     pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(&'a self,
518                                                                sp: S,
519                                                                msg: &str,
520                                                                code: &str)
521                                                                -> DiagnosticBuilder<'a> {
522         self.bump_err_count();
523         let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg);
524         result.set_span(sp);
525         result.code(code.to_owned());
526         result
527     }
528     pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
529         self.bump_err_count();
530         DiagnosticBuilder::new(self, Level::Fatal, msg)
531     }
532
533     pub fn cancel(&self, err: &mut DiagnosticBuilder) {
534         if err.level == Level::Error || err.level == Level::Fatal {
535             self.err_count.set(
536                 self.err_count.get().checked_sub(1)
537                     .expect("cancelled an error but err_count is 0")
538             );
539         }
540         err.cancel();
541     }
542
543     fn panic_if_treat_err_as_bug(&self) {
544         if self.treat_err_as_bug {
545             panic!("encountered error with `-Z treat_err_as_bug");
546         }
547     }
548
549     pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str)
550                                           -> FatalError {
551         self.emit(&sp.into(), msg, Fatal);
552         self.bump_err_count();
553         self.panic_if_treat_err_as_bug();
554         return FatalError;
555     }
556     pub fn span_fatal_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str)
557                                                     -> FatalError {
558         self.emit_with_code(&sp.into(), msg, code, Fatal);
559         self.bump_err_count();
560         self.panic_if_treat_err_as_bug();
561         return FatalError;
562     }
563     pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
564         self.emit(&sp.into(), msg, Error);
565         self.bump_err_count();
566         self.panic_if_treat_err_as_bug();
567     }
568     pub fn mut_span_err<'a, S: Into<MultiSpan>>(&'a self,
569                                                 sp: S,
570                                                 msg: &str)
571                                                 -> DiagnosticBuilder<'a> {
572         let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
573         result.set_span(sp);
574         self.bump_err_count();
575         result
576     }
577     pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
578         self.emit_with_code(&sp.into(), msg, code, Error);
579         self.bump_err_count();
580         self.panic_if_treat_err_as_bug();
581     }
582     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
583         self.emit(&sp.into(), msg, Warning);
584     }
585     pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
586         self.emit_with_code(&sp.into(), msg, code, Warning);
587     }
588     pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
589         self.emit(&sp.into(), msg, Bug);
590         panic!(ExplicitBug);
591     }
592     pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
593         let mut delayed = self.delayed_span_bug.borrow_mut();
594         *delayed = Some((sp.into(), msg.to_string()));
595     }
596     pub fn span_bug_no_panic<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
597         self.emit(&sp.into(), msg, Bug);
598         self.bump_err_count();
599     }
600     pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
601         self.emit(&sp.into(), msg, Note);
602     }
603     pub fn span_unimpl<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
604         self.span_bug(sp, &format!("unimplemented {}", msg));
605     }
606     pub fn fatal(&self, msg: &str) -> FatalError {
607         if self.treat_err_as_bug {
608             self.bug(msg);
609         }
610         let mut db = DiagnosticBuilder::new(self,
611                                             Fatal,
612                                             msg);
613         db.emit();
614         self.bump_err_count();
615         FatalError
616     }
617     pub fn err(&self, msg: &str) {
618         if self.treat_err_as_bug {
619             self.bug(msg);
620         }
621         let mut db = DiagnosticBuilder::new(self,
622                                             Error,
623                                             msg);
624         db.emit();
625         self.bump_err_count();
626     }
627     pub fn warn(&self, msg: &str) {
628         let mut db = DiagnosticBuilder::new(self,
629                                             Warning,
630                                             msg);
631         db.emit();
632     }
633     pub fn note_without_error(&self, msg: &str) {
634         let mut db = DiagnosticBuilder::new(self,
635                                             Note,
636                                             msg);
637         db.emit();
638     }
639     pub fn bug(&self, msg: &str) -> ! {
640         let mut db = DiagnosticBuilder::new(self,
641                                             Bug,
642                                             msg);
643         db.emit();
644         panic!(ExplicitBug);
645     }
646     pub fn unimpl(&self, msg: &str) -> ! {
647         self.bug(&format!("unimplemented {}", msg));
648     }
649
650     pub fn bump_err_count(&self) {
651         self.err_count.set(self.err_count.get() + 1);
652     }
653
654     pub fn err_count(&self) -> usize {
655         self.err_count.get()
656     }
657
658     pub fn has_errors(&self) -> bool {
659         self.err_count.get() > 0
660     }
661     pub fn abort_if_errors(&self) {
662         let s;
663         match self.err_count.get() {
664             0 => {
665                 let delayed_bug = self.delayed_span_bug.borrow();
666                 match *delayed_bug {
667                     Some((ref span, ref errmsg)) => {
668                         self.span_bug(span.clone(), errmsg);
669                     },
670                     _ => {}
671                 }
672
673                 return;
674             }
675             1 => s = "aborting due to previous error".to_string(),
676             _  => {
677                 s = format!("aborting due to {} previous errors",
678                             self.err_count.get());
679             }
680         }
681
682         panic!(self.fatal(&s));
683     }
684     pub fn emit(&self,
685                 msp: &MultiSpan,
686                 msg: &str,
687                 lvl: Level) {
688         if lvl == Warning && !self.can_emit_warnings { return }
689         let mut db = DiagnosticBuilder::new(self, lvl, msg);
690         db.set_span(msp.clone());
691         db.emit();
692         if !self.continue_after_error.get() { self.abort_if_errors(); }
693     }
694     pub fn emit_with_code(&self,
695                           msp: &MultiSpan,
696                           msg: &str,
697                           code: &str,
698                           lvl: Level) {
699         if lvl == Warning && !self.can_emit_warnings { return }
700         let mut db = DiagnosticBuilder::new_with_code(self,
701                                                       lvl,
702                                                       Some(code.to_owned()),
703                                                       msg);
704         db.set_span(msp.clone());
705         db.emit();
706         if !self.continue_after_error.get() { self.abort_if_errors(); }
707     }
708 }
709
710
711 #[derive(Copy, PartialEq, Clone, Debug)]
712 pub enum Level {
713     Bug,
714     Fatal,
715     // An error which while not immediately fatal, should stop the compiler
716     // progressing beyond the current phase.
717     PhaseFatal,
718     Error,
719     Warning,
720     Note,
721     Help,
722     Cancelled,
723 }
724
725 impl fmt::Display for Level {
726     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
727         self.to_str().fmt(f)
728     }
729 }
730
731 impl Level {
732     pub fn color(self) -> term::color::Color {
733         match self {
734             Bug | Fatal | PhaseFatal | Error => term::color::BRIGHT_RED,
735             Warning => term::color::YELLOW,
736             Note => term::color::BRIGHT_GREEN,
737             Help => term::color::BRIGHT_CYAN,
738             Cancelled => unreachable!(),
739         }
740     }
741
742     pub fn to_str(self) -> &'static str {
743         match self {
744             Bug => "error: internal compiler error",
745             Fatal | PhaseFatal | Error => "error",
746             Warning => "warning",
747             Note => "note",
748             Help => "help",
749             Cancelled => panic!("Shouldn't call on cancelled error"),
750         }
751     }
752 }
753
754 pub fn expect<T, M>(diag: &Handler, opt: Option<T>, msg: M) -> T where
755     M: FnOnce() -> String,
756 {
757     match opt {
758         Some(t) => t,
759         None => diag.bug(&msg()),
760     }
761 }