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