]> git.proxmox.com Git - rustc.git/blame - src/librustc_errors/lib.rs
New upstream version 1.14.0+dfsg1
[rustc.git] / src / librustc_errors / lib.rs
CommitLineData
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
29extern crate serialize;
30extern crate term;
c30ab7b3
SL
31#[macro_use]
32extern crate log;
33#[macro_use]
34extern crate libc;
3157f602
XL
35extern crate rustc_unicode;
36extern crate serialize as rustc_serialize; // used by deriving
37extern crate syntax_pos;
38
39pub use emitter::ColorConfig;
9cc50fc6
SL
40
41use self::Level::*;
9cc50fc6 42
3157f602 43use emitter::{Emitter, EmitterWriter};
9cc50fc6
SL
44
45use std::cell::{RefCell, Cell};
46use std::{error, fmt};
9cc50fc6 47use std::rc::Rc;
9cc50fc6 48
c30ab7b3
SL
49pub mod diagnostic;
50pub mod diagnostic_builder;
9cc50fc6 51pub mod emitter;
a7813a04 52pub mod snippet;
3157f602 53pub mod registry;
5bcae85e 54pub mod styled_buffer;
9e0c209e 55mod lock;
3157f602 56
c30ab7b3
SL
57use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION};
58use syntax_pos::MacroBacktrace;
9cc50fc6 59
c30ab7b3 60#[derive(Clone, Debug, PartialEq)]
9cc50fc6
SL
61pub 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 75pub struct CodeSuggestion {
3157f602
XL
76 pub msp: MultiSpan,
77 pub substitutes: Vec<String>,
78}
79
80pub 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
89impl 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]
183pub struct FatalError;
184
185impl fmt::Display for FatalError {
186 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
187 write!(f, "parser fatal error")
188 }
189}
190
191impl 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)]
200pub struct ExplicitBug;
201
202impl fmt::Display for ExplicitBug {
203 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
204 write!(f, "parser internal bug")
205 }
206}
207
208impl error::Error for ExplicitBug {
209 fn description(&self) -> &str {
210 "The parser has encountered an internal bug"
211 }
212}
213
c30ab7b3
SL
214pub use diagnostic::{Diagnostic, SubDiagnostic};
215pub 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.
220pub 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
229impl 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)]
489pub 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
502impl 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
508impl 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
537pub 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}