]> git.proxmox.com Git - rustc.git/blame - src/librustc/session/mod.rs
Imported Upstream version 1.1.0+dfsg1
[rustc.git] / src / librustc / session / mod.rs
CommitLineData
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
JJ
11use lint;
12use metadata::cstore::CStore;
13use metadata::filesearch;
14use session::search_paths::PathKind;
15use util::nodemap::NodeMap;
16
17use syntax::ast::NodeId;
18use syntax::codemap::Span;
19use syntax::diagnostic::{self, Emitter};
20use syntax::diagnostics;
21use syntax::feature_gate;
22use syntax::parse;
23use syntax::parse::token;
24use syntax::parse::ParseSess;
25use syntax::{ast, codemap};
26
85aaf69f
SL
27use rustc_back::target::Target;
28
c34b1796 29use std::path::{Path, PathBuf};
1a4d82fc 30use std::cell::{Cell, RefCell};
c34b1796 31use std::env;
1a4d82fc
JJ
32
33pub mod config;
34pub mod search_paths;
35
36// Represents the data associated with a compilation
37// session for a single crate.
38pub struct Session {
39 pub target: config::Config,
85aaf69f 40 pub host: Target,
1a4d82fc
JJ
41 pub opts: config::Options,
42 pub cstore: CStore,
43 pub parse_sess: ParseSess,
44 // For a library crate, this is always none
45 pub entry_fn: RefCell<Option<(NodeId, codemap::Span)>>,
46 pub entry_type: Cell<Option<config::EntryFnType>>,
47 pub plugin_registrar_fn: Cell<Option<ast::NodeId>>,
c34b1796 48 pub default_sysroot: Option<PathBuf>,
d9579d0f
AL
49 // The name of the root source file of the crate, in the local file system.
50 // The path is always expected to be absolute. `None` means that there is no
51 // source file.
c34b1796
AL
52 pub local_crate_source_file: Option<PathBuf>,
53 pub working_dir: PathBuf,
1a4d82fc
JJ
54 pub lint_store: RefCell<lint::LintStore>,
55 pub lints: RefCell<NodeMap<Vec<(lint::LintId, codemap::Span, String)>>>,
9346a6ac 56 pub plugin_llvm_passes: RefCell<Vec<String>>,
1a4d82fc
JJ
57 pub crate_types: RefCell<Vec<config::CrateType>>,
58 pub crate_metadata: RefCell<Vec<String>>,
59 pub features: RefCell<feature_gate::Features>,
60
d9579d0f
AL
61 pub delayed_span_bug: RefCell<Option<(codemap::Span, String)>>,
62
1a4d82fc
JJ
63 /// The maximum recursion limit for potentially infinitely recursive
64 /// operations such as auto-dereference and monomorphization.
c34b1796 65 pub recursion_limit: Cell<usize>,
1a4d82fc
JJ
66
67 pub can_print_warnings: bool
68}
69
70impl Session {
71 pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
c34b1796
AL
72 if self.opts.treat_err_as_bug {
73 self.span_bug(sp, msg);
74 }
9346a6ac 75 panic!(self.diagnostic().span_fatal(sp, msg))
1a4d82fc 76 }
85aaf69f 77 pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> ! {
c34b1796
AL
78 if self.opts.treat_err_as_bug {
79 self.span_bug(sp, msg);
80 }
9346a6ac 81 panic!(self.diagnostic().span_fatal_with_code(sp, msg, code))
85aaf69f 82 }
1a4d82fc 83 pub fn fatal(&self, msg: &str) -> ! {
c34b1796
AL
84 if self.opts.treat_err_as_bug {
85 self.bug(msg);
86 }
1a4d82fc
JJ
87 self.diagnostic().handler().fatal(msg)
88 }
89 pub fn span_err(&self, sp: Span, msg: &str) {
c34b1796
AL
90 if self.opts.treat_err_as_bug {
91 self.span_bug(sp, msg);
92 }
85aaf69f
SL
93 match split_msg_into_multilines(msg) {
94 Some(msg) => self.diagnostic().span_err(sp, &msg[..]),
95 None => self.diagnostic().span_err(sp, msg)
96 }
1a4d82fc
JJ
97 }
98 pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
c34b1796
AL
99 if self.opts.treat_err_as_bug {
100 self.span_bug(sp, msg);
101 }
85aaf69f
SL
102 match split_msg_into_multilines(msg) {
103 Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[..], code),
104 None => self.diagnostic().span_err_with_code(sp, msg, code)
105 }
1a4d82fc
JJ
106 }
107 pub fn err(&self, msg: &str) {
c34b1796
AL
108 if self.opts.treat_err_as_bug {
109 self.bug(msg);
110 }
1a4d82fc
JJ
111 self.diagnostic().handler().err(msg)
112 }
c34b1796 113 pub fn err_count(&self) -> usize {
1a4d82fc
JJ
114 self.diagnostic().handler().err_count()
115 }
116 pub fn has_errors(&self) -> bool {
117 self.diagnostic().handler().has_errors()
118 }
119 pub fn abort_if_errors(&self) {
d9579d0f
AL
120 self.diagnostic().handler().abort_if_errors();
121
122 let delayed_bug = self.delayed_span_bug.borrow();
123 match *delayed_bug {
124 Some((span, ref errmsg)) => {
125 self.diagnostic().span_bug(span, errmsg);
126 },
127 _ => {}
128 }
1a4d82fc
JJ
129 }
130 pub fn span_warn(&self, sp: Span, msg: &str) {
131 if self.can_print_warnings {
132 self.diagnostic().span_warn(sp, msg)
133 }
134 }
135 pub fn span_warn_with_code(&self, sp: Span, msg: &str, code: &str) {
136 if self.can_print_warnings {
137 self.diagnostic().span_warn_with_code(sp, msg, code)
138 }
139 }
140 pub fn warn(&self, msg: &str) {
141 if self.can_print_warnings {
142 self.diagnostic().handler().warn(msg)
143 }
144 }
145 pub fn opt_span_warn(&self, opt_sp: Option<Span>, msg: &str) {
146 match opt_sp {
147 Some(sp) => self.span_warn(sp, msg),
148 None => self.warn(msg),
149 }
150 }
151 pub fn span_note(&self, sp: Span, msg: &str) {
152 self.diagnostic().span_note(sp, msg)
153 }
154 pub fn span_end_note(&self, sp: Span, msg: &str) {
155 self.diagnostic().span_end_note(sp, msg)
156 }
9346a6ac
AL
157
158 /// Prints out a message with a suggested edit of the code.
159 ///
160 /// See `diagnostic::RenderSpan::Suggestion` for more information.
161 pub fn span_suggestion(&self, sp: Span, msg: &str, suggestion: String) {
162 self.diagnostic().span_suggestion(sp, msg, suggestion)
163 }
1a4d82fc
JJ
164 pub fn span_help(&self, sp: Span, msg: &str) {
165 self.diagnostic().span_help(sp, msg)
166 }
167 pub fn fileline_note(&self, sp: Span, msg: &str) {
168 self.diagnostic().fileline_note(sp, msg)
169 }
85aaf69f
SL
170 pub fn fileline_help(&self, sp: Span, msg: &str) {
171 self.diagnostic().fileline_help(sp, msg)
172 }
1a4d82fc
JJ
173 pub fn note(&self, msg: &str) {
174 self.diagnostic().handler().note(msg)
175 }
176 pub fn help(&self, msg: &str) {
9346a6ac 177 self.diagnostic().handler().help(msg)
1a4d82fc
JJ
178 }
179 pub fn opt_span_bug(&self, opt_sp: Option<Span>, msg: &str) -> ! {
180 match opt_sp {
181 Some(sp) => self.span_bug(sp, msg),
182 None => self.bug(msg),
183 }
184 }
d9579d0f
AL
185 /// Delay a span_bug() call until abort_if_errors()
186 pub fn delay_span_bug(&self, sp: Span, msg: &str) {
187 let mut delayed = self.delayed_span_bug.borrow_mut();
188 *delayed = Some((sp, msg.to_string()));
189 }
1a4d82fc
JJ
190 pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
191 self.diagnostic().span_bug(sp, msg)
192 }
193 pub fn bug(&self, msg: &str) -> ! {
194 self.diagnostic().handler().bug(msg)
195 }
196 pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
197 self.diagnostic().span_unimpl(sp, msg)
198 }
199 pub fn unimpl(&self, msg: &str) -> ! {
200 self.diagnostic().handler().unimpl(msg)
201 }
202 pub fn add_lint(&self,
203 lint: &'static lint::Lint,
204 id: ast::NodeId,
205 sp: Span,
206 msg: String) {
207 let lint_id = lint::LintId::of(lint);
208 let mut lints = self.lints.borrow_mut();
209 match lints.get_mut(&id) {
210 Some(arr) => { arr.push((lint_id, sp, msg)); return; }
211 None => {}
212 }
213 lints.insert(id, vec!((lint_id, sp, msg)));
214 }
215 pub fn next_node_id(&self) -> ast::NodeId {
216 self.parse_sess.next_node_id()
217 }
218 pub fn reserve_node_ids(&self, count: ast::NodeId) -> ast::NodeId {
219 self.parse_sess.reserve_node_ids(count)
220 }
221 pub fn diagnostic<'a>(&'a self) -> &'a diagnostic::SpanHandler {
222 &self.parse_sess.span_diagnostic
223 }
224 pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap {
225 &self.parse_sess.span_diagnostic.cm
226 }
227 // This exists to help with refactoring to eliminate impossible
228 // cases later on
229 pub fn impossible_case(&self, sp: Span, msg: &str) -> ! {
230 self.span_bug(sp,
c34b1796 231 &format!("impossible case reached: {}", msg));
1a4d82fc
JJ
232 }
233 pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose }
234 pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes }
235 pub fn count_llvm_insns(&self) -> bool {
236 self.opts.debugging_opts.count_llvm_insns
237 }
238 pub fn count_type_sizes(&self) -> bool {
239 self.opts.debugging_opts.count_type_sizes
240 }
241 pub fn time_llvm_passes(&self) -> bool {
242 self.opts.debugging_opts.time_llvm_passes
243 }
244 pub fn trans_stats(&self) -> bool { self.opts.debugging_opts.trans_stats }
245 pub fn meta_stats(&self) -> bool { self.opts.debugging_opts.meta_stats }
246 pub fn asm_comments(&self) -> bool { self.opts.debugging_opts.asm_comments }
247 pub fn no_verify(&self) -> bool { self.opts.debugging_opts.no_verify }
248 pub fn borrowck_stats(&self) -> bool { self.opts.debugging_opts.borrowck_stats }
249 pub fn print_llvm_passes(&self) -> bool {
250 self.opts.debugging_opts.print_llvm_passes
251 }
252 pub fn lto(&self) -> bool {
253 self.opts.cg.lto
254 }
255 pub fn no_landing_pads(&self) -> bool {
256 self.opts.debugging_opts.no_landing_pads
257 }
258 pub fn unstable_options(&self) -> bool {
259 self.opts.debugging_opts.unstable_options
260 }
261 pub fn print_enum_sizes(&self) -> bool {
262 self.opts.debugging_opts.print_enum_sizes
263 }
264 pub fn sysroot<'a>(&'a self) -> &'a Path {
265 match self.opts.maybe_sysroot {
266 Some (ref sysroot) => sysroot,
267 None => self.default_sysroot.as_ref()
268 .expect("missing sysroot and default_sysroot in Session")
269 }
270 }
271 pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
272 filesearch::FileSearch::new(self.sysroot(),
c34b1796 273 &self.opts.target_triple,
1a4d82fc
JJ
274 &self.opts.search_paths,
275 kind)
276 }
277 pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
278 filesearch::FileSearch::new(
279 self.sysroot(),
280 config::host_triple(),
281 &self.opts.search_paths,
282 kind)
283 }
284}
285
85aaf69f
SL
286fn split_msg_into_multilines(msg: &str) -> Option<String> {
287 // Conditions for enabling multi-line errors:
288 if !msg.contains("mismatched types") &&
289 !msg.contains("type mismatch resolving") &&
290 !msg.contains("if and else have incompatible types") &&
291 !msg.contains("if may be missing an else clause") &&
292 !msg.contains("match arms have incompatible types") &&
293 !msg.contains("structure constructor specifies a structure of type") {
294 return None
295 }
296 let first = msg.match_indices("expected").filter(|s| {
297 s.0 > 0 && (msg.char_at_reverse(s.0) == ' ' ||
298 msg.char_at_reverse(s.0) == '(')
299 }).map(|(a, b)| (a - 1, b));
300 let second = msg.match_indices("found").filter(|s| {
301 msg.char_at_reverse(s.0) == ' '
302 }).map(|(a, b)| (a - 1, b));
303
304 let mut new_msg = String::new();
305 let mut head = 0;
306
307 // Insert `\n` before expected and found.
308 for (pos1, pos2) in first.zip(second) {
309 new_msg = new_msg +
310 // A `(` may be preceded by a space and it should be trimmed
311 msg[head..pos1.0].trim_right() + // prefix
312 "\n" + // insert before first
313 &msg[pos1.0..pos1.1] + // insert what first matched
314 &msg[pos1.1..pos2.0] + // between matches
315 "\n " + // insert before second
316 // 123
317 // `expected` is 3 char longer than `found`. To align the types,
318 // `found` gets 3 spaces prepended.
319 &msg[pos2.0..pos2.1]; // insert what second matched
320
321 head = pos2.1;
322 }
323
324 let mut tail = &msg[head..];
c34b1796
AL
325 let third = tail.find("(values differ")
326 .or(tail.find("(lifetime"))
327 .or(tail.find("(cyclic type of infinite size"));
85aaf69f
SL
328 // Insert `\n` before any remaining messages which match.
329 if let Some(pos) = third {
330 // The end of the message may just be wrapped in `()` without
331 // `expected`/`found`. Push this also to a new line and add the
332 // final tail after.
333 new_msg = new_msg +
334 // `(` is usually preceded by a space and should be trimmed.
335 tail[..pos].trim_right() + // prefix
336 "\n" + // insert before paren
337 &tail[pos..]; // append the tail
338
339 tail = "";
340 }
341
342 new_msg.push_str(tail);
343 return Some(new_msg);
344}
345
1a4d82fc 346pub fn build_session(sopts: config::Options,
c34b1796 347 local_crate_source_file: Option<PathBuf>,
1a4d82fc
JJ
348 registry: diagnostics::registry::Registry)
349 -> Session {
85aaf69f
SL
350 // FIXME: This is not general enough to make the warning lint completely override
351 // normal diagnostic warnings, since the warning lint can also be denied and changed
352 // later via the source code.
353 let can_print_warnings = sopts.lint_opts
354 .iter()
355 .filter(|&&(ref key, _)| *key == "warnings")
356 .map(|&(_, ref level)| *level != lint::Allow)
357 .last()
358 .unwrap_or(true);
359
1a4d82fc
JJ
360 let codemap = codemap::CodeMap::new();
361 let diagnostic_handler =
85aaf69f 362 diagnostic::default_handler(sopts.color, Some(registry), can_print_warnings);
1a4d82fc
JJ
363 let span_diagnostic_handler =
364 diagnostic::mk_span_handler(diagnostic_handler, codemap);
365
366 build_session_(sopts, local_crate_source_file, span_diagnostic_handler)
367}
368
369pub fn build_session_(sopts: config::Options,
c34b1796 370 local_crate_source_file: Option<PathBuf>,
1a4d82fc
JJ
371 span_diagnostic: diagnostic::SpanHandler)
372 -> Session {
85aaf69f
SL
373 let host = match Target::search(config::host_triple()) {
374 Ok(t) => t,
375 Err(e) => {
376 span_diagnostic.handler()
377 .fatal(&format!("Error loading host specification: {}", e));
378 }
379 };
1a4d82fc
JJ
380 let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
381 let p_s = parse::new_parse_sess_special_handler(span_diagnostic);
382 let default_sysroot = match sopts.maybe_sysroot {
383 Some(_) => None,
384 None => Some(filesearch::get_or_default_sysroot())
385 };
386
387 // Make the path absolute, if necessary
388 let local_crate_source_file = local_crate_source_file.map(|path|
389 if path.is_absolute() {
390 path.clone()
391 } else {
85aaf69f 392 env::current_dir().unwrap().join(&path)
1a4d82fc
JJ
393 }
394 );
395
396 let can_print_warnings = sopts.lint_opts
397 .iter()
398 .filter(|&&(ref key, _)| *key == "warnings")
399 .map(|&(_, ref level)| *level != lint::Allow)
400 .last()
401 .unwrap_or(true);
402
403 let sess = Session {
404 target: target_cfg,
85aaf69f 405 host: host,
1a4d82fc
JJ
406 opts: sopts,
407 cstore: CStore::new(token::get_ident_interner()),
408 parse_sess: p_s,
409 // For a library crate, this is always none
410 entry_fn: RefCell::new(None),
411 entry_type: Cell::new(None),
412 plugin_registrar_fn: Cell::new(None),
413 default_sysroot: default_sysroot,
414 local_crate_source_file: local_crate_source_file,
85aaf69f 415 working_dir: env::current_dir().unwrap(),
1a4d82fc 416 lint_store: RefCell::new(lint::LintStore::new()),
85aaf69f 417 lints: RefCell::new(NodeMap()),
9346a6ac 418 plugin_llvm_passes: RefCell::new(Vec::new()),
1a4d82fc
JJ
419 crate_types: RefCell::new(Vec::new()),
420 crate_metadata: RefCell::new(Vec::new()),
d9579d0f 421 delayed_span_bug: RefCell::new(None),
1a4d82fc
JJ
422 features: RefCell::new(feature_gate::Features::new()),
423 recursion_limit: Cell::new(64),
424 can_print_warnings: can_print_warnings
425 };
426
1a4d82fc
JJ
427 sess
428}
429
430// Seems out of place, but it uses session, so I'm putting it here
431pub fn expect<T, M>(sess: &Session, opt: Option<T>, msg: M) -> T where
432 M: FnOnce() -> String,
433{
434 diagnostic::expect(sess.diagnostic(), opt, msg)
435}
436
437pub fn early_error(msg: &str) -> ! {
438 let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None);
439 emitter.emit(None, msg, None, diagnostic::Fatal);
440 panic!(diagnostic::FatalError);
441}
442
443pub fn early_warn(msg: &str) {
444 let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None);
445 emitter.emit(None, msg, None, diagnostic::Warning);
446}