(index<- )        ./libsyntax/diagnostic.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   1  // Copyright 2012 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  extern crate libc;
  12  
  13  use codemap::{Pos, Span};
  14  use codemap;
  15  
  16  use std::cell::{RefCell, Cell};
  17  use std::fmt;
  18  use std::io;
  19  use std::iter::range;
  20  use std::strbuf::StrBuf;
  21  use term;
  22  
  23  // maximum number of lines we will print for each error; arbitrary.
  24  static MAX_LINES: uint = 6u;
  25  
  26  #[deriving(Clone)]
  27  pub enum RenderSpan {
  28      /// A FullSpan renders with both with an initial line for the
  29      /// message, prefixed by file:linenum, followed by a summary of
  30      /// the source code covered by the span.
  31      FullSpan(Span),
  32  
  33      /// A FileLine renders with just a line for the message prefixed
  34      /// by file:linenum.
  35      FileLine(Span),
  36  }
  37  
  38  impl RenderSpan {
  39      fn span(self) -> Span {
  40          match self {
  41              FullSpan(s) | FileLine(s) => s
  42          }
  43      }
  44      fn is_full_span(&self) -> bool {
  45          match self {
  46              &FullSpan(..) => true,
  47              &FileLine(..) => false,
  48          }
  49      }
  50  }
  51  
  52  pub trait Emitter {
  53      fn emit(&mut self, cmsp: Option<(&codemap::CodeMap, Span)>,
  54              msg: &str, lvl: Level);
  55      fn custom_emit(&mut self, cm: &codemap::CodeMap,
  56                     sp: RenderSpan, msg: &str, lvl: Level);
  57  }
  58  
  59  /// This structure is used to signify that a task has failed with a fatal error
  60  /// from the diagnostics. You can use this with the `Any` trait to figure out
  61  /// how a rustc task died (if so desired).
  62  pub struct FatalError;
  63  
  64  /// Signifies that the compiler died with an explicit call to `.bug`
  65  /// or `.span_bug` rather than a failed assertion, etc.
  66  pub struct ExplicitBug;
  67  
  68  // a span-handler is like a handler but also
  69  // accepts span information for source-location
  70  // reporting.
  71  pub struct SpanHandler {
  72      pub handler: Handler,
  73      pub cm: codemap::CodeMap,
  74  }
  75  
  76  impl SpanHandler {
  77      pub fn span_fatal(&self, spSpan, msg&str) -> ! {
  78          self.handler.emit(Some((&self.cm, sp)), msg, Fatal);
  79          fail!(FatalError);
  80      }
  81      pub fn span_err(&self, spSpan, msg&str) {
  82          self.handler.emit(Some((&self.cm, sp)), msg, Error);
  83          self.handler.bump_err_count();
  84      }
  85      pub fn span_warn(&self, spSpan, msg&str) {
  86          self.handler.emit(Some((&self.cm, sp)), msg, Warning);
  87      }
  88      pub fn span_note(&self, spSpan, msg&str) {
  89          self.handler.emit(Some((&self.cm, sp)), msg, Note);
  90      }
  91      pub fn span_end_note(&self, spSpan, msg&str) {
  92          self.handler.custom_emit(&self.cm, FullSpan(sp), msg, Note);
  93      }
  94      pub fn fileline_note(&self, spSpan, msg&str) {
  95          self.handler.custom_emit(&self.cm, FileLine(sp), msg, Note);
  96      }
  97      pub fn span_bug(&self, spSpan, msg&str) -> ! {
  98          self.handler.emit(Some((&self.cm, sp)), msg, Bug);
  99          fail!(ExplicitBug);
 100      }
 101      pub fn span_unimpl(&self, spSpan, msg&str) -> ! {
 102          self.span_bug(sp, "unimplemented ".to_owned() + msg);
 103      }
 104      pub fn handler<'a>(&'a self) -> &'a Handler {
 105          &self.handler
 106      }
 107  }
 108  
 109  // a handler deals with errors; certain errors
 110  // (fatal, bug, unimpl) may cause immediate exit,
 111  // others log errors for later reporting.
 112  pub struct Handler {
 113      err_count: Cell<uint>,
 114      emit: RefCell<Box<Emitter:Send>>,
 115  }
 116  
 117  impl Handler {
 118      pub fn fatal(&self, msg&str) -> ! {
 119          self.emit.borrow_mut().emit(None, msg, Fatal);
 120          fail!(FatalError);
 121      }
 122      pub fn err(&self, msg&str) {
 123          self.emit.borrow_mut().emit(None, msg, Error);
 124          self.bump_err_count();
 125      }
 126      pub fn bump_err_count(&self) {
 127          self.err_count.set(self.err_count.get() + 1u);
 128      }
 129      pub fn err_count(&self) -> uint {
 130          self.err_count.get()
 131      }
 132      pub fn has_errors(&self) -> bool {
 133          self.err_count.get()0u
 134      }
 135      pub fn abort_if_errors(&self) {
 136          let s;
 137          match self.err_count.get() {
 138            0u => return,
 139            1u => s = "aborting due to previous error".to_owned(),
 140            _  => {
 141              s = format!("aborting due to {} previous errors",
 142                       self.err_count.get());
 143            }
 144          }
 145          self.fatal(s);
 146      }
 147      pub fn warn(&self, msg&str) {
 148          self.emit.borrow_mut().emit(None, msg, Warning);
 149      }
 150      pub fn note(&self, msg&str) {
 151          self.emit.borrow_mut().emit(None, msg, Note);
 152      }
 153      pub fn bug(&self, msg&str) -> ! {
 154          self.emit.borrow_mut().emit(None, msg, Bug);
 155          fail!(ExplicitBug);
 156      }
 157      pub fn unimpl(&self, msg&str) -> ! {
 158          self.bug("unimplemented ".to_owned() + msg);
 159      }
 160      pub fn emit(&self,
 161                  cmspOption<(&codemap::CodeMap, Span)>,
 162                  msg&str,
 163                  lvlLevel) {
 164          self.emit.borrow_mut().emit(cmsp, msg, lvl);
 165      }
 166      pub fn custom_emit(&self, cm&codemap::CodeMap,
 167                         spRenderSpan, msg&str, lvlLevel) {
 168          self.emit.borrow_mut().custom_emit(cm, sp, msg, lvl);
 169      }
 170  }
 171  
 172  pub fn mk_span_handler(handlerHandler, cmcodemap::CodeMap) -> SpanHandler {
 173      SpanHandler {
 174          handler: handler,
 175          cm: cm,
 176      }
 177  }
 178  
 179  pub fn default_handler() -> Handler {
 180      mk_handler(box EmitterWriter::stderr())
 181  }
 182  
 183  pub fn mk_handler(eBox<Emitter:Send>) -> Handler {
 184      Handler {
 185          err_count: Cell::new(0),
 186          emit: RefCell::new(e),
 187      }
 188  }
 189  
 190  #[deriving(Eq)]
 191  pub enum Level {
 192      Bug,
 193      Fatal,
 194      Error,
 195      Warning,
 196      Note,
 197  }
 198  
 199  impl fmt::Show for Level {
 200      fn fmt(&self, f&mut fmt::Formatter) -> fmt::Result {
 201          use std::fmt::Show;
 202  
 203          match *self {
 204              Bug => "error: internal compiler error".fmt(f),
 205              Fatal | Error => "error".fmt(f),
 206              Warning => "warning".fmt(f),
 207              Note => "note".fmt(f),
 208          }
 209      }
 210  }
 211  
 212  impl Level {
 213      fn color(self) -> term::color::Color {
 214          match self {
 215              Bug | Fatal | Error => term::color::BRIGHT_RED,
 216              Warning => term::color::BRIGHT_YELLOW,
 217              Note => term::color::BRIGHT_GREEN
 218          }
 219      }
 220  }
 221  
 222  fn print_maybe_styled(w: &mut EmitterWriter,
 223                        msg: &str,
 224                        colorterm::attr::Attr) -> io::IoResult<()> {
 225      match w.dst {
 226          Terminal(ref mut t) => {
 227              try!(t.attr(color));
 228              try!(t.write_str(msg));
 229              try!(t.reset());
 230              Ok(())
 231          }
 232          Raw(ref mut w) => {
 233              w.write_str(msg)
 234          }
 235      }
 236  }
 237  
 238  fn print_diagnostic(dst: &mut EmitterWriter,
 239                      topic: &str, lvlLevel, msg: &str) -> io::IoResult<()> {
 240      if !topic.is_empty() {
 241          try!(write!(&mut dst.dst, "{} ", topic));
 242      }
 243  
 244      try!(print_maybe_styled(dst, format!("{}: ", lvl.to_str()),
 245                              term::attr::ForegroundColor(lvl.color())));
 246      try!(print_maybe_styled(dst, format!("{}\n", msg), term::attr::Bold));
 247      Ok(())
 248  }
 249  
 250  pub struct EmitterWriter {
 251      dst: Destination,
 252  }
 253  
 254  enum Destination {
 255      Terminal(term::Terminal<io::stdio::StdWriter>),
 256      Raw(Box<Writer:Send>),
 257  }
 258  
 259  impl EmitterWriter {
 260      pub fn stderr() -> EmitterWriter {
 261          let stderr = io::stderr();
 262          if stderr.get_ref().isatty() {
 263              let dst = match term::Terminal::new(stderr.unwrap()) {
 264                  Ok(t) => Terminal(t),
 265                  Err(..) => Raw(box io::stderr()),
 266              };
 267              EmitterWriter { dst: dst }
 268          } else {
 269              EmitterWriter { dst: Raw(box stderr) }
 270          }
 271      }
 272  
 273      pub fn new(dstBox<Writer:Send>) -> EmitterWriter {
 274          EmitterWriter { dst: Raw(dst) }
 275      }
 276  }
 277  
 278  impl Writer for Destination {
 279      fn write(&mut self, bytes&[u8]) -> io::IoResult<()> {
 280          match *self {
 281              Terminal(ref mut t) => t.write(bytes),
 282              Raw(ref mut w) => w.write(bytes),
 283          }
 284      }
 285  }
 286  
 287  impl Emitter for EmitterWriter {
 288      fn emit(&mut self,
 289              cmspOption<(&codemap::CodeMap, Span)>,
 290              msg&str,
 291              lvlLevel) {
 292          let error = match cmsp {
 293              Some((cm, sp)) => emit(self, cm, FullSpan(sp), msg, lvl, false),
 294              None => print_diagnostic(self, "", lvl, msg),
 295          };
 296  
 297          match error {
 298              Ok(()) => {}
 299              Err(e) => fail!("failed to print diagnostics: {}", e),
 300          }
 301      }
 302  
 303      fn custom_emit(&mut self, cm&codemap::CodeMap,
 304                     spRenderSpan, msg&str, lvlLevel) {
 305          match emit(self, cm, sp, msg, lvl, true) {
 306              Ok(()) => {}
 307              Err(e) => fail!("failed to print diagnostics: {}", e),
 308          }
 309      }
 310  }
 311  
 312  fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rspRenderSpan,
 313          msg: &str, lvlLevel, custom: bool) -> io::IoResult<()> {
 314      let sp = rsp.span();
 315      let ss = cm.span_to_str(sp);
 316      let lines = cm.span_to_lines(sp);
 317      if custom {
 318          // we want to tell compiletest/runtest to look at the last line of the
 319          // span (since `custom_highlight_lines` displays an arrow to the end of
 320          // the span)
 321          let span_end = Span { lo: sp.hi, hi: sp.hi, expn_info: sp.expn_info};
 322          let ses = cm.span_to_str(span_end);
 323          try!(print_diagnostic(dst, ses.as_slice(), lvl, msg));
 324          if rsp.is_full_span() {
 325              try!(custom_highlight_lines(dst, cm, sp, lvl, lines));
 326          }
 327      } else {
 328          try!(print_diagnostic(dst, ss.as_slice(), lvl, msg));
 329          if rsp.is_full_span() {
 330              try!(highlight_lines(dst, cm, sp, lvl, lines));
 331          }
 332      }
 333      print_macro_backtrace(dst, cm, sp)
 334  }
 335  
 336  fn highlight_lines(err: &mut EmitterWriter,
 337                     cm: &codemap::CodeMap,
 338                     spSpan,
 339                     lvlLevel,
 340                     linescodemap::FileLines) -> io::IoResult<()> {
 341      let fm = &*lines.file;
 342  
 343      let mut elided = false;
 344      let mut display_lines = lines.lines.as_slice();
 345      if display_lines.len() > MAX_LINES {
 346          display_lines = display_lines.slice(0u, MAX_LINES);
 347          elided = true;
 348      }
 349      // Print the offending lines
 350      for line in display_lines.iter() {
 351          try!(write!(&mut err.dst, "{}:{} {}\n", fm.name, *line + 1,
 352                      fm.get_line(*line as int)));
 353      }
 354      if elided {
 355          let last_line = display_lines[display_lines.len() - 1u];
 356          let s = format!("{}:{} ", fm.name, last_line + 1u);
 357          try!(write!(&mut err.dst, "{0:1$}...\n", "", s.len()));
 358      }
 359  
 360      // FIXME (#3260)
 361      // If there's one line at fault we can easily point to the problem
 362      if lines.lines.len() == 1u {
 363          let lo = cm.lookup_char_pos(sp.lo);
 364          let mut digits = 0u;
 365          let mut num = (*lines.lines.get(0) + 1u) / 10u;
 366  
 367          // how many digits must be indent past?
 368          while num > 0u { num /= 10u; digits += 1u; }
 369  
 370          // indent past |name:## | and the 0-offset column location
 371          let left = fm.name.len() + digits + lo.col.to_uint() + 3u;
 372          let mut s = StrBuf::new();
 373          // Skip is the number of characters we need to skip because they are
 374          // part of the 'filename:line ' part of the previous line.
 375          let skip = fm.name.len() + digits + 3u;
 376          for _ in range(0, skip) {
 377              s.push_char(' ');
 378          }
 379          let orig = fm.get_line(*lines.lines.get(0) as int);
 380          for pos in range(0u, left-skip) {
 381              let cur_char = orig.as_slice()[pos] as char;
 382              // Whenever a tab occurs on the previous line, we insert one on
 383              // the error-point-squiggly-line as well (instead of a space).
 384              // That way the squiggly line will usually appear in the correct
 385              // position.
 386              match cur_char {
 387                  '\t' => s.push_char('\t'),
 388                  _ => s.push_char(' '),
 389              };
 390          }
 391          try!(write!(&mut err.dst, "{}", s));
 392          let mut s = StrBuf::from_str("^");
 393          let hi = cm.lookup_char_pos(sp.hi);
 394          if hi.col != lo.col {
 395              // the ^ already takes up one space
 396              let num_squigglies = hi.col.to_uint()-lo.col.to_uint()-1u;
 397              for _ in range(0, num_squigglies) {
 398                  s.push_char('~');
 399              }
 400          }
 401          try!(print_maybe_styled(err, s.into_owned() + "\n",
 402                                  term::attr::ForegroundColor(lvl.color())));
 403      }
 404      Ok(())
 405  }
 406  
 407  // Here are the differences between this and the normal `highlight_lines`:
 408  // `custom_highlight_lines` will always put arrow on the last byte of the
 409  // span (instead of the first byte). Also, when the span is too long (more
 410  // than 6 lines), `custom_highlight_lines` will print the first line, then
 411  // dot dot dot, then last line, whereas `highlight_lines` prints the first
 412  // six lines.
 413  fn custom_highlight_lines(w: &mut EmitterWriter,
 414                            cm: &codemap::CodeMap,
 415                            spSpan,
 416                            lvlLevel,
 417                            linescodemap::FileLines)
 418                            -> io::IoResult<()> {
 419      let fm = &*lines.file;
 420  
 421      let lines = lines.lines.as_slice();
 422      if lines.len() > MAX_LINES {
 423          try!(write!(&mut w.dst, "{}:{} {}\n", fm.name,
 424                      lines[0] + 1, fm.get_line(lines[0] as int)));
 425          try!(write!(&mut w.dst, "...\n"));
 426          let last_line = lines[lines.len()-1];
 427          try!(write!(&mut w.dst, "{}:{} {}\n", fm.name,
 428                      last_line + 1, fm.get_line(last_line as int)));
 429      } else {
 430          for line in lines.iter() {
 431              try!(write!(&mut w.dst, "{}:{} {}\n", fm.name,
 432                          *line + 1, fm.get_line(*line as int)));
 433          }
 434      }
 435      let last_line_start = format!("{}:{} ", fm.name, lines[lines.len()-1]+1);
 436      let hi = cm.lookup_char_pos(sp.hi);
 437      // Span seems to use half-opened interval, so subtract 1
 438      let skip = last_line_start.len() + hi.col.to_uint() - 1;
 439      let mut s = StrBuf::new();
 440      for _ in range(0, skip) {
 441          s.push_char(' ');
 442      }
 443      s.push_char('^');
 444      s.push_char('\n');
 445      print_maybe_styled(w,
 446                         s.into_owned(),
 447                         term::attr::ForegroundColor(lvl.color()))
 448  }
 449  
 450  fn print_macro_backtrace(w: &mut EmitterWriter,
 451                           cm: &codemap::CodeMap,
 452                           spSpan)
 453                           -> io::IoResult<()> {
 454      for ei in sp.expn_info.iter() {
 455          let ss = ei.callee
 456                     .span
 457                     .as_ref()
 458                     .map_or("".to_strbuf(), |span| cm.span_to_str(*span));
 459          let (pre, post) = match ei.callee.format {
 460              codemap::MacroAttribute => ("#[", "]"),
 461              codemap::MacroBang => ("", "!")
 462          };
 463          try!(print_diagnostic(w, ss.as_slice(), Note,
 464                                format!("in expansion of {}{}{}", pre,
 465                                        ei.callee.name, post)));
 466          let ss = cm.span_to_str(ei.call_site);
 467          try!(print_diagnostic(w, ss.as_slice(), Note, "expansion site"));
 468          try!(print_macro_backtrace(w, cm, ei.call_site));
 469      }
 470      Ok(())
 471  }
 472  
 473  pub fn expect<T:Clone>(diag: &SpanHandler, optOption<T>, msg: || -> StrBuf)
 474                -> T {
 475      match opt {
 476         Some(ref t) => (*t).clone(),
 477         None => diag.handler().bug(msg().as_slice()),
 478      }
 479  }


libsyntax/diagnostic.rs:190:16-190:16 -enum- definition:
pub enum Level {
    Bug,
    Fatal,
references:- 15
191: pub enum Level {
--
415:                           sp: Span,
416:                           lvl: Level,
417:                           lines: codemap::FileLines)


libsyntax/diagnostic.rs:51:1-51:1 -trait- definition:
pub trait Emitter {
    fn emit(&mut self, cmsp: Option<(&codemap::CodeMap, Span)>,
            msg: &str, lvl: Level);
references:- 3
287: impl Emitter for EmitterWriter {
288:     fn emit(&mut self,


libsyntax/diagnostic.rs:249:1-249:1 -struct- definition:
pub struct EmitterWriter {
    dst: Destination,
}
references:- 13
273:     pub fn new(dst: Box<Writer:Send>) -> EmitterWriter {
274:         EmitterWriter { dst: Raw(dst) }
275:     }
--
336: fn highlight_lines(err: &mut EmitterWriter,
337:                    cm: &codemap::CodeMap,
--
450: fn print_macro_backtrace(w: &mut EmitterWriter,
451:                          cm: &codemap::CodeMap,


libsyntax/diagnostic.rs:237:1-237:1 -fn- definition:
fn print_diagnostic(dst: &mut EmitterWriter,
                    topic: &str, lvl: Level, msg: &str) -> io::IoResult<()> {
    if !topic.is_empty() {
references:- 5
466:         let ss = cm.span_to_str(ei.call_site);
467:         try!(print_diagnostic(w, ss.as_slice(), Note, "expansion site"));
468:         try!(print_macro_backtrace(w, cm, ei.call_site));


libsyntax/diagnostic.rs:311:1-311:1 -fn- definition:
fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan,
        msg: &str, lvl: Level, custom: bool) -> io::IoResult<()> {
    let sp = rsp.span();
references:- 2
304:                    sp: RenderSpan, msg: &str, lvl: Level) {
305:         match emit(self, cm, sp, msg, lvl, true) {
306:             Ok(()) => {}


libsyntax/diagnostic.rs:111:42-111:42 -struct- definition:
// others log errors for later reporting.
pub struct Handler {
    err_count: Cell<uint>,
references:- 7
179: pub fn default_handler() -> Handler {
180:     mk_handler(box EmitterWriter::stderr())
--
183: pub fn mk_handler(e: Box<Emitter:Send>) -> Handler {
184:     Handler {
185:         err_count: Cell::new(0),


libsyntax/diagnostic.rs:449:1-449:1 -fn- definition:
fn print_macro_backtrace(w: &mut EmitterWriter,
                         cm: &codemap::CodeMap,
                         sp: Span)
references:- 2
332:     }
333:     print_macro_backtrace(dst, cm, sp)
334: }
--
467:         try!(print_diagnostic(w, ss.as_slice(), Note, "expansion site"));
468:         try!(print_macro_backtrace(w, cm, ei.call_site));
469:     }


libsyntax/diagnostic.rs:70:14-70:14 -struct- definition:
// reporting.
pub struct SpanHandler {
    pub handler: Handler,
references:- 19
172: pub fn mk_span_handler(handler: Handler, cm: codemap::CodeMap) -> SpanHandler {
173:     SpanHandler {
174:         handler: handler,
--
473: pub fn expect<T:Clone>(diag: &SpanHandler, opt: Option<T>, msg: || -> StrBuf)
474:               -> T {
libsyntax/parse/mod.rs:
36: pub struct ParseSess {
37:     pub span_diagnostic: SpanHandler, // better be the same as the one in the reader!
38:     /// Used to determine and report recursive mod inclusions
--
49: pub fn new_parse_sess_special_handler(sh: SpanHandler) -> ParseSess {
50:     ParseSess {
libsyntax/parse/lexer.rs:
128:     }
129:     fn span_diag<'a>(&'a self) -> &'a SpanHandler { self.sp_diag }
130:     fn peek(&self) -> TokenAndSpan {
libsyntax/parse/comments.rs:
365: pub fn gather_comments_and_literals(span_diagnostic:
366:                                         &diagnostic::SpanHandler,
367:                                     path: StrBuf,
libsyntax/print/pprust.rs:
97: pub fn print_crate<'a>(cm: &'a CodeMap,
98:                        span_diagnostic: &diagnostic::SpanHandler,
99:                        krate: &ast::Crate,
libsyntax/ext/registrar.rs:
38: pub fn find_macro_registrar(diagnostic: &diagnostic::SpanHandler,
39:                             krate: &ast::Crate) -> Option<ast::NodeId> {
libsyntax/ext/tt/transcribe.rs:
48:  *  should) be none. */
49: pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler,
50:                          interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
libsyntax/attr.rs:
378: pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[@MetaItem]) {
379:     let mut set = HashSet::new();
--
402:  */
403: pub fn find_repr_attr(diagnostic: &SpanHandler, attr: @ast::MetaItem, acc: ReprAttr)
404:     -> ReprAttr {
libsyntax/diagnostic.rs:
172: pub fn mk_span_handler(handler: Handler, cm: codemap::CodeMap) -> SpanHandler {
173:     SpanHandler {


libsyntax/diagnostic.rs:26:19-26:19 -enum- definition:
pub enum RenderSpan {
    /// A FullSpan renders with both with an initial line for the
    /// message, prefixed by file:linenum, followed by a summary of
references:- 7
312: fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan,
313:         msg: &str, lvl: Level, custom: bool) -> io::IoResult<()> {


libsyntax/diagnostic.rs:221:1-221:1 -fn- definition:
fn print_maybe_styled(w: &mut EmitterWriter,
                      msg: &str,
                      color: term::attr::Attr) -> io::IoResult<()> {
references:- 4
400:         }
401:         try!(print_maybe_styled(err, s.into_owned() + "\n",
402:                                 term::attr::ForegroundColor(lvl.color())));
--
444:     s.push_char('\n');
445:     print_maybe_styled(w,
446:                        s.into_owned(),


libsyntax/diagnostic.rs:253:1-253:1 -enum- definition:
enum Destination {
    Terminal(term::Terminal<io::stdio::StdWriter>),
    Raw(Box<Writer:Send>),
references:- 2
250: pub struct EmitterWriter {
251:     dst: Destination,
252: }
--
278: impl Writer for Destination {
279:     fn write(&mut self, bytes: &[u8]) -> io::IoResult<()> {