]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2012-2013 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 | ||
1a4d82fc | 11 | use lint; |
92a42be0 | 12 | use middle::cstore::CrateStore; |
e9174d1e | 13 | use middle::dependency_format; |
1a4d82fc | 14 | use session::search_paths::PathKind; |
54a0048b | 15 | use ty::tls; |
e9174d1e | 16 | use util::nodemap::{NodeMap, FnvHashMap}; |
54a0048b | 17 | use mir::transform as mir_pass; |
1a4d82fc | 18 | |
92a42be0 | 19 | use syntax::ast::{NodeId, NodeIdAssigner, Name}; |
7453a54e | 20 | use syntax::codemap::{Span, MultiSpan}; |
9cc50fc6 SL |
21 | use syntax::errors::{self, DiagnosticBuilder}; |
22 | use syntax::errors::emitter::{Emitter, BasicEmitter, EmitterWriter}; | |
23 | use syntax::errors::json::JsonEmitter; | |
1a4d82fc JJ |
24 | use syntax::diagnostics; |
25 | use syntax::feature_gate; | |
26 | use syntax::parse; | |
1a4d82fc | 27 | use syntax::parse::ParseSess; |
54a0048b | 28 | use syntax::parse::token; |
1a4d82fc | 29 | use syntax::{ast, codemap}; |
62682a34 | 30 | use syntax::feature_gate::AttributeType; |
1a4d82fc | 31 | |
85aaf69f SL |
32 | use rustc_back::target::Target; |
33 | ||
c34b1796 | 34 | use std::path::{Path, PathBuf}; |
1a4d82fc | 35 | use std::cell::{Cell, RefCell}; |
7453a54e | 36 | use std::collections::{HashMap, HashSet}; |
c34b1796 | 37 | use std::env; |
92a42be0 | 38 | use std::rc::Rc; |
54a0048b | 39 | use std::fmt; |
1a4d82fc JJ |
40 | |
41 | pub mod config; | |
92a42be0 | 42 | pub mod filesearch; |
1a4d82fc JJ |
43 | pub mod search_paths; |
44 | ||
45 | // Represents the data associated with a compilation | |
46 | // session for a single crate. | |
47 | pub struct Session { | |
48 | pub target: config::Config, | |
85aaf69f | 49 | pub host: Target, |
1a4d82fc | 50 | pub opts: config::Options, |
92a42be0 | 51 | pub cstore: Rc<for<'a> CrateStore<'a>>, |
1a4d82fc JJ |
52 | pub parse_sess: ParseSess, |
53 | // For a library crate, this is always none | |
7453a54e | 54 | pub entry_fn: RefCell<Option<(NodeId, Span)>>, |
1a4d82fc JJ |
55 | pub entry_type: Cell<Option<config::EntryFnType>>, |
56 | pub plugin_registrar_fn: Cell<Option<ast::NodeId>>, | |
c34b1796 | 57 | pub default_sysroot: Option<PathBuf>, |
d9579d0f AL |
58 | // The name of the root source file of the crate, in the local file system. |
59 | // The path is always expected to be absolute. `None` means that there is no | |
60 | // source file. | |
c34b1796 AL |
61 | pub local_crate_source_file: Option<PathBuf>, |
62 | pub working_dir: PathBuf, | |
1a4d82fc | 63 | pub lint_store: RefCell<lint::LintStore>, |
7453a54e | 64 | pub lints: RefCell<NodeMap<Vec<(lint::LintId, Span, String)>>>, |
9346a6ac | 65 | pub plugin_llvm_passes: RefCell<Vec<String>>, |
54a0048b | 66 | pub mir_passes: RefCell<mir_pass::Passes>, |
62682a34 | 67 | pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>, |
1a4d82fc | 68 | pub crate_types: RefCell<Vec<config::CrateType>>, |
e9174d1e | 69 | pub dependency_formats: RefCell<dependency_format::Dependencies>, |
54a0048b SL |
70 | // The crate_disambiguator is constructed out of all the `-C metadata` |
71 | // arguments passed to the compiler. Its value together with the crate-name | |
72 | // forms a unique global identifier for the crate. It is used to allow | |
73 | // multiple crates with the same name to coexist. See the | |
74 | // trans::back::symbol_names module for more information. | |
75 | pub crate_disambiguator: Cell<ast::Name>, | |
1a4d82fc JJ |
76 | pub features: RefCell<feature_gate::Features>, |
77 | ||
78 | /// The maximum recursion limit for potentially infinitely recursive | |
79 | /// operations such as auto-dereference and monomorphization. | |
c34b1796 | 80 | pub recursion_limit: Cell<usize>, |
1a4d82fc | 81 | |
e9174d1e SL |
82 | /// The metadata::creader module may inject an allocator dependency if it |
83 | /// didn't already find one, and this tracks what was injected. | |
84 | pub injected_allocator: Cell<Option<ast::CrateNum>>, | |
85 | ||
92a42be0 SL |
86 | /// Names of all bang-style macros and syntax extensions |
87 | /// available in this crate | |
88 | pub available_macros: RefCell<HashSet<Name>>, | |
89 | ||
7453a54e SL |
90 | /// Map from imported macro spans (which consist of |
91 | /// the localized span for the macro body) to the | |
92 | /// macro name and defintion span in the source crate. | |
93 | pub imported_macro_spans: RefCell<HashMap<Span, (String, Span)>>, | |
94 | ||
e9174d1e | 95 | next_node_id: Cell<ast::NodeId>, |
1a4d82fc JJ |
96 | } |
97 | ||
98 | impl Session { | |
7453a54e SL |
99 | pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self, |
100 | sp: S, | |
101 | msg: &str) | |
102 | -> DiagnosticBuilder<'a> { | |
9cc50fc6 SL |
103 | self.diagnostic().struct_span_warn(sp, msg) |
104 | } | |
7453a54e SL |
105 | pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(&'a self, |
106 | sp: S, | |
107 | msg: &str, | |
108 | code: &str) | |
109 | -> DiagnosticBuilder<'a> { | |
9cc50fc6 SL |
110 | self.diagnostic().struct_span_warn_with_code(sp, msg, code) |
111 | } | |
112 | pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> { | |
113 | self.diagnostic().struct_warn(msg) | |
114 | } | |
7453a54e SL |
115 | pub fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self, |
116 | sp: S, | |
117 | msg: &str) | |
118 | -> DiagnosticBuilder<'a> { | |
9cc50fc6 SL |
119 | match split_msg_into_multilines(msg) { |
120 | Some(ref msg) => self.diagnostic().struct_span_err(sp, msg), | |
121 | None => self.diagnostic().struct_span_err(sp, msg), | |
122 | } | |
123 | } | |
7453a54e SL |
124 | pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self, |
125 | sp: S, | |
126 | msg: &str, | |
127 | code: &str) | |
128 | -> DiagnosticBuilder<'a> { | |
9cc50fc6 SL |
129 | match split_msg_into_multilines(msg) { |
130 | Some(ref msg) => self.diagnostic().struct_span_err_with_code(sp, msg, code), | |
131 | None => self.diagnostic().struct_span_err_with_code(sp, msg, code), | |
c34b1796 | 132 | } |
9cc50fc6 SL |
133 | } |
134 | pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> { | |
135 | self.diagnostic().struct_err(msg) | |
136 | } | |
7453a54e SL |
137 | pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self, |
138 | sp: S, | |
139 | msg: &str) | |
140 | -> DiagnosticBuilder<'a> { | |
9cc50fc6 SL |
141 | self.diagnostic().struct_span_fatal(sp, msg) |
142 | } | |
7453a54e SL |
143 | pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(&'a self, |
144 | sp: S, | |
145 | msg: &str, | |
146 | code: &str) | |
147 | -> DiagnosticBuilder<'a> { | |
9cc50fc6 SL |
148 | self.diagnostic().struct_span_fatal_with_code(sp, msg, code) |
149 | } | |
150 | pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> { | |
151 | self.diagnostic().struct_fatal(msg) | |
152 | } | |
153 | ||
7453a54e | 154 | pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! { |
9346a6ac | 155 | panic!(self.diagnostic().span_fatal(sp, msg)) |
1a4d82fc | 156 | } |
7453a54e | 157 | pub fn span_fatal_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) -> ! { |
9346a6ac | 158 | panic!(self.diagnostic().span_fatal_with_code(sp, msg, code)) |
85aaf69f | 159 | } |
1a4d82fc | 160 | pub fn fatal(&self, msg: &str) -> ! { |
9cc50fc6 | 161 | panic!(self.diagnostic().fatal(msg)) |
1a4d82fc | 162 | } |
7453a54e | 163 | pub fn span_err_or_warn<S: Into<MultiSpan>>(&self, is_warning: bool, sp: S, msg: &str) { |
e9174d1e SL |
164 | if is_warning { |
165 | self.span_warn(sp, msg); | |
166 | } else { | |
167 | self.span_err(sp, msg); | |
168 | } | |
169 | } | |
7453a54e | 170 | pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { |
85aaf69f | 171 | match split_msg_into_multilines(msg) { |
9cc50fc6 | 172 | Some(msg) => self.diagnostic().span_err(sp, &msg), |
85aaf69f SL |
173 | None => self.diagnostic().span_err(sp, msg) |
174 | } | |
1a4d82fc | 175 | } |
7453a54e | 176 | pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) { |
85aaf69f | 177 | match split_msg_into_multilines(msg) { |
9cc50fc6 | 178 | Some(msg) => self.diagnostic().span_err_with_code(sp, &msg, code), |
85aaf69f SL |
179 | None => self.diagnostic().span_err_with_code(sp, msg, code) |
180 | } | |
1a4d82fc JJ |
181 | } |
182 | pub fn err(&self, msg: &str) { | |
9cc50fc6 | 183 | self.diagnostic().err(msg) |
1a4d82fc | 184 | } |
c34b1796 | 185 | pub fn err_count(&self) -> usize { |
9cc50fc6 | 186 | self.diagnostic().err_count() |
1a4d82fc JJ |
187 | } |
188 | pub fn has_errors(&self) -> bool { | |
9cc50fc6 | 189 | self.diagnostic().has_errors() |
1a4d82fc JJ |
190 | } |
191 | pub fn abort_if_errors(&self) { | |
9cc50fc6 SL |
192 | self.diagnostic().abort_if_errors(); |
193 | } | |
7453a54e SL |
194 | pub fn track_errors<F, T>(&self, f: F) -> Result<T, usize> |
195 | where F: FnOnce() -> T | |
9cc50fc6 | 196 | { |
7453a54e SL |
197 | let old_count = self.err_count(); |
198 | let result = f(); | |
199 | let errors = self.err_count() - old_count; | |
200 | if errors == 0 { | |
201 | Ok(result) | |
202 | } else { | |
203 | Err(errors) | |
d9579d0f | 204 | } |
1a4d82fc | 205 | } |
7453a54e | 206 | pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { |
9cc50fc6 | 207 | self.diagnostic().span_warn(sp, msg) |
1a4d82fc | 208 | } |
7453a54e | 209 | pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) { |
9cc50fc6 | 210 | self.diagnostic().span_warn_with_code(sp, msg, code) |
1a4d82fc JJ |
211 | } |
212 | pub fn warn(&self, msg: &str) { | |
9cc50fc6 | 213 | self.diagnostic().warn(msg) |
1a4d82fc | 214 | } |
7453a54e | 215 | pub fn opt_span_warn<S: Into<MultiSpan>>(&self, opt_sp: Option<S>, msg: &str) { |
1a4d82fc JJ |
216 | match opt_sp { |
217 | Some(sp) => self.span_warn(sp, msg), | |
218 | None => self.warn(msg), | |
219 | } | |
220 | } | |
d9579d0f | 221 | /// Delay a span_bug() call until abort_if_errors() |
7453a54e | 222 | pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { |
9cc50fc6 | 223 | self.diagnostic().delay_span_bug(sp, msg) |
d9579d0f | 224 | } |
9cc50fc6 SL |
225 | pub fn note_without_error(&self, msg: &str) { |
226 | self.diagnostic().note_without_error(msg) | |
227 | } | |
7453a54e | 228 | pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { |
9cc50fc6 | 229 | self.diagnostic().span_note_without_error(sp, msg) |
1a4d82fc | 230 | } |
7453a54e | 231 | pub fn span_unimpl<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! { |
1a4d82fc JJ |
232 | self.diagnostic().span_unimpl(sp, msg) |
233 | } | |
234 | pub fn unimpl(&self, msg: &str) -> ! { | |
9cc50fc6 | 235 | self.diagnostic().unimpl(msg) |
1a4d82fc JJ |
236 | } |
237 | pub fn add_lint(&self, | |
238 | lint: &'static lint::Lint, | |
239 | id: ast::NodeId, | |
240 | sp: Span, | |
241 | msg: String) { | |
242 | let lint_id = lint::LintId::of(lint); | |
243 | let mut lints = self.lints.borrow_mut(); | |
244 | match lints.get_mut(&id) { | |
54a0048b SL |
245 | Some(arr) => { |
246 | let tuple = (lint_id, sp, msg); | |
247 | if !arr.contains(&tuple) { | |
248 | arr.push(tuple); | |
249 | } | |
250 | return; | |
251 | } | |
1a4d82fc JJ |
252 | None => {} |
253 | } | |
254 | lints.insert(id, vec!((lint_id, sp, msg))); | |
255 | } | |
1a4d82fc | 256 | pub fn reserve_node_ids(&self, count: ast::NodeId) -> ast::NodeId { |
62682a34 SL |
257 | let id = self.next_node_id.get(); |
258 | ||
259 | match id.checked_add(count) { | |
260 | Some(next) => self.next_node_id.set(next), | |
54a0048b | 261 | None => bug!("Input too large, ran out of node ids!") |
62682a34 SL |
262 | } |
263 | ||
264 | id | |
1a4d82fc | 265 | } |
9cc50fc6 | 266 | pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler { |
1a4d82fc JJ |
267 | &self.parse_sess.span_diagnostic |
268 | } | |
269 | pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap { | |
62682a34 | 270 | self.parse_sess.codemap() |
1a4d82fc | 271 | } |
1a4d82fc JJ |
272 | pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose } |
273 | pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes } | |
274 | pub fn count_llvm_insns(&self) -> bool { | |
275 | self.opts.debugging_opts.count_llvm_insns | |
276 | } | |
277 | pub fn count_type_sizes(&self) -> bool { | |
278 | self.opts.debugging_opts.count_type_sizes | |
279 | } | |
280 | pub fn time_llvm_passes(&self) -> bool { | |
281 | self.opts.debugging_opts.time_llvm_passes | |
282 | } | |
283 | pub fn trans_stats(&self) -> bool { self.opts.debugging_opts.trans_stats } | |
284 | pub fn meta_stats(&self) -> bool { self.opts.debugging_opts.meta_stats } | |
285 | pub fn asm_comments(&self) -> bool { self.opts.debugging_opts.asm_comments } | |
286 | pub fn no_verify(&self) -> bool { self.opts.debugging_opts.no_verify } | |
287 | pub fn borrowck_stats(&self) -> bool { self.opts.debugging_opts.borrowck_stats } | |
288 | pub fn print_llvm_passes(&self) -> bool { | |
289 | self.opts.debugging_opts.print_llvm_passes | |
290 | } | |
291 | pub fn lto(&self) -> bool { | |
292 | self.opts.cg.lto | |
293 | } | |
294 | pub fn no_landing_pads(&self) -> bool { | |
295 | self.opts.debugging_opts.no_landing_pads | |
296 | } | |
297 | pub fn unstable_options(&self) -> bool { | |
298 | self.opts.debugging_opts.unstable_options | |
299 | } | |
300 | pub fn print_enum_sizes(&self) -> bool { | |
301 | self.opts.debugging_opts.print_enum_sizes | |
302 | } | |
c1a9b12d SL |
303 | pub fn nonzeroing_move_hints(&self) -> bool { |
304 | self.opts.debugging_opts.enable_nonzeroing_move_hints | |
305 | } | |
1a4d82fc JJ |
306 | pub fn sysroot<'a>(&'a self) -> &'a Path { |
307 | match self.opts.maybe_sysroot { | |
308 | Some (ref sysroot) => sysroot, | |
309 | None => self.default_sysroot.as_ref() | |
310 | .expect("missing sysroot and default_sysroot in Session") | |
311 | } | |
312 | } | |
313 | pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch { | |
314 | filesearch::FileSearch::new(self.sysroot(), | |
c34b1796 | 315 | &self.opts.target_triple, |
1a4d82fc JJ |
316 | &self.opts.search_paths, |
317 | kind) | |
318 | } | |
319 | pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch { | |
320 | filesearch::FileSearch::new( | |
321 | self.sysroot(), | |
322 | config::host_triple(), | |
323 | &self.opts.search_paths, | |
324 | kind) | |
325 | } | |
326 | } | |
327 | ||
b039eaaf SL |
328 | impl NodeIdAssigner for Session { |
329 | fn next_node_id(&self) -> NodeId { | |
330 | self.reserve_node_ids(1) | |
331 | } | |
332 | ||
333 | fn peek_node_id(&self) -> NodeId { | |
334 | self.next_node_id.get().checked_add(1).unwrap() | |
335 | } | |
54a0048b SL |
336 | |
337 | fn diagnostic(&self) -> &errors::Handler { | |
338 | self.diagnostic() | |
339 | } | |
b039eaaf SL |
340 | } |
341 | ||
85aaf69f SL |
342 | fn split_msg_into_multilines(msg: &str) -> Option<String> { |
343 | // Conditions for enabling multi-line errors: | |
344 | if !msg.contains("mismatched types") && | |
345 | !msg.contains("type mismatch resolving") && | |
346 | !msg.contains("if and else have incompatible types") && | |
347 | !msg.contains("if may be missing an else clause") && | |
348 | !msg.contains("match arms have incompatible types") && | |
c1a9b12d SL |
349 | !msg.contains("structure constructor specifies a structure of type") && |
350 | !msg.contains("has an incompatible type for trait") { | |
85aaf69f SL |
351 | return None |
352 | } | |
353 | let first = msg.match_indices("expected").filter(|s| { | |
54a0048b SL |
354 | let last = msg[..s.0].chars().rev().next(); |
355 | last == Some(' ') || last == Some('(') | |
b039eaaf | 356 | }).map(|(a, b)| (a - 1, a + b.len())); |
85aaf69f | 357 | let second = msg.match_indices("found").filter(|s| { |
54a0048b | 358 | msg[..s.0].chars().rev().next() == Some(' ') |
b039eaaf | 359 | }).map(|(a, b)| (a - 1, a + b.len())); |
85aaf69f SL |
360 | |
361 | let mut new_msg = String::new(); | |
362 | let mut head = 0; | |
363 | ||
364 | // Insert `\n` before expected and found. | |
365 | for (pos1, pos2) in first.zip(second) { | |
366 | new_msg = new_msg + | |
367 | // A `(` may be preceded by a space and it should be trimmed | |
368 | msg[head..pos1.0].trim_right() + // prefix | |
369 | "\n" + // insert before first | |
370 | &msg[pos1.0..pos1.1] + // insert what first matched | |
371 | &msg[pos1.1..pos2.0] + // between matches | |
372 | "\n " + // insert before second | |
373 | // 123 | |
374 | // `expected` is 3 char longer than `found`. To align the types, | |
375 | // `found` gets 3 spaces prepended. | |
376 | &msg[pos2.0..pos2.1]; // insert what second matched | |
377 | ||
378 | head = pos2.1; | |
379 | } | |
380 | ||
381 | let mut tail = &msg[head..]; | |
c34b1796 AL |
382 | let third = tail.find("(values differ") |
383 | .or(tail.find("(lifetime")) | |
384 | .or(tail.find("(cyclic type of infinite size")); | |
85aaf69f SL |
385 | // Insert `\n` before any remaining messages which match. |
386 | if let Some(pos) = third { | |
387 | // The end of the message may just be wrapped in `()` without | |
388 | // `expected`/`found`. Push this also to a new line and add the | |
389 | // final tail after. | |
390 | new_msg = new_msg + | |
391 | // `(` is usually preceded by a space and should be trimmed. | |
392 | tail[..pos].trim_right() + // prefix | |
393 | "\n" + // insert before paren | |
394 | &tail[pos..]; // append the tail | |
395 | ||
396 | tail = ""; | |
397 | } | |
398 | ||
399 | new_msg.push_str(tail); | |
400 | return Some(new_msg); | |
401 | } | |
402 | ||
1a4d82fc | 403 | pub fn build_session(sopts: config::Options, |
c34b1796 | 404 | local_crate_source_file: Option<PathBuf>, |
92a42be0 SL |
405 | registry: diagnostics::registry::Registry, |
406 | cstore: Rc<for<'a> CrateStore<'a>>) | |
1a4d82fc | 407 | -> Session { |
85aaf69f SL |
408 | // FIXME: This is not general enough to make the warning lint completely override |
409 | // normal diagnostic warnings, since the warning lint can also be denied and changed | |
410 | // later via the source code. | |
411 | let can_print_warnings = sopts.lint_opts | |
412 | .iter() | |
413 | .filter(|&&(ref key, _)| *key == "warnings") | |
414 | .map(|&(_, ref level)| *level != lint::Allow) | |
415 | .last() | |
416 | .unwrap_or(true); | |
9cc50fc6 SL |
417 | let treat_err_as_bug = sopts.treat_err_as_bug; |
418 | ||
419 | let codemap = Rc::new(codemap::CodeMap::new()); | |
420 | let emitter: Box<Emitter> = match sopts.error_format { | |
421 | config::ErrorOutputType::HumanReadable(color_config) => { | |
422 | Box::new(EmitterWriter::stderr(color_config, Some(registry), codemap.clone())) | |
423 | } | |
424 | config::ErrorOutputType::Json => { | |
425 | Box::new(JsonEmitter::stderr(Some(registry), codemap.clone())) | |
426 | } | |
427 | }; | |
85aaf69f | 428 | |
1a4d82fc | 429 | let diagnostic_handler = |
9cc50fc6 SL |
430 | errors::Handler::with_emitter(can_print_warnings, |
431 | treat_err_as_bug, | |
432 | emitter); | |
1a4d82fc | 433 | |
9cc50fc6 | 434 | build_session_(sopts, local_crate_source_file, diagnostic_handler, codemap, cstore) |
1a4d82fc JJ |
435 | } |
436 | ||
437 | pub fn build_session_(sopts: config::Options, | |
c34b1796 | 438 | local_crate_source_file: Option<PathBuf>, |
9cc50fc6 SL |
439 | span_diagnostic: errors::Handler, |
440 | codemap: Rc<codemap::CodeMap>, | |
92a42be0 | 441 | cstore: Rc<for<'a> CrateStore<'a>>) |
1a4d82fc | 442 | -> Session { |
85aaf69f SL |
443 | let host = match Target::search(config::host_triple()) { |
444 | Ok(t) => t, | |
445 | Err(e) => { | |
9cc50fc6 | 446 | panic!(span_diagnostic.fatal(&format!("Error loading host specification: {}", e))); |
85aaf69f SL |
447 | } |
448 | }; | |
1a4d82fc | 449 | let target_cfg = config::build_target_config(&sopts, &span_diagnostic); |
9cc50fc6 | 450 | let p_s = parse::ParseSess::with_span_handler(span_diagnostic, codemap); |
1a4d82fc JJ |
451 | let default_sysroot = match sopts.maybe_sysroot { |
452 | Some(_) => None, | |
453 | None => Some(filesearch::get_or_default_sysroot()) | |
454 | }; | |
455 | ||
456 | // Make the path absolute, if necessary | |
457 | let local_crate_source_file = local_crate_source_file.map(|path| | |
458 | if path.is_absolute() { | |
459 | path.clone() | |
460 | } else { | |
85aaf69f | 461 | env::current_dir().unwrap().join(&path) |
1a4d82fc JJ |
462 | } |
463 | ); | |
464 | ||
1a4d82fc JJ |
465 | let sess = Session { |
466 | target: target_cfg, | |
85aaf69f | 467 | host: host, |
1a4d82fc | 468 | opts: sopts, |
92a42be0 | 469 | cstore: cstore, |
1a4d82fc JJ |
470 | parse_sess: p_s, |
471 | // For a library crate, this is always none | |
472 | entry_fn: RefCell::new(None), | |
473 | entry_type: Cell::new(None), | |
474 | plugin_registrar_fn: Cell::new(None), | |
475 | default_sysroot: default_sysroot, | |
476 | local_crate_source_file: local_crate_source_file, | |
85aaf69f | 477 | working_dir: env::current_dir().unwrap(), |
1a4d82fc | 478 | lint_store: RefCell::new(lint::LintStore::new()), |
85aaf69f | 479 | lints: RefCell::new(NodeMap()), |
9346a6ac | 480 | plugin_llvm_passes: RefCell::new(Vec::new()), |
54a0048b | 481 | mir_passes: RefCell::new(mir_pass::Passes::new()), |
62682a34 | 482 | plugin_attributes: RefCell::new(Vec::new()), |
1a4d82fc | 483 | crate_types: RefCell::new(Vec::new()), |
e9174d1e | 484 | dependency_formats: RefCell::new(FnvHashMap()), |
54a0048b | 485 | crate_disambiguator: Cell::new(token::intern("")), |
1a4d82fc JJ |
486 | features: RefCell::new(feature_gate::Features::new()), |
487 | recursion_limit: Cell::new(64), | |
e9174d1e SL |
488 | next_node_id: Cell::new(1), |
489 | injected_allocator: Cell::new(None), | |
92a42be0 | 490 | available_macros: RefCell::new(HashSet::new()), |
7453a54e | 491 | imported_macro_spans: RefCell::new(HashMap::new()), |
1a4d82fc JJ |
492 | }; |
493 | ||
1a4d82fc JJ |
494 | sess |
495 | } | |
496 | ||
9cc50fc6 SL |
497 | pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { |
498 | let mut emitter: Box<Emitter> = match output { | |
499 | config::ErrorOutputType::HumanReadable(color_config) => { | |
500 | Box::new(BasicEmitter::stderr(color_config)) | |
501 | } | |
502 | config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()), | |
503 | }; | |
504 | emitter.emit(None, msg, None, errors::Level::Fatal); | |
505 | panic!(errors::FatalError); | |
1a4d82fc JJ |
506 | } |
507 | ||
9cc50fc6 SL |
508 | pub fn early_warn(output: config::ErrorOutputType, msg: &str) { |
509 | let mut emitter: Box<Emitter> = match output { | |
510 | config::ErrorOutputType::HumanReadable(color_config) => { | |
511 | Box::new(BasicEmitter::stderr(color_config)) | |
512 | } | |
513 | config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()), | |
514 | }; | |
515 | emitter.emit(None, msg, None, errors::Level::Warning); | |
1a4d82fc | 516 | } |
7453a54e SL |
517 | |
518 | // Err(0) means compilation was stopped, but no errors were found. | |
519 | // This would be better as a dedicated enum, but using try! is so convenient. | |
520 | pub type CompileResult = Result<(), usize>; | |
521 | ||
522 | pub fn compile_result_from_err_count(err_count: usize) -> CompileResult { | |
523 | if err_count == 0 { | |
524 | Ok(()) | |
525 | } else { | |
526 | Err(err_count) | |
527 | } | |
528 | } | |
54a0048b SL |
529 | |
530 | #[cold] | |
531 | #[inline(never)] | |
532 | pub fn bug_fmt(file: &'static str, line: u32, args: fmt::Arguments) -> ! { | |
533 | // this wrapper mostly exists so I don't have to write a fully | |
534 | // qualified path of None::<Span> inside the bug!() macro defintion | |
535 | opt_span_bug_fmt(file, line, None::<Span>, args); | |
536 | } | |
537 | ||
538 | #[cold] | |
539 | #[inline(never)] | |
540 | pub fn span_bug_fmt<S: Into<MultiSpan>>(file: &'static str, | |
541 | line: u32, | |
542 | span: S, | |
543 | args: fmt::Arguments) -> ! { | |
544 | opt_span_bug_fmt(file, line, Some(span), args); | |
545 | } | |
546 | ||
547 | fn opt_span_bug_fmt<S: Into<MultiSpan>>(file: &'static str, | |
548 | line: u32, | |
549 | span: Option<S>, | |
550 | args: fmt::Arguments) -> ! { | |
551 | tls::with_opt(move |tcx| { | |
552 | let msg = format!("{}:{}: {}", file, line, args); | |
553 | match (tcx, span) { | |
554 | (Some(tcx), Some(span)) => tcx.sess.diagnostic().span_bug(span, &msg), | |
555 | (Some(tcx), None) => tcx.sess.diagnostic().bug(&msg), | |
556 | (None, _) => panic!(msg) | |
557 | } | |
558 | }); | |
559 | unreachable!(); | |
560 | } |