Skip to content

Commit 9c65c8c

Browse files
committed
Memoize format_expr
1 parent 4a053f2 commit 9c65c8c

File tree

10 files changed

+11441
-4
lines changed

10 files changed

+11441
-4
lines changed

Diff for: src/expr.rs

+40-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::borrow::Cow;
22
use std::cmp::min;
3+
use std::collections::HashMap;
34

45
use itertools::Itertools;
56
use rustc_ast::token::{DelimToken, LitKind};
@@ -22,7 +23,7 @@ use crate::macros::{rewrite_macro, MacroPosition};
2223
use crate::matches::rewrite_match;
2324
use crate::overflow::{self, IntoOverflowableItem, OverflowableItem};
2425
use crate::pairs::{rewrite_all_pairs, rewrite_pair, PairParts};
25-
use crate::rewrite::{Rewrite, RewriteContext};
26+
use crate::rewrite::{QueryId, Rewrite, RewriteContext};
2627
use crate::shape::{Indent, Shape};
2728
use crate::source_map::{LineRangeUtils, SpanUtils};
2829
use crate::spanned::Spanned;
@@ -53,6 +54,44 @@ pub(crate) fn format_expr(
5354
expr_type: ExprType,
5455
context: &RewriteContext<'_>,
5556
shape: Shape,
57+
) -> Option<String> {
58+
if context.inside_macro() || context.is_macro_def {
59+
return format_expr_inner(expr, expr_type, context, shape);
60+
}
61+
let mut map = context.memoize.borrow_mut();
62+
let clean;
63+
let query_id = QueryId {
64+
shape,
65+
span: expr.span,
66+
};
67+
if let Some(map) = &*map {
68+
if let Some(r) = map.get(&query_id) {
69+
return r.clone();
70+
}
71+
clean = false;
72+
} else {
73+
*map = Some(HashMap::default());
74+
clean = true;
75+
}
76+
drop(map);
77+
let r = format_expr_inner(expr, expr_type, context, shape);
78+
let mut map = context.memoize.borrow_mut();
79+
if clean {
80+
*map = None;
81+
} else {
82+
if let Some(map) = &mut *map {
83+
map.insert(query_id, r.clone());
84+
}
85+
}
86+
drop(map);
87+
r
88+
}
89+
90+
fn format_expr_inner(
91+
expr: &ast::Expr,
92+
expr_type: ExprType,
93+
context: &RewriteContext<'_>,
94+
shape: Shape,
5695
) -> Option<String> {
5796
skip_out_of_file_lines_range!(context, expr.span);
5897

Diff for: src/formatting.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
use std::collections::HashMap;
44
use std::io::{self, Write};
5+
use std::rc::Rc;
56
use std::time::{Duration, Instant};
67

78
use rustc_ast::ast;
@@ -188,6 +189,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
188189
self.config,
189190
&snippet_provider,
190191
self.report.clone(),
192+
Rc::default(),
191193
);
192194
visitor.skip_context.update_with_attrs(&self.krate.attrs);
193195
visitor.is_macro_def = is_macro_def;

Diff for: src/rewrite.rs

+10
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::shape::Shape;
1212
use crate::skip::SkipContext;
1313
use crate::visitor::SnippetProvider;
1414
use crate::FormatReport;
15+
use rustc_data_structures::stable_map::FxHashMap;
1516

1617
pub(crate) trait Rewrite {
1718
/// Rewrite self into shape.
@@ -24,10 +25,19 @@ impl<T: Rewrite> Rewrite for ptr::P<T> {
2425
}
2526
}
2627

28+
#[derive(Clone, PartialEq, Eq, Hash)]
29+
pub(crate) struct QueryId {
30+
pub(crate) shape: Shape,
31+
pub(crate) span: Span,
32+
}
33+
34+
pub(crate) type Memoize = Option<FxHashMap<QueryId, Option<String>>>;
35+
2736
#[derive(Clone)]
2837
pub(crate) struct RewriteContext<'a> {
2938
pub(crate) parse_sess: &'a ParseSess,
3039
pub(crate) config: &'a Config,
40+
pub(crate) memoize: Rc<RefCell<Memoize>>,
3141
pub(crate) inside_macro: Rc<Cell<bool>>,
3242
// Force block indent style even if we are using visual indent style.
3343
pub(crate) use_block: Cell<bool>,

Diff for: src/shape.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::ops::{Add, Sub};
44

55
use crate::Config;
66

7-
#[derive(Copy, Clone, Debug)]
7+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
88
pub(crate) struct Indent {
99
// Width of the block indent, in characters. Must be a multiple of
1010
// Config::tab_spaces.
@@ -139,7 +139,7 @@ impl Sub<usize> for Indent {
139139
// 8096 is close enough to infinite for rustfmt.
140140
const INFINITE_SHAPE_WIDTH: usize = 8096;
141141

142-
#[derive(Copy, Clone, Debug)]
142+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
143143
pub(crate) struct Shape {
144144
pub(crate) width: usize,
145145
// The current indentation of code.

Diff for: src/visitor.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::items::{
1717
use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition};
1818
use crate::modules::Module;
1919
use crate::parse::session::ParseSess;
20-
use crate::rewrite::{Rewrite, RewriteContext};
20+
use crate::rewrite::{Memoize, Rewrite, RewriteContext};
2121
use crate::shape::{Indent, Shape};
2222
use crate::skip::{is_skip_attr, SkipContext};
2323
use crate::source_map::{LineRangeUtils, SpanUtils};
@@ -71,6 +71,7 @@ impl SnippetProvider {
7171

7272
pub(crate) struct FmtVisitor<'a> {
7373
parent_context: Option<&'a RewriteContext<'a>>,
74+
pub(crate) memoize: Rc<RefCell<Memoize>>,
7475
pub(crate) parse_sess: &'a ParseSess,
7576
pub(crate) buffer: String,
7677
pub(crate) last_pos: BytePos,
@@ -754,6 +755,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
754755
ctx.config,
755756
ctx.snippet_provider,
756757
ctx.report.clone(),
758+
ctx.memoize.clone(),
757759
);
758760
visitor.skip_context.update(ctx.skip_context.clone());
759761
visitor.set_parent_context(ctx);
@@ -765,10 +767,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
765767
config: &'a Config,
766768
snippet_provider: &'a SnippetProvider,
767769
report: FormatReport,
770+
memoize: Rc<RefCell<Memoize>>,
768771
) -> FmtVisitor<'a> {
769772
FmtVisitor {
770773
parent_context: None,
771774
parse_sess: parse_session,
775+
memoize,
772776
buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2),
773777
last_pos: BytePos(0),
774778
block_indent: Indent::empty(),
@@ -987,6 +991,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
987991
RewriteContext {
988992
parse_sess: self.parse_sess,
989993
config: self.config,
994+
memoize: self.memoize.clone(),
990995
inside_macro: Rc::new(Cell::new(false)),
991996
use_block: Cell::new(false),
992997
is_if_else_block: Cell::new(false),

0 commit comments

Comments
 (0)