]>
Commit | Line | Data |
---|---|---|
9cc50fc6 SL |
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 | ||
3157f602 XL |
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)] | |
9e0c209e | 24 | #![cfg_attr(stage0, feature(question_mark))] |
3157f602 XL |
25 | #![feature(range_contains)] |
26 | #![feature(libc)] | |
27 | #![feature(unicode)] | |
28 | ||
29 | extern crate serialize; | |
30 | extern crate term; | |
c30ab7b3 SL |
31 | #[macro_use] |
32 | extern crate log; | |
33 | #[macro_use] | |
34 | extern crate libc; | |
3157f602 XL |
35 | extern crate rustc_unicode; |
36 | extern crate serialize as rustc_serialize; // used by deriving | |
37 | extern crate syntax_pos; | |
38 | ||
39 | pub use emitter::ColorConfig; | |
9cc50fc6 SL |
40 | |
41 | use self::Level::*; | |
9cc50fc6 | 42 | |
3157f602 | 43 | use emitter::{Emitter, EmitterWriter}; |
9cc50fc6 SL |
44 | |
45 | use std::cell::{RefCell, Cell}; | |
46 | use std::{error, fmt}; | |
9cc50fc6 | 47 | use std::rc::Rc; |
9cc50fc6 | 48 | |
c30ab7b3 SL |
49 | pub mod diagnostic; |
50 | pub mod diagnostic_builder; | |
9cc50fc6 | 51 | pub mod emitter; |
a7813a04 | 52 | pub mod snippet; |
3157f602 | 53 | pub mod registry; |
5bcae85e | 54 | pub mod styled_buffer; |
9e0c209e | 55 | mod lock; |
3157f602 | 56 | |
c30ab7b3 SL |
57 | use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION}; |
58 | use syntax_pos::MacroBacktrace; | |
9cc50fc6 | 59 | |
c30ab7b3 | 60 | #[derive(Clone, Debug, PartialEq)] |
9cc50fc6 SL |
61 | pub enum RenderSpan { |
62 | /// A FullSpan renders with both with an initial line for the | |
63 | /// message, prefixed by file:linenum, followed by a summary of | |
64 | /// the source code covered by the span. | |
7453a54e | 65 | FullSpan(MultiSpan), |
9cc50fc6 | 66 | |
9cc50fc6 SL |
67 | /// A suggestion renders with both with an initial line for the |
68 | /// message, prefixed by file:linenum, followed by a summary | |
7453a54e SL |
69 | /// of hypothetical source code, where each `String` is spliced |
70 | /// into the lines in place of the code covered by each span. | |
71 | Suggestion(CodeSuggestion), | |
7453a54e SL |
72 | } |
73 | ||
c30ab7b3 | 74 | #[derive(Clone, Debug, PartialEq)] |
7453a54e | 75 | pub struct CodeSuggestion { |
3157f602 XL |
76 | pub msp: MultiSpan, |
77 | pub substitutes: Vec<String>, | |
78 | } | |
79 | ||
80 | pub trait CodeMapper { | |
81 | fn lookup_char_pos(&self, pos: BytePos) -> Loc; | |
82 | fn span_to_lines(&self, sp: Span) -> FileLinesResult; | |
83 | fn span_to_string(&self, sp: Span) -> String; | |
84 | fn span_to_filename(&self, sp: Span) -> FileName; | |
85 | fn macro_backtrace(&self, span: Span) -> Vec<MacroBacktrace>; | |
9e0c209e | 86 | fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span>; |
9cc50fc6 SL |
87 | } |
88 | ||
7453a54e SL |
89 | impl CodeSuggestion { |
90 | /// Returns the assembled code suggestion. | |
3157f602 XL |
91 | pub fn splice_lines(&self, cm: &CodeMapper) -> String { |
92 | use syntax_pos::{CharPos, Loc, Pos}; | |
7453a54e | 93 | |
c30ab7b3 SL |
94 | fn push_trailing(buf: &mut String, |
95 | line_opt: Option<&str>, | |
96 | lo: &Loc, | |
97 | hi_opt: Option<&Loc>) { | |
98 | let (lo, hi_opt) = (lo.col.to_usize(), hi_opt.map(|hi| hi.col.to_usize())); | |
7453a54e SL |
99 | if let Some(line) = line_opt { |
100 | if line.len() > lo { | |
101 | buf.push_str(match hi_opt { | |
102 | Some(hi) => &line[lo..hi], | |
103 | None => &line[lo..], | |
104 | }); | |
105 | } | |
106 | if let None = hi_opt { | |
107 | buf.push('\n'); | |
108 | } | |
109 | } | |
9cc50fc6 | 110 | } |
7453a54e | 111 | |
a7813a04 XL |
112 | let mut primary_spans = self.msp.primary_spans().to_owned(); |
113 | ||
114 | assert_eq!(primary_spans.len(), self.substitutes.len()); | |
115 | if primary_spans.is_empty() { | |
116 | return format!(""); | |
117 | } | |
118 | ||
119 | // Assumption: all spans are in the same file, and all spans | |
120 | // are disjoint. Sort in ascending order. | |
121 | primary_spans.sort_by_key(|sp| sp.lo); | |
122 | ||
123 | // Find the bounding span. | |
124 | let lo = primary_spans.iter().map(|sp| sp.lo).min().unwrap(); | |
125 | let hi = primary_spans.iter().map(|sp| sp.hi).min().unwrap(); | |
c30ab7b3 SL |
126 | let bounding_span = Span { |
127 | lo: lo, | |
128 | hi: hi, | |
129 | expn_id: NO_EXPANSION, | |
130 | }; | |
a7813a04 XL |
131 | let lines = cm.span_to_lines(bounding_span).unwrap(); |
132 | assert!(!lines.lines.is_empty()); | |
7453a54e SL |
133 | |
134 | // To build up the result, we do this for each span: | |
135 | // - push the line segment trailing the previous span | |
136 | // (at the beginning a "phantom" span pointing at the start of the line) | |
137 | // - push lines between the previous and current span (if any) | |
138 | // - if the previous and current span are not on the same line | |
139 | // push the line segment leading up to the current span | |
140 | // - splice in the span substitution | |
141 | // | |
142 | // Finally push the trailing line segment of the last span | |
143 | let fm = &lines.file; | |
a7813a04 | 144 | let mut prev_hi = cm.lookup_char_pos(bounding_span.lo); |
7453a54e SL |
145 | prev_hi.col = CharPos::from_usize(0); |
146 | ||
147 | let mut prev_line = fm.get_line(lines.lines[0].line_index); | |
148 | let mut buf = String::new(); | |
149 | ||
a7813a04 | 150 | for (sp, substitute) in primary_spans.iter().zip(self.substitutes.iter()) { |
7453a54e SL |
151 | let cur_lo = cm.lookup_char_pos(sp.lo); |
152 | if prev_hi.line == cur_lo.line { | |
153 | push_trailing(&mut buf, prev_line, &prev_hi, Some(&cur_lo)); | |
154 | } else { | |
155 | push_trailing(&mut buf, prev_line, &prev_hi, None); | |
156 | // push lines between the previous and current span (if any) | |
157 | for idx in prev_hi.line..(cur_lo.line - 1) { | |
158 | if let Some(line) = fm.get_line(idx) { | |
159 | buf.push_str(line); | |
160 | buf.push('\n'); | |
161 | } | |
162 | } | |
163 | if let Some(cur_line) = fm.get_line(cur_lo.line - 1) { | |
c30ab7b3 | 164 | buf.push_str(&cur_line[..cur_lo.col.to_usize()]); |
7453a54e SL |
165 | } |
166 | } | |
167 | buf.push_str(substitute); | |
168 | prev_hi = cm.lookup_char_pos(sp.hi); | |
169 | prev_line = fm.get_line(prev_hi.line - 1); | |
170 | } | |
171 | push_trailing(&mut buf, prev_line, &prev_hi, None); | |
172 | // remove trailing newline | |
173 | buf.pop(); | |
174 | buf | |
9cc50fc6 SL |
175 | } |
176 | } | |
177 | ||
178 | /// Used as a return value to signify a fatal error occurred. (It is also | |
179 | /// used as the argument to panic at the moment, but that will eventually | |
180 | /// not be true.) | |
181 | #[derive(Copy, Clone, Debug)] | |
182 | #[must_use] | |
183 | pub struct FatalError; | |
184 | ||
185 | impl fmt::Display for FatalError { | |
186 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { | |
187 | write!(f, "parser fatal error") | |
188 | } | |
189 | } | |
190 | ||
191 | impl error::Error for FatalError { | |
192 | fn description(&self) -> &str { | |
193 | "The parser has encountered a fatal error" | |
194 | } | |
195 | } | |
196 | ||
197 | /// Signifies that the compiler died with an explicit call to `.bug` | |
198 | /// or `.span_bug` rather than a failed assertion, etc. | |
199 | #[derive(Copy, Clone, Debug)] | |
200 | pub struct ExplicitBug; | |
201 | ||
202 | impl fmt::Display for ExplicitBug { | |
203 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { | |
204 | write!(f, "parser internal bug") | |
205 | } | |
206 | } | |
207 | ||
208 | impl error::Error for ExplicitBug { | |
209 | fn description(&self) -> &str { | |
210 | "The parser has encountered an internal bug" | |
211 | } | |
212 | } | |
213 | ||
c30ab7b3 SL |
214 | pub use diagnostic::{Diagnostic, SubDiagnostic}; |
215 | pub use diagnostic_builder::DiagnosticBuilder; | |
9cc50fc6 SL |
216 | |
217 | /// A handler deals with errors; certain errors | |
218 | /// (fatal, bug, unimpl) may cause immediate exit, | |
219 | /// others log errors for later reporting. | |
220 | pub struct Handler { | |
221 | err_count: Cell<usize>, | |
5bcae85e | 222 | emitter: RefCell<Box<Emitter>>, |
9cc50fc6 SL |
223 | pub can_emit_warnings: bool, |
224 | treat_err_as_bug: bool, | |
7453a54e SL |
225 | continue_after_error: Cell<bool>, |
226 | delayed_span_bug: RefCell<Option<(MultiSpan, String)>>, | |
9cc50fc6 SL |
227 | } |
228 | ||
229 | impl Handler { | |
230 | pub fn with_tty_emitter(color_config: ColorConfig, | |
9cc50fc6 SL |
231 | can_emit_warnings: bool, |
232 | treat_err_as_bug: bool, | |
5bcae85e | 233 | cm: Option<Rc<CodeMapper>>) |
9cc50fc6 | 234 | -> Handler { |
5bcae85e | 235 | let emitter = Box::new(EmitterWriter::stderr(color_config, cm)); |
9cc50fc6 SL |
236 | Handler::with_emitter(can_emit_warnings, treat_err_as_bug, emitter) |
237 | } | |
238 | ||
239 | pub fn with_emitter(can_emit_warnings: bool, | |
240 | treat_err_as_bug: bool, | |
c30ab7b3 SL |
241 | e: Box<Emitter>) |
242 | -> Handler { | |
9cc50fc6 SL |
243 | Handler { |
244 | err_count: Cell::new(0), | |
5bcae85e | 245 | emitter: RefCell::new(e), |
9cc50fc6 SL |
246 | can_emit_warnings: can_emit_warnings, |
247 | treat_err_as_bug: treat_err_as_bug, | |
7453a54e | 248 | continue_after_error: Cell::new(true), |
9cc50fc6 SL |
249 | delayed_span_bug: RefCell::new(None), |
250 | } | |
251 | } | |
252 | ||
7453a54e SL |
253 | pub fn set_continue_after_error(&self, continue_after_error: bool) { |
254 | self.continue_after_error.set(continue_after_error); | |
255 | } | |
256 | ||
9cc50fc6 | 257 | pub fn struct_dummy<'a>(&'a self) -> DiagnosticBuilder<'a> { |
a7813a04 | 258 | DiagnosticBuilder::new(self, Level::Cancelled, "") |
9cc50fc6 SL |
259 | } |
260 | ||
7453a54e SL |
261 | pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self, |
262 | sp: S, | |
263 | msg: &str) | |
264 | -> DiagnosticBuilder<'a> { | |
a7813a04 XL |
265 | let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); |
266 | result.set_span(sp); | |
9cc50fc6 SL |
267 | if !self.can_emit_warnings { |
268 | result.cancel(); | |
269 | } | |
270 | result | |
271 | } | |
7453a54e SL |
272 | pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(&'a self, |
273 | sp: S, | |
274 | msg: &str, | |
275 | code: &str) | |
276 | -> DiagnosticBuilder<'a> { | |
a7813a04 XL |
277 | let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); |
278 | result.set_span(sp); | |
9cc50fc6 SL |
279 | result.code(code.to_owned()); |
280 | if !self.can_emit_warnings { | |
281 | result.cancel(); | |
282 | } | |
283 | result | |
284 | } | |
285 | pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> { | |
a7813a04 | 286 | let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); |
9cc50fc6 SL |
287 | if !self.can_emit_warnings { |
288 | result.cancel(); | |
289 | } | |
290 | result | |
291 | } | |
7453a54e SL |
292 | pub fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self, |
293 | sp: S, | |
294 | msg: &str) | |
295 | -> DiagnosticBuilder<'a> { | |
a7813a04 XL |
296 | let mut result = DiagnosticBuilder::new(self, Level::Error, msg); |
297 | result.set_span(sp); | |
9cc50fc6 SL |
298 | result |
299 | } | |
7453a54e SL |
300 | pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self, |
301 | sp: S, | |
302 | msg: &str, | |
303 | code: &str) | |
304 | -> DiagnosticBuilder<'a> { | |
a7813a04 XL |
305 | let mut result = DiagnosticBuilder::new(self, Level::Error, msg); |
306 | result.set_span(sp); | |
9cc50fc6 SL |
307 | result.code(code.to_owned()); |
308 | result | |
309 | } | |
310 | pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> { | |
a7813a04 | 311 | DiagnosticBuilder::new(self, Level::Error, msg) |
9cc50fc6 | 312 | } |
7453a54e SL |
313 | pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self, |
314 | sp: S, | |
315 | msg: &str) | |
316 | -> DiagnosticBuilder<'a> { | |
a7813a04 XL |
317 | let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg); |
318 | result.set_span(sp); | |
9cc50fc6 SL |
319 | result |
320 | } | |
7453a54e SL |
321 | pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(&'a self, |
322 | sp: S, | |
323 | msg: &str, | |
324 | code: &str) | |
325 | -> DiagnosticBuilder<'a> { | |
a7813a04 XL |
326 | let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg); |
327 | result.set_span(sp); | |
9cc50fc6 SL |
328 | result.code(code.to_owned()); |
329 | result | |
330 | } | |
331 | pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> { | |
a7813a04 | 332 | DiagnosticBuilder::new(self, Level::Fatal, msg) |
9cc50fc6 SL |
333 | } |
334 | ||
5bcae85e | 335 | pub fn cancel(&self, err: &mut DiagnosticBuilder) { |
9cc50fc6 SL |
336 | err.cancel(); |
337 | } | |
338 | ||
a7813a04 | 339 | fn panic_if_treat_err_as_bug(&self) { |
9cc50fc6 | 340 | if self.treat_err_as_bug { |
a7813a04 | 341 | panic!("encountered error with `-Z treat_err_as_bug"); |
9cc50fc6 | 342 | } |
a7813a04 XL |
343 | } |
344 | ||
c30ab7b3 | 345 | pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> FatalError { |
a7813a04 | 346 | self.emit(&sp.into(), msg, Fatal); |
a7813a04 | 347 | self.panic_if_treat_err_as_bug(); |
9cc50fc6 SL |
348 | return FatalError; |
349 | } | |
c30ab7b3 SL |
350 | pub fn span_fatal_with_code<S: Into<MultiSpan>>(&self, |
351 | sp: S, | |
352 | msg: &str, | |
353 | code: &str) | |
a7813a04 XL |
354 | -> FatalError { |
355 | self.emit_with_code(&sp.into(), msg, code, Fatal); | |
a7813a04 | 356 | self.panic_if_treat_err_as_bug(); |
9cc50fc6 SL |
357 | return FatalError; |
358 | } | |
7453a54e | 359 | pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { |
a7813a04 | 360 | self.emit(&sp.into(), msg, Error); |
a7813a04 | 361 | self.panic_if_treat_err_as_bug(); |
9cc50fc6 | 362 | } |
9e0c209e SL |
363 | pub fn mut_span_err<'a, S: Into<MultiSpan>>(&'a self, |
364 | sp: S, | |
365 | msg: &str) | |
366 | -> DiagnosticBuilder<'a> { | |
367 | let mut result = DiagnosticBuilder::new(self, Level::Error, msg); | |
368 | result.set_span(sp); | |
9e0c209e SL |
369 | result |
370 | } | |
7453a54e | 371 | pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) { |
a7813a04 | 372 | self.emit_with_code(&sp.into(), msg, code, Error); |
a7813a04 | 373 | self.panic_if_treat_err_as_bug(); |
9cc50fc6 | 374 | } |
7453a54e | 375 | pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { |
a7813a04 | 376 | self.emit(&sp.into(), msg, Warning); |
9cc50fc6 | 377 | } |
7453a54e | 378 | pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) { |
a7813a04 | 379 | self.emit_with_code(&sp.into(), msg, code, Warning); |
9cc50fc6 | 380 | } |
7453a54e | 381 | pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! { |
a7813a04 | 382 | self.emit(&sp.into(), msg, Bug); |
9cc50fc6 SL |
383 | panic!(ExplicitBug); |
384 | } | |
7453a54e | 385 | pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { |
9cc50fc6 | 386 | let mut delayed = self.delayed_span_bug.borrow_mut(); |
7453a54e | 387 | *delayed = Some((sp.into(), msg.to_string())); |
9cc50fc6 | 388 | } |
7453a54e | 389 | pub fn span_bug_no_panic<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { |
a7813a04 | 390 | self.emit(&sp.into(), msg, Bug); |
9cc50fc6 | 391 | } |
7453a54e | 392 | pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { |
5bcae85e | 393 | self.emit(&sp.into(), msg, Note); |
9cc50fc6 | 394 | } |
7453a54e | 395 | pub fn span_unimpl<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! { |
9cc50fc6 SL |
396 | self.span_bug(sp, &format!("unimplemented {}", msg)); |
397 | } | |
398 | pub fn fatal(&self, msg: &str) -> FatalError { | |
399 | if self.treat_err_as_bug { | |
400 | self.bug(msg); | |
401 | } | |
c30ab7b3 | 402 | let mut db = DiagnosticBuilder::new(self, Fatal, msg); |
5bcae85e | 403 | db.emit(); |
9cc50fc6 SL |
404 | FatalError |
405 | } | |
406 | pub fn err(&self, msg: &str) { | |
407 | if self.treat_err_as_bug { | |
408 | self.bug(msg); | |
409 | } | |
c30ab7b3 | 410 | let mut db = DiagnosticBuilder::new(self, Error, msg); |
5bcae85e | 411 | db.emit(); |
9cc50fc6 SL |
412 | } |
413 | pub fn warn(&self, msg: &str) { | |
c30ab7b3 | 414 | let mut db = DiagnosticBuilder::new(self, Warning, msg); |
5bcae85e | 415 | db.emit(); |
9cc50fc6 SL |
416 | } |
417 | pub fn note_without_error(&self, msg: &str) { | |
c30ab7b3 | 418 | let mut db = DiagnosticBuilder::new(self, Note, msg); |
5bcae85e | 419 | db.emit(); |
9cc50fc6 SL |
420 | } |
421 | pub fn bug(&self, msg: &str) -> ! { | |
c30ab7b3 | 422 | let mut db = DiagnosticBuilder::new(self, Bug, msg); |
5bcae85e | 423 | db.emit(); |
9cc50fc6 SL |
424 | panic!(ExplicitBug); |
425 | } | |
426 | pub fn unimpl(&self, msg: &str) -> ! { | |
427 | self.bug(&format!("unimplemented {}", msg)); | |
428 | } | |
429 | ||
430 | pub fn bump_err_count(&self) { | |
431 | self.err_count.set(self.err_count.get() + 1); | |
432 | } | |
433 | ||
434 | pub fn err_count(&self) -> usize { | |
435 | self.err_count.get() | |
436 | } | |
437 | ||
438 | pub fn has_errors(&self) -> bool { | |
439 | self.err_count.get() > 0 | |
440 | } | |
9cc50fc6 SL |
441 | pub fn abort_if_errors(&self) { |
442 | let s; | |
443 | match self.err_count.get() { | |
444 | 0 => { | |
445 | let delayed_bug = self.delayed_span_bug.borrow(); | |
446 | match *delayed_bug { | |
7453a54e SL |
447 | Some((ref span, ref errmsg)) => { |
448 | self.span_bug(span.clone(), errmsg); | |
c30ab7b3 | 449 | } |
9cc50fc6 SL |
450 | _ => {} |
451 | } | |
452 | ||
453 | return; | |
454 | } | |
455 | 1 => s = "aborting due to previous error".to_string(), | |
c30ab7b3 SL |
456 | _ => { |
457 | s = format!("aborting due to {} previous errors", self.err_count.get()); | |
9cc50fc6 SL |
458 | } |
459 | } | |
460 | ||
461 | panic!(self.fatal(&s)); | |
462 | } | |
c30ab7b3 SL |
463 | pub fn emit(&self, msp: &MultiSpan, msg: &str, lvl: Level) { |
464 | if lvl == Warning && !self.can_emit_warnings { | |
465 | return; | |
466 | } | |
5bcae85e SL |
467 | let mut db = DiagnosticBuilder::new(self, lvl, msg); |
468 | db.set_span(msp.clone()); | |
469 | db.emit(); | |
c30ab7b3 SL |
470 | if !self.continue_after_error.get() { |
471 | self.abort_if_errors(); | |
472 | } | |
473 | } | |
474 | pub fn emit_with_code(&self, msp: &MultiSpan, msg: &str, code: &str, lvl: Level) { | |
475 | if lvl == Warning && !self.can_emit_warnings { | |
476 | return; | |
477 | } | |
478 | let mut db = DiagnosticBuilder::new_with_code(self, lvl, Some(code.to_owned()), msg); | |
5bcae85e SL |
479 | db.set_span(msp.clone()); |
480 | db.emit(); | |
c30ab7b3 SL |
481 | if !self.continue_after_error.get() { |
482 | self.abort_if_errors(); | |
483 | } | |
9cc50fc6 SL |
484 | } |
485 | } | |
486 | ||
487 | ||
488 | #[derive(Copy, PartialEq, Clone, Debug)] | |
489 | pub enum Level { | |
490 | Bug, | |
491 | Fatal, | |
7453a54e SL |
492 | // An error which while not immediately fatal, should stop the compiler |
493 | // progressing beyond the current phase. | |
494 | PhaseFatal, | |
9cc50fc6 SL |
495 | Error, |
496 | Warning, | |
497 | Note, | |
498 | Help, | |
499 | Cancelled, | |
500 | } | |
501 | ||
502 | impl fmt::Display for Level { | |
503 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
9cc50fc6 SL |
504 | self.to_str().fmt(f) |
505 | } | |
506 | } | |
507 | ||
508 | impl Level { | |
3157f602 | 509 | pub fn color(self) -> term::color::Color { |
9cc50fc6 | 510 | match self { |
7453a54e | 511 | Bug | Fatal | PhaseFatal | Error => term::color::BRIGHT_RED, |
9e0c209e SL |
512 | Warning => { |
513 | if cfg!(windows) { | |
514 | term::color::BRIGHT_YELLOW | |
515 | } else { | |
516 | term::color::YELLOW | |
517 | } | |
c30ab7b3 | 518 | } |
9cc50fc6 SL |
519 | Note => term::color::BRIGHT_GREEN, |
520 | Help => term::color::BRIGHT_CYAN, | |
521 | Cancelled => unreachable!(), | |
522 | } | |
523 | } | |
524 | ||
3157f602 | 525 | pub fn to_str(self) -> &'static str { |
9cc50fc6 SL |
526 | match self { |
527 | Bug => "error: internal compiler error", | |
7453a54e | 528 | Fatal | PhaseFatal | Error => "error", |
9cc50fc6 SL |
529 | Warning => "warning", |
530 | Note => "note", | |
531 | Help => "help", | |
532 | Cancelled => panic!("Shouldn't call on cancelled error"), | |
533 | } | |
534 | } | |
535 | } | |
536 | ||
c30ab7b3 SL |
537 | pub fn expect<T, M>(diag: &Handler, opt: Option<T>, msg: M) -> T |
538 | where M: FnOnce() -> String | |
9cc50fc6 SL |
539 | { |
540 | match opt { | |
541 | Some(t) => t, | |
542 | None => diag.bug(&msg()), | |
543 | } | |
9e0c209e | 544 | } |