Skip to content

Commit 41def27

Browse files
committed
Add --pretty everybody_loops option.
This prints out a transformed version of the input source code where every function body is replaced with `loop { }`. All such bodies are (1.) trivial and (2.) guaranteed to pass the type-checker in a valid compiler; therefore they make very nice input to start with when narrowing down a bug exposed by a large test input (such as librustc itself).
1 parent e711e2d commit 41def27

File tree

1 file changed

+74
-1
lines changed

1 file changed

+74
-1
lines changed

src/librustc_driver/pretty.rs

+74-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ use rustc_borrowck::graphviz as borrowck_dot;
3030

3131
use syntax::ast;
3232
use syntax::ast_map::{mod, blocks, NodePrinter};
33+
use syntax::codemap;
34+
use syntax::fold::{mod, Folder};
3335
use syntax::print::{pp, pprust};
36+
use syntax::ptr::P;
3437

3538
use graphviz as dot;
3639

@@ -42,6 +45,7 @@ use arena::TypedArena;
4245
#[deriving(Copy, PartialEq, Show)]
4346
pub enum PpSourceMode {
4447
PpmNormal,
48+
PpmEveryBodyLoops,
4549
PpmExpanded,
4650
PpmTyped,
4751
PpmIdentified,
@@ -61,6 +65,7 @@ pub fn parse_pretty(sess: &Session, name: &str) -> (PpMode, Option<UserIdentifie
6165
let opt_second = split.next();
6266
let first = match first {
6367
"normal" => PpmSource(PpmNormal),
68+
"everybody_loops" => PpmSource(PpmEveryBodyLoops),
6469
"expanded" => PpmSource(PpmExpanded),
6570
"typed" => PpmSource(PpmTyped),
6671
"expanded,identified" => PpmSource(PpmExpandedIdentified),
@@ -105,7 +110,7 @@ impl PpSourceMode {
105110
F: FnOnce(&PrinterSupport, B) -> A,
106111
{
107112
match *self {
108-
PpmNormal | PpmExpanded => {
113+
PpmNormal | PpmEveryBodyLoops | PpmExpanded => {
109114
let annotation = NoAnn { sess: sess, ast_map: ast_map };
110115
f(&annotation, payload)
111116
}
@@ -384,6 +389,7 @@ impl UserIdentifiedItem {
384389
fn needs_ast_map(ppm: &PpMode, opt_uii: &Option<UserIdentifiedItem>) -> bool {
385390
match *ppm {
386391
PpmSource(PpmNormal) |
392+
PpmSource(PpmEveryBodyLoops) |
387393
PpmSource(PpmIdentified) => opt_uii.is_some(),
388394

389395
PpmSource(PpmExpanded) |
@@ -397,6 +403,7 @@ fn needs_ast_map(ppm: &PpMode, opt_uii: &Option<UserIdentifiedItem>) -> bool {
397403
fn needs_expansion(ppm: &PpMode) -> bool {
398404
match *ppm {
399405
PpmSource(PpmNormal) |
406+
PpmSource(PpmEveryBodyLoops) |
400407
PpmSource(PpmIdentified) => false,
401408

402409
PpmSource(PpmExpanded) |
@@ -407,13 +414,79 @@ fn needs_expansion(ppm: &PpMode) -> bool {
407414
}
408415
}
409416

417+
struct ReplaceBodyWithLoop {
418+
within_static_or_const: bool,
419+
}
420+
421+
impl ReplaceBodyWithLoop {
422+
fn new() -> ReplaceBodyWithLoop {
423+
ReplaceBodyWithLoop { within_static_or_const: false }
424+
}
425+
}
426+
427+
impl fold::Folder for ReplaceBodyWithLoop {
428+
fn fold_item_underscore(&mut self, i: ast::Item_) -> ast::Item_ {
429+
match i {
430+
ast::ItemStatic(..) | ast::ItemConst(..) => {
431+
self.within_static_or_const = true;
432+
let ret = fold::noop_fold_item_underscore(i, self);
433+
self.within_static_or_const = false;
434+
return ret;
435+
}
436+
_ => {
437+
fold::noop_fold_item_underscore(i, self)
438+
}
439+
}
440+
}
441+
442+
443+
fn fold_block(&mut self, b: P<ast::Block>) -> P<ast::Block> {
444+
fn expr_to_block(rules: ast::BlockCheckMode,
445+
e: Option<P<ast::Expr>>) -> P<ast::Block> {
446+
P(ast::Block {
447+
expr: e,
448+
view_items: vec![], stmts: vec![], rules: rules,
449+
id: ast::DUMMY_NODE_ID, span: codemap::DUMMY_SP,
450+
})
451+
}
452+
453+
if !self.within_static_or_const {
454+
455+
let empty_block = expr_to_block(ast::DefaultBlock, None);
456+
let loop_expr = P(ast::Expr {
457+
node: ast::ExprLoop(empty_block, None),
458+
id: ast::DUMMY_NODE_ID, span: codemap::DUMMY_SP
459+
});
460+
461+
expr_to_block(b.rules, Some(loop_expr))
462+
463+
} else {
464+
fold::noop_fold_block(b, self)
465+
}
466+
}
467+
468+
// in general the pretty printer processes unexpanded code, so
469+
// we override the default `fold_mac` method which panics.
470+
fn fold_mac(&mut self, _macro: ast::Mac) -> ast::Mac {
471+
fold::noop_fold_mac(_macro, self)
472+
}
473+
}
474+
410475
pub fn pretty_print_input(sess: Session,
411476
cfg: ast::CrateConfig,
412477
input: &Input,
413478
ppm: PpMode,
414479
opt_uii: Option<UserIdentifiedItem>,
415480
ofile: Option<Path>) {
416481
let krate = driver::phase_1_parse_input(&sess, cfg, input);
482+
483+
let krate = if let PpmSource(PpmEveryBodyLoops) = ppm {
484+
let mut fold = ReplaceBodyWithLoop::new();
485+
fold.fold_crate(krate)
486+
} else {
487+
krate
488+
};
489+
417490
let id = link::find_crate_name(Some(&sess), krate.attrs.as_slice(), input);
418491

419492
let is_expanded = needs_expansion(&ppm);

0 commit comments

Comments
 (0)