rustc_monomorphize/
util.rs

1use std::fs::OpenOptions;
2use std::io::prelude::*;
3
4use rustc_middle::ty::{self, ClosureSizeProfileData, Instance, TyCtxt};
5
6/// For a given closure, writes out the data for the profiling the impact of RFC 2229 on
7/// closure size into a CSV.
8///
9/// During the same compile all closures dump the information in the same file
10/// "closure_profile_XXXXX.csv", which is created in the directory where the compiler is invoked.
11pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: Instance<'tcx>) {
12    let Ok(mut file) = OpenOptions::new()
13        .create(true)
14        .append(true)
15        .open(&format!("closure_profile_{}.csv", std::process::id()))
16    else {
17        eprintln!("Couldn't open file for writing closure profile");
18        return;
19    };
20
21    let closure_def_id = closure_instance.def_id().expect_local();
22    let typeck_results = tcx.typeck(closure_def_id);
23
24    if typeck_results.closure_size_eval.contains_key(&closure_def_id) {
25        let typing_env = ty::TypingEnv::fully_monomorphized();
26
27        let ClosureSizeProfileData { before_feature_tys, after_feature_tys } =
28            typeck_results.closure_size_eval[&closure_def_id];
29
30        let before_feature_tys = tcx.instantiate_and_normalize_erasing_regions(
31            closure_instance.args,
32            typing_env,
33            ty::EarlyBinder::bind(before_feature_tys),
34        );
35        let after_feature_tys = tcx.instantiate_and_normalize_erasing_regions(
36            closure_instance.args,
37            typing_env,
38            ty::EarlyBinder::bind(after_feature_tys),
39        );
40
41        let new_size = tcx
42            .layout_of(typing_env.as_query_input(after_feature_tys))
43            .map(|l| format!("{:?}", l.size.bytes()))
44            .unwrap_or_else(|e| format!("Failed {e:?}"));
45
46        let old_size = tcx
47            .layout_of(typing_env.as_query_input(before_feature_tys))
48            .map(|l| format!("{:?}", l.size.bytes()))
49            .unwrap_or_else(|e| format!("Failed {e:?}"));
50
51        let closure_span = tcx.def_span(closure_def_id);
52        let src_file = tcx.sess.source_map().span_to_filename(closure_span);
53        let line_nos = tcx
54            .sess
55            .source_map()
56            .span_to_lines(closure_span)
57            .map(|l| format!("{:?} {:?}", l.lines.first(), l.lines.last()))
58            .unwrap_or_else(|e| format!("{e:?}"));
59
60        if let Err(e) = writeln!(
61            file,
62            "{}, {}, {}, {:?}",
63            old_size,
64            new_size,
65            src_file.prefer_local(),
66            line_nos
67        ) {
68            eprintln!("Error writing to file {e}")
69        }
70    }
71}