Skip to content

Commit 0156575

Browse files
ytmimicalebcartwright
authored andcommitted
Revert "Memoize format_expr"
Fixes 5399 Memoizing expressions lead to cases where rustfmt's stability guarantees were violated. This reverts commit a37d3ab.
1 parent 2c8b3be commit 0156575

File tree

10 files changed

+4
-11454
lines changed

10 files changed

+4
-11454
lines changed

src/expr.rs

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

54
use itertools::Itertools;
65
use rustc_ast::token::{Delimiter, LitKind};
@@ -23,7 +22,7 @@ use crate::macros::{rewrite_macro, MacroPosition};
2322
use crate::matches::rewrite_match;
2423
use crate::overflow::{self, IntoOverflowableItem, OverflowableItem};
2524
use crate::pairs::{rewrite_all_pairs, rewrite_pair, PairParts};
26-
use crate::rewrite::{QueryId, Rewrite, RewriteContext};
25+
use crate::rewrite::{Rewrite, RewriteContext};
2726
use crate::shape::{Indent, Shape};
2827
use crate::source_map::{LineRangeUtils, SpanUtils};
2928
use crate::spanned::Spanned;
@@ -54,54 +53,6 @@ pub(crate) fn format_expr(
5453
expr_type: ExprType,
5554
context: &RewriteContext<'_>,
5655
shape: Shape,
57-
) -> Option<String> {
58-
// when max_width is tight, we should check all possible formattings, in order to find
59-
// if we can fit expression in the limit. Doing it recursively takes exponential time
60-
// relative to input size, and people hit it with rustfmt takes minutes in #4476 #4867 #5128
61-
// By memoization of format_expr function, we format each pair of expression and shape
62-
// only once, so worst case execution time becomes O(n*max_width^3).
63-
if context.inside_macro() || context.is_macro_def {
64-
// span ids are not unique in macros, so we don't memoize result of them.
65-
return format_expr_inner(expr, expr_type, context, shape);
66-
}
67-
let clean;
68-
let query_id = QueryId {
69-
shape,
70-
span: expr.span,
71-
};
72-
if let Some(map) = context.memoize.take() {
73-
if let Some(r) = map.get(&query_id) {
74-
let r = r.clone();
75-
context.memoize.set(Some(map)); // restore map in the memoize cell for other users
76-
return r;
77-
}
78-
context.memoize.set(Some(map));
79-
clean = false;
80-
} else {
81-
context.memoize.set(Some(HashMap::default()));
82-
clean = true; // We got None, so we are the top level called function. When
83-
// this function finishes, no one is interested in what is in the map, because
84-
// all of them are sub expressions of this top level expression, and this is
85-
// done. So we should clean up memoize map to save some memory.
86-
}
87-
88-
let r = format_expr_inner(expr, expr_type, context, shape);
89-
if clean {
90-
context.memoize.set(None);
91-
} else {
92-
if let Some(mut map) = context.memoize.take() {
93-
map.insert(query_id, r.clone()); // insert the result in the memoize map
94-
context.memoize.set(Some(map)); // so it won't be computed again
95-
}
96-
}
97-
r
98-
}
99-
100-
fn format_expr_inner(
101-
expr: &ast::Expr,
102-
expr_type: ExprType,
103-
context: &RewriteContext<'_>,
104-
shape: Shape,
10556
) -> Option<String> {
10657
skip_out_of_file_lines_range!(context, expr.span);
10758

src/formatting.rs

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

33
use std::collections::HashMap;
44
use std::io::{self, Write};
5-
use std::rc::Rc;
65
use std::time::{Duration, Instant};
76

87
use rustc_ast::ast;
@@ -203,7 +202,6 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
203202
self.config,
204203
&snippet_provider,
205204
self.report.clone(),
206-
Rc::default(),
207205
);
208206
visitor.skip_context.update_with_attrs(&self.krate.attrs);
209207
visitor.is_macro_def = is_macro_def;

src/rewrite.rs

-13
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ 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;
1615

1716
pub(crate) trait Rewrite {
1817
/// Rewrite self into shape.
@@ -25,22 +24,10 @@ impl<T: Rewrite> Rewrite for ptr::P<T> {
2524
}
2625
}
2726

28-
#[derive(Clone, PartialEq, Eq, Hash)]
29-
pub(crate) struct QueryId {
30-
pub(crate) shape: Shape,
31-
pub(crate) span: Span,
32-
}
33-
34-
// We use Option<HashMap> instead of HashMap, because in case of `None`
35-
// the function clean the memoize map, but it doesn't clean when
36-
// there is `Some(empty)`, so they are different.
37-
pub(crate) type Memoize = Rc<Cell<Option<FxHashMap<QueryId, Option<String>>>>>;
38-
3927
#[derive(Clone)]
4028
pub(crate) struct RewriteContext<'a> {
4129
pub(crate) parse_sess: &'a ParseSess,
4230
pub(crate) config: &'a Config,
43-
pub(crate) memoize: Memoize,
4431
pub(crate) inside_macro: Rc<Cell<bool>>,
4532
// Force block indent style even if we are using visual indent style.
4633
pub(crate) use_block: Cell<bool>,

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

src/visitor.rs

+1-6
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::{Memoize, Rewrite, RewriteContext};
20+
use crate::rewrite::{Rewrite, RewriteContext};
2121
use crate::shape::{Indent, Shape};
2222
use crate::skip::{is_skip_attr, SkipContext};
2323
use crate::source_map::{LineRangeUtils, SpanUtils};
@@ -71,7 +71,6 @@ impl SnippetProvider {
7171

7272
pub(crate) struct FmtVisitor<'a> {
7373
parent_context: Option<&'a RewriteContext<'a>>,
74-
pub(crate) memoize: Memoize,
7574
pub(crate) parse_sess: &'a ParseSess,
7675
pub(crate) buffer: String,
7776
pub(crate) last_pos: BytePos,
@@ -759,7 +758,6 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
759758
ctx.config,
760759
ctx.snippet_provider,
761760
ctx.report.clone(),
762-
ctx.memoize.clone(),
763761
);
764762
visitor.skip_context.update(ctx.skip_context.clone());
765763
visitor.set_parent_context(ctx);
@@ -771,12 +769,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
771769
config: &'a Config,
772770
snippet_provider: &'a SnippetProvider,
773771
report: FormatReport,
774-
memoize: Memoize,
775772
) -> FmtVisitor<'a> {
776773
FmtVisitor {
777774
parent_context: None,
778775
parse_sess: parse_session,
779-
memoize,
780776
buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2),
781777
last_pos: BytePos(0),
782778
block_indent: Indent::empty(),
@@ -999,7 +995,6 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
999995
RewriteContext {
1000996
parse_sess: self.parse_sess,
1001997
config: self.config,
1002-
memoize: self.memoize.clone(),
1003998
inside_macro: Rc::new(Cell::new(false)),
1004999
use_block: Cell::new(false),
10051000
is_if_else_block: Cell::new(false),

0 commit comments

Comments
 (0)