Skip to content

Commit a8dfa37

Browse files
committed
rustc_errors: only box the diagnostic field in DiagnosticBuilder.
1 parent 68fa81b commit a8dfa37

File tree

3 files changed

+25
-31
lines changed

3 files changed

+25
-31
lines changed

compiler/rustc_errors/src/diagnostic_builder.rs

+22-28
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,14 @@ use tracing::debug;
1515
/// extending `HandlerFlags`, accessed via `self.handler.flags`.
1616
#[must_use]
1717
#[derive(Clone)]
18-
pub struct DiagnosticBuilder<'a>(Box<DiagnosticBuilderInner<'a>>);
19-
20-
/// This is a large type, and often used as a return value, especially within
21-
/// the frequently-used `PResult` type. In theory, return value optimization
22-
/// (RVO) should avoid unnecessary copying. In practice, it does not (at the
23-
/// time of writing). The split between `DiagnosticBuilder` and
24-
/// `DiagnosticBuilderInner` exists to avoid many `memcpy` calls.
25-
// FIXME(eddyb) try having two pointers in `DiagnosticBuilder`, by only boxing
26-
// `Diagnostic` (i.e. `struct DiagnosticBuilder(&Handler, Box<Diagnostic>);`).
27-
#[must_use]
28-
#[derive(Clone)]
29-
struct DiagnosticBuilderInner<'a> {
18+
pub struct DiagnosticBuilder<'a> {
3019
handler: &'a Handler,
31-
diagnostic: Diagnostic,
20+
21+
/// `Diagnostic` is a large type, and `DiagnosticBuilder` is often used as a
22+
/// return value, especially within the frequently-used `PResult` type.
23+
/// In theory, return value optimization (RVO) should avoid unnecessary
24+
/// copying. In practice, it does not (at the time of writing).
25+
diagnostic: Box<Diagnostic>,
3226
}
3327

3428
/// In general, the `DiagnosticBuilder` uses deref to allow access to
@@ -61,7 +55,7 @@ macro_rules! forward {
6155
$(#[$attrs])*
6256
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
6357
pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
64-
self.0.diagnostic.$n($($name),*);
58+
self.diagnostic.$n($($name),*);
6559
self
6660
}
6761
};
@@ -78,7 +72,7 @@ macro_rules! forward {
7872
$(#[$attrs])*
7973
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
8074
pub fn $n<$($generic: $bound),*>(&mut self, $($name: $ty),*) -> &mut Self {
81-
self.0.diagnostic.$n($($name),*);
75+
self.diagnostic.$n($($name),*);
8276
self
8377
}
8478
};
@@ -88,20 +82,20 @@ impl<'a> Deref for DiagnosticBuilder<'a> {
8882
type Target = Diagnostic;
8983

9084
fn deref(&self) -> &Diagnostic {
91-
&self.0.diagnostic
85+
&self.diagnostic
9286
}
9387
}
9488

9589
impl<'a> DerefMut for DiagnosticBuilder<'a> {
9690
fn deref_mut(&mut self) -> &mut Diagnostic {
97-
&mut self.0.diagnostic
91+
&mut self.diagnostic
9892
}
9993
}
10094

10195
impl<'a> DiagnosticBuilder<'a> {
10296
/// Emit the diagnostic.
10397
pub fn emit(&mut self) {
104-
self.0.handler.emit_diagnostic(&self);
98+
self.handler.emit_diagnostic(&self);
10599
self.cancel();
106100
}
107101

@@ -131,19 +125,19 @@ impl<'a> DiagnosticBuilder<'a> {
131125
/// Converts the builder to a `Diagnostic` for later emission,
132126
/// unless handler has disabled such buffering.
133127
pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a Handler)> {
134-
if self.0.handler.flags.dont_buffer_diagnostics
135-
|| self.0.handler.flags.treat_err_as_bug.is_some()
128+
if self.handler.flags.dont_buffer_diagnostics
129+
|| self.handler.flags.treat_err_as_bug.is_some()
136130
{
137131
self.emit();
138132
return None;
139133
}
140134

141-
let handler = self.0.handler;
135+
let handler = self.handler;
142136

143137
// We must use `Level::Cancelled` for `dummy` to avoid an ICE about an
144138
// unused diagnostic.
145139
let dummy = Diagnostic::new(Level::Cancelled, "");
146-
let diagnostic = std::mem::replace(&mut self.0.diagnostic, dummy);
140+
let diagnostic = std::mem::replace(&mut *self.diagnostic, dummy);
147141

148142
// Logging here is useful to help track down where in logs an error was
149143
// actually emitted.
@@ -170,7 +164,7 @@ impl<'a> DiagnosticBuilder<'a> {
170164
/// locally in whichever way makes the most sense.
171165
pub fn delay_as_bug(&mut self) {
172166
self.level = Level::Bug;
173-
self.0.handler.delay_as_bug(self.0.diagnostic.clone());
167+
self.handler.delay_as_bug((*self.diagnostic).clone());
174168
self.cancel();
175169
}
176170

@@ -187,7 +181,7 @@ impl<'a> DiagnosticBuilder<'a> {
187181
/// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is
188182
/// primary.
189183
pub fn span_label(&mut self, span: Span, label: impl Into<String>) -> &mut Self {
190-
self.0.diagnostic.span_label(span, label);
184+
self.diagnostic.span_label(span, label);
191185
self
192186
}
193187

@@ -200,7 +194,7 @@ impl<'a> DiagnosticBuilder<'a> {
200194
) -> &mut Self {
201195
let label = label.as_ref();
202196
for span in spans {
203-
self.0.diagnostic.span_label(span, label);
197+
self.diagnostic.span_label(span, label);
204198
}
205199
self
206200
}
@@ -340,13 +334,13 @@ impl<'a> DiagnosticBuilder<'a> {
340334
/// diagnostic.
341335
crate fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> DiagnosticBuilder<'a> {
342336
debug!("Created new diagnostic");
343-
DiagnosticBuilder(Box::new(DiagnosticBuilderInner { handler, diagnostic }))
337+
DiagnosticBuilder { handler, diagnostic: Box::new(diagnostic) }
344338
}
345339
}
346340

347341
impl<'a> Debug for DiagnosticBuilder<'a> {
348342
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
349-
self.0.diagnostic.fmt(f)
343+
self.diagnostic.fmt(f)
350344
}
351345
}
352346

@@ -356,7 +350,7 @@ impl<'a> Drop for DiagnosticBuilder<'a> {
356350
fn drop(&mut self) {
357351
if !panicking() && !self.cancelled() {
358352
let mut db = DiagnosticBuilder::new(
359-
self.0.handler,
353+
self.handler,
360354
Level::Bug,
361355
"the following error was constructed but not emitted",
362356
);

compiler/rustc_errors/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ pub use snippet::Style;
5454
pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a>>;
5555

5656
// `PResult` is used a lot. Make sure it doesn't unintentionally get bigger.
57-
// (See also the comment on `DiagnosticBuilderInner`.)
57+
// (See also the comment on `DiagnosticBuilder`'s `diagnostic` field.)
5858
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
59-
rustc_data_structures::static_assert_size!(PResult<'_, bool>, 16);
59+
rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24);
6060

6161
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)]
6262
pub enum SuggestionStyle {

src/tools/rustfmt/src/parse/session.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ mod tests {
315315
code: None,
316316
message: vec![],
317317
children: vec![],
318-
suggestions: vec![],
318+
suggestions: Ok(vec![]),
319319
span: span.unwrap_or_else(MultiSpan::new),
320320
sort_span: DUMMY_SP,
321321
is_lint: false,

0 commit comments

Comments
 (0)