Skip to content

Commit 5ed6c52

Browse files
committed
---
yaml --- r: 7269 b: refs/heads/master c: e36ea8e h: refs/heads/master i: 7267: b2990b1 v: v3
1 parent d1d5b6a commit 5ed6c52

File tree

2 files changed

+66
-7
lines changed

2 files changed

+66
-7
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: d9d3be7acc660e3b587fe468f237217990423c69
2+
refs/heads/master: e36ea8e9939dfadbf8c6e130f771442d4442cedd

trunk/src/comp/driver/rustc.rs

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,19 +62,14 @@ options:
6262
");
6363
}
6464

65-
fn main(args: [str]) {
65+
fn run_compiler(args: [str], demitter: diagnostic::emitter) {
6666
// Don't display log spew by default. Can override with RUST_LOG.
6767
logging::console_off();
6868

6969
let args = args, binary = vec::shift(args);
7070

7171
if vec::len(args) == 0u { usage(binary); ret; }
7272

73-
let demitter = fn@(cmsp: option<(codemap::codemap, codemap::span)>,
74-
msg: str, lvl: diagnostic::level) {
75-
diagnostic::emit(cmsp, msg, lvl);
76-
};
77-
7873
let match =
7974
alt getopts::getopts(args, opts()) {
8075
ok(m) { m }
@@ -118,6 +113,70 @@ fn main(args: [str]) {
118113
compile_input(sess, cfg, ifile, odir, ofile);
119114
}
120115

116+
/*
117+
This is a sanity check that any failure of the compiler is performed
118+
through the diagnostic module and reported properly - we shouldn't be calling
119+
plain-old-fail on any execution path that might be taken. Since we have
120+
console logging off by default, hitting a plain fail statement would make the
121+
compiler silently exit, which would be terrible.
122+
123+
This method wraps the compiler in a subtask and injects a function into the
124+
diagnostic emitter which records when we hit a fatal error. If the task
125+
fails without recording a fatal error then we've encountered a compiler
126+
bug and need to present an error.
127+
*/
128+
fn monitor(f: fn~(diagnostic::emitter)) {
129+
tag monitor_msg {
130+
fatal;
131+
done;
132+
};
133+
134+
let p = comm::port();
135+
let ch = comm::chan(p);
136+
137+
alt task::try {||
138+
139+
task::unsupervise();
140+
141+
// The 'diagnostics emitter'. Every error, warning, etc. should
142+
// go through this function.
143+
let demitter = fn@(cmsp: option<(codemap::codemap, codemap::span)>,
144+
msg: str, lvl: diagnostic::level) {
145+
if lvl == diagnostic::fatal {
146+
comm::send(ch, fatal);
147+
}
148+
diagnostic::emit(cmsp, msg, lvl);
149+
};
150+
151+
resource finally(ch: comm::chan<monitor_msg>) {
152+
comm::send(ch, done);
153+
}
154+
155+
let _finally = finally(ch);
156+
157+
f(demitter)
158+
} {
159+
result::ok(_) { /* fallthrough */ }
160+
result::err(_) {
161+
// Task failed without emitting a fatal diagnostic
162+
if comm::recv(p) == done {
163+
diagnostic::emit(
164+
none,
165+
diagnostic::ice_msg("unexpected failure"),
166+
diagnostic::error);
167+
}
168+
// Fail so the process returns a failure code
169+
fail;
170+
}
171+
}
172+
}
173+
174+
fn main(args: [str]) {
175+
monitor {|demitter|
176+
run_compiler(args, demitter);
177+
}
178+
}
179+
121180
// Local Variables:
122181
// mode: rust
123182
// fill-column: 78;

0 commit comments

Comments
 (0)